| 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 java.util.*; |
| |
| /** Scorer for conjunctions, sets of queries, all of which are required. */ |
| final class ConjunctionScorer extends Scorer { |
| private LinkedList scorers = new LinkedList(); |
| private boolean firstTime = true; |
| private boolean more = true; |
| private float coord; |
| |
| public ConjunctionScorer(Similarity similarity) { |
| super(similarity); |
| } |
| |
| final void add(Scorer scorer) throws IOException { |
| scorers.addLast(scorer); |
| } |
| |
| private Scorer first() { return (Scorer)scorers.getFirst(); } |
| private Scorer last() { return (Scorer)scorers.getLast(); } |
| |
| public int doc() { return first().doc(); } |
| |
| public boolean next() throws IOException { |
| if (firstTime) { |
| init(); |
| } else if (more) { |
| more = last().next(); // trigger further scanning |
| } |
| return doNext(); |
| } |
| |
| private boolean doNext() throws IOException { |
| while (more && first().doc() < last().doc()) { // find doc w/ all clauses |
| more = first().skipTo(last().doc()); // skip first upto last |
| scorers.addLast(scorers.removeFirst()); // move first to last |
| } |
| return more; // found a doc with all clauses |
| } |
| |
| public boolean skipTo(int target) throws IOException { |
| Iterator i = scorers.iterator(); |
| while (more && i.hasNext()) { |
| more = ((Scorer)i.next()).skipTo(target); |
| } |
| if (more) |
| sortScorers(); // re-sort scorers |
| return doNext(); |
| } |
| |
| public float score() throws IOException { |
| float score = 0.0f; // sum scores |
| Iterator i = scorers.iterator(); |
| while (i.hasNext()) |
| score += ((Scorer)i.next()).score(); |
| score *= coord; |
| return score; |
| } |
| |
| private void init() throws IOException { |
| more = scorers.size() > 0; |
| |
| // compute coord factor |
| coord = getSimilarity().coord(scorers.size(), scorers.size()); |
| |
| // move each scorer to its first entry |
| Iterator i = scorers.iterator(); |
| while (more && i.hasNext()) { |
| more = ((Scorer)i.next()).next(); |
| } |
| if (more) |
| sortScorers(); // initial sort of list |
| |
| firstTime = false; |
| } |
| |
| private void sortScorers() throws IOException { |
| // move scorers to an array |
| Scorer[] array = (Scorer[])scorers.toArray(new Scorer[scorers.size()]); |
| scorers.clear(); // empty the list |
| |
| // note that this comparator is not consistent with equals! |
| Arrays.sort(array, new Comparator() { // sort the array |
| public int compare(Object o1, Object o2) { |
| return ((Scorer)o1).doc() - ((Scorer)o2).doc(); |
| } |
| public boolean equals(Object o1, Object o2) { |
| return ((Scorer)o1).doc() == ((Scorer)o2).doc(); |
| } |
| }); |
| |
| for (int i = 0; i < array.length; i++) { |
| scorers.addLast(array[i]); // re-build list, now sorted |
| } |
| } |
| |
| public Explanation explain(int doc) throws IOException { |
| throw new UnsupportedOperationException(); |
| } |
| |
| } |