2 * Copyright 2004 The Apache Software Foundation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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 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.
24 /// <p>Created: Feb 11, 2004 2:04:21 PM
27 /// <author> Tim Jones (Nacimiento Software)
29 /// <since> lucene 1.4
31 /// <version> $Id: FieldDocSortedHitQueue.cs,v 1.1 2005/01/17 19:54:30 joeshaw Exp $
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
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).
48 /// <param name="size"> The number of hits to retain. Must be greater than zero.
50 /// <throws> IOException </throws>
51 internal FieldDocSortedHitQueue(SortField
[] fields
, int size
)
54 this.collators
= HasCollators(fields
);
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.
65 /// <param name="">fields
67 internal virtual void SetFields(SortField
[] fields
)
71 if (this.fields
== null)
74 this.collators
= HasCollators(fields
);
80 /// <summary>Returns the fields being used to sort. </summary>
81 internal virtual SortField
[] GetFields()
87 /// <summary>Returns an array of collators, possibly <code>null</code>. The collators
88 /// correspond to any SortFields which were given a specific locale.
90 /// <param name="fields">Array of sort fields.
92 /// <returns> Array, possibly <code>null</code>.
94 private System
.Globalization
.CompareInfo
[] HasCollators(SortField
[] fields
)
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();
103 ret
[i
] = locale
.CompareInfo
;
109 /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
110 /// <param name="a">ScoreDoc
112 /// <param name="b">ScoreDoc
114 /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
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
;
122 for (int i
= 0; i
< n
&& c
== 0; ++i
)
124 int type
= fields
[i
].GetType();
125 if (fields
[i
].GetReverse())
130 case SortField
.SCORE
:
131 float r1
= (float) ((System
.Single
) docA
.fields
[i
]);
132 float r2
= (float) ((System
.Single
) docB
.fields
[i
]);
141 int i1
= ((System
.Int32
) docA
.fields
[i
]);
142 int i2
= ((System
.Int32
) docB
.fields
[i
]);
149 case SortField
.STRING
:
150 System
.String s1
= (System
.String
) docA
.fields
[i
];
151 System
.String s2
= (System
.String
) docB
.fields
[i
];
154 // could be null if there are
157 // no terms in the given Field
158 else if (fields
[i
].GetLocale() == null)
160 c
= String
.CompareOrdinal(s2
, s1
);
164 c
= collators
[i
].Compare(s2
.ToString(), s1
.ToString());
168 case SortField
.FLOAT
:
169 float f1
= (float) ((System
.Single
) docA
.fields
[i
]);
170 float f2
= (float) ((System
.Single
) docB
.fields
[i
]);
177 case SortField
.CUSTOM
:
178 c
= docB
.fields
[i
].CompareTo(docA
.fields
[i
]);
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");
189 throw new System
.SystemException("invalid SortField type: " + type
);
198 case SortField
.SCORE
:
199 float r1
= (float) ((System
.Single
) docA
.fields
[i
]);
200 float r2
= (float) ((System
.Single
) docB
.fields
[i
]);
209 int i1
= ((System
.Int32
) docA
.fields
[i
]);
210 int i2
= ((System
.Int32
) docB
.fields
[i
]);
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
225 // could be null if there are
228 // no terms in the given Field
229 else if (fields
[i
].GetLocale() == null)
231 c
= String
.CompareOrdinal(s1
, s2
);
235 c
= collators
[i
].Compare(s1
.ToString(), s2
.ToString());
239 case SortField
.FLOAT
:
240 float f1
= (float) ((System
.Single
) docA
.fields
[i
]);
241 float f2
= (float) ((System
.Single
) docB
.fields
[i
]);
248 case SortField
.CUSTOM
:
249 c
= docA
.fields
[i
].CompareTo(docB
.fields
[i
]);
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");
260 throw new System
.SystemException("invalid SortField type: " + type
);