01: package org.apache.lucene.search;
02:
03: /**
04: * Licensed to the Apache Software Foundation (ASF) under one or more
05: * contributor license agreements. See the NOTICE file distributed with
06: * this work for additional information regarding copyright ownership.
07: * The ASF licenses this file to You under the Apache License, Version 2.0
08: * (the "License"); you may not use this file except in compliance with
09: * the License. You may obtain a copy of the License at
10: *
11: * http://www.apache.org/licenses/LICENSE-2.0
12: *
13: * Unless required by applicable law or agreed to in writing, software
14: * distributed under the License is distributed on an "AS IS" BASIS,
15: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16: * See the License for the specific language governing permissions and
17: * limitations under the License.
18: */
19:
20: import org.apache.lucene.util.PriorityQueue;
21:
22: /** A {@link HitCollector} implementation that collects the top-scoring
23: * documents, returning them as a {@link TopDocs}. This is used by {@link
24: * IndexSearcher} to implement {@link TopDocs}-based search.
25: *
26: * <p>This may be extended, overriding the collect method to, e.g.,
27: * conditionally invoke <code>super()</code> in order to filter which
28: * documents are collected.
29: **/
30: public class TopDocCollector extends HitCollector {
31:
32: private ScoreDoc reusableSD;
33:
34: int totalHits;
35: PriorityQueue hq;
36:
37: /** Construct to collect a given number of hits.
38: * @param numHits the maximum number of hits to collect
39: */
40: public TopDocCollector(int numHits) {
41: this (numHits, new HitQueue(numHits));
42: }
43:
44: TopDocCollector(int numHits, PriorityQueue hq) {
45: this .hq = hq;
46: }
47:
48: // javadoc inherited
49: public void collect(int doc, float score) {
50: if (score > 0.0f) {
51: totalHits++;
52: if (reusableSD == null) {
53: reusableSD = new ScoreDoc(doc, score);
54: } else if (score >= reusableSD.score) {
55: // reusableSD holds the last "rejected" entry, so, if
56: // this new score is not better than that, there's no
57: // need to try inserting it
58: reusableSD.doc = doc;
59: reusableSD.score = score;
60: } else {
61: return;
62: }
63: reusableSD = (ScoreDoc) hq.insertWithOverflow(reusableSD);
64: }
65: }
66:
67: /** The total number of documents that matched this query. */
68: public int getTotalHits() {
69: return totalHits;
70: }
71:
72: /** The top-scoring hits. */
73: public TopDocs topDocs() {
74: ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
75: for (int i = hq.size() - 1; i >= 0; i--)
76: // put docs in array
77: scoreDocs[i] = (ScoreDoc) hq.pop();
78:
79: float maxScore = (totalHits == 0) ? Float.NEGATIVE_INFINITY
80: : scoreDocs[0].score;
81:
82: return new TopDocs(totalHits, scoreDocs, maxScore);
83: }
84: }
|