+++ /dev/null
-package org.apache.lucene.search;
-
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.util.Locale;
-
-import org.apache.lucene.util.StringHelper;
-
-/**
- * Stores information about how to sort documents by terms in an individual
- * field. Fields must be indexed in order to sort by them.
- *
- * <p>Created: Feb 11, 2004 1:25:29 PM
- *
- * @since lucene 1.4
- * @see Sort
- */
-public class SortField
-implements Serializable {
-
- /** Sort by document score (relevance). Sort values are Float and higher
- * values are at the front. */
- public static final int SCORE = 0;
-
- /** Sort by document number (index order). Sort values are Integer and lower
- * values are at the front. */
- public static final int DOC = 1;
-
- // reserved, in Lucene 2.9, there was a constant: AUTO = 2;
-
- /** Sort using term values as Strings. Sort values are String and lower
- * values are at the front. */
- public static final int STRING = 3;
-
- /** Sort using term values as encoded Integers. Sort values are Integer and
- * lower values are at the front. */
- public static final int INT = 4;
-
- /** Sort using term values as encoded Floats. Sort values are Float and
- * lower values are at the front. */
- public static final int FLOAT = 5;
-
- /** Sort using term values as encoded Longs. Sort values are Long and
- * lower values are at the front. */
- public static final int LONG = 6;
-
- /** Sort using term values as encoded Doubles. Sort values are Double and
- * lower values are at the front. */
- public static final int DOUBLE = 7;
-
- /** Sort using term values as encoded Shorts. Sort values are Short and
- * lower values are at the front. */
- public static final int SHORT = 8;
-
- /** Sort using a custom Comparator. Sort values are any Comparable and
- * sorting is done according to natural order. */
- public static final int CUSTOM = 9;
-
- /** Sort using term values as encoded Bytes. Sort values are Byte and
- * lower values are at the front. */
- public static final int BYTE = 10;
-
- /** Sort using term values as Strings, but comparing by
- * value (using String.compareTo) for all comparisons.
- * This is typically slower than {@link #STRING}, which
- * uses ordinals to do the sorting. */
- public static final int STRING_VAL = 11;
-
- // IMPLEMENTATION NOTE: the FieldCache.STRING_INDEX is in the same "namespace"
- // as the above static int values. Any new values must not have the same value
- // as FieldCache.STRING_INDEX.
-
- /** Represents sorting by document score (relevance). */
- public static final SortField FIELD_SCORE = new SortField(null, SCORE);
-
- /** Represents sorting by document number (index order). */
- public static final SortField FIELD_DOC = new SortField(null, DOC);
-
- private String field;
- private int type; // defaults to determining type dynamically
- private Locale locale; // defaults to "natural order" (no Locale)
- boolean reverse = false; // defaults to natural order
- private FieldCache.Parser parser;
-
- // Used for CUSTOM sort
- private FieldComparatorSource comparatorSource;
-
- private Object missingValue;
-
- /** Creates a sort by terms in the given field with the type of term
- * values explicitly given.
- * @param field Name of field to sort by. Can be <code>null</code> if
- * <code>type</code> is SCORE or DOC.
- * @param type Type of values in the terms.
- */
- public SortField(String field, int type) {
- initFieldType(field, type);
- }
-
- /** Creates a sort, possibly in reverse, by terms in the given field with the
- * type of term values explicitly given.
- * @param field Name of field to sort by. Can be <code>null</code> if
- * <code>type</code> is SCORE or DOC.
- * @param type Type of values in the terms.
- * @param reverse True if natural order should be reversed.
- */
- public SortField(String field, int type, boolean reverse) {
- initFieldType(field, type);
- this.reverse = reverse;
- }
-
- /** Creates a sort by terms in the given field, parsed
- * to numeric values using a custom {@link FieldCache.Parser}.
- * @param field Name of field to sort by. Must not be null.
- * @param parser Instance of a {@link FieldCache.Parser},
- * which must subclass one of the existing numeric
- * parsers from {@link FieldCache}. Sort type is inferred
- * by testing which numeric parser the parser subclasses.
- * @throws IllegalArgumentException if the parser fails to
- * subclass an existing numeric parser, or field is null
- */
- public SortField(String field, FieldCache.Parser parser) {
- this(field, parser, false);
- }
-
- /** Creates a sort, possibly in reverse, by terms in the given field, parsed
- * to numeric values using a custom {@link FieldCache.Parser}.
- * @param field Name of field to sort by. Must not be null.
- * @param parser Instance of a {@link FieldCache.Parser},
- * which must subclass one of the existing numeric
- * parsers from {@link FieldCache}. Sort type is inferred
- * by testing which numeric parser the parser subclasses.
- * @param reverse True if natural order should be reversed.
- * @throws IllegalArgumentException if the parser fails to
- * subclass an existing numeric parser, or field is null
- */
- public SortField(String field, FieldCache.Parser parser, boolean reverse) {
- if (parser instanceof FieldCache.IntParser) initFieldType(field, INT);
- else if (parser instanceof FieldCache.FloatParser) initFieldType(field, FLOAT);
- else if (parser instanceof FieldCache.ShortParser) initFieldType(field, SHORT);
- else if (parser instanceof FieldCache.ByteParser) initFieldType(field, BYTE);
- else if (parser instanceof FieldCache.LongParser) initFieldType(field, LONG);
- else if (parser instanceof FieldCache.DoubleParser) initFieldType(field, DOUBLE);
- else
- throw new IllegalArgumentException("Parser instance does not subclass existing numeric parser from FieldCache (got " + parser + ")");
-
- this.reverse = reverse;
- this.parser = parser;
- }
-
- /** Creates a sort by terms in the given field sorted
- * according to the given locale.
- * @param field Name of field to sort by, cannot be <code>null</code>.
- * @param locale Locale of values in the field.
- */
- public SortField (String field, Locale locale) {
- initFieldType(field, STRING);
- this.locale = locale;
- }
-
- /** Creates a sort, possibly in reverse, by terms in the given field sorted
- * according to the given locale.
- * @param field Name of field to sort by, cannot be <code>null</code>.
- * @param locale Locale of values in the field.
- */
- public SortField (String field, Locale locale, boolean reverse) {
- initFieldType(field, STRING);
- this.locale = locale;
- this.reverse = reverse;
- }
-
- /** Creates a sort with a custom comparison function.
- * @param field Name of field to sort by; cannot be <code>null</code>.
- * @param comparator Returns a comparator for sorting hits.
- */
- public SortField(String field, FieldComparatorSource comparator) {
- initFieldType(field, CUSTOM);
- this.comparatorSource = comparator;
- }
-
- /** Creates a sort, possibly in reverse, with a custom comparison function.
- * @param field Name of field to sort by; cannot be <code>null</code>.
- * @param comparator Returns a comparator for sorting hits.
- * @param reverse True if natural order should be reversed.
- */
- public SortField(String field, FieldComparatorSource comparator, boolean reverse) {
- initFieldType(field, CUSTOM);
- this.reverse = reverse;
- this.comparatorSource = comparator;
- }
-
- /** Set a default sorting value for documents which lacks one */
- public SortField setMissingValue(Object missingValue) {
- if (type != BYTE && type != SHORT && type != INT && type != FLOAT && type != LONG && type != DOUBLE) {
- throw new IllegalArgumentException( "Missing value only works for numeric types" );
- }
- this.missingValue = missingValue;
-
- return this;
- }
-
- // Sets field & type, and ensures field is not NULL unless
- // type is SCORE or DOC
- private void initFieldType(String field, int type) {
- this.type = type;
- if (field == null) {
- if (type != SCORE && type != DOC)
- throw new IllegalArgumentException("field can only be null when type is SCORE or DOC");
- } else {
- this.field = StringHelper.intern(field);
- }
- }
-
- /** Returns the name of the field. Could return <code>null</code>
- * if the sort is by SCORE or DOC.
- * @return Name of field, possibly <code>null</code>.
- */
- public String getField() {
- return field;
- }
-
- /** Returns the type of contents in the field.
- * @return One of the constants SCORE, DOC, STRING, INT or FLOAT.
- */
- public int getType() {
- return type;
- }
-
- /** Returns the Locale by which term values are interpreted.
- * May return <code>null</code> if no Locale was specified.
- * @return Locale, or <code>null</code>.
- */
- public Locale getLocale() {
- return locale;
- }
-
- /** Returns the instance of a {@link FieldCache} parser that fits to the given sort type.
- * May return <code>null</code> if no parser was specified. Sorting is using the default parser then.
- * @return An instance of a {@link FieldCache} parser, or <code>null</code>.
- */
- public FieldCache.Parser getParser() {
- return parser;
- }
-
- /** Returns whether the sort should be reversed.
- * @return True if natural order should be reversed.
- */
- public boolean getReverse() {
- return reverse;
- }
-
- /** Returns the {@link FieldComparatorSource} used for
- * custom sorting
- */
- public FieldComparatorSource getComparatorSource() {
- return comparatorSource;
- }
-
- @Override
- public String toString() {
- StringBuilder buffer = new StringBuilder();
- switch (type) {
- case SCORE:
- buffer.append("<score>");
- break;
-
- case DOC:
- buffer.append("<doc>");
- break;
-
- case STRING:
- buffer.append("<string: \"").append(field).append("\">");
- break;
-
- case STRING_VAL:
- buffer.append("<string_val: \"").append(field).append("\">");
- break;
-
- case BYTE:
- buffer.append("<byte: \"").append(field).append("\">");
- break;
-
- case SHORT:
- buffer.append("<short: \"").append(field).append("\">");
- break;
-
- case INT:
- buffer.append("<int: \"").append(field).append("\">");
- break;
-
- case LONG:
- buffer.append("<long: \"").append(field).append("\">");
- break;
-
- case FLOAT:
- buffer.append("<float: \"").append(field).append("\">");
- break;
-
- case DOUBLE:
- buffer.append("<double: \"").append(field).append("\">");
- break;
-
- case CUSTOM:
- buffer.append("<custom:\"").append(field).append("\": ").append(comparatorSource).append('>');
- break;
-
- default:
- buffer.append("<???: \"").append(field).append("\">");
- break;
- }
-
- if (locale != null) buffer.append('(').append(locale).append(')');
- if (parser != null) buffer.append('(').append(parser).append(')');
- if (reverse) buffer.append('!');
-
- return buffer.toString();
- }
-
- /** Returns true if <code>o</code> is equal to this. If a
- * {@link FieldComparatorSource} or {@link
- * FieldCache.Parser} was provided, it must properly
- * implement equals (unless a singleton is always used). */
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof SortField)) return false;
- final SortField other = (SortField)o;
- return (
- other.field == this.field // field is always interned
- && other.type == this.type
- && other.reverse == this.reverse
- && (other.locale == null ? this.locale == null : other.locale.equals(this.locale))
- && (other.comparatorSource == null ? this.comparatorSource == null : other.comparatorSource.equals(this.comparatorSource))
- && (other.parser == null ? this.parser == null : other.parser.equals(this.parser))
- );
- }
-
- /** Returns true if <code>o</code> is equal to this. If a
- * {@link FieldComparatorSource} or {@link
- * FieldCache.Parser} was provided, it must properly
- * implement hashCode (unless a singleton is always
- * used). */
- @Override
- public int hashCode() {
- int hash=type^0x346565dd + Boolean.valueOf(reverse).hashCode()^0xaf5998bb;
- if (field != null) hash += field.hashCode()^0xff5685dd;
- if (locale != null) hash += locale.hashCode()^0x08150815;
- if (comparatorSource != null) hash += comparatorSource.hashCode();
- if (parser != null) hash += parser.hashCode()^0x3aaf56ff;
- return hash;
- }
-
- // field must be interned after reading from stream
- private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
- in.defaultReadObject();
- if (field != null)
- field = StringHelper.intern(field);
- }
-
- /** Returns the {@link FieldComparator} to use for
- * sorting.
- *
- * @lucene.experimental
- *
- * @param numHits number of top hits the queue will store
- * @param sortPos position of this SortField within {@link
- * Sort}. The comparator is primary if sortPos==0,
- * secondary if sortPos==1, etc. Some comparators can
- * optimize themselves when they are the primary sort.
- * @return {@link FieldComparator} to use when sorting
- */
- public FieldComparator getComparator(final int numHits, final int sortPos) throws IOException {
-
- if (locale != null) {
- // TODO: it'd be nice to allow FieldCache.getStringIndex
- // to optionally accept a Locale so sorting could then use
- // the faster StringComparator impls
- return new FieldComparator.StringComparatorLocale(numHits, field, locale);
- }
-
- switch (type) {
- case SortField.SCORE:
- return new FieldComparator.RelevanceComparator(numHits);
-
- case SortField.DOC:
- return new FieldComparator.DocComparator(numHits);
-
- case SortField.INT:
- return new FieldComparator.IntComparator(numHits, field, parser).setMissingValue((Integer) missingValue);
-
- case SortField.FLOAT:
- return new FieldComparator.FloatComparator(numHits, field, parser).setMissingValue((Float) missingValue);
-
- case SortField.LONG:
- return new FieldComparator.LongComparator(numHits, field, parser).setMissingValue((Long) missingValue);
-
- case SortField.DOUBLE:
- return new FieldComparator.DoubleComparator(numHits, field, parser).setMissingValue((Double) missingValue);
-
- case SortField.BYTE:
- return new FieldComparator.ByteComparator(numHits, field, parser).setMissingValue((Byte) missingValue);
-
- case SortField.SHORT:
- return new FieldComparator.ShortComparator(numHits, field, parser).setMissingValue((Short) missingValue);
-
- case SortField.CUSTOM:
- assert comparatorSource != null;
- return comparatorSource.newComparator(field, numHits, sortPos, reverse);
-
- case SortField.STRING:
- return new FieldComparator.StringOrdValComparator(numHits, field, sortPos, reverse);
-
- case SortField.STRING_VAL:
- return new FieldComparator.StringValComparator(numHits, field);
-
- default:
- throw new IllegalStateException("Illegal sort type: " + type);
- }
- }
-}