1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sf.eos.lucene;
17
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.lucene.analysis.Analyzer;
21 import org.apache.lucene.queryParser.ParseException;
22 import org.apache.lucene.queryParser.QueryParser;
23 import org.apache.lucene.search.Hits;
24 import org.apache.lucene.search.Query;
25 import org.apache.lucene.search.Searcher;
26
27 import java.io.IOException;
28 import java.util.ArrayList;
29 import java.util.List;
30
31 import net.sf.eos.EosException;
32 import net.sf.eos.config.Configuration;
33 import net.sf.eos.config.Configured;
34 import net.sf.eos.entity.CommonNameResolver;
35 import net.sf.eos.lucene.DefaultEosQuery.Entry.Bool;
36 import net.sf.eos.search.EosQuery;
37 import net.sf.eos.search.LookupEntry;
38
39
40
41
42
43
44 public class DefaultEosQuery extends Configured implements CommonDocument, EosQuery {
45
46
47 private static final Log LOG =
48 LogFactory.getLog(DefaultEosQuery.class.getName());
49
50 final static class Entry {
51
52 public static enum Bool {AND, OR, AND_NOT}
53
54 private final Bool bool;
55 private final String fieldName;
56 private final String lowerBoundValue;
57 private final String upperBoundValue;
58
59 public Entry (final Bool op,
60 final String fieldName,
61 final String lowerBoundValue) {
62 this(op, fieldName, lowerBoundValue, null);
63 }
64
65 public Entry (@SuppressWarnings("hiding") final Bool op,
66 @SuppressWarnings("hiding") final String fieldName,
67 @SuppressWarnings("hiding") final String lowerBoundValue,
68 @SuppressWarnings("hiding") final String upperBoundValue) {
69 this.bool = op;
70 this.fieldName = fieldName;
71 this.lowerBoundValue = lowerBoundValue;
72 this.upperBoundValue = upperBoundValue;
73 }
74
75 public Bool getBool() {
76 return this.bool;
77 }
78
79 public String getFieldName() {
80 return this.fieldName;
81 }
82
83 public String getLowerBoundValue() {
84 return this.lowerBoundValue;
85 }
86
87 public String getUpperBoundValue() {
88 return this.upperBoundValue;
89 }
90 }
91
92 private final List<Entry> query = new ArrayList<Entry>();
93
94 public DefaultEosQuery and(final String phrase) {
95 andMeta(FieldName.CONTENT.name(), phrase);
96 return this;
97 }
98
99 public DefaultEosQuery andNot(final String phrase) throws EosException {
100 andNotMeta(FieldName.CONTENT.name(), phrase);
101 return this;
102 }
103
104 public DefaultEosQuery andMeta(final String fieldName, final String value) {
105 final Entry entry = new Entry(Bool.AND, fieldName, value);
106 this.query.add(entry);
107 return this;
108 }
109
110 public DefaultEosQuery andNotMeta(final String fieldName, final String value) {
111 final Entry entry = new Entry(Bool.AND_NOT, fieldName, value);
112 this.query.add(entry);
113 return this;
114 }
115
116 public DefaultEosQuery andMetaRange(final String fieldName,
117 final String lowerBound,
118 final String upperBound) {
119 final Entry entry = new Entry(Bool.AND, fieldName, lowerBound, upperBound);
120 this.query.add(entry);
121 return this;
122 }
123
124 public DefaultEosQuery or(final String phrase) {
125 orMeta(FieldName.CONTENT.name(), phrase);
126 return this;
127 }
128
129 public DefaultEosQuery orMeta(final String fieldName, final String value) {
130 final Entry entry = new Entry(Bool.OR, fieldName, value);
131 this.query.add(entry);
132 return this;
133 }
134
135 public DefaultEosQuery orMetaRange(final String fieldName,
136 final String lowerBound,
137 final String upperBound) {
138 final Entry entry = new Entry(Bool.OR, fieldName, lowerBound, upperBound);
139 this.query.add(entry);
140 return this;
141 }
142
143 @SuppressWarnings("nls")
144 public List<LookupEntry> execute() throws EosException {
145
146 final Configuration conf = getConfiguration();
147
148 final AnalyzerSupplier analyzerProvider =
149 AnalyzerSupplier.newInstance(conf);
150 final Analyzer analyzer = analyzerProvider.get();
151 final String queryString = createLuceneQuery();
152 final QueryParser parser =
153 new QueryParser(CommonDocument.FieldName.CONTENT.name(), analyzer);
154
155 final SearcherSupplier provider = SearcherSupplier.newInstance(conf);
156 final Searcher searcher = provider.get(conf);
157
158 try {
159 final Query query = parser.parse(queryString);
160 final Hits hits = searcher.search(query);
161
162 } catch (final ParseException e) {
163 final String message = e.getMessage();
164 throw new EosException(message, e);
165 } catch (final IOException e) {
166 final String message = e.getMessage();
167 throw new EosException(message, e);
168 } finally {
169 try {
170 searcher.close();
171 } catch (final IOException e) {
172 throw new EosException("Unable to close Searcher", e);
173 }
174 }
175
176 return null;
177 }
178
179
180
181
182
183 final String createLuceneQuery() {
184 final StringBuilder sb = new StringBuilder();
185 final int size = this.query.size();
186 Entry[] entries = this.query.toArray(new Entry[size]);
187
188 for (int i = 0; i < size; i++) {
189 final Bool b = entries[i].getBool();
190 if (i != 0) {
191 if (b == Bool.AND || b == Bool.OR) {
192 sb.append(b);
193 } else {
194 sb.append(Bool.AND);
195 }
196 sb.append(" ");
197 }
198 if (b == Bool.AND_NOT) {
199 sb.append("-");
200 }
201 final String fieldName = entries[i].getFieldName();
202 sb.append(fieldName);
203 sb.append(":");
204
205 final String lower = entries[i].getLowerBoundValue();
206 final String lowerEscaped = QueryParser.escape(lower);
207 final String upper = entries[i].getUpperBoundValue();
208 String upperEscaped = null;
209 if (upper != null) {
210 upperEscaped = QueryParser.escape(upper);
211 }
212
213 if (upper != null) {
214 sb.append("[");
215 }
216 sb.append("\"");
217
218 sb.append(lowerEscaped);
219 if (upper != null) {
220 sb.append("\" TO \"");
221 sb.append(upperEscaped);
222 }
223 sb.append("\"");
224 if (upper != null) {
225 sb.append("]");
226 }
227 sb.append(" ");
228 }
229 final String q = sb.toString();
230 if (LOG.isDebugEnabled()) {
231 LOG.debug("QUERY: " + q);
232 }
233
234 return q;
235 }
236 }