~slub.team/goobi-indexserver/3.x

« back to all changes in this revision

Viewing changes to lucene/src/java/org/apache/lucene/search/SortField.java

  • Committer: Sebastian Meyer
  • Date: 2012-08-03 09:12:40 UTC
  • Revision ID: sebastian.meyer@slub-dresden.de-20120803091240-x6861b0vabq1xror
Remove Lucene and Solr source code and add patches instead
Fix Bug #985487: Auto-suggestion for the search interface

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.apache.lucene.search;
2
 
 
3
 
/**
4
 
 * Licensed to the Apache Software Foundation (ASF) under one or more
5
 
 * contributor license agreements.  See the NOTICE file distributed with
6
 
 * this work for additional information regarding copyright ownership.
7
 
 * The ASF licenses this file to You under the Apache License, Version 2.0
8
 
 * (the "License"); you may not use this file except in compliance with
9
 
 * the License.  You may obtain a copy of the License at
10
 
 *
11
 
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 
 *
13
 
 * Unless required by applicable law or agreed to in writing, software
14
 
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 
 * See the License for the specific language governing permissions and
17
 
 * limitations under the License.
18
 
 */
19
 
 
20
 
import java.io.IOException;
21
 
import java.io.Serializable;
22
 
import java.util.Locale;
23
 
 
24
 
import org.apache.lucene.util.StringHelper;
25
 
 
26
 
/**
27
 
 * Stores information about how to sort documents by terms in an individual
28
 
 * field.  Fields must be indexed in order to sort by them.
29
 
 *
30
 
 * <p>Created: Feb 11, 2004 1:25:29 PM
31
 
 *
32
 
 * @since   lucene 1.4
33
 
 * @see Sort
34
 
 */
35
 
public class SortField
36
 
