github.com/balzaczyy/golucene@v0.0.0-20151210033525-d0be9ee89713/queryparser/classic/queryParserBase.go (about)

     1  package classic
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/balzaczyy/golucene/core/analysis"
     7  	"github.com/balzaczyy/golucene/core/search"
     8  	"strings"
     9  )
    10  
    11  const (
    12  	CONJ_NONE = iota
    13  	CONJ_AND
    14  	CONJ_OR
    15  )
    16  
    17  const (
    18  	MOD_NONE = 0
    19  	MOD_NOT  = 10
    20  	MOD_REQ  = 11
    21  )
    22  
    23  type QueryParserBaseSPI interface {
    24  	ReInit(CharStream)
    25  	TopLevelQuery(string) (search.Query, error)
    26  }
    27  
    28  type QueryParserBase struct {
    29  	*QueryBuilder
    30  
    31  	spi QueryParserBaseSPI
    32  
    33  	operator Operator
    34  
    35  	field      string
    36  	phraseSlop int
    37  
    38  	autoGeneratePhraseQueries bool
    39  }
    40  
    41  func newQueryParserBase(spi QueryParserBaseSPI) *QueryParserBase {
    42  	return &QueryParserBase{
    43  		QueryBuilder: newQueryBuilder(),
    44  		spi:          spi,
    45  		operator:     OP_OR,
    46  	}
    47  }
    48  
    49  // L116
    50  func (qp *QueryParserBase) Parse(query string) (res search.Query, err error) {
    51  	qp.spi.ReInit(newFastCharStream(strings.NewReader(query)))
    52  	if res, err = qp.spi.TopLevelQuery(qp.field); err != nil {
    53  		return nil, errors.New(fmt.Sprintf("Cannot parse '%v': %v", query, err))
    54  	}
    55  	if res != nil {
    56  		return res, nil
    57  	}
    58  	return qp.newBooleanQuery(false), nil
    59  }
    60  
    61  // L408
    62  func (qp *QueryParserBase) addClause(clauses []*search.BooleanClause,
    63  	conj, mods int, q search.Query) []*search.BooleanClause {
    64  	var required, prohibited bool
    65  
    66  	// If this term is introduced by AND, make the preceding term required,
    67  	// unless it's already prohibited
    68  	if len(clauses) > 0 && conj == CONJ_AND {
    69  		panic("not implemented yet")
    70  	}
    71  
    72  	if len(clauses) > 0 && qp.operator == OP_AND && conj == CONJ_OR {
    73  		panic("not implemented yet")
    74  	}
    75  
    76  	// We might have been passed an empty query; the term might have been
    77  	// filtered away by the analyzer.
    78  	if q == nil {
    79  		return clauses
    80  	}
    81  
    82  	if qp.operator == OP_OR {
    83  		// We set REQUIRED if we're introduced by AND or +; PROHIBITED if
    84  		// introduced by NOT or -; make sure not to set both.
    85  		prohibited = (mods == MOD_NOT)
    86  		required = (mods == MOD_REQ)
    87  		if conj == CONJ_AND && !prohibited {
    88  			required = true
    89  		}
    90  	} else {
    91  		panic("not implemented yet")
    92  	}
    93  	if required {
    94  		panic("not implemented yet")
    95  	} else if !prohibited {
    96  		return append(clauses, qp.newBooleanClause(q, search.SHOULD))
    97  	} else {
    98  		panic("not implemented yet")
    99  	}
   100  }
   101  
   102  // L461
   103  func (qp *QueryParserBase) fieldQuery(field, queryText string, quoted bool) search.Query {
   104  	return qp.newFieldQuery(qp.analyzer, field, queryText, quoted)
   105  }
   106  
   107  func (qp *QueryParserBase) newFieldQuery(analyzer analysis.Analyzer,
   108  	field, queryText string, quoted bool) search.Query {
   109  
   110  	var occur search.Occur
   111  	if qp.operator == OP_AND {
   112  		occur = search.MUST
   113  	} else {
   114  		occur = search.SHOULD
   115  	}
   116  	return qp.createFieldQuery(analyzer, occur, field, queryText,
   117  		quoted || qp.autoGeneratePhraseQueries, qp.phraseSlop)
   118  }
   119  
   120  // L539
   121  
   122  func (qp *QueryParserBase) newBooleanClause(q search.Query, occur search.Occur) *search.BooleanClause {
   123  	return search.NewBooleanClause(q, occur)
   124  }
   125  
   126  // L676
   127  /*
   128  Factory method for generating query, given a set of clauses.
   129  By default creates a boolean query composed of clauses passed in.
   130  
   131  Can be overridden by extending classes, to modify query being
   132  returned.
   133  */
   134  func (qp *QueryParserBase) booleanQuery(clauses []*search.BooleanClause) (search.Query, error) {
   135  	return qp.booleanQueryDisableCoord(clauses, false)
   136  }
   137  
   138  func (qp *QueryParserBase) booleanQueryDisableCoord(clauses []*search.BooleanClause, disableCoord bool) (search.Query, error) {
   139  	if len(clauses) == 0 {
   140  		return nil, nil // all clause words were filetered away by the analyzer.
   141  	}
   142  	query := qp.newBooleanQuery(disableCoord)
   143  	for _, clause := range clauses {
   144  		query.AddClause(clause)
   145  	}
   146  	return query, nil
   147  }
   148  
   149  // L827
   150  func (qp *QueryParserBase) handleBareTokenQuery(qField string,
   151  	term, fuzzySlop *Token, prefix, wildcard, fuzzy, regexp bool) (q search.Query, err error) {
   152  
   153  	var termImage string
   154  	if termImage, err = qp.discardEscapeChar(term.image); err != nil {
   155  		return nil, err
   156  	}
   157  	if wildcard {
   158  		panic("not implemented yet")
   159  	} else if prefix {
   160  		panic("not implemented yet")
   161  	} else if regexp {
   162  		panic("not implemented yet")
   163  	} else if fuzzy {
   164  		panic("not implemented yet")
   165  	} else {
   166  		return qp.fieldQuery(qField, termImage, false), nil
   167  	}
   168  }
   169  
   170  // L876
   171  func (qp *QueryParserBase) handleBoost(q search.Query, boost *Token) search.Query {
   172  	if boost != nil {
   173  		panic("not implemented yet")
   174  	}
   175  	return q
   176  }
   177  
   178  // L906
   179  func (qp *QueryParserBase) discardEscapeChar(input string) (string, error) {
   180  	output := make([]rune, len(input))
   181  
   182  	length := 0
   183  
   184  	lastCharWasEscapeChar := false
   185  
   186  	codePointMultiplier := 0
   187  
   188  	// codePoint := 0
   189  
   190  	for _, curChar := range input {
   191  		if codePointMultiplier > 0 {
   192  			panic("not implemented yet")
   193  		} else if lastCharWasEscapeChar {
   194  			panic("not implemented yet")
   195  		} else {
   196  			if curChar == '\\' {
   197  				lastCharWasEscapeChar = true
   198  			} else {
   199  				output[length] = curChar
   200  				length++
   201  			}
   202  		}
   203  	}
   204  
   205  	if codePointMultiplier > 0 {
   206  		return "", errors.New("Truncated unicode escape sequence.")
   207  	}
   208  	if lastCharWasEscapeChar {
   209  		return "", errors.New("Term can not end with escape character.")
   210  	}
   211  	return string(output), nil
   212  }