Thumbnail file hits. Based on a patch from D Bera
[beagle.git] / beagled / Lucene.Net / Search / FieldDocSortedHitQueue.cs
blobf1fac1ac909cffecc3940b7b7f5579f57fde00b4
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.
16 using System;
17 using PriorityQueue = Lucene.Net.Util.PriorityQueue;
18 namespace Lucene.Net.Search
21 /// <summary> Expert: Collects sorted results from Searchable's and collates them.
22 /// The elements put into this queue must be of type FieldDoc.
23 ///
24 /// <p>Created: Feb 11, 2004 2:04:21 PM
25 ///
26 /// </summary>
27 /// <author> Tim Jones (Nacimiento Software)
28 /// </author>
29 /// <since> lucene 1.4
30 /// </since>
31 /// <version> $Id: FieldDocSortedHitQueue.cs,v 1.1 2005/01/17 19:54:30 joeshaw Exp $
32 /// </version>
33 class FieldDocSortedHitQueue : PriorityQueue
36 // this cannot contain AUTO fields - any AUTO fields should
37 // have been resolved by the time this class is used.
38 internal volatile SortField[] fields;
40 // used in the case where the fields are sorted by locale
41 // based strings
42 internal volatile System.Globalization.CompareInfo[] collators;
45 /// <summary> Creates a hit queue sorted by the given list of fields.</summary>
46 /// <param name="fields">Field names, in priority order (highest priority first).
47 /// </param>
48 /// <param name="size"> The number of hits to retain. Must be greater than zero.
49 /// </param>
50 /// <throws> IOException </throws>
51 internal FieldDocSortedHitQueue(SortField[] fields, int size)
53 this.fields = fields;
54 this.collators = HasCollators(fields);
55 Initialize(size);
59 /// <summary> Allows redefinition of sort fields if they are <code>null</code>.
60 /// This is to handle the case using ParallelMultiSearcher where the
61 /// original list contains AUTO and we don't know the actual sort
62 /// type until the values come back. The fields can only be set once.
63 /// This method is thread safe.
64 /// </summary>
65 /// <param name="">fields
66 /// </param>
67 internal virtual void SetFields(SortField[] fields)
69 lock (this)
71 if (this.fields == null)
73 this.fields = fields;
74 this.collators = HasCollators(fields);
80 /// <summary>Returns the fields being used to sort. </summary>
81 internal virtual SortField[] GetFields()
83 return fields;
87 /// <summary>Returns an array of collators, possibly <code>null</code>. The collators
88 /// correspond to any SortFields which were given a specific locale.
89 /// </summary>
90 /// <param name="fields">Array of sort fields.
91 /// </param>
92 /// <returns> Array, possibly <code>null</code>.
93 /// </returns>
94 private System.Globalization.CompareInfo[] HasCollators(SortField[] fields)
96 if (fields == null)
97 return null;
98 System.Globalization.CompareInfo[] ret = new System.Globalization.CompareInfo[fields.Length];
99 for (int i = 0; i < fields.Length; ++i)
101 System.Globalization.CultureInfo locale = fields[i].GetLocale();
102 if (locale != null)
103 ret[i] = locale.CompareInfo;
105 return ret;
109 /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
110 /// <param name="a">ScoreDoc
111 /// </param>
112 /// <param name="b">ScoreDoc
113 /// </param>
114 /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
115 /// </returns>
116 public override bool LessThan(System.Object a, System.Object b)
118 FieldDoc docA = (FieldDoc) a;
119 FieldDoc docB = (FieldDoc) b;
120 int n = fields.Length;
121 int c = 0;
122 for (int i = 0; i < n && c == 0; ++i)
124 int type = fields[i].GetType();
125 if (fields[i].GetReverse())
127 switch (type)
130 case SortField.SCORE:
131 float r1 = (float) ((System.Single) docA.fields[i]);
132 float r2 = (float) ((System.Single) docB.fields[i]);
133 if (r1 < r2)
134 c = - 1;
135 if (r1 > r2)
136 c = 1;
137 break;
139 case SortField.DOC:
140 case SortField.INT:
141 int i1 = ((System.Int32) docA.fields[i]);
142 int i2 = ((System.Int32) docB.fields[i]);
143 if (i1 > i2)
144 c = - 1;
145 if (i1 < i2)
146 c = 1;
147 break;
149 case SortField.STRING:
150 System.String s1 = (System.String) docA.fields[i];
151 System.String s2 = (System.String) docB.fields[i];
152 if (s2 == null)
153 c = - 1;
154 // could be null if there are
155 else if (s1 == null)
156 c = 1;
157 // no terms in the given Field
158 else if (fields[i].GetLocale() == null)
160 c = String.CompareOrdinal(s2, s1);
162 else
164 c = collators[i].Compare(s2.ToString(), s1.ToString());
166 break;
168 case SortField.FLOAT:
169 float f1 = (float) ((System.Single) docA.fields[i]);
170 float f2 = (float) ((System.Single) docB.fields[i]);
171 if (f1 > f2)
172 c = - 1;
173 if (f1 < f2)
174 c = 1;
175 break;
177 case SortField.CUSTOM:
178 c = docB.fields[i].CompareTo(docA.fields[i]);
179 break;
181 case SortField.AUTO:
182 // we cannot handle this - even if we determine the type of object (Float or
183 // Integer), we don't necessarily know how to compare them (both SCORE and
184 // FLOAT both contain floats, but are sorted opposite of each other). Before
185 // we get here, each AUTO should have been replaced with its actual value.
186 throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
188 default:
189 throw new System.SystemException("invalid SortField type: " + type);
193 else
195 switch (type)
198 case SortField.SCORE:
199 float r1 = (float) ((System.Single) docA.fields[i]);
200 float r2 = (float) ((System.Single) docB.fields[i]);
201 if (r1 > r2)
202 c = - 1;
203 if (r1 < r2)
204 c = 1;
205 break;
207 case SortField.DOC:
208 case SortField.INT:
209 int i1 = ((System.Int32) docA.fields[i]);
210 int i2 = ((System.Int32) docB.fields[i]);
211 if (i1 < i2)
212 c = - 1;
213 if (i1 > i2)
214 c = 1;
215 break;
217 case SortField.STRING:
218 System.String s1 = (System.String) docA.fields[i];
219 System.String s2 = (System.String) docB.fields[i];
220 // null values need to be sorted first, because of how FieldCache.getStringIndex()
221 // works - in that routine, any documents without a value in the given Field are
222 // put first.
223 if (s1 == null)
224 c = - 1;
225 // could be null if there are
226 else if (s2 == null)
227 c = 1;
228 // no terms in the given Field
229 else if (fields[i].GetLocale() == null)
231 c = String.CompareOrdinal(s1, s2);
233 else
235 c = collators[i].Compare(s1.ToString(), s2.ToString());
237 break;
239 case SortField.FLOAT:
240 float f1 = (float) ((System.Single) docA.fields[i]);
241 float f2 = (float) ((System.Single) docB.fields[i]);
242 if (f1 < f2)
243 c = - 1;
244 if (f1 > f2)
245 c = 1;
246 break;
248 case SortField.CUSTOM:
249 c = docA.fields[i].CompareTo(docB.fields[i]);
250 break;
252 case SortField.AUTO:
253 // we cannot handle this - even if we determine the type of object (Float or
254 // Integer), we don't necessarily know how to compare them (both SCORE and
255 // FLOAT both contain floats, but are sorted opposite of each other). Before
256 // we get here, each AUTO should have been replaced with its actual value.
257 throw new System.SystemException("FieldDocSortedHitQueue cannot use an AUTO SortField");
259 default:
260 throw new System.SystemException("invalid SortField type: " + type);
265 return c > 0;