package railo.runtime.search.lucene2.query;
import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import java.util.Vector;
import java.util.WeakHashMap;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import railo.commons.lang.ParserString;
/**
* @deprecated no longer in use
* The simple query is the default query type and is appropriate for the vast majority of searches.
* When entering text on a search form, you perform a simple query by entering a word or comma-delimited strings,
* with optional wildcard characters.
* Verity treats each comma as a logical OR. If you omit the commas, Verity treats the expression as a phrase.
*/
public final class Simple {
private String OR="or";
private String AND="and";
private String NOT="not";
private char QUOTER='"';
private String FIELD="contents";
private static final short TYPE_TERMAL=0;
private static final short TYPE_WILDCARD=1;
private static final short TYPE_PREFIX=2;
private static final short TYPE_FUZZY=3;
private static final short TYPE_PHRASE=4;
private Analyzer analyzer;
private Map results=new WeakHashMap();
/**
* constructor of the class
* @param analyzer
*/
public Simple(Analyzer analyzer) {
this.analyzer=analyzer;
}
/**
* parse given string query
* @param criteria
* @return matching Query
*/
public Query parse(String criteria) {
Query qry=(Query) results.get(criteria);
if(qry!=null) return qry;
// remove operators at start
if(criteria.length()>0) {
char first=criteria.charAt(0);
// start with operator
while(first=='*' || first=='~' || first=='?') {
criteria=criteria.substring(1);
if(criteria.length()==0) break;
first=criteria.charAt(0);
}
}
// make never foud query if quey is empty
if(criteria.length()==0) {
BooleanQuery bool = new BooleanQuery();
bool.add(new TermQuery(new Term(FIELD, "dshnuiaslfspfhsadhfisd")), OccurUtil.toOccur(false, true));
results.put(criteria,bool);
return bool;
}
ParserString ps=new ParserString(criteria);
qry= orOp(ps);
results.put(criteria,qry);
return qry;
}
private Query orOp(ParserString ps) {
Query query=andOp(ps);
ps.removeSpace();
// OR
while(ps.isValidIndex() && ps.forwardIfCurrent(OR) || ps.forwardIfCurrent(',')) {
ps.removeSpace();
BooleanQuery bool = new BooleanQuery();
bool.add(query, OccurUtil.toOccur(false, false));
//bool.add(query, false, false);
bool.add(andOp(ps), OccurUtil.toOccur(false, false));
query = bool;
}
return query;
}
private Query andOp(ParserString ps) {
Query query = notOp(ps);
ps.removeSpace();
// AND
while(ps.isValidIndex() && ps.forwardIfCurrent(AND)) {
ps.removeSpace();
BooleanQuery bool = new BooleanQuery();
bool.add(query, OccurUtil.toOccur(true, false));
bool.add(notOp(ps), OccurUtil.toOccur(true, false));
query = bool;
}
return query;
}
private Query notOp(ParserString ps) {
// NOT
if(ps.isValidIndex() && ps.forwardIfCurrent(NOT)) {
ps.removeSpace();
BooleanQuery bool = new BooleanQuery();
bool.add(clip(ps), OccurUtil.toOccur(false, true));
return bool;
}
return clip(ps);
}
private Query clip(ParserString ps) {
// ()
if(ps.isValidIndex() && ps.forwardIfCurrent('(')) {
Query query=orOp(ps);
ps.removeSpace();
ps.forwardIfCurrent(')');
ps.removeSpace();
return query;
}
return literal(ps);
}
private Query literal(ParserString ps) {
_Term term=term(ps);
ps.removeSpace();
while(ps.isValidIndex() && !ps.isCurrent(',') && !ps.isCurrent(OR) && !ps.isCurrent(AND) && !ps.isCurrent(')')) {
term.append(term(ps));
ps.removeSpace();
}
return term.toQuery();
}
private _Term term(ParserString ps) {
short type=TYPE_TERMAL;
ps.removeSpace();
StringBuffer sb=new StringBuffer();
boolean inside=false;
char c=0;
while(ps.isValidIndex() && ((c=ps.getCurrentLower())!=' ' && c!=',' && c!=')' || inside)) {
ps.next();
if(c==QUOTER) {
inside=!inside;
type=TYPE_PHRASE;
continue;
}
sb.append(c);
if(!inside) {
if(type==TYPE_PREFIX)type=TYPE_WILDCARD;
if(type==TYPE_TERMAL && c=='*')type=TYPE_PREFIX;
if(c=='?')type=TYPE_WILDCARD;
if(type==TYPE_TERMAL && c=='~') {
type=TYPE_FUZZY;
break;
}
}
}
return new _Term(type,sb.toString());
}
class _Term {
private short type;
private String content;
private _Term(short type, String content) {
this.type = type;
this.content=content;
}
private void append(_Term term) {
content+=' '+term.content;
type=TYPE_PHRASE;
}
private Query toQuery() {
if(type==TYPE_FUZZY) return toFuzzyQuery();
else if(type==TYPE_WILDCARD) return new WildcardQuery(toTerm());
else if(type==TYPE_PREFIX)return toPrefixQuery();
else if(type==TYPE_PHRASE) return toPhraseQuery();
return new TermQuery(toTerm());
}
private FuzzyQuery toFuzzyQuery() {
String c=toContent();
return new FuzzyQuery(new Term(FIELD,c.substring(0,c.length()-1)));
}
private PrefixQuery toPrefixQuery() {
String c=toContent();
return new PrefixQuery(new Term(FIELD,c.substring(0,c.length()-1)));
}
private PhraseQuery toPhraseQuery() {
TokenStream source = analyzer.tokenStream(FIELD,new StringReader(content));
Vector v = new Vector();
org.apache.lucene.analysis.Token t;
while (true) {
try {
t = source.next();
}
catch (IOException e) {
t = null;
}
if (t == null)
break;
v.addElement(t.termText());
}
try {
source.close();
}
catch (IOException e) {
// ignore
}
PhraseQuery q = new PhraseQuery();
q.setSlop(0);
for (int i=0; i<v.size(); i++) {
q.add(new Term(FIELD, (String) v.elementAt(i)));
}
return q;
}
private String toContent() {
return content;
}
private Term toTerm() {
return new Term(FIELD, toContent());
}
@Override
public String toString() {
return toContent();
}
}
}