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.
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.
26 /// <p>Created: Feb 11, 2004 2:04:21 PM
29 /// <author> Tim Jones (Nacimiento Software)
31 /// <since> lucene 1.4
33 /// <version> $Id: FieldDocSortedHitQueue.cs,v 1.3 2006/10/02 17:09:04 joeshaw Exp $
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
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).
50 /// <param name="size"> The number of hits to retain. Must be greater than zero.
52 internal FieldDocSortedHitQueue(SortField
[] fields
, int size
)
55 this.collators
= HasCollators(fields
);
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.
66 /// <param name="fields">
68 internal virtual void SetFields(SortField
[] fields
)
72 if (this.fields
== null)
75 this.collators
= HasCollators(fields
);
81 /// <summary>Returns the fields being used to sort. </summary>
82 internal virtual SortField
[] GetFields()
88 /// <summary>Returns an array of collators, possibly <code>null</code>. The collators
89 /// correspond to any SortFields which were given a specific locale.
91 /// <param name="fields">Array of sort fields.
93 /// <returns> Array, possibly <code>null</code>.
95 private System
.Globalization
.CompareInfo
[] HasCollators(SortField
[] fields
)
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();
104 ret
[i
] = locale
.CompareInfo
;
110 /// <summary> Returns whether <code>a</code> is less relevant than <code>b</code>.</summary>
111 /// <param name="a">ScoreDoc
113 /// <param name="b">ScoreDoc
115 /// <returns> <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
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
;
123 for (int i
= 0; i
< n
&& c
== 0; ++i
)
125 int type
= fields
[i
].GetType();
129 case SortField
.SCORE
:
130 float r1
= (float) ((System
.Single
) docA
.fields
[i
]);
131 float r2
= (float) ((System
.Single
) docB
.fields
[i
]);
140 int i1
= ((System
.Int32
) docA
.fields
[i
]);
141 int i2
= ((System
.Int32
) docB
.fields
[i
]);
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
155 c
= (s2
== null)?0:- 1;
159 else if (fields
[i
].GetLocale() == null)
161 c
= String
.CompareOrdinal(s1
, s2
);
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());
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
]);
181 case SortField
.CUSTOM
:
182 c
= docA
.fields
[i
].CompareTo(docB
.fields
[i
]);
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");
193 throw new System
.SystemException("invalid SortField type: " + type
);
196 if (fields
[i
].GetReverse())
202 // avoid random sort order that could lead to duplicates (bug #31241):
204 return docA
.doc
> docB
.doc
;