|
1 |
| package org.apache.lucene.search; |
|
2 |
| |
|
3 |
| |
|
4 |
| |
|
5 |
| |
|
6 |
| |
|
7 |
| |
|
8 |
| |
|
9 |
| |
|
10 |
| |
|
11 |
| |
|
12 |
| |
|
13 |
| |
|
14 |
| |
|
15 |
| |
|
16 |
| |
|
17 |
| |
|
18 |
| |
|
19 |
| |
|
20 |
| import org.apache.lucene.index.IndexReader; |
|
21 |
| import org.apache.lucene.index.Term; |
|
22 |
| import org.apache.lucene.index.TermDocs; |
|
23 |
| import org.apache.lucene.index.TermEnum; |
|
24 |
| |
|
25 |
| import java.io.IOException; |
|
26 |
| import java.util.Locale; |
|
27 |
| import java.util.Map; |
|
28 |
| import java.util.WeakHashMap; |
|
29 |
| import java.util.HashMap; |
|
30 |
| |
|
31 |
| |
|
32 |
| |
|
33 |
| |
|
34 |
| |
|
35 |
| |
|
36 |
| |
|
37 |
| |
|
38 |
| |
|
39 |
| |
|
40 |
| |
|
41 |
| class FieldCacheImpl |
|
42 |
| implements FieldCache { |
|
43 |
| |
|
44 |
| |
|
45 |
| abstract static class Cache { |
|
46 |
| private final Map readerCache = new WeakHashMap(); |
|
47 |
| |
|
48 |
| protected abstract Object createValue(IndexReader reader, Object key) |
|
49 |
| throws IOException; |
|
50 |
| |
|
51 |
9888
| public Object get(IndexReader reader, Object key) throws IOException {
|
|
52 |
9888
| Map innerCache;
|
|
53 |
9888
| Object value;
|
|
54 |
9888
| synchronized (readerCache) {
|
|
55 |
9888
| innerCache = (Map) readerCache.get(reader);
|
|
56 |
9888
| if (innerCache == null) {
|
|
57 |
134
| innerCache = new HashMap();
|
|
58 |
134
| readerCache.put(reader, innerCache);
|
|
59 |
134
| value = null;
|
|
60 |
| } else { |
|
61 |
9754
| value = innerCache.get(key);
|
|
62 |
| } |
|
63 |
9888
| if (value == null) {
|
|
64 |
218
| value = new CreationPlaceholder();
|
|
65 |
218
| innerCache.put(key, value);
|
|
66 |
| } |
|
67 |
| } |
|
68 |
9888
| if (value instanceof CreationPlaceholder) {
|
|
69 |
218
| synchronized (value) {
|
|
70 |
218
| CreationPlaceholder progress = (CreationPlaceholder) value;
|
|
71 |
218
| if (progress.value == null) {
|
|
72 |
218
| progress.value = createValue(reader, key);
|
|
73 |
218
| synchronized (readerCache) {
|
|
74 |
218
| innerCache.put(key, progress.value);
|
|
75 |
| } |
|
76 |
| } |
|
77 |
218
| return progress.value;
|
|
78 |
| } |
|
79 |
| } |
|
80 |
9670
| return value;
|
|
81 |
| } |
|
82 |
| } |
|
83 |
| |
|
84 |
| static final class CreationPlaceholder { |
|
85 |
| Object value; |
|
86 |
| } |
|
87 |
| |
|
88 |
| |
|
89 |
| static class Entry { |
|
90 |
| final String field; |
|
91 |
| final int type; |
|
92 |
| final Object custom; |
|
93 |
| final Locale locale; |
|
94 |
| |
|
95 |
| |
|
96 |
278
| Entry (String field, int type, Locale locale) {
|
|
97 |
278
| this.field = field.intern();
|
|
98 |
278
| this.type = type;
|
|
99 |
278
| this.custom = null;
|
|
100 |
278
| this.locale = locale;
|
|
101 |
| } |
|
102 |
| |
|
103 |
| |
|
104 |
9316
| Entry (String field, Object custom) {
|
|
105 |
9316
| this.field = field.intern();
|
|
106 |
9316
| this.type = SortField.CUSTOM;
|
|
107 |
9316
| this.custom = custom;
|
|
108 |
9316
| this.locale = null;
|
|
109 |
| } |
|
110 |
| |
|
111 |
| |
|
112 |
9449
| public boolean equals (Object o) {
|
|
113 |
9449
| if (o instanceof Entry) {
|
|
114 |
9449
| Entry other = (Entry) o;
|
|
115 |
9449
| if (other.field == field && other.type == type) {
|
|
116 |
9449
| if (other.locale == null ? locale == null : other.locale.equals(locale)) {
|
|
117 |
9449
| if (other.custom == null) {
|
|
118 |
205
| if (custom == null) return true;
|
|
119 |
9244
| } else if (other.custom.equals (custom)) {
|
|
120 |
9244
| return true;
|
|
121 |
| } |
|
122 |
| } |
|
123 |
| } |
|
124 |
| } |
|
125 |
0
| return false;
|
|
126 |
| } |
|
127 |
| |
|
128 |
| |
|
129 |
9797
| public int hashCode() {
|
|
130 |
9797
| return field.hashCode() ^ type ^ (custom==null ? 0 : custom.hashCode()) ^ (locale==null ? 0 : locale.hashCode());
|
|
131 |
| } |
|
132 |
| } |
|
133 |
| |
|
134 |
| private static final ByteParser BYTE_PARSER = new ByteParser() { |
|
135 |
102
| public byte parseByte(String value) {
|
|
136 |
102
| return Byte.parseByte(value);
|
|
137 |
| } |
|
138 |
| }; |
|
139 |
| |
|
140 |
| private static final ShortParser SHORT_PARSER = new ShortParser() { |
|
141 |
102
| public short parseShort(String value) {
|
|
142 |
102
| return Short.parseShort(value);
|
|
143 |
| } |
|
144 |
| }; |
|
145 |
| |
|
146 |
| private static final IntParser INT_PARSER = new IntParser() { |
|
147 |
402
| public int parseInt(String value) {
|
|
148 |
402
| return Integer.parseInt(value);
|
|
149 |
| } |
|
150 |
| }; |
|
151 |
| |
|
152 |
| private static final FloatParser FLOAT_PARSER = new FloatParser() { |
|
153 |
324
| public float parseFloat(String value) {
|
|
154 |
324
| return Float.parseFloat(value);
|
|
155 |
| } |
|
156 |
| }; |
|
157 |
| |
|
158 |
| |
|
159 |
1847
| public byte[] getBytes (IndexReader reader, String field) throws IOException {
|
|
160 |
1847
| return getBytes(reader, field, BYTE_PARSER);
|
|
161 |
| } |
|
162 |
| |
|
163 |
| |
|
164 |
1847
| public byte[] getBytes(IndexReader reader, String field, ByteParser parser)
|
|
165 |
| throws IOException { |
|
166 |
1847
| return (byte[]) bytesCache.get(reader, new Entry(field, parser));
|
|
167 |
| } |
|
168 |
| |
|
169 |
| Cache bytesCache = new Cache() { |
|
170 |
| |
|
171 |
6
| protected Object createValue(IndexReader reader, Object entryKey)
|
|
172 |
| throws IOException { |
|
173 |
6
| Entry entry = (Entry) entryKey;
|
|
174 |
6
| String field = entry.field;
|
|
175 |
6
| ByteParser parser = (ByteParser) entry.custom;
|
|
176 |
6
| final byte[] retArray = new byte[reader.maxDoc()];
|
|
177 |
6
| TermDocs termDocs = reader.termDocs();
|
|
178 |
6
| TermEnum termEnum = reader.terms (new Term (field, ""));
|
|
179 |
6
| try {
|
|
180 |
6
| do {
|
|
181 |
108
| Term term = termEnum.term();
|
|
182 |
6
| if (term==null || term.field() != field) break;
|
|
183 |
102
| byte termval = parser.parseByte(term.text());
|
|
184 |
102
| termDocs.seek (termEnum);
|
|
185 |
102
| while (termDocs.next()) {
|
|
186 |
102
| retArray[termDocs.doc()] = termval;
|
|
187 |
| } |
|
188 |
102
| } while (termEnum.next());
|
|
189 |
| } finally { |
|
190 |
6
| termDocs.close();
|
|
191 |
6
| termEnum.close();
|
|
192 |
| } |
|
193 |
6
| return retArray;
|
|
194 |
| } |
|
195 |
| }; |
|
196 |
| |
|
197 |
| |
|
198 |
1847
| public short[] getShorts (IndexReader reader, String field) throws IOException {
|
|
199 |
1847
| return getShorts(reader, field, SHORT_PARSER);
|
|
200 |
| } |
|
201 |
| |
|
202 |
| |
|
203 |
1847
| public short[] getShorts(IndexReader reader, String field, ShortParser parser)
|
|
204 |
| throws IOException { |
|
205 |
1847
| return (short[]) shortsCache.get(reader, new Entry(field, parser));
|
|
206 |
| } |
|
207 |
| |
|
208 |
| Cache shortsCache = new Cache() { |
|
209 |
| |
|
210 |
6
| protected Object createValue(IndexReader reader, Object entryKey)
|
|
211 |
| throws IOException { |
|
212 |
6
| Entry entry = (Entry) entryKey;
|
|
213 |
6
| String field = entry.field;
|
|
214 |
6
| ShortParser parser = (ShortParser) entry.custom;
|
|
215 |
6
| final short[] retArray = new short[reader.maxDoc()];
|
|
216 |
6
| TermDocs termDocs = reader.termDocs();
|
|
217 |
6
| TermEnum termEnum = reader.terms (new Term (field, ""));
|
|
218 |
6
| try {
|
|
219 |
6
| do {
|
|
220 |
108
| Term term = termEnum.term();
|
|
221 |
6
| if (term==null || term.field() != field) break;
|
|
222 |
102
| short termval = parser.parseShort(term.text());
|
|
223 |
102
| termDocs.seek (termEnum);
|
|
224 |
102
| while (termDocs.next()) {
|
|
225 |
102
| retArray[termDocs.doc()] = termval;
|
|
226 |
| } |
|
227 |
102
| } while (termEnum.next());
|
|
228 |
| } finally { |
|
229 |
6
| termDocs.close();
|
|
230 |
6
| termEnum.close();
|
|
231 |
| } |
|
232 |
6
| return retArray;
|
|
233 |
| } |
|
234 |
| }; |
|
235 |
| |
|
236 |
| |
|
237 |
1886
| public int[] getInts (IndexReader reader, String field) throws IOException {
|
|
238 |
1886
| return getInts(reader, field, INT_PARSER);
|
|
239 |
| } |
|
240 |
| |
|
241 |
| |
|
242 |
1886
| public int[] getInts(IndexReader reader, String field, IntParser parser)
|
|
243 |
| throws IOException { |
|
244 |
1886
| return (int[]) intsCache.get(reader, new Entry(field, parser));
|
|
245 |
| } |
|
246 |
| |
|
247 |
| Cache intsCache = new Cache() { |
|
248 |
| |
|
249 |
24
| protected Object createValue(IndexReader reader, Object entryKey)
|
|
250 |
| throws IOException { |
|
251 |
24
| Entry entry = (Entry) entryKey;
|
|
252 |
24
| String field = entry.field;
|
|
253 |
24
| IntParser parser = (IntParser) entry.custom;
|
|
254 |
24
| final int[] retArray = new int[reader.maxDoc()];
|
|
255 |
24
| TermDocs termDocs = reader.termDocs();
|
|
256 |
24
| TermEnum termEnum = reader.terms (new Term (field, ""));
|
|
257 |
24
| try {
|
|
258 |
24
| do {
|
|
259 |
422
| Term term = termEnum.term();
|
|
260 |
20
| if (term==null || term.field() != field) break;
|
|
261 |
402
| int termval = parser.parseInt(term.text());
|
|
262 |
402
| termDocs.seek (termEnum);
|
|
263 |
402
| while (termDocs.next()) {
|
|
264 |
6632
| retArray[termDocs.doc()] = termval;
|
|
265 |
| } |
|
266 |
402
| } while (termEnum.next());
|
|
267 |
| } finally { |
|
268 |
24
| termDocs.close();
|
|
269 |
24
| termEnum.close();
|
|
270 |
| } |
|
271 |
24
| return retArray;
|
|
272 |
| } |
|
273 |
| }; |
|
274 |
| |
|
275 |
| |
|
276 |
3725
| public float[] getFloats (IndexReader reader, String field)
|
|
277 |
| throws IOException { |
|
278 |
3725
| return getFloats(reader, field, FLOAT_PARSER);
|
|
279 |
| } |
|
280 |
| |
|
281 |
| |
|
282 |
3725
| public float[] getFloats(IndexReader reader, String field, FloatParser parser)
|
|
283 |
| throws IOException { |
|
284 |
3725
| return (float[]) floatsCache.get(reader, new Entry(field, parser));
|
|
285 |
| } |
|
286 |
| |
|
287 |
| Cache floatsCache = new Cache() { |
|
288 |
| |
|
289 |
26
| protected Object createValue(IndexReader reader, Object entryKey)
|
|
290 |
| throws IOException { |
|
291 |
26
| Entry entry = (Entry) entryKey;
|
|
292 |
26
| String field = entry.field;
|
|
293 |
26
| FloatParser parser = (FloatParser) entry.custom;
|
|
294 |
26
| final float[] retArray = new float[reader.maxDoc()];
|
|
295 |
26
| TermDocs termDocs = reader.termDocs();
|
|
296 |
26
| TermEnum termEnum = reader.terms (new Term (field, ""));
|
|
297 |
26
| try {
|
|
298 |
26
| do {
|
|
299 |
350
| Term term = termEnum.term();
|
|
300 |
26
| if (term==null || term.field() != field) break;
|
|
301 |
324
| float termval = parser.parseFloat(term.text());
|
|
302 |
324
| termDocs.seek (termEnum);
|
|
303 |
324
| while (termDocs.next()) {
|
|
304 |
324
| retArray[termDocs.doc()] = termval;
|
|
305 |
| } |
|
306 |
324
| } while (termEnum.next());
|
|
307 |
| } finally { |
|
308 |
26
| termDocs.close();
|
|
309 |
26
| termEnum.close();
|
|
310 |
| } |
|
311 |
26
| return retArray;
|
|
312 |
| } |
|
313 |
| }; |
|
314 |
| |
|
315 |
| |
|
316 |
14
| public String[] getStrings(IndexReader reader, String field)
|
|
317 |
| throws IOException { |
|
318 |
14
| return (String[]) stringsCache.get(reader, field);
|
|
319 |
| } |
|
320 |
| |
|
321 |
| Cache stringsCache = new Cache() { |
|
322 |
| |
|
323 |
9
| protected Object createValue(IndexReader reader, Object fieldKey)
|
|
324 |
| throws IOException { |
|
325 |
9
| String field = ((String) fieldKey).intern();
|
|
326 |
9
| final String[] retArray = new String[reader.maxDoc()];
|
|
327 |
9
| TermDocs termDocs = reader.termDocs();
|
|
328 |
9
| TermEnum termEnum = reader.terms (new Term (field, ""));
|
|
329 |
9
| try {
|
|
330 |
9
| do {
|
|
331 |
73
| Term term = termEnum.term();
|
|
332 |
3
| if (term==null || term.field() != field) break;
|
|
333 |
70
| String termval = term.text();
|
|
334 |
70
| termDocs.seek (termEnum);
|
|
335 |
70
| while (termDocs.next()) {
|
|
336 |
70
| retArray[termDocs.doc()] = termval;
|
|
337 |
| } |
|
338 |
70
| } while (termEnum.next());
|
|
339 |
| } finally { |
|
340 |
9
| termDocs.close();
|
|
341 |
9
| termEnum.close();
|
|
342 |
| } |
|
343 |
9
| return retArray;
|
|
344 |
| } |
|
345 |
| }; |
|
346 |
| |
|
347 |
| |
|
348 |
239
| public StringIndex getStringIndex(IndexReader reader, String field)
|
|
349 |
| throws IOException { |
|
350 |
239
| return (StringIndex) stringsIndexCache.get(reader, field);
|
|
351 |
| } |
|
352 |
| |
|
353 |
| Cache stringsIndexCache = new Cache() { |
|
354 |
| |
|
355 |
23
| protected Object createValue(IndexReader reader, Object fieldKey)
|
|
356 |
| throws IOException { |
|
357 |
23
| String field = ((String) fieldKey).intern();
|
|
358 |
23
| final int[] retArray = new int[reader.maxDoc()];
|
|
359 |
23
| String[] mterms = new String[reader.maxDoc()+1];
|
|
360 |
23
| TermDocs termDocs = reader.termDocs();
|
|
361 |
23
| TermEnum termEnum = reader.terms (new Term (field, ""));
|
|
362 |
23
| int t = 0;
|
|
363 |
| |
|
364 |
| |
|
365 |
| |
|
366 |
| |
|
367 |
| |
|
368 |
23
| mterms[t++] = null;
|
|
369 |
| |
|
370 |
23
| try {
|
|
371 |
23
| do {
|
|
372 |
232
| Term term = termEnum.term();
|
|
373 |
9
| if (term==null || term.field() != field) break;
|
|
374 |
| |
|
375 |
| |
|
376 |
| |
|
377 |
0
| if (t >= mterms.length) throw new RuntimeException ("there are more terms than " +
|
|
378 |
| "documents in field \"" + field + "\", but it's impossible to sort on " + |
|
379 |
| "tokenized fields"); |
|
380 |
223
| mterms[t] = term.text();
|
|
381 |
| |
|
382 |
223
| termDocs.seek (termEnum);
|
|
383 |
223
| while (termDocs.next()) {
|
|
384 |
223
| retArray[termDocs.doc()] = t;
|
|
385 |
| } |
|
386 |
| |
|
387 |
223
| t++;
|
|
388 |
223
| } while (termEnum.next());
|
|
389 |
| } finally { |
|
390 |
23
| termDocs.close();
|
|
391 |
23
| termEnum.close();
|
|
392 |
| } |
|
393 |
| |
|
394 |
23
| if (t == 0) {
|
|
395 |
| |
|
396 |
| |
|
397 |
0
| mterms = new String[1];
|
|
398 |
23
| } else if (t < mterms.length) {
|
|
399 |
| |
|
400 |
| |
|
401 |
14
| String[] terms = new String[t];
|
|
402 |
14
| System.arraycopy (mterms, 0, terms, 0, t);
|
|
403 |
14
| mterms = terms;
|
|
404 |
| } |
|
405 |
| |
|
406 |
23
| StringIndex value = new StringIndex (retArray, mterms);
|
|
407 |
23
| return value;
|
|
408 |
| } |
|
409 |
| }; |
|
410 |
| |
|
411 |
| |
|
412 |
| |
|
413 |
| |
|
414 |
| |
|
415 |
| |
|
416 |
| |
|
417 |
| |
|
418 |
| |
|
419 |
| |
|
420 |
| |
|
421 |
| |
|
422 |
| |
|
423 |
41
| public Object getAuto(IndexReader reader, String field) throws IOException {
|
|
424 |
41
| return autoCache.get(reader, field);
|
|
425 |
| } |
|
426 |
| |
|
427 |
| Cache autoCache = new Cache() { |
|
428 |
| |
|
429 |
41
| protected Object createValue(IndexReader reader, Object fieldKey)
|
|
430 |
| throws IOException { |
|
431 |
41
| String field = ((String)fieldKey).intern();
|
|
432 |
41
| TermEnum enumerator = reader.terms (new Term (field, ""));
|
|
433 |
41
| try {
|
|
434 |
41
| Term term = enumerator.term();
|
|
435 |
41
| if (term == null) {
|
|
436 |
0
| throw new RuntimeException ("no terms in field " + field + " - cannot determine sort type");
|
|
437 |
| } |
|
438 |
41
| Object ret = null;
|
|
439 |
41
| if (term.field() == field) {
|
|
440 |
41
| String termtext = term.text().trim();
|
|
441 |
| |
|
442 |
| |
|
443 |
| |
|
444 |
| |