001    package railo.runtime.search.lucene2.query;
002    
003    import java.io.IOException;
004    import java.io.StringReader;
005    import java.util.Map;
006    import java.util.Vector;
007    import java.util.WeakHashMap;
008    
009    import org.apache.lucene.analysis.Analyzer;
010    import org.apache.lucene.analysis.TokenStream;
011    import org.apache.lucene.index.Term;
012    import org.apache.lucene.search.BooleanQuery;
013    import org.apache.lucene.search.FuzzyQuery;
014    import org.apache.lucene.search.PhraseQuery;
015    import org.apache.lucene.search.PrefixQuery;
016    import org.apache.lucene.search.Query;
017    import org.apache.lucene.search.TermQuery;
018    import org.apache.lucene.search.WildcardQuery;
019    
020    import railo.commons.lang.ParserString;
021    
022    /**
023     * @deprecated no longer in use
024     * The simple query is the default query type and is appropriate for the vast majority of searches. 
025     * When entering text on a search form, you perform a simple query by entering a word or comma-delimited strings, 
026     * with optional wildcard characters. 
027     * Verity treats each comma as a logical OR. If you omit the commas, Verity treats the expression as a phrase.
028     */
029    public final class Simple {
030        private String OR="or";
031        private String AND="and";
032        private String NOT="not";
033        private char QUOTER='"';
034        private String FIELD="contents";
035        
036        private static final short TYPE_TERMAL=0;
037        private static final short TYPE_WILDCARD=1;
038        private static final short TYPE_PREFIX=2;
039        private static final short TYPE_FUZZY=3;
040        private static final short TYPE_PHRASE=4;
041        
042        private Analyzer analyzer;
043        
044        private Map results=new WeakHashMap();
045        
046        /**
047         * constructor of the class
048         * @param analyzer
049         */
050        public Simple(Analyzer analyzer) {
051            this.analyzer=analyzer;
052            
053        }
054        /**
055         * parse given string query
056         * @param criteria
057         * @return matching Query
058         */
059        public Query parse(String criteria) {
060            Query qry=(Query) results.get(criteria);
061            if(qry!=null) return qry;
062            
063            // remove operators at start
064            if(criteria.length()>0) {
065                char first=criteria.charAt(0);
066                // start with operator
067                while(first=='*' || first=='~' || first=='?') {
068                    criteria=criteria.substring(1);
069                    if(criteria.length()==0) break;
070                    first=criteria.charAt(0);
071                } 
072            }
073            
074            // make never foud query if quey is empty
075            if(criteria.length()==0) {
076                BooleanQuery bool = new BooleanQuery();
077                bool.add(new TermQuery(new Term(FIELD, "dshnuiaslfspfhsadhfisd")), OccurUtil.toOccur(false, true));
078                results.put(criteria,bool);
079                return bool;
080            }
081            
082            ParserString ps=new ParserString(criteria);
083            qry= orOp(ps);
084            results.put(criteria,qry);
085            return qry;
086        }
087        
088        
089    
090        private Query orOp(ParserString ps) {
091            Query query=andOp(ps);
092            ps.removeSpace();
093                   
094            // OR
095            while(ps.isValidIndex() && ps.forwardIfCurrent(OR) || ps.forwardIfCurrent(',')) {
096                ps.removeSpace();
097                BooleanQuery bool = new BooleanQuery();
098                
099                bool.add(query, OccurUtil.toOccur(false, false));
100                //bool.add(query, false, false);
101                bool.add(andOp(ps), OccurUtil.toOccur(false, false));
102                query = bool;
103            }
104            return query;
105        }
106    
107        private Query andOp(ParserString ps) {
108            Query query = notOp(ps);
109            ps.removeSpace();
110            
111            // AND
112            while(ps.isValidIndex() && ps.forwardIfCurrent(AND)) {
113                ps.removeSpace();
114                BooleanQuery bool = new BooleanQuery();
115                bool.add(query, OccurUtil.toOccur(true, false));
116                bool.add(notOp(ps), OccurUtil.toOccur(true, false));
117                query = bool;
118            }
119            return query;
120        }
121        private Query notOp(ParserString ps) {
122            // NOT
123            if(ps.isValidIndex() && ps.forwardIfCurrent(NOT)) {
124                ps.removeSpace();
125                BooleanQuery bool = new BooleanQuery();
126                bool.add(clip(ps), OccurUtil.toOccur(false, true));
127                return bool;
128            }
129            return clip(ps);
130        }
131    
132        private Query clip(ParserString ps) {
133            // ()
134            if(ps.isValidIndex() && ps.forwardIfCurrent('(')) {
135                Query query=orOp(ps);
136                ps.removeSpace();
137                ps.forwardIfCurrent(')');
138                ps.removeSpace();
139                return query;
140            }
141            return literal(ps);
142        }
143    
144        private Query literal(ParserString ps) {
145            _Term term=term(ps);
146            ps.removeSpace();
147            while(ps.isValidIndex() && !ps.isCurrent(',') && !ps.isCurrent(OR) && !ps.isCurrent(AND) && !ps.isCurrent(')')) {
148                term.append(term(ps));
149                ps.removeSpace();
150            }
151            return term.toQuery();
152        }
153    
154        private _Term term(ParserString ps) {
155            short type=TYPE_TERMAL;
156            ps.removeSpace();
157            StringBuffer sb=new StringBuffer();
158            boolean inside=false;
159            char c=0;
160            while(ps.isValidIndex() && ((c=ps.getCurrentLower())!=' ' && c!=',' && c!=')' || inside)) {
161                ps.next();
162                if(c==QUOTER) {
163                    inside=!inside;
164                    type=TYPE_PHRASE;
165                    continue;
166                }
167                sb.append(c);
168                if(!inside) {
169                        if(type==TYPE_PREFIX)type=TYPE_WILDCARD;
170                        if(type==TYPE_TERMAL && c=='*')type=TYPE_PREFIX;
171                        if(c=='?')type=TYPE_WILDCARD;
172                        if(type==TYPE_TERMAL && c=='~') {
173                            type=TYPE_FUZZY;
174                            break;
175                        }
176                }
177            }
178            return new _Term(type,sb.toString());
179    
180        }
181        
182        class _Term {
183            private short type;
184            private String content;
185            
186            private _Term(short type, String content) {
187                this.type = type;
188                this.content=content;
189            }
190            
191            private void append(_Term term) {
192                content+=' '+term.content;
193                type=TYPE_PHRASE;
194            }
195    
196            private Query toQuery() {
197                if(type==TYPE_FUZZY) return toFuzzyQuery();
198                else if(type==TYPE_WILDCARD) return new WildcardQuery(toTerm());
199                else if(type==TYPE_PREFIX)return toPrefixQuery();
200                else if(type==TYPE_PHRASE) return toPhraseQuery();
201                return new TermQuery(toTerm());
202            }
203            
204            private FuzzyQuery toFuzzyQuery() {
205                String c=toContent();
206                return new FuzzyQuery(new Term(FIELD,c.substring(0,c.length()-1)));
207            }
208            
209            private PrefixQuery toPrefixQuery() {
210                String c=toContent();
211                return new PrefixQuery(new Term(FIELD,c.substring(0,c.length()-1)));
212            }
213            
214            private PhraseQuery toPhraseQuery() {
215                
216    
217                TokenStream source = analyzer.tokenStream(FIELD,new StringReader(content));
218                Vector v = new Vector();
219                org.apache.lucene.analysis.Token t;
220    
221                while (true) {
222                  try {
223                    t = source.next();
224                  }
225                  catch (IOException e) {
226                    t = null;
227                  }
228                  if (t == null)
229                    break;
230                  v.addElement(t.termText());
231                }
232                try {
233                  source.close();
234                }
235                catch (IOException e) {
236                  // ignore
237                }
238    
239                PhraseQuery q = new PhraseQuery();
240                 q.setSlop(0);
241                 
242                 for (int i=0; i<v.size(); i++) {
243                    q.add(new Term(FIELD, (String) v.elementAt(i)));
244                  }
245                  return q;
246                
247            }
248    
249            private String toContent() {
250                return content;
251            }
252            private Term toTerm() {
253                return new Term(FIELD, toContent());
254            }
255            @Override
256            public String toString() {
257                return toContent();
258            }
259        }   
260    }