FieldDocSortedHitQueue.cs
上传用户:zhangkuixh
上传日期:2013-09-30
资源大小:5473k
文件大小:7k
- /*
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed 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.
- */
- using System;
- using PriorityQueue = Lucene.Net.Util.PriorityQueue;
- namespace Lucene.Net.Search
- {
-
- /// <summary> Expert: Collects sorted results from Searchable's and collates them.
- /// The elements put into this queue must be of type FieldDoc.
- ///
- /// <p>Created: Feb 11, 2004 2:04:21 PM
- ///
- /// </summary>
- /// <author> Tim Jones (Nacimiento Software)
- /// </author>
- /// <since> lucene 1.4
- /// </since>
- /// <version> $Id: FieldDocSortedHitQueue.java 332431 2005-11-11 03:13:10Z yonik $
- /// </version>
- class FieldDocSortedHitQueue : PriorityQueue
- {
-
- // this cannot contain AUTO fields - any AUTO fields should
- // have been resolved by the time this class is used.
- internal volatile SortField[] fields;
-
- // used in the case where the fields are sorted by locale
- // based strings
- internal volatile System.Globalization.CompareInfo[] collators;
-
-
- /// <summary> Creates a hit queue sorted by the given list of fields.</summary>
- /// <param name="fields">Field names, in priority order (highest priority first).
- /// </param>
- /// <param name="size"> The number of hits to retain. Must be greater than zero.
- /// </param>
- internal FieldDocSortedHitQueue(SortField[] fields, int size)
- {
- this.fields = fields;
- this.collators = HasCollators(fields);
- Initialize(size);
- }
-
-
- /// <summary> Allows redefinition of sort fields if they are <code>null</code>.
- /// This is to handle the case using ParallelMultiSearcher where the
- /// original list contains AUTO and we don't know the actual sort
- /// type until the values come back. The fields can only be set once.
- /// This method is thread safe.
- /// </summary>
- /// <param name="fields">
- /// </param>
- internal virtual void SetFields(SortField[] fields)
- {
- lock (this)
- {
- if (this.fields == null)
- {
- this.fields = fields;
- this.collators = HasCollators(fields);
- }
- }
- }
-
-
- /// <summary>Returns the fields being used to sort. </summary>
- internal virtual SortField[] GetFields()
- {
- return fields;
- }
-
-
- /// <summary>Returns an array of collators, possibly <code>null</code>. The collators
- /// correspond to any SortFields which were given a specific locale.
- /// </summary>
- /// <param name="fields">Array of sort fields.
- /// </param>
- /// <returns> Array, possibly <code>null</code>.
- /// </returns>
- private System.Globalization.CompareInfo[] HasCollators(SortField[] fields)
- {
- if (fields == null)
- return null;
- System.Globalization.CompareInfo[] ret = new System.Globalization.CompareInfo[fields.Length];
- for (int i = 0; i < fields.Length; ++i)
- {
- System.Globalization.CultureInfo locale = fields[i].GetLocale();
- if (locale != null)
- ret[i] = locale.CompareInfo;
- }
- return ret;
- }
-
-
- /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
- /// <param name="a">ScoreDoc
- /// </param>
- /// <param name="b">ScoreDoc
- /// </param>
- /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
- /// </returns>
- public override bool LessThan(System.Object a, System.Object b)
- {
- FieldDoc docA = (FieldDoc) a;
- FieldDoc docB = (FieldDoc) b;
- int n = fields.Length;
- int c = 0;
- for (int i = 0; i < n && c == 0; ++i)
- {
- int type = fields[i].GetType();
- switch (type)
- {
-
- case SortField.SCORE:
- float r1 = (float) ((System.Single) docA.fields[i]);
- float r2 = (float) ((System.Single) docB.fields[i]);
- if (r1 > r2)
- c = - 1;
- if (r1 < r2)
- c = 1;
- break;
-
- case SortField.DOC:
- case SortField.INT:
- int i1 = ((System.Int32) docA.fields[i]);
- int i2 = ((System.Int32) docB.fields[i]);
- if (i1 < i2)
- c = - 1;
- if (i1 > i2)
- c = 1;
- break;
-
- case SortField.STRING:
- System.String s1 = (System.String) docA.fields[i];
- System.String s2 = (System.String) docB.fields[i];
- // null values need to be sorted first, because of how FieldCache.getStringIndex()
- // works - in that routine, any documents without a value in the given field are
- // put first. If both are null, the next SortField is used
- if (s1 == null)
- c = (s2 == null)?0:- 1;
- else if (s2 == null)
- c = 1;
- //
- else if (fields[i].GetLocale() == null)
- {
- c = String.CompareOrdinal(s1, s2);
- }
- else
- {
- //UPGRADE_TODO: The equivalent in .NET for method 'java.text.Collator.compare' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
- c = collators[i].Compare(s1.ToString(), s2.ToString());
- }
- break;
-
- case SortField.FLOAT:
- //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
- float f1 = (float) ((System.Single) docA.fields[i]);
- //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
- float f2 = (float) ((System.Single) docB.fields[i]);
- if (f1 < f2)
- c = - 1;
- if (f1 > f2)
- c = 1;
- break;
-
- case SortField.CUSTOM:
- c = docA.fields[i].CompareTo(docB.fields[i]);
- break;
-
- case SortField.AUTO:
- // we cannot handle this - even if we determine the type of object (Float or
- // Integer), we don't necessarily know how to compare them (both SCORE and
- // FLOAT contain floats, but are sorted opposite of each other). Before
- // we get here, each AUTO should have been replaced with its actual value.
- throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
-
- default:
- throw new System.SystemException("invalid SortField type: " + type);
-
- }
- if (fields[i].GetReverse())
- {
- c = - c;
- }
- }
-
- // avoid random sort order that could lead to duplicates (bug #31241):
- if (c == 0)
- return docA.doc > docB.doc;
-
- return c > 0;
- }
- }
- }