implements Serializable {
37
 
 
38
 
  /** Sort by document score (relevance).  Sort values are Float and higher
39
 
   * values are at the front. */
40
 
  public static final int SCORE = 0;
41
 
 
42
 
  /** Sort by document number (index order).  Sort values are Integer and lower
43
 
   * values are at the front. */
44
 
  public static final int DOC = 1;
45
 
 
46
 
  // reserved, in Lucene 2.9, there was a constant: AUTO = 2;
47
 
 
48
 
  /** Sort using term values as Strings.  Sort values are String and lower
49
 
   * values are at the front. */
50
 
  public static final int STRING = 3;
51
 
 
52
 
  /** Sort using term values as encoded Integers.  Sort values are Integer and
53
 
   * lower values are at the front. */
54
 
  public static final int INT = 4;
55
 
 
56
 
  /** Sort using term values as encoded Floats.  Sort values are Float and
57
 
   * lower values are at the front. */
58
 
  public static final int FLOAT = 5;
59
 
 
60
 
  /** Sort using term values as encoded Longs.  Sort values are Long and
61
 
   * lower values are at the front. */
62
 
  public static final int LONG = 6;
63
 
 
64
 
  /** Sort using term values as encoded Doubles.  Sort values are Double and
65
 
   * lower values are at the front. */
66
 
  public static final int DOUBLE = 7;
67
 
 
68
 
  /** Sort using term values as encoded Shorts.  Sort values are Short and
69
 
   * lower values are at the front. */
70
 
  public static final int SHORT = 8;
71
 
 
72
 
  /** Sort using a custom Comparator.  Sort values are any Comparable and
73
 
   * sorting is done according to natural order. */
74
 
  public static final int CUSTOM = 9;
75
 
 
76
 
  /** Sort using term values as encoded Bytes.  Sort values are Byte and
77
 
   * lower values are at the front. */
78
 
  public static final int BYTE = 10;
79
 
  
80
 
  /** Sort using term values as Strings, but comparing by
81
 
   * value (using String.compareTo) for all comparisons.
82
 
   * This is typically slower than {@link #STRING}, which
83
 
   * uses ordinals to do the sorting. */
84
 
  public static final int STRING_VAL = 11;
85
 
  
86
 
  // IMPLEMENTATION NOTE: the FieldCache.STRING_INDEX is in the same "namespace"
87
 
  // as the above static int values.  Any new values must not have the same value
88
 
  // as FieldCache.STRING_INDEX.
89
 
 
90
 
  /** Represents sorting by document score (relevance). */
91
 
  public static final SortField FIELD_SCORE = new SortField(null, SCORE);
92
 
 
93
 
  /** Represents sorting by document number (index order). */
94
 
  public static final SortField FIELD_DOC = new SortField(null, DOC);
95
 
 
96
 
  private String field;
97
 
  private int type;  // defaults to determining type dynamically
98
 
  private Locale locale;    // defaults to "natural order" (no Locale)
99
 
  boolean reverse = false;  // defaults to natural order
100
 
  private FieldCache.Parser parser;
101
 
 
102
 
  // Used for CUSTOM sort
103
 
  private FieldComparatorSource comparatorSource;
104
 
 
105
 
  private Object missingValue;
106
 
 
107
 
  /** Creates a sort by terms in the given field with the type of term
108
 
   * values explicitly given.
109
 
   * @param field  Name of field to sort by.  Can be <code>null</code> if
110
 
   *               <code>type</code> is SCORE or DOC.
111
 
   * @param type   Type of values in the terms.
112
 
   */
113
 
  public SortField(String field, int type) {
114
 
    initFieldType(field, type);
115
 
  }
116
 
 
117
 
  /** Creates a sort, possibly in reverse, by terms in the given field with the
118
 
   * type of term values explicitly given.
119
 
   * @param field  Name of field to sort by.  Can be <code>null</code> if
120
 
   *               <code>type</code> is SCORE or DOC.
121
 
   * @param type   Type of values in the terms.
122
 
   * @param reverse True if natural order should be reversed.
123
 
   */
124
 
  public SortField(String field, int type, boolean reverse) {
125
 
    initFieldType(field, type);
126
 
    this.reverse = reverse;
127
 
  }
128
 
 
129
 
  /** Creates a sort by terms in the given field, parsed
130
 
   * to numeric values using a custom {@link FieldCache.Parser}.
131
 
   * @param field  Name of field to sort by.  Must not be null.
132
 
   * @param parser Instance of a {@link FieldCache.Parser},
133
 
   *  which must subclass one of the existing numeric
134
 
   *  parsers from {@link FieldCache}. Sort type is inferred
135
 
   *  by testing which numeric parser the parser subclasses.
136
 
   * @throws IllegalArgumentException if the parser fails to
137
 
   *  subclass an existing numeric parser, or field is null
138
 
   */
139
 
  public SortField(String field, FieldCache.Parser parser) {
140
 
    this(field, parser, false);
141
 
  }
142
 
 
143
 
  /** Creates a sort, possibly in reverse, by terms in the given field, parsed
144
 
   * to numeric values using a custom {@link FieldCache.Parser}.
145
 
   * @param field  Name of field to sort by.  Must not be null.
146
 
   * @param parser Instance of a {@link FieldCache.Parser},
147
 
   *  which must subclass one of the existing numeric
148
 
   *  parsers from {@link FieldCache}. Sort type is inferred
149
 
   *  by testing which numeric parser the parser subclasses.
150
 
   * @param reverse True if natural order should be reversed.
151
 
   * @throws IllegalArgumentException if the parser fails to
152
 
   *  subclass an existing numeric parser, or field is null
153
 
   */
154
 
  public SortField(String field, FieldCache.Parser parser, boolean reverse) {
155
 
    if (parser instanceof FieldCache.IntParser) initFieldType(field, INT);
156
 
    else if (parser instanceof FieldCache.FloatParser) initFieldType(field, FLOAT);
157
 
    else if (parser instanceof FieldCache.ShortParser) initFieldType(field, SHORT);
158
 
    else if (parser instanceof FieldCache.ByteParser) initFieldType(field, BYTE);
159
 
    else if (parser instanceof FieldCache.LongParser) initFieldType(field, LONG);
160
 
    else if (parser instanceof FieldCache.DoubleParser) initFieldType(field, DOUBLE);
161
 
    else
162
 
      throw new IllegalArgumentException("Parser instance does not subclass existing numeric parser from FieldCache (got " + parser + ")");
163
 
 
164
 
    this.reverse = reverse;
165
 
    this.parser = parser;
166
 
  }
167
 
 
168
 
  /** Creates a sort by terms in the given field sorted
169
 
   * according to the given locale.
170
 
   * @param field  Name of field to sort by, cannot be <code>null</code>.
171
 
   * @param locale Locale of values in the field.
172
 
   */
173
 
  public SortField (String field, Locale locale) {
174
 
    initFieldType(field, STRING);
175
 
    this.locale = locale;
176
 
  }
177
 
 
178
 
  /** Creates a sort, possibly in reverse, by terms in the given field sorted
179
 
   * according to the given locale.
180
 
   * @param field  Name of field to sort by, cannot be <code>null</code>.
181
 
   * @param locale Locale of values in the field.
182
 
   */
183
 
  public SortField (String field, Locale locale, boolean reverse) {
184
 
    initFieldType(field, STRING);
185
 
    this.locale = locale;
186
 
    this.reverse = reverse;
187
 
  }
188
 
 
189
 
  /** Creates a sort with a custom comparison function.
190
 
   * @param field Name of field to sort by; cannot be <code>null</code>.
191
 
   * @param comparator Returns a comparator for sorting hits.
192
 
   */
193
 
  public SortField(String field, FieldComparatorSource comparator) {
194
 
    initFieldType(field, CUSTOM);
195
 
    this.comparatorSource = comparator;
196
 
  }
197
 
 
198
 
  /** Creates a sort, possibly in reverse, with a custom comparison function.
199
 
   * @param field Name of field to sort by; cannot be <code>null</code>.
200
 
   * @param comparator Returns a comparator for sorting hits.
201
 
   * @param reverse True if natural order should be reversed.
202
 
   */
203
 
  public SortField(String field, FieldComparatorSource comparator, boolean reverse) {
204
 
    initFieldType(field, CUSTOM);
205
 
    this.reverse = reverse;
206
 
    this.comparatorSource = comparator;
207
 
  }
208
 
 
209
 
  /** Set a default sorting value for documents which lacks one */
210
 
  public SortField setMissingValue(Object missingValue) {
211
 
    if (type != BYTE && type != SHORT && type != INT && type != FLOAT && type != LONG && type != DOUBLE) {
212
 
      throw new IllegalArgumentException( "Missing value only works for numeric types" );
213
 
    }
214
 
    this.missingValue = missingValue;
215
 
    
216
 
    return this;
217
 
  }
218
 
  
219
 
  // Sets field & type, and ensures field is not NULL unless
220
 
  // type is SCORE or DOC
221
 
  private void initFieldType(String field, int type) {
222
 
    this.type = type;
223
 
    if (field == null) {
224
 
      if (type != SCORE && type != DOC)
225
 
        throw new IllegalArgumentException("field can only be null when type is SCORE or DOC");
226
 
    } else {
227
 
      this.field = StringHelper.intern(field);
228
 
    }
229
 
  }
230
 
 
231
 
  /** Returns the name of the field.  Could return <code>null</code>
232
 
   * if the sort is by SCORE or DOC.
233
 
   * @return Name of field, possibly <code>null</code>.
234
 
   */
235
 
  public String getField() {
236
 
    return field;
237
 
  }
238
 
 
239
 
  /** Returns the type of contents in the field.
240
 
   * @return One of the constants SCORE, DOC, STRING, INT or FLOAT.
241
 
   */
242
 
  public int getType() {
243
 
    return type;
244
 
  }
245
 
 
246
 
  /** Returns the Locale by which term values are interpreted.
247
 
   * May return <code>null</code> if no Locale was specified.
248
 
   * @return Locale, or <code>null</code>.
249
 
   */
250
 
  public Locale getLocale() {
251
 
    return locale;
252
 
  }
253
 
 
254
 
  /** Returns the instance of a {@link FieldCache} parser that fits to the given sort type.
255
 
   * May return <code>null</code> if no parser was specified. Sorting is using the default parser then.
256
 
   * @return An instance of a {@link FieldCache} parser, or <code>null</code>.
257
 
   */
258
 
  public FieldCache.Parser getParser() {
259
 
    return parser;
260
 
  }
261
 
 
262
 
  /** Returns whether the sort should be reversed.
263
 
   * @return  True if natural order should be reversed.
264
 
   */
265
 
  public boolean getReverse() {
266
 
    return reverse;
267
 
  }
268
 
 
269
 
  /** Returns the {@link FieldComparatorSource} used for
270
 
   * custom sorting
271
 
   */
272
 
  public FieldComparatorSource getComparatorSource() {
273
 
    return comparatorSource;
274
 
  }
275
 
 
276
 
  @Override
277
 
  public String toString() {
278
 
    StringBuilder buffer = new StringBuilder();
279
 
    switch (type) {
280
 
      case SCORE:
281
 
        buffer.append("<score>");
282
 
        break;
283
 
 
284
 
      case DOC:
285
 
        buffer.append("<doc>");
286
 
        break;
287
 
 
288
 
      case STRING:
289
 
        buffer.append("<string: \"").append(field).append("\">");
290
 
        break;
291
 
 
292
 
      case STRING_VAL:
293
 
        buffer.append("<string_val: \"").append(field).append("\">");
294
 
        break;
295
 
 
296
 
      case BYTE:
297
 
        buffer.append("<byte: \"").append(field).append("\">");
298
 
        break;
299
 
 
300
 
      case SHORT:
301
 
        buffer.append("<short: \"").append(field).append("\">");
302
 
        break;
303
 
 
304
 
      case INT:
305
 
        buffer.append("<int: \"").append(field).append("\">");
306
 
        break;
307
 
 
308
 
      case LONG:
309
 
        buffer.append("<long: \"").append(field).append("\">");
310
 
        break;
311
 
 
312
 
      case FLOAT:
313
 
        buffer.append("<float: \"").append(field).append("\">");
314
 
        break;
315
 
 
316
 
      case DOUBLE:
317
 
        buffer.append("<double: \"").append(field).append("\">");
318
 
        break;
319
 
 
320
 
      case CUSTOM:
321
 
        buffer.append("<custom:\"").append(field).append("\": ").append(comparatorSource).append('>');
322
 
        break;
323
 
 
324
 
      default:
325
 
        buffer.append("<???: \"").append(field).append("\">");
326
 
        break;
327
 
    }
328
 
 
329
 
    if (locale != null) buffer.append('(').append(locale).append(')');
330
 
    if (parser != null) buffer.append('(').append(parser).append(')');
331
 
    if (reverse) buffer.append('!');
332
 
 
333
 
    return buffer.toString();
334
 
  }
335
 
 
336
 
  /** Returns true if <code>o</code> is equal to this.  If a
337
 
   *  {@link FieldComparatorSource} or {@link
338
 
   *  FieldCache.Parser} was provided, it must properly
339
 
   *  implement equals (unless a singleton is always used). */
340
 
  @Override
341
 
  public boolean equals(Object o) {
342
 
    if (this == o) return true;
343
 
    if (!(o instanceof SortField)) return false;
344
 
    final SortField other = (SortField)o;
345
 
    return (
346
 
      other.field == this.field // field is always interned
347
 
      && other.type == this.type
348
 
      && other.reverse == this.reverse
349
 
      && (other.locale == null ? this.locale == null : other.locale.equals(this.locale))
350
 
      && (other.comparatorSource == null ? this.comparatorSource == null : other.comparatorSource.equals(this.comparatorSource))
351
 
      && (other.parser == null ? this.parser == null : other.parser.equals(this.parser))
352
 
    );
353
 
  }
354
 
 
355
 
  /** Returns true if <code>o</code> is equal to this.  If a
356
 
   *  {@link FieldComparatorSource} or {@link
357
 
   *  FieldCache.Parser} was provided, it must properly
358
 
   *  implement hashCode (unless a singleton is always
359
 
   *  used). */
360
 
  @Override
361
 
  public int hashCode() {
362
 
    int hash=type^0x346565dd + Boolean.valueOf(reverse).hashCode()^0xaf5998bb;
363
 
    if (field != null) hash += field.hashCode()^0xff5685dd;
364
 
    if (locale != null) hash += locale.hashCode()^0x08150815;
365
 
    if (comparatorSource != null) hash += comparatorSource.hashCode();
366
 
    if (parser != null) hash += parser.hashCode()^0x3aaf56ff;
367
 
    return hash;
368
 
  }
369
 
 
370
 
  // field must be interned after reading from stream
371
 
  private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
372
 
    in.defaultReadObject();
373
 
    if (field != null)
374
 
      field = StringHelper.intern(field);
375
 
  }
376
 
 
377
 
  /** Returns the {@link FieldComparator} to use for
378
 
   * sorting.
379
 
   *
380
 
   * @lucene.experimental
381
 
   *
382
 
   * @param numHits number of top hits the queue will store
383
 
   * @param sortPos position of this SortField within {@link
384
 
   *   Sort}.  The comparator is primary if sortPos==0,
385
 
   *   secondary if sortPos==1, etc.  Some comparators can
386
 
   *   optimize themselves when they are the primary sort.
387
 
   * @return {@link FieldComparator} to use when sorting
388
 
   */
389
 
  public FieldComparator getComparator(final int numHits, final int sortPos) throws IOException {
390
 
 
391
 
    if (locale != null) {
392
 
      // TODO: it'd be nice to allow FieldCache.getStringIndex
393
 
      // to optionally accept a Locale so sorting could then use
394
 
      // the faster StringComparator impls
395
 
      return new FieldComparator.StringComparatorLocale(numHits, field, locale);
396
 
    }
397
 
 
398
 
    switch (type) {
399
 
    case SortField.SCORE:
400
 
      return new FieldComparator.RelevanceComparator(numHits);
401
 
 
402
 
    case SortField.DOC:
403
 
      return new FieldComparator.DocComparator(numHits);
404
 
 
405
 
    case SortField.INT:
406
 
      return new FieldComparator.IntComparator(numHits, field, parser, (Integer) missingValue);
407
 
 
408
 
    case SortField.FLOAT:
409
 
      return new FieldComparator.FloatComparator(numHits, field, parser, (Float) missingValue);
410
 
 
411
 
    case SortField.LONG:
412
 
      return new FieldComparator.LongComparator(numHits, field, parser, (Long) missingValue);
413
 
 
414
 
    case SortField.DOUBLE:
415
 
      return new FieldComparator.DoubleComparator(numHits, field, parser, (Double) missingValue);
416
 
 
417
 
    case SortField.BYTE:
418
 
      return new FieldComparator.ByteComparator(numHits, field, parser, (Byte) missingValue);
419
 
 
420
 
    case SortField.SHORT:
421
 
      return new FieldComparator.ShortComparator(numHits, field, parser, (Short) missingValue);
422
 
 
423
 
    case SortField.CUSTOM:
424
 
      assert comparatorSource != null;
425
 
      return comparatorSource.newComparator(field, numHits, sortPos, reverse);
426
 
 
427
 
    case SortField.STRING:
428
 
      return new FieldComparator.StringOrdValComparator(numHits, field, sortPos, reverse);
429
 
 
430
 
    case SortField.STRING_VAL:
431
 
      return new FieldComparator.StringValComparator(numHits, field);
432
 
        
433
 
    default:
434
 
      throw new IllegalStateException("Illegal sort type: " + type);
435
 
    }
436
 
  }
437
 
}