PhraseScorer.java
001 package gate.creole.annic.apache.lucene.search;
002 
003 /**
004  * Copyright 2004 The Apache Software Foundation
005  *
006  * Licensed under the Apache License, Version 2.0 (the "License");
007  * you may not use this file except in compliance with the License.
008  * You may obtain a copy of the License at
009  *
010  *     http://www.apache.org/licenses/LICENSE-2.0
011  *
012  * Unless required by applicable law or agreed to in writing, software
013  * distributed under the License is distributed on an "AS IS" BASIS,
014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015  * See the License for the specific language governing permissions and
016  * limitations under the License.
017  */
018 
019 import java.io.IOException;
020 
021 import gate.creole.annic.apache.lucene.index.*;
022 
023 abstract class PhraseScorer extends Scorer {
024   private Weight weight;
025   protected byte[] norms;
026   protected float value;
027 
028   private boolean firstTime = true;
029   private boolean more = true;
030   protected PhraseQueue pq;
031   protected PhrasePositions first, last;
032 
033   private float freq;
034   
035   PhraseScorer(Weight weight, TermPositions[] tps, java.util.Vector positions, Similarity similarity,
036                byte[] norms, Searcher searcherthrows IOException {
037     super(similarity);
038     this.norms = norms;
039     this.weight = weight;
040     this.value = weight.getValue();
041     this.searcher = searcher;
042 
043     // convert tps to a list
044     for (int i = 0; i < tps.length; i++) {
045       PhrasePositions pp = new PhrasePositions(tps[i]((Integer)positions.get(i)).intValue());
046       if (last != null) {        // add next to end of list
047         last.next = pp;
048       else
049         first = pp;
050 
051       last = pp;
052     }
053 
054     pq = new PhraseQueue(tps.length);             // construct empty pq
055 
056   }
057 
058   PhraseScorer(Weight weight, TermPositions[] tps, Similarity similarity,
059                byte[] normsthrows IOException {
060     super(similarity);
061     this.norms = norms;
062     this.weight = weight;
063     this.value = weight.getValue();
064 
065     // convert tps to a list
066     for (int i = 0; i < tps.length; i++) {
067       PhrasePositions pp = new PhrasePositions(tps[i], i);
068       if (last != null) {        // add next to end of list
069         last.next = pp;
070       else
071         first = pp;
072 
073       last = pp;
074     }
075 
076     pq = new PhraseQueue(tps.length);             // construct empty pq
077 
078   }
079 
080   public int doc() { return first.doc; }
081 
082   public boolean next(Searcher searcherthrows IOException {
083     this.searcher = searcher;
084     if (firstTime) {
085       init();
086       firstTime = false;
087     else if (more) {
088       more = last.next();                         // trigger further scanning
089     }
090     return doNext();
091   }
092 
093   // next without initial increment
094   private boolean doNext() throws IOException {
095     while (more) {
096       while (more && first.doc < last.doc) {      // find doc w/ all the terms
097         more = first.skipTo(last.doc);            // skip first upto last
098         firstToLast();                            // and move it to the end
099       }
100 
101       if (more) {
102         // found a doc with all of the terms
103         freq = phraseFreq();                      // check for phrase
104         if (freq == 0.0f)                         // no match
105           more = last.next();                     // trigger further scanning
106         else
107           return true;                            // found a match
108       }
109     }
110     return false;                                 // no more matches
111   }
112 
113   public float score(Searcher searcherthrows IOException {
114     this.searcher = searcher;
115     float raw = getSimilarity().tf(freq* value; // raw score
116     return raw * Similarity.decodeNorm(norms[first.doc])// normalize
117   }
118 
119   public boolean skipTo(int targetthrows IOException {
120     for (PhrasePositions pp = first; more && pp != null; pp = pp.next) {
121       more = pp.skipTo(target);
122     }
123     if (more)
124       sort();                                     // re-sort
125     return doNext();
126   }
127 
128   protected abstract float phraseFreq() throws IOException;
129 
130   private void init() throws IOException {
131     for (PhrasePositions pp = first; more && pp != null; pp = pp.next)
132       more = pp.next();
133     if(more)
134       sort();
135   }
136 
137   private void sort() {
138     pq.clear();
139     for (PhrasePositions pp = first; pp != null; pp = pp.next)
140       pq.put(pp);
141     pqToList();
142   }
143 
144   protected final void pqToList() {
145     last = first = null;
146     while (pq.top() != null) {
147       PhrasePositions pp = (PhrasePositionspq.pop();
148       if (last != null) {        // add next to end of list
149         last.next = pp;
150       else
151         first = pp;
152       last = pp;
153       pp.next = null;
154     }
155   }
156 
157   protected final void firstToLast() {
158     last.next = first;        // move first to end of list
159     last = first;
160     first = first.next;
161     last.next = null;
162   }
163 
164   public Explanation explain(final int docthrows IOException {
165     Explanation tfExplanation = new Explanation();
166 
167     while (next(this.searcher&& doc() < doc) {}
168 
169     float phraseFreq = (doc() == doc? freq : 0.0f;
170     tfExplanation.setValue(getSimilarity().tf(phraseFreq));
171     tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")");
172 
173     return tfExplanation;
174   }
175 
176   public String toString() { return "scorer(" + weight + ")"}
177 
178 }