QueryResponses.cs, DumpIndex.cs, IQueryResult.cs, QueryExecutor.cs, QueryResult.cs...
[beagle.git] / beagled / Lucene.Net / Search / FieldDocSortedHitQueue.cs
blob8ac80916895065542854661e22ccd19da248c11d
1 /*
2 * Copyright 2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 using System;
18 using PriorityQueue = Lucene.Net.Util.PriorityQueue;
20 namespace Lucene.Net.Search
23 /// <summary> Expert: Collects sorted results from Searchable's and collates them.
24 /// The elements put into this queue must be of type FieldDoc.
25 ///
26 /// <p>Created: Feb 11, 2004 2:04:21 PM
27 ///
28 /// </summary>
29 /// <author> Tim Jones (Nacimiento Software)
30 /// </author>
31 /// <since> lucene 1.4
32 /// </since>
33 /// <version> $Id: FieldDocSortedHitQueue.cs,v 1.3 2006/10/02 17:09:04 joeshaw Exp $
34 /// </version>
35 class FieldDocSortedHitQueue : PriorityQueue
38 // this cannot contain AUTO fields - any AUTO fields should
39 // have been resolved by the time this class is used.
40 internal volatile SortField[] fields;
42 // used in the case where the fields are sorted by locale
43 // based strings
44 internal volatile System.Globalization.CompareInfo[] collators;
47 /// <summary> Creates a hit queue sorted by the given list of fields.</summary>
48 /// <param name="fields">Field names, in priority order (highest priority first).
49 /// </param>
50 /// <param name="size"> The number of hits to retain. Must be greater than zero.
51 /// </param>
52 internal FieldDocSortedHitQueue(SortField[] fields, int size)
54 this.fields = fields;
55 this.collators = HasCollators(fields);
56 Initialize(size);
60 /// <summary> Allows redefinition of sort fields if they are <code>null</code>.
61 /// This is to handle the case using ParallelMultiSearcher where the
62 /// original list contains AUTO and we don't know the actual sort
63 /// type until the values come back. The fields can only be set once.
64 /// This method is thread safe.
65 /// </summary>
66 /// <param name="fields">
67 /// </param>
68 internal virtual void SetFields(SortField[] fields)
70 lock (this)
72 if (this.fields == null)
74 this.fields = fields;
75 this.collators = HasCollators(fields);
81 /// <summary>Returns the fields being used to sort. </summary>
82 internal virtual SortField[] GetFields()
84 return fields;
88 /// <summary>Returns an array of collators, possibly <code>null</code>. The collators
89 /// correspond to any SortFields which were given a specific locale.
90 /// </summary>
91 /// <param name="fields">Array of sort fields.
92 /// </param>
93 /// <returns> Array, possibly <code>null</code>.
94 /// </returns>
95 private System.Globalization.CompareInfo[] HasCollators(SortField[] fields)
97 if (fields == null)
98 return null;
99 System.Globalization.CompareInfo[] ret = new System.Globalization.CompareInfo[fields.Length];
100 for (int i = 0; i < fields.Length; ++i)
102 System.Globalization.CultureInfo locale = fields[i].GetLocale();
103 if (locale != null)
104 ret[i] = locale.CompareInfo;
106 return ret;
110 /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
111 /// <param name="a">ScoreDoc
112 /// </param>
113 /// <param name="b">ScoreDoc
114 /// </param>
115 /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
116 /// </returns>
117 public override bool LessThan(System.Object a, System.Object b)
119 FieldDoc docA = (FieldDoc) a;
120 FieldDoc docB = (FieldDoc) b;
121 int n = fields.Length;
122 int c = 0;
123 for (int i = 0; i < n && c == 0; ++i)
125 int type = fields[i].GetType();
126 switch (type)
129 case SortField.SCORE:
130 float r1 = (float) ((System.Single) docA.fields[i]);
131 float r2 = (float) ((System.Single) docB.fields[i]);
132 if (r1 > r2)
133 c = - 1;
134 if (r1 < r2)
135 c = 1;
136 break;
138 case SortField.DOC:
139 case SortField.INT:
140 int i1 = ((System.Int32) docA.fields[i]);
141 int i2 = ((System.Int32) docB.fields[i]);
142 if (i1 < i2)
143 c = - 1;
144 if (i1 > i2)
145 c = 1;
146 break;
148 case SortField.STRING:
149 System.String s1 = (System.String) docA.fields[i];
150 System.String s2 = (System.String) docB.fields[i];
151 // null values need to be sorted first, because of how FieldCache.getStringIndex()
152 // works - in that routine, any documents without a value in the given field are
153 // put first. If both are null, the next SortField is used
154 if (s1 == null)
155 c = (s2 == null)?0:- 1;
156 else if (s2 == null)
157 c = 1;
159 else if (fields[i].GetLocale() == null)
161 c = String.CompareOrdinal(s1, s2);
163 else
165 //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'"
166 c = collators[i].Compare(s1.ToString(), s2.ToString());
168 break;
170 case SortField.FLOAT:
171 //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'"
172 float f1 = (float) ((System.Single) docA.fields[i]);
173 //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'"
174 float f2 = (float) ((System.Single) docB.fields[i]);
175 if (f1 < f2)
176 c = - 1;
177 if (f1 > f2)
178 c = 1;
179 break;
181 case SortField.CUSTOM:
182 c = docA.fields[i].CompareTo(docB.fields[i]);
183 break;
185 case SortField.AUTO:
186 // we cannot handle this - even if we determine the type of object (Float or
187 // Integer), we don't necessarily know how to compare them (both SCORE and
188 // FLOAT contain floats, but are sorted opposite of each other). Before
189 // we get here, each AUTO should have been replaced with its actual value.
190 throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
192 default:
193 throw new System.SystemException("invalid SortField type: " + type);
196 if (fields[i].GetReverse())
198 c = - c;
202 // avoid random sort order that could lead to duplicates (bug #31241):
203 if (c == 0)
204 return docA.doc > docB.doc;
206 return c > 0;