blob: fcc25a61e554a83842cfb270ba039af8d47bec3a [file] [log] [blame]
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();
}
}