/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ using System; using Lucene.Net.Index; namespace Lucene.Net.Search { abstract class PhraseScorer : Scorer { private Weight weight; protected internal byte[] norms; protected internal float value_Renamed; private bool firstTime = true; private bool more = true; protected internal PhraseQueue pq; protected internal PhrasePositions first, last; private float freq; internal PhraseScorer(Weight weight, TermPositions[] tps, int[] positions, Similarity similarity, byte[] norms) : base(similarity) { this.norms = norms; this.weight = weight; this.value_Renamed = 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 override int Doc() { return first.doc; } public override bool Next() { if (firstTime) { Init(); firstTime = false; } else if (more) { more = last.Next(); // trigger further scanning } return DoNext(); } // next without initial increment private bool DoNext() { 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 override float Score() { //System.out.println("scoring " + first.doc); float raw = GetSimilarity().Tf(freq) * value_Renamed; // raw score return raw * Similarity.DecodeNorm(norms[first.doc]); // normalize } public override bool SkipTo(int target) { for (PhrasePositions pp = first; more && pp != null; pp = pp.next) { more = pp.SkipTo(target); } if (more) Sort(); // re-sort return DoNext(); } protected internal abstract float PhraseFreq(); private void Init() { 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 internal 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 internal void FirstToLast() { last.next = first; // move first to end of list last = first; first = first.next; last.next = null; } public override Explanation Explain(int doc) { 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 override System.String ToString() { return "scorer(" + weight + ")"; } } }