KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > lucene > search > FieldDocSortedHitQueue


1 package org.apache.lucene.search;
2
3 /**
4  * Copyright 2004 The Apache Software Foundation
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 import org.apache.lucene.util.PriorityQueue;
20
21 import java.text.Collator JavaDoc;
22 import java.util.Locale JavaDoc;
23
24 /**
25  * Expert: Collects sorted results from Searchable's and collates them.
26  * The elements put into this queue must be of type FieldDoc.
27  *
28  * <p>Created: Feb 11, 2004 2:04:21 PM
29  *
30  * @author Tim Jones (Nacimiento Software)
31  * @since lucene 1.4
32  * @version $Id: FieldDocSortedHitQueue.java 332431 2005-11-11 03:13:10Z yonik $
33  */

34 class FieldDocSortedHitQueue
35 extends PriorityQueue {
36
37     // this cannot contain AUTO fields - any AUTO fields should
38
// have been resolved by the time this class is used.
39
volatile SortField[] fields;
40
41     // used in the case where the fields are sorted by locale
42
// based strings
43
volatile Collator JavaDoc[] collators;
44
45
46     /**
47      * Creates a hit queue sorted by the given list of fields.
48      * @param fields Field names, in priority order (highest priority first).
49      * @param size The number of hits to retain. Must be greater than zero.
50      */

51     FieldDocSortedHitQueue (SortField[] fields, int size) {
52         this.fields = fields;
53         this.collators = hasCollators (fields);
54         initialize (size);
55     }
56
57
58     /**
59      * 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      * @param fields
65      */

66     synchronized void setFields (SortField[] fields) {
67         if (this.fields == null) {
68             this.fields = fields;
69             this.collators = hasCollators (fields);
70         }
71     }
72
73
74     /** Returns the fields being used to sort. */
75     SortField[] getFields() {
76         return fields;
77     }
78
79
80     /** Returns an array of collators, possibly <code>null</code>. The collators
81      * correspond to any SortFields which were given a specific locale.
82      * @param fields Array of sort fields.
83      * @return Array, possibly <code>null</code>.
84      */

85     private Collator JavaDoc[] hasCollators (final SortField[] fields) {
86         if (fields == null) return null;
87         Collator JavaDoc[] ret = new Collator JavaDoc[fields.length];
88         for (int i=0; i<fields.length; ++i) {
89             Locale JavaDoc locale = fields[i].getLocale();
90             if (locale != null)
91                 ret[i] = Collator.getInstance (locale);
92         }
93         return ret;
94     }
95
96
97     /**
98      * Returns whether <code>a</code> is less relevant than <code>b</code>.
99      * @param a ScoreDoc
100      * @param b ScoreDoc
101      * @return <code>true</code> if document <code>a</code> should be sorted after document <code>b</code>.
102      */

103     protected final boolean lessThan (final Object JavaDoc a, final Object JavaDoc b) {
104         final FieldDoc docA = (FieldDoc) a;
105         final FieldDoc docB = (FieldDoc) b;
106         final int n = fields.length;
107         int c = 0;
108         for (int i=0; i<n && c==0; ++i) {
109             final int type = fields[i].getType();
110             switch (type) {
111                 case SortField.SCORE:
112                     float r1 = ((Float JavaDoc)docA.fields[i]).floatValue();
113                     float r2 = ((Float JavaDoc)docB.fields[i]).floatValue();
114                     if (r1 > r2) c = -1;
115                     if (r1 < r2) c = 1;
116                     break;
117                 case SortField.DOC:
118                 case SortField.INT:
119                     int i1 = ((Integer JavaDoc)docA.fields[i]).intValue();
120                     int i2 = ((Integer JavaDoc)docB.fields[i]).intValue();
121                     if (i1 < i2) c = -1;
122                     if (i1 > i2) c = 1;
123                     break;
124                 case SortField.STRING:
125                     String JavaDoc s1 = (String JavaDoc) docA.fields[i];
126                     String JavaDoc s2 = (String JavaDoc) docB.fields[i];
127                     // null values need to be sorted first, because of how FieldCache.getStringIndex()
128
// works - in that routine, any documents without a value in the given field are
129
// put first. If both are null, the next SortField is used
130
if (s1 == null) c = (s2==null) ? 0 : -1;
131                     else if (s2 == null) c = 1; //
132
else if (fields[i].getLocale() == null) {
133                         c = s1.compareTo(s2);
134                     } else {
135                         c = collators[i].compare (s1, s2);
136                     }
137                     break;
138                 case SortField.FLOAT:
139                     float f1 = ((Float JavaDoc)docA.fields[i]).floatValue();
140                     float f2 = ((Float JavaDoc)docB.fields[i]).floatValue();
141                     if (f1 < f2) c = -1;
142                     if (f1 > f2) c = 1;
143                     break;
144                 case SortField.CUSTOM:
145                     c = docA.fields[i].compareTo (docB.fields[i]);
146                     break;
147                 case SortField.AUTO:
148                     // we cannot handle this - even if we determine the type of object (Float or
149
// Integer), we don't necessarily know how to compare them (both SCORE and
150
// FLOAT contain floats, but are sorted opposite of each other). Before
151
// we get here, each AUTO should have been replaced with its actual value.
152
throw new RuntimeException JavaDoc ("FieldDocSortedHitQueue cannot use an AUTO SortField");
153                 default:
154                     throw new RuntimeException JavaDoc ("invalid SortField type: "+type);
155             }
156             if (fields[i].getReverse()) {
157                 c = -c;
158             }
159         }
160
161     // avoid random sort order that could lead to duplicates (bug #31241):
162
if (c == 0)
163       return docA.doc > docB.doc;
164
165     return c > 0;
166     }
167 }
168
Popular Tags