#include "CLucene/StdHeader.h" #include "QueryParserBase.h" #include "CLucene/search/BooleanClause.h" #include "CLucene/util/VoidList.h" #include "CLucene/analysis/AnalysisHeader.h" #include "CLucene/analysis/Analyzers.h" #include "CLucene/index/Term.h" #include "CLucene/search/TermQuery.h" #include "CLucene/search/PhraseQuery.h" #include "CLucene/search/RangeQuery.h" using namespace lucene::search; using namespace lucene::util; using namespace lucene::analysis; using namespace lucene::index; namespace lucene{ namespace queryParser{ QueryParserBase::QueryParserBase(): PhraseSlop(0) { } QueryParserBase::~QueryParserBase(){ } // Adds the next parsed clause. void QueryParserBase::AddClause(VoidList& clauses, int_t conj, int_t mods, Query* q) { bool required; bool prohibited; // If this term is introduced by AND, make the preceding term required, // unless it's already prohibited if (conj == CONJ_AND) { BooleanClause* c = clauses[clauses.size()-1]; if (!c->prohibited) c->required = true; } // We might have been passed a NULL query; the term might have been // filtered away by the analyzer. if (q == NULL) return; // We set REQUIRED if we're introduced by AND or +; PROHIBITED if // introduced by NOT or -; make sure not to set both. prohibited = (mods == MOD_NOT); required = (mods == MOD_REQ); if (conj == CONJ_AND && !prohibited) required = true; clauses.push_back(new BooleanClause(*q,true, required, prohibited)); } void QueryParserBase::throwParserException(const char_t* message, char_t ch, int_t col, int_t line ) { char_t msg[1024]; stringPrintF(msg,message,ch,col,line); _THROWX ( msg ); } // Returns a query for the specified field. Query* QueryParserBase::GetFieldQuery(const char_t* field, Analyzer& analyzer, const char_t* queryText) { // Use the analyzer to get all the tokens, and then build a TermQuery, // PhraseQuery, or nothing based on the term count StringReader reader(queryText); TokenStream& source = analyzer.tokenStream(field, &reader); StringArrayConst v; v.setDoDelete(DELETE_TYPE_DELETE_ARRAY); Token* t = NULL; while (true) { try { t = source.next(); } catch(...) { t = NULL; } if (t == NULL) break; v.push_back( stringDuplicate(t->TermText())); delete t; } if (v.size() == 0){ delete &source; return NULL; }else if (v.size() == 1){ Term* t = new Term(field, v[0]); Query* ret = new TermQuery( *t ); t->finalize(); delete &source; return ret; }else { PhraseQuery* q = new PhraseQuery; q->setSlop(PhraseSlop); StringArrayConstIterator itr = v.begin(); while ( itr != v.end() ) { const char_t* data = *itr; Term* t = new Term(field, data); q->add(t); t->finalize(); itr++; } delete &source; return q; } } #ifndef NO_RANGE_QUERY // Returns a range query. Query* QueryParserBase::GetRangeQuery(const char_t* field, Analyzer& analyzer, const char_t* queryText, bool inclusive) { // Use the analyzer to get all the tokens. There should be 1 or 2. Reader* reader = new StringReader(queryText); TokenStream& source = analyzer.tokenStream(field, reader); Term* terms[2]; Token* t; for (int_t i = 0; i < 2; i++) { try { t = source.next(); } catch (...) { t = NULL; } if (t != NULL) { const char_t* text = t->TermText(); //if ( text.ToUpper() != "NULL") //{ terms[i] = new Term(field, text); //} delete t; } /* DSR:CL_BUG Unless terms[i] is set NULL, an uninitialized access can ** be performed below. */ else { terms[i] = NULL; } } Query* ret = new RangeQuery(terms[0], terms[1], inclusive); /* DSR:CL_BUG: Don't try to call finalize method if the Term* is NULL. */ if (terms[0] != NULL) terms[0]->finalize(); if (terms[1] != NULL) terms[1]->finalize(); delete &source; delete reader; return ret; } #endif }}