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 import java.util.*;
021
022 /** Scorer for conjunctions, sets of queries, all of which are required. */
023 final class ConjunctionScorer extends Scorer {
024 private LinkedList scorers = new LinkedList();
025 private boolean firstTime = true;
026 private boolean more = true;
027 private float coord;
028
029 public ConjunctionScorer(Similarity similarity) {
030 super(similarity);
031 }
032
033 final void add(Scorer scorer) throws IOException {
034 scorers.addLast(scorer);
035 }
036
037 private Scorer first() { return (Scorer)scorers.getFirst(); }
038 private Scorer last() { return (Scorer)scorers.getLast(); }
039
040 public int doc() { return first().doc(); }
041
042 public boolean next(Searcher searcher) throws IOException {
043 this.searcher = searcher;
044 if (firstTime) {
045 init();
046 } else if (more) {
047 more = last().next(this.searcher); // trigger further scanning
048 }
049 return doNext();
050 }
051
052 private boolean doNext() throws IOException {
053 while (more && first().doc() < last().doc()) { // find doc w/ all clauses
054 more = first().skipTo(last().doc()); // skip first upto last
055 scorers.addLast(scorers.removeFirst()); // move first to last
056 }
057 return more; // found a doc with all clauses
058 }
059
060 public boolean skipTo(int target) throws IOException {
061 Iterator i = scorers.iterator();
062 while (more && i.hasNext()) {
063 more = ((Scorer)i.next()).skipTo(target);
064 }
065 if (more)
066 sortScorers(); // re-sort scorers
067 return doNext();
068 }
069
070 public float score(Searcher searcher) throws IOException {
071 this.searcher = searcher;
072 float score = 0.0f; // sum scores
073 Iterator i = scorers.iterator();
074 while (i.hasNext())
075 score += ((Scorer)i.next()).score(this.searcher);
076 score *= coord;
077 return score;
078 }
079
080 private void init() throws IOException {
081 more = scorers.size() > 0;
082
083 // compute coord factor
084 coord = getSimilarity().coord(scorers.size(), scorers.size());
085
086 // move each scorer to its first entry
087 Iterator i = scorers.iterator();
088 while (more && i.hasNext()) {
089 more = ((Scorer)i.next()).next(this.searcher);
090 }
091 if (more)
092 sortScorers(); // initial sort of list
093
094 firstTime = false;
095 }
096
097 private void sortScorers() throws IOException {
098 // move scorers to an array
099 Scorer[] array = (Scorer[])scorers.toArray(new Scorer[scorers.size()]);
100 scorers.clear(); // empty the list
101
102 // note that this comparator is not consistent with equals!
103 Arrays.sort(array, new Comparator() { // sort the array
104 public int compare(Object o1, Object o2) {
105 return ((Scorer)o1).doc() - ((Scorer)o2).doc();
106 }
107 public boolean equals(Object o1, Object o2) {
108 return ((Scorer)o1).doc() == ((Scorer)o2).doc();
109 }
110 });
111
112 for (int i = 0; i < array.length; i++) {
113 scorers.addLast(array[i]); // re-build list, now sorted
114 }
115 }
116
117 public Explanation explain(int doc) throws IOException {
118 throw new UnsupportedOperationException();
119 }
120
121 }
|