1 package org.apache.lucene.search; 2 3 18 19 import org.apache.lucene.index.IndexReader; 20 import org.apache.lucene.util.PriorityQueue; 21 22 import java.io.IOException ; 23 import java.util.WeakHashMap ; 24 import java.util.HashMap ; 25 import java.util.Map ; 26 import java.util.Locale ; 27 import java.text.Collator ; 28 29 41 public class FieldSortedHitQueue 42 extends PriorityQueue { 43 44 51 public FieldSortedHitQueue (IndexReader reader, SortField[] fields, int size) 52 throws IOException { 53 final int n = fields.length; 54 comparators = new ScoreDocComparator[n]; 55 this.fields = new SortField[n]; 56 for (int i=0; i<n; ++i) { 57 String fieldname = fields[i].getField(); 58 comparators[i] = getCachedComparator (reader, fieldname, fields[i].getType(), fields[i].getLocale(), fields[i].getFactory()); 59 this.fields[i] = new SortField (fieldname, comparators[i].sortType(), fields[i].getReverse()); 60 } 61 initialize (size); 62 } 63 64 65 66 protected ScoreDocComparator[] comparators; 67 68 69 protected SortField[] fields; 70 71 72 protected float maxscore = Float.NEGATIVE_INFINITY; 73 74 76 public float getMaxScore() { 77 return maxscore; 78 } 79 80 public boolean insert(FieldDoc fdoc) { 84 maxscore = Math.max(maxscore,fdoc.score); 85 return super.insert(fdoc); 86 } 87 88 public boolean insert(Object fdoc) { 92 return insert((FieldDoc)fdoc); 93 } 94 95 101 protected boolean lessThan (final Object a, final Object b) { 102 final ScoreDoc docA = (ScoreDoc) a; 103 final ScoreDoc docB = (ScoreDoc) b; 104 105 final int n = comparators.length; 107 int c = 0; 108 for (int i=0; i<n && c==0; ++i) { 109 c = (fields[i].reverse) ? comparators[i].compare (docB, docA) 110 : comparators[i].compare (docA, docB); 111 } 112 if (c == 0) 114 return docA.doc > docB.doc; 115 return c > 0; 116 } 117 118 119 129 FieldDoc fillFields (final FieldDoc doc) { 130 final int n = comparators.length; 131 final Comparable [] fields = new Comparable [n]; 132 for (int i=0; i<n; ++i) 133 fields[i] = comparators[i].sortValue(doc); 134 doc.fields = fields; 135 return doc; 137 } 138 139 140 141 SortField[] getFields() { 142 return fields; 143 } 144 145 147 static final Map Comparators = new WeakHashMap (); 148 149 150 static ScoreDocComparator lookup (IndexReader reader, String field, int type, Object factory) { 151 FieldCacheImpl.Entry entry = (factory != null) 152 ? new FieldCacheImpl.Entry (field, factory) 153 : new FieldCacheImpl.Entry (field, type); 154 synchronized (Comparators) { 155 HashMap readerCache = (HashMap )Comparators.get(reader); 156 if (readerCache == null) return null; 157 return (ScoreDocComparator) readerCache.get (entry); 158 } 159 } 160 161 162 static Object store (IndexReader reader, String field, int type, Object factory, Object value) { 163 FieldCacheImpl.Entry entry = (factory != null) 164 ? new FieldCacheImpl.Entry (field, factory) 165 : new FieldCacheImpl.Entry (field, type); 166 synchronized (Comparators) { 167 HashMap readerCache = (HashMap )Comparators.get(reader); 168 if (readerCache == null) { 169 readerCache = new HashMap (); 170 Comparators.put(reader,readerCache); 171 } 172 return readerCache.put (entry, value); 173 } 174 } 175 176 static ScoreDocComparator getCachedComparator (IndexReader reader, String fieldname, int type, Locale locale, SortComparatorSource factory) 177 throws IOException { 178 if (type == SortField.DOC) return ScoreDocComparator.INDEXORDER; 179 if (type == SortField.SCORE) return ScoreDocComparator.RELEVANCE; 180 ScoreDocComparator comparator = lookup (reader, fieldname, type, factory); 181 if (comparator == null) { 182 switch (type) { 183 case SortField.AUTO: 184 comparator = comparatorAuto (reader, fieldname); 185 break; 186 case SortField.INT: 187 comparator = comparatorInt (reader, fieldname); 188 break; 189 case SortField.FLOAT: 190 comparator = comparatorFloat (reader, fieldname); 191 break; 192 case SortField.STRING: 193 if (locale != null) comparator = comparatorStringLocale (reader, fieldname, locale); 194 else comparator = comparatorString (reader, fieldname); 195 break; 196 case SortField.CUSTOM: 197 comparator = factory.newComparator (reader, fieldname); 198 break; 199 default: 200 throw new RuntimeException ("unknown field type: "+type); 201 } 202 store (reader, fieldname, type, factory, comparator); 203 } 204 return comparator; 205 } 206 207 214 static ScoreDocComparator comparatorInt (final IndexReader reader, final String fieldname) 215 throws IOException { 216 final String field = fieldname.intern(); 217 final int[] fieldOrder = FieldCache.DEFAULT.getInts (reader, field); 218 return new ScoreDocComparator() { 219 220 public final int compare (final ScoreDoc i, final ScoreDoc j) { 221 final int fi = fieldOrder[i.doc]; 222 final int fj = fieldOrder[j.doc]; 223 if (fi < fj) return -1; 224 if (fi > fj) return 1; 225 return 0; 226 } 227 228 public Comparable sortValue (final ScoreDoc i) { 229 return new Integer (fieldOrder[i.doc]); 230 } 231 232 public int sortType() { 233 return SortField.INT; 234 } 235 }; 236 } 237 238 245 static ScoreDocComparator comparatorFloat (final IndexReader reader, final String fieldname) 246 throws IOException { 247 final String field = fieldname.intern(); 248 final float[] fieldOrder = FieldCache.DEFAULT.getFloats (reader, field); 249 return new ScoreDocComparator () { 250 251 public final int compare (final ScoreDoc i, final ScoreDoc j) { 252 final float fi = fieldOrder[i.doc]; 253 final float fj = fieldOrder[j.doc]; 254 if (fi < fj) return -1; 255 if (fi > fj) return 1; 256 return 0; 257 } 258 259 public Comparable sortValue (final ScoreDoc i) { 260 return new Float (fieldOrder[i.doc]); 261 } 262 263 public int sortType() { 264 return SortField.FLOAT; 265 } 266 }; 267 } 268 269 276 static ScoreDocComparator comparatorString (final IndexReader reader, final String fieldname) 277 throws IOException { 278 final String field = fieldname.intern(); 279 final FieldCache.StringIndex index = FieldCache.DEFAULT.getStringIndex (reader, field); 280 return new ScoreDocComparator () { 281 282 public final int compare (final ScoreDoc i, final ScoreDoc j) { 283 final int fi = index.order[i.doc]; 284 final int fj = index.order[j.doc]; 285 if (fi < fj) return -1; 286 if (fi > fj) return 1; 287 return 0; 288 } 289 290 public Comparable sortValue (final ScoreDoc i) { 291 return index.lookup[index.order[i.doc]]; 292 } 293 294 public int sortType() { 295 return SortField.STRING; 296 } 297 }; 298 } 299 300 307 static ScoreDocComparator comparatorStringLocale (final IndexReader reader, final String fieldname, final Locale locale) 308 throws IOException { 309 final Collator collator = Collator.getInstance (locale); 310 final String field = fieldname.intern(); 311 final String [] index = FieldCache.DEFAULT.getStrings (reader, field); 312 return new ScoreDocComparator() { 313 314 public final int compare (final ScoreDoc i, final ScoreDoc j) { 315 return collator.compare (index[i.doc], index[j.doc]); 316 } 317 318 public Comparable sortValue (final ScoreDoc i) { 319 return index[i.doc]; 320 } 321 322 public int sortType() { 323 return SortField.STRING; 324 } 325 }; 326 } 327 328 338 static ScoreDocComparator comparatorAuto (final IndexReader reader, final String fieldname) 339 throws IOException { 340 final String field = fieldname.intern(); 341 Object lookupArray = FieldCache.DEFAULT.getAuto (reader, field); 342 if (lookupArray instanceof FieldCache.StringIndex) { 343 return comparatorString (reader, field); 344 } else if (lookupArray instanceof int[]) { 345 return comparatorInt (reader, field); 346 } else if (lookupArray instanceof float[]) { 347 return comparatorFloat (reader, field); 348 } else if (lookupArray instanceof String []) { 349 return comparatorString (reader, field); 350 } else { 351 throw new RuntimeException ("unknown data type in field '"+field+"'"); 352 } 353 } 354 } 355 | Popular Tags |