KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.IOException JavaDoc;
20
21 import org.apache.lucene.index.TermDocs;
22
23 /** Expert: A <code>Scorer</code> for documents matching a <code>Term</code>.
24  */

25 final class TermScorer extends Scorer {
26   private Weight weight;
27   private TermDocs termDocs;
28   private byte[] norms;
29   private float weightValue;
30   private int doc;
31
32   private final int[] docs = new int[32]; // buffered doc numbers
33
private final int[] freqs = new int[32]; // buffered term freqs
34
private int pointer;
35   private int pointerMax;
36
37   private static final int SCORE_CACHE_SIZE = 32;
38   private float[] scoreCache = new float[SCORE_CACHE_SIZE];
39
40   /** Construct a <code>TermScorer</code>.
41    * @param weight The weight of the <code>Term</code> in the query.
42    * @param td An iterator over the documents matching the <code>Term</code>.
43    * @param similarity The </code>Similarity</code> implementation to be used for score computations.
44    * @param norms The field norms of the document fields for the <code>Term</code>.
45    */

46   TermScorer(Weight weight, TermDocs td, Similarity similarity,
47              byte[] norms) {
48     super(similarity);
49     this.weight = weight;
50     this.termDocs = td;
51     this.norms = norms;
52     this.weightValue = weight.getValue();
53
54     for (int i = 0; i < SCORE_CACHE_SIZE; i++)
55       scoreCache[i] = getSimilarity().tf(i) * weightValue;
56   }
57
58   public void score(HitCollector hc) throws IOException JavaDoc {
59     next();
60     score(hc, Integer.MAX_VALUE);
61   }
62
63   protected boolean score(HitCollector c, int end) throws IOException JavaDoc {
64     Similarity similarity = getSimilarity(); // cache sim in local
65
float[] normDecoder = Similarity.getNormDecoder();
66     while (doc < end) { // for docs in window
67
int f = freqs[pointer];
68       float score = // compute tf(f)*weight
69
f < SCORE_CACHE_SIZE // check cache
70
? scoreCache[f] // cache hit
71
: similarity.tf(f)*weightValue; // cache miss
72

73       score *= normDecoder[norms[doc] & 0xFF]; // normalize for field
74

75       c.collect(doc, score); // collect score
76

77       if (++pointer >= pointerMax) {
78         pointerMax = termDocs.read(docs, freqs); // refill buffers
79
if (pointerMax != 0) {
80           pointer = 0;
81         } else {
82           termDocs.close(); // close stream
83
doc = Integer.MAX_VALUE; // set to sentinel value
84
return false;
85         }
86       }
87       doc = docs[pointer];
88     }
89     return true;
90   }
91
92   /** Returns the current document number matching the query.
93    * Initially invalid, until {@link #next()} is called the first time.
94    */

95   public int doc() { return doc; }
96
97   /** Advances to the next document matching the query.
98    * <br>The iterator over the matching documents is buffered using
99    * {@link TermDocs#read(int[],int[])}.
100    * @return true iff there is another document matching the query.
101    */

102   public boolean next() throws IOException JavaDoc {
103     pointer++;
104     if (pointer >= pointerMax) {
105       pointerMax = termDocs.read(docs, freqs); // refill buffer
106
if (pointerMax != 0) {
107         pointer = 0;
108       } else {
109         termDocs.close(); // close stream
110
doc = Integer.MAX_VALUE; // set to sentinel value
111
return false;
112       }
113     }
114     doc = docs[pointer];
115     return true;
116   }
117
118   public float score() {
119     int f = freqs[pointer];
120     float raw = // compute tf(f)*weight
121
f < SCORE_CACHE_SIZE // check cache
122
? scoreCache[f] // cache hit
123
: getSimilarity().tf(f)*weightValue; // cache miss
124

125     return raw * Similarity.decodeNorm(norms[doc]); // normalize for field
126
}
127
128   /** Skips to the first match beyond the current whose document number is
129    * greater than or equal to a given target.
130    * <br>The implementation uses {@link TermDocs#skipTo(int)}.
131    * @param target The target document number.
132    * @return true iff there is such a match.
133    */

134   public boolean skipTo(int target) throws IOException JavaDoc {
135     // first scan in cache
136
for (pointer++; pointer < pointerMax; pointer++) {
137       if (docs[pointer] >= target) {
138         doc = docs[pointer];
139         return true;
140       }
141     }
142
143     // not found in cache, seek underlying stream
144
boolean result = termDocs.skipTo(target);
145     if (result) {
146       pointerMax = 1;
147       pointer = 0;
148       docs[pointer] = doc = termDocs.doc();
149       freqs[pointer] = termDocs.freq();
150     } else {
151       doc = Integer.MAX_VALUE;
152     }
153     return result;
154   }
155
156   /** Returns an explanation of the score for a document.
157    * <br>When this method is used, the {@link #next()} method
158    * and the {@link #score(HitCollector)} method should not be used.
159    * @param doc The document number for the explanation.
160    * @todo Modify to make use of {@link TermDocs#skipTo(int)}.
161    */

162   public Explanation explain(int doc) throws IOException JavaDoc {
163     TermQuery query = (TermQuery)weight.getQuery();
164     Explanation tfExplanation = new Explanation();
165     int tf = 0;
166     while (pointer < pointerMax) {
167       if (docs[pointer] == doc)
168         tf = freqs[pointer];
169       pointer++;
170     }
171     if (tf == 0) {
172       while (termDocs.next()) {
173         if (termDocs.doc() == doc) {
174           tf = termDocs.freq();
175         }
176       }
177     }
178     termDocs.close();
179     tfExplanation.setValue(getSimilarity().tf(tf));
180     tfExplanation.setDescription("tf(termFreq("+query.getTerm()+")="+tf+")");
181     
182     return tfExplanation;
183   }
184
185   /** Returns a string representation of this <code>TermScorer</code>. */
186   public String JavaDoc toString() { return "scorer(" + weight + ")"; }
187 }
188
Popular Tags