#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"
#include "CLucene/analysis/standard/StandardFilter.h"
#include "CLucene/analysis/standard/StandardTokenizer.h"
using
namespace
lucene::search;
using
namespace
lucene::util;
using
namespace
lucene::analysis;
using
namespace
lucene::analysis::standard;
using
namespace
lucene::index;
namespace
lucene{
namespace
queryParser{
QueryParserBase::QueryParserBase(){
PhraseSlop = 0;
lowercaseExpandedTerms =
true
;
}
QueryParserBase::~QueryParserBase(){
}
void
QueryParserBase::setLowercaseExpandedTerms(
bool
LowercaseExpandedTerms){
lowercaseExpandedTerms = LowercaseExpandedTerms;
}
bool
QueryParserBase::getLowercaseExpandedTerms() {
return
lowercaseExpandedTerms;
}
void
QueryParserBase::AddClause(VoidList<BooleanClause*>& clauses, int_t conj, int_t mods, Query* q){
bool
required;
bool
prohibited;
if
(conj == CONJ_AND) {
const
uint_t nPreviousClauses = clauses.size();
if
(nPreviousClauses > 0) {
BooleanClause* c = clauses[nPreviousClauses-1];
if
(!c->prohibited)
c->required =
true
;
}
}
if
(q == NULL)
return
;
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 );
}
Query* QueryParserBase::GetFieldQuery(
const
char_t* field, Analyzer& analyzer,
const
char_t* queryText){
CND_PRECONDITION(field != NULL,
"field is NULL"
)
CND_PRECONDITION(queryText != NULL,
"queryText is NULL"
)
StringReader reader(queryText);
TokenStream* source = &analyzer.tokenStream(field, &reader);
CND_CONDITION(source != NULL,
"source is NULL"
)
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
Query* QueryParserBase::GetRangeQuery(
const
char_t* field, Analyzer& analyzer,
const
char_t* queryText,
bool
inclusive)
{
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();
terms[i] =
new
Term(field, text);
delete
t;
}
else
{
terms[i] = NULL;
}
}
Query* ret =
new
RangeQuery(terms[0], terms[1], inclusive);
if
(terms[0] != NULL) terms[0]->finalize();
if
(terms[1] != NULL) terms[1]->finalize();
delete
&source;
delete
reader;
return
ret;
}
char_t *QueryParserBase::AnalyzeExpandedTerm(
const
char_t* field,
const
char_t* termStr){
CND_PRECONDITION(field != NULL,
"field is NULL"
)
CND_PRECONDITION(termStr != NULL,
"termStr is NULL"
)
StringReader *reader =
new
StringReader(termStr);
CND_CONDITION(reader != NULL,
"Could not allocate memory for StringReader reader"
)
TokenStream* source = NULL;
source =
new
StandardTokenizer(*reader);
source =
new
StandardFilter(source,
true
);
source =
new
LowerCaseFilter(source,
true
);
CND_CONDITION(source != NULL,
"source is NULL"
)
Token* T = NULL;
try
{
T = source->next();
}
catch
(...){
T = NULL;
}
_DELETE(source);
_DELETE(reader);
if
(T == NULL){
return
NULL;
}
char_t* text = stringDuplicate(T->TermText());
_DELETE(T);
return
text;
}
#ifndef NO_PREFIX_QUERY
Query* QueryParserBase::GetPrefixQuery(
const
char_t* field,
const
char_t* termStr){
CND_PRECONDITION(field != NULL,
"field is NULL"
)
CND_PRECONDITION(termStr != NULL,
"termStr is NULL"
)
char_t* queryText = stringDuplicate(termStr);
if
(lowercaseExpandedTerms){
if
(queryText[stringLength(queryText)-1] ==
'*'
){
queryText[stringLength(queryText)-1] =
'\0'
;
}
const
char_t* TempQueryText = (
const
char_t*) queryText;
queryText = AnalyzeExpandedTerm(field,TempQueryText);
_DELETE_ARRAY(TempQueryText);
}
Term* t =
new
Term(field, queryText);
CND_CONDITION(t != NULL,
"Could not allocate memory for term T"
)
Query *q =
new
PrefixQuery(t);
CND_CONDITION(q != NULL,
"Could not allocate memory for PrefixQuery q"
)
t->finalize();
_DELETE_ARRAY(queryText);
return
q;
}
#endif
#ifndef NO_FUZZY_QUERY
Query* QueryParserBase::GetFuzzyQuery(
const
char_t* field,
const
char_t* termStr){
CND_PRECONDITION(field != NULL,
"field is NULL"
)
CND_PRECONDITION(field != NULL,
"field is NULL"
)
char_t* queryText = stringDuplicate(termStr);
if
(lowercaseExpandedTerms){
if
(queryText[stringLength(queryText)-1] ==
'~'
){
queryText[stringLength(queryText)-1] =
'\0'
;
}
const
char_t* TempQueryText = (
const
char_t*) queryText;
queryText = AnalyzeExpandedTerm(field,TempQueryText);
_DELETE_ARRAY(TempQueryText);
}
Term* t =
new
Term(field, queryText);
CND_CONDITION(t != NULL,
"Could not allocate memory for term T"
)
Query *q =
new
FuzzyQuery(t);
CND_CONDITION(q != NULL,
"Could not allocate memory for FuzzyQuery q"
)
t->finalize();
_DELETE_ARRAY(queryText);
return
q;
}
#endif
#endif
}}