| package org.apache.lucene.search; |
| |
| /** |
| * Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import java.io.IOException; |
| |
| import org.apache.lucene.index.*; |
| |
| abstract class PhraseScorer extends Scorer { |
| private Weight weight; |
| protected byte[] norms; |
| protected float value; |
| |
| private boolean firstTime = true; |
| private boolean more = true; |
| protected PhraseQueue pq; |
| protected PhrasePositions first, last; |
| |
| private float freq; |
| |
| |
| PhraseScorer(Weight weight, TermPositions[] tps, int[] positions, Similarity similarity, |
| byte[] norms) { |
| super(similarity); |
| this.norms = norms; |
| this.weight = weight; |
| this.value = weight.getValue(); |
| |
| // convert tps to a list |
| for (int i = 0; i < tps.length; i++) { |
| PhrasePositions pp = new PhrasePositions(tps[i], positions[i]); |
| if (last != null) { // add next to end of list |
| last.next = pp; |
| } else |
| first = pp; |
| last = pp; |
| } |
| |
| pq = new PhraseQueue(tps.length); // construct empty pq |
| |
| } |
| |
| public int doc() { return first.doc; } |
| |
| public boolean next() throws IOException { |
| if (firstTime) { |
| init(); |
| firstTime = false; |
| } else if (more) { |
| more = last.next(); // trigger further scanning |
| } |
| return doNext(); |
| } |
| |
| // next without initial increment |
| private boolean doNext() throws IOException { |
| while (more) { |
| while (more && first.doc < last.doc) { // find doc w/ all the terms |
| more = first.skipTo(last.doc); // skip first upto last |
| firstToLast(); // and move it to the end |
| } |
| |
| if (more) { |
| // found a doc with all of the terms |
| freq = phraseFreq(); // check for phrase |
| if (freq == 0.0f) // no match |
| more = last.next(); // trigger further scanning |
| else |
| return true; // found a match |
| } |
| } |
| return false; // no more matches |
| } |
| |
| public float score() throws IOException { |
| //System.out.println("scoring " + first.doc); |
| float raw = getSimilarity().tf(freq) * value; // raw score |
| return raw * Similarity.decodeNorm(norms[first.doc]); // normalize |
| } |
| |
| public boolean skipTo(int target) throws IOException { |
| for (PhrasePositions pp = first; more && pp != null; pp = pp.next) { |
| more = pp.skipTo(target); |
| } |
| if (more) |
| sort(); // re-sort |
| return doNext(); |
| } |
| |
| protected abstract float phraseFreq() throws IOException; |
| |
| private void init() throws IOException { |
| for (PhrasePositions pp = first; more && pp != null; pp = pp.next) |
| more = pp.next(); |
| if(more) |
| sort(); |
| } |
| |
| private void sort() { |
| pq.clear(); |
| for (PhrasePositions pp = first; pp != null; pp = pp.next) |
| pq.put(pp); |
| pqToList(); |
| } |
| |
| protected final void pqToList() { |
| last = first = null; |
| while (pq.top() != null) { |
| PhrasePositions pp = (PhrasePositions) pq.pop(); |
| if (last != null) { // add next to end of list |
| last.next = pp; |
| } else |
| first = pp; |
| last = pp; |
| pp.next = null; |
| } |
| } |
| |
| protected final void firstToLast() { |
| last.next = first; // move first to end of list |
| last = first; |
| first = first.next; |
| last.next = null; |
| } |
| |
| public Explanation explain(final int doc) throws IOException { |
| Explanation tfExplanation = new Explanation(); |
| |
| while (next() && doc() < doc) {} |
| |
| float phraseFreq = (doc() == doc) ? freq : 0.0f; |
| tfExplanation.setValue(getSimilarity().tf(phraseFreq)); |
| tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")"); |
| |
| return tfExplanation; |
| } |
| |
| public String toString() { return "scorer(" + weight + ")"; } |
| |
| } |