comparison src/goodjava/lucene/queryparser/StringFieldParser.java @ 1458:6b6c11c9164e

goodjava.lucene
author Franklin Schmidt <fschmidt@gmail.com>
date Fri, 20 Mar 2020 10:58:53 -0600
parents src/goodjava/queryparser/StringFieldParser.java@f6075d7a36f2
children b04b8fc5f4f4
comparison
equal deleted inserted replaced
1457:a84ce37f3892 1458:6b6c11c9164e
1 package goodjava.lucene.queryparser;
2
3 import java.io.StringReader;
4 import java.io.IOException;
5 import org.apache.lucene.analysis.Analyzer;
6 import org.apache.lucene.analysis.TokenStream;
7 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
8 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
9 import org.apache.lucene.search.Query;
10 import org.apache.lucene.search.TermQuery;
11 import org.apache.lucene.search.TermRangeQuery;
12 import org.apache.lucene.search.PhraseQuery;
13 import org.apache.lucene.search.WildcardQuery;
14 import org.apache.lucene.search.PrefixQuery;
15 import org.apache.lucene.search.SortField;
16 import org.apache.lucene.index.Term;
17 import goodjava.parser.ParseException;
18
19
20 public class StringFieldParser implements FieldParser {
21 public int slop = 0;
22 public final Analyzer analyzer;
23
24 public StringFieldParser(Analyzer analyzer) {
25 this.analyzer = analyzer;
26 }
27
28 @Override public Query getQuery(SaneQueryParser qp,String field,String query) throws ParseException {
29 String wildcard = wildcard(qp,query);
30 if( wildcard != null )
31 return new WildcardQuery(new Term(field,wildcard));
32 if( query.endsWith("*") && !query.endsWith("\\*") )
33 return new PrefixQuery(new Term(field,query.substring(0,query.length()-1)));
34 query = escape(qp,query);
35 PhraseQuery pq = new PhraseQuery();
36 try {
37 TokenStream ts = analyzer.tokenStream(field,new StringReader(query));
38 CharTermAttribute termAttr = ts.addAttribute(CharTermAttribute.class);
39 PositionIncrementAttribute posAttr = ts.addAttribute(PositionIncrementAttribute.class);
40 ts.reset();
41 int pos = -1;
42 while( ts.incrementToken() ) {
43 pos += posAttr.getPositionIncrement();
44 pq.add( new Term(field,termAttr.toString()), pos );
45 }
46 ts.end();
47 ts.close();
48 } catch(IOException e) {
49 throw new RuntimeException(e);
50 }
51 Term[] terms = pq.getTerms();
52 if( terms.length==1 && pq.getPositions()[0]==0 )
53 return new TermQuery(terms[0]);
54 return pq;
55 }
56
57 @Override public Query getRangeQuery(SaneQueryParser qp,String field,String minQuery,String maxQuery,boolean includeMin,boolean includeMax) throws ParseException {
58 minQuery = minQuery.equals("*") ? null : escape(qp,minQuery);
59 maxQuery = maxQuery.equals("*") ? null : escape(qp,maxQuery);
60 return TermRangeQuery.newStringRange(field,minQuery,maxQuery,includeMin,includeMax);
61 }
62
63 static String escape(SaneQueryParser qp,String s) throws ParseException {
64 final char[] a = s.toCharArray();
65 int i, n;
66 if( a[0] == '"' ) {
67 if( a[a.length-1] != '"' ) throw new RuntimeException();
68 i = 1;
69 n = a.length - 1;
70 } else {
71 i = 0;
72 n = a.length;
73 }
74 StringBuilder sb = new StringBuilder();
75 for( ; i<n; i++ ) {
76 char c = a[i];
77 if( c == '\\' ) {
78 if( ++i == a.length )
79 throw qp.exception("ends with '\\'");
80 c = a[i];
81 }
82 sb.append(c);
83 }
84 return sb.toString();
85 }
86
87 private static String wildcard(SaneQueryParser qp,String s) throws ParseException {
88 final char[] a = s.toCharArray();
89 if( a[0] == '"' )
90 return null;
91 boolean hasWildcard = false;
92 StringBuilder sb = new StringBuilder();
93 for( int i=0; i<a.length; i++ ) {
94 char c = a[i];
95 if( c=='?' || c=='*' && i<a.length-1 )
96 hasWildcard = true;
97 if( c == '\\' ) {
98 if( ++i == a.length )
99 throw qp.exception("ends with '\\'");
100 c = a[i];
101 if( c=='?' || c=='*' )
102 sb.append('\\');
103 }
104 sb.append(c);
105 }
106 return hasWildcard ? sb.toString() : null;
107 }
108
109 @Override public SortField getSortField(SaneQueryParser qp,String field,boolean reverse) {
110 return new SortField( field, SortField.Type.STRING, reverse );
111 }
112
113 }