Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 780809) +++ CHANGES.txt (working copy) @@ -27,12 +27,12 @@ implement Searchable or extend Searcher, you should change you code to implement this method. If you already extend IndexSearcher, no further changes are needed to use Collector. - - Finally, the values Float.Nan, Float.NEGATIVE_INFINITY and + + Finally, the values Float.NaN, Float.NEGATIVE_INFINITY and Float.POSITIVE_INFINITY are not valid scores. Lucene uses these values internally in certain places, so if you have hits with such scores it will cause problems. (Shai Erera via Mike McCandless) - + Changes in runtime behavior 1. LUCENE-1424: QueryParser now by default uses constant score query @@ -158,6 +158,18 @@ to pick a good default FSDirectory implementation given the OS. (Michael McCandless, Uwe Schindler) +16. LUCENE-1614: DocIdSetIterator's next() and skipTo() were deprecated in favor + of the new nextDoc() and advance(). The new methods return the doc Id they + landed on, saving an extra call to doc() in most cases. + For easy migration of the code, you can change the calls to next() to + nextDoc() != DocIdSetIterator.NO_MORE_DOCS and similarly for skipTo(). + However it is advised that you take advantage of the returned doc ID and not + call doc() following those two. + Also, doc() was deprecated in favor of docID(). docID() should return -1 or + NO_MORE_DOCS if nextDoc/advance were not called yet, or NO_MORE_DOCS if the + iterator has exhausted. Otherwise it should return the current doc ID. + (Shai Erera via Mike McCandless) + Bug fixes 1. LUCENE-1415: MultiPhraseQuery has incorrect hashCode() and equals() Index: contrib/miscellaneous/src/test/org/apache/lucene/misc/ChainedFilterTest.java =================================================================== --- contrib/miscellaneous/src/test/org/apache/lucene/misc/ChainedFilterTest.java (revision 780809) +++ contrib/miscellaneous/src/test/org/apache/lucene/misc/ChainedFilterTest.java (working copy) @@ -20,16 +20,12 @@ import junit.framework.TestCase; import java.util.*; import java.io.IOException; -import java.text.ParseException; -import java.text.SimpleDateFormat; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.index.IndexWriter.MaxFieldLength; import org.apache.lucene.store.Directory; -import org.apache.lucene.store.FSDirectory; -import org.apache.lucene.store.NoLockFactory; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.WhitespaceAnalyzer; @@ -77,7 +73,7 @@ query = bq; // date filter matches everything too - Date pastTheEnd = parseDate("2099 Jan 1"); + //Date pastTheEnd = parseDate("2099 Jan 1"); // dateFilter = DateFilter.Before("date", pastTheEnd); // just treat dates as strings and select the whole range for now... dateFilter = new RangeFilter("date","","ZZZZ",true,true); @@ -94,15 +90,17 @@ final Filter f = chain[i]; // create old BitSet-based Filter as wrapper oldFilters[i] = new Filter() { + /** @deprecated */ public BitSet bits(IndexReader reader) throws IOException { BitSet bits = new BitSet(reader.maxDoc()); - DocIdSetIterator it = f.getDocIdSet(reader).iterator(); - while(it.next()) { - bits.set(it.doc()); + DocIdSetIterator it = f.getDocIdSet(reader).iterator(); + int doc; + while((doc = it.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + bits.set(doc); } return bits; } - }; + }; } return oldFilters; } @@ -211,37 +209,36 @@ } } + /* private Date parseDate(String s) throws ParseException { return new SimpleDateFormat("yyyy MMM dd", Locale.US).parse(s); } + */ public void testWithCachingFilter() throws Exception { - for (int mode = 0; mode < 2; mode++) { - boolean old = (mode==0); - Directory dir = new RAMDirectory(); - Analyzer analyzer = new WhitespaceAnalyzer(); + Directory dir = new RAMDirectory(); + Analyzer analyzer = new WhitespaceAnalyzer(); - IndexWriter writer = new IndexWriter(dir, analyzer, true, MaxFieldLength.LIMITED); - writer.close(); + IndexWriter writer = new IndexWriter(dir, analyzer, true, MaxFieldLength.LIMITED); + writer.close(); - Searcher searcher = new IndexSearcher(dir); + Searcher searcher = new IndexSearcher(dir); - Query query = new TermQuery(new Term("none", "none")); + Query query = new TermQuery(new Term("none", "none")); - QueryWrapperFilter queryFilter = new QueryWrapperFilter(query); - CachingWrapperFilter cachingFilter = new CachingWrapperFilter(queryFilter); + QueryWrapperFilter queryFilter = new QueryWrapperFilter(query); + CachingWrapperFilter cachingFilter = new CachingWrapperFilter(queryFilter); - searcher.search(query, cachingFilter, 1); + searcher.search(query, cachingFilter, 1); - CachingWrapperFilter cachingFilter2 = new CachingWrapperFilter(queryFilter); - Filter[] chain = new Filter[2]; - chain[0] = cachingFilter; - chain[1] = cachingFilter2; - ChainedFilter cf = new ChainedFilter(chain); + CachingWrapperFilter cachingFilter2 = new CachingWrapperFilter(queryFilter); + Filter[] chain = new Filter[2]; + chain[0] = cachingFilter; + chain[1] = cachingFilter2; + ChainedFilter cf = new ChainedFilter(chain); - // throws java.lang.ClassCastException: org.apache.lucene.util.OpenBitSet cannot be cast to java.util.BitSet - searcher.search(new MatchAllDocsQuery(), cf, 1); - } + // throws java.lang.ClassCastException: org.apache.lucene.util.OpenBitSet cannot be cast to java.util.BitSet + searcher.search(new MatchAllDocsQuery(), cf, 1); } } Index: src/java/org/apache/lucene/index/DocumentsWriter.java =================================================================== --- src/java/org/apache/lucene/index/DocumentsWriter.java (revision 780809) +++ src/java/org/apache/lucene/index/DocumentsWriter.java (working copy) @@ -991,11 +991,11 @@ int limit = ((Integer) entry.getValue()).intValue(); Weight weight = query.weight(searcher); Scorer scorer = weight.scorer(reader); - while(scorer.next()) { - final int docID = scorer.doc(); - if (docIDStart + docID >= limit) + while(true) { + int doc = scorer.nextDoc(); + if (((long) docIDStart) + doc >= limit) break; - reader.deleteDocument(docID); + reader.deleteDocument(doc); any = true; } } Index: src/java/org/apache/lucene/search/BooleanQuery.java =================================================================== --- src/java/org/apache/lucene/search/BooleanQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/BooleanQuery.java (working copy) @@ -217,13 +217,15 @@ } } - /** @return Returns BooleanScorer2 that uses and provides skipTo(), - * and scores documents in document number order. + /** + * @return Returns BooleanScorer2 that uses and provides advance(), and + * scores documents in document number order. */ public Scorer scorer(IndexReader reader) throws IOException { // TODO (3.0): instantiate either BS or BS2, according to // allowDocsOutOfOrder (basically, try to inline BS2.score(Collector)'s // logic. + BooleanScorer2 result = new BooleanScorer2(similarity, minNrShouldMatch, allowDocsOutOfOrder); Index: src/java/org/apache/lucene/search/BooleanScorer.java =================================================================== --- src/java/org/apache/lucene/search/BooleanScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/BooleanScorer.java (working copy) @@ -18,8 +18,11 @@ */ import java.io.IOException; +import java.util.Iterator; +import java.util.List; import org.apache.lucene.index.IndexReader; + /* Description from Doug Cutting (excerpted from * LUCENE-1483): * @@ -54,30 +57,105 @@ * updates for the optional terms. */ final class BooleanScorer extends Scorer { - private SubScorer scorers = null; - private BucketTable bucketTable = new BucketTable(); + + private static final class BooleanScorerCollector extends Collector { + private BucketTable bucketTable; + private int mask; + private Scorer scorer; + + public BooleanScorerCollector(int mask, BucketTable bucketTable) { + this.mask = mask; + this.bucketTable = bucketTable; + } + public final void collect(final int doc) throws IOException { + final BucketTable table = bucketTable; + final int i = doc & BucketTable.MASK; + Bucket bucket = table.buckets[i]; + if (bucket == null) + table.buckets[i] = bucket = new Bucket(); + + if (bucket.doc != doc) { // invalid bucket + bucket.doc = doc; // set doc + bucket.score = scorer.score(); // initialize score + bucket.bits = mask; // initialize mask + bucket.coord = 1; // initialize coord - private int maxCoord = 1; - private float[] coordFactors = null; + bucket.next = table.first; // push onto valid list + table.first = bucket; + } else { // valid bucket + bucket.score += scorer.score(); // increment score + bucket.bits |= mask; // add bits in mask + bucket.coord++; // increment coord + } + } + + public void setNextReader(IndexReader reader, int docBase) { + // not needed by this implementation + } + public void setScorer(Scorer scorer) throws IOException { + this.scorer = scorer; + } + } + + // An internal class which is used in score(Collector, int) for setting the + // current score. This is required since Collector exposes a setScorer method + // and implementations that need the score will call scorer.score(). + // Therefore the only methods that are implemented are score() and doc(). + private static final class BucketScorer extends Scorer { - private int requiredMask = 0; - private int prohibitedMask = 0; - private int nextMask = 1; + float score; + int doc = NO_MORE_DOCS; + + public BucketScorer() { super(null); } + + public int advance(int target) throws IOException { return NO_MORE_DOCS; } - private final int minNrShouldMatch; + /** @deprecated use {@link #docID()} instead. */ + public int doc() { return doc; } - BooleanScorer(Similarity similarity) { - this(similarity, 1); + public int docID() { return doc; } + + public Explanation explain(int doc) throws IOException { return null; } + + /** @deprecated use {@link #nextDoc()} instead. */ + public boolean next() throws IOException { return false; } + + public int nextDoc() throws IOException { return NO_MORE_DOCS; } + + public float score() throws IOException { return score; } + + /** @deprecated use {@link #advance(int)} instead. */ + public boolean skipTo(int target) throws IOException { return false; } + } - - BooleanScorer(Similarity similarity, int minNrShouldMatch) { - super(similarity); - this.minNrShouldMatch = minNrShouldMatch; + + static final class Bucket { + int doc = -1; // tells if bucket is valid + float score; // incremental score + int bits; // used for bool constraints + int coord; // count of terms in score + Bucket next; // next valid bucket } + /** A simple hash table of document scores within a range. */ + static final class BucketTable { + public static final int SIZE = 1 << 11; + public static final int MASK = SIZE - 1; + + final Bucket[] buckets = new Bucket[SIZE]; + Bucket first = null; // head of valid list + + public BucketTable() {} + + public Collector newCollector(int mask) { + return new BooleanScorerCollector(mask, this); + } + + public final int size() { return SIZE; } + } + static final class SubScorer { public Scorer scorer; - public boolean done; public boolean required = false; public boolean prohibited = false; public Collector collector; @@ -87,41 +165,52 @@ Collector collector, SubScorer next) throws IOException { this.scorer = scorer; - this.done = !scorer.next(); this.required = required; this.prohibited = prohibited; this.collector = collector; this.next = next; } } + + private SubScorer scorers = null; + private BucketTable bucketTable = new BucketTable(); + private int maxCoord = 1; + private final float[] coordFactors; + private int requiredMask = 0; + private int prohibitedMask = 0; + private int nextMask = 1; + private final int minNrShouldMatch; + private int end; + private Bucket current; + private int doc = -1; - final void add(Scorer scorer, boolean required, boolean prohibited) - throws IOException { - int mask = 0; - if (required || prohibited) { - if (nextMask == 0) { - throw new IndexOutOfBoundsException( - "More than 32 required/prohibited clauses in query."); + BooleanScorer(Similarity similarity, int minNrShouldMatch, + List optionalScorers, List prohibitedScorers) throws IOException { + super(similarity); + this.minNrShouldMatch = minNrShouldMatch; + + if (optionalScorers != null && optionalScorers.size() > 0) { + for (Iterator si = optionalScorers.iterator(); si.hasNext();) { + Scorer scorer = (Scorer) si.next(); + maxCoord++; + if (scorer.nextDoc() != NO_MORE_DOCS) { + scorers = new SubScorer(scorer, false, false, bucketTable.newCollector(0), scorers); + } } - mask = nextMask; - nextMask = nextMask << 1; } - - if (!prohibited) { - maxCoord++; - if (required) { - requiredMask |= mask; // update required mask + + if (prohibitedScorers != null && prohibitedScorers.size() > 0) { + for (Iterator si = prohibitedScorers.iterator(); si.hasNext();) { + Scorer scorer = (Scorer) si.next(); + int mask = nextMask; + nextMask = nextMask << 1; + prohibitedMask |= mask; // update prohibited mask + if (scorer.nextDoc() != NO_MORE_DOCS) { + scorers = new SubScorer(scorer, false, true, bucketTable.newCollector(mask), scorers); + } } - } else { - // prohibited - prohibitedMask |= mask; // update prohibited mask } - scorers = new SubScorer(scorer, required, prohibited, - bucketTable.newCollector(mask), scorers); - } - - private final void computeCoordFactors() { coordFactors = new float[maxCoord]; Similarity sim = getSimilarity(); for (int i = 0; i < maxCoord; i++) { @@ -129,31 +218,10 @@ } } - private int end; - private Bucket current; - - /** @deprecated use {@link #score(Collector)} instead. */ - public void score(HitCollector hc) throws IOException { - score(new HitCollectorWrapper(hc)); - } - - public void score(Collector collector) throws IOException { - next(); - score(collector, Integer.MAX_VALUE); - } - - /** @deprecated use {@link #score(Collector, int)} instead. */ - protected boolean score(HitCollector hc, int max) throws IOException { - return score(new HitCollectorWrapper(hc), max); - } - - protected boolean score(Collector collector, int max) throws IOException { - if (coordFactors == null) { - computeCoordFactors(); - } + // firstDocID is ignored since nextDoc() initializes 'current' + protected boolean score(Collector collector, int max, int firstDocID) throws IOException { boolean more; Bucket tmp; - BucketScorer bs = new BucketScorer(); // The internal loop will set the score and doc before calling collect. collector.setScorer(bs); @@ -194,10 +262,9 @@ more = false; end += BucketTable.SIZE; for (SubScorer sub = scorers; sub != null; sub = sub.next) { - if (!sub.done) { - sub.done = !sub.scorer.score(sub.collector, end); - if (!sub.done) - more = true; + int subScorerDocID = sub.scorer.docID(); + if (subScorerDocID != NO_MORE_DOCS) { + more |= sub.scorer.score(sub.collector, end, subScorerDocID); } } current = bucketTable.first; @@ -207,9 +274,32 @@ return false; } + /** @deprecated use {@link #score(Collector, int)} instead. */ + protected boolean score(HitCollector hc, int max) throws IOException { + return score(new HitCollectorWrapper(hc), max, docID()); + } + + public int advance(int target) throws IOException { + throw new UnsupportedOperationException(); + } + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return current.doc; } + + public int docID() { + return doc; + } + public Explanation explain(int doc) { + throw new UnsupportedOperationException(); + } + + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { boolean more; do { while (bucketTable.first != null) { // more queued @@ -220,7 +310,7 @@ if ((current.bits & prohibitedMask) == 0 && (current.bits & requiredMask) == requiredMask && current.coord >= minNrShouldMatch) { - return true; + return doc = current.doc; } } @@ -230,134 +320,36 @@ for (SubScorer sub = scorers; sub != null; sub = sub.next) { Scorer scorer = sub.scorer; sub.collector.setScorer(scorer); - while (!sub.done && scorer.doc() < end) { - sub.collector.collect(scorer.doc()); - sub.done = !scorer.next(); + int doc = scorer.docID(); + while (doc < end) { + sub.collector.collect(doc); + doc = scorer.nextDoc(); } - if (!sub.done) { - more = true; - } + more |= (doc != NO_MORE_DOCS); } } while (bucketTable.first != null || more); - return false; + return doc = NO_MORE_DOCS; } public float score() { - if (coordFactors == null) { - computeCoordFactors(); - } return current.score * coordFactors[current.coord]; } - static final class Bucket { - int doc = -1; // tells if bucket is valid - float score; // incremental score - int bits; // used for bool constraints - int coord; // count of terms in score - Bucket next; // next valid bucket + public void score(Collector collector) throws IOException { + score(collector, Integer.MAX_VALUE, nextDoc()); } - // An internal class which is used in score(Collector, int) for setting the - // current score. This is required since Collector exposes a setScorer method - // and implementations that need the score will call scorer.score(). - // Therefore the only methods that are implemented are score() and doc(). - private static final class BucketScorer extends Scorer { - - float score; - int doc; - - public BucketScorer() { - super(null); - } - - - public Explanation explain(int doc) throws IOException { - return null; - } - - public float score() throws IOException { - return score; - } - - public int doc() { - return doc; - } - - public boolean next() throws IOException { - return false; - } - - public boolean skipTo(int target) throws IOException { - return false; - } - + /** @deprecated use {@link #score(Collector)} instead. */ + public void score(HitCollector hc) throws IOException { + score(new HitCollectorWrapper(hc)); } - /** A simple hash table of document scores within a range. */ - static final class BucketTable { - public static final int SIZE = 1 << 11; - public static final int MASK = SIZE - 1; - - final Bucket[] buckets = new Bucket[SIZE]; - Bucket first = null; // head of valid list - - public BucketTable() {} - - public final int size() { return SIZE; } - - public Collector newCollector(int mask) { - return new BooleanScorerCollector(mask, this); - } - } - - private static final class BooleanScorerCollector extends Collector { - private BucketTable bucketTable; - private int mask; - private Scorer scorer; - - public BooleanScorerCollector(int mask, BucketTable bucketTable) { - this.mask = mask; - this.bucketTable = bucketTable; - } - public void setScorer(Scorer scorer) throws IOException { - this.scorer = scorer; - } - - public final void collect(final int doc) throws IOException { - final BucketTable table = bucketTable; - final int i = doc & BucketTable.MASK; - Bucket bucket = table.buckets[i]; - if (bucket == null) - table.buckets[i] = bucket = new Bucket(); - - if (bucket.doc != doc) { // invalid bucket - bucket.doc = doc; // set doc - bucket.score = scorer.score(); // initialize score - bucket.bits = mask; // initialize mask - bucket.coord = 1; // initialize coord - - bucket.next = table.first; // push onto valid list - table.first = bucket; - } else { // valid bucket - bucket.score += scorer.score(); // increment score - bucket.bits |= mask; // add bits in mask - bucket.coord++; // increment coord - } - } - public void setNextReader(IndexReader reader, int docBase) { - // not needed by this implementation - } - } - + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) { throw new UnsupportedOperationException(); } - public Explanation explain(int doc) { - throw new UnsupportedOperationException(); - } - public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("boolean("); Index: src/java/org/apache/lucene/search/BooleanScorer2.java =================================================================== --- src/java/org/apache/lucene/search/BooleanScorer2.java (revision 780809) +++ src/java/org/apache/lucene/search/BooleanScorer2.java (working copy) @@ -20,7 +20,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; -import java.util.Iterator; /* See the description in BooleanScorer.java, comparing * BooleanScorer & BooleanScorer2 */ @@ -65,6 +64,7 @@ */ private boolean allowDocsOutOfOrder; + private int doc = -1; /** Create a BooleanScorer2. * @param similarity The similarity to be used. @@ -151,7 +151,7 @@ this.scorer = scorer; } public float score() throws IOException { - int doc = doc(); + int doc = docID(); if (doc >= lastScoredDoc) { if (doc > lastScoredDoc) { lastDocScore = scorer.score(); @@ -161,15 +161,27 @@ } return lastDocScore; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return scorer.doc(); } + public int docID() { + return scorer.docID(); + } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - return scorer.next(); + return scorer.nextDoc() != NO_MORE_DOCS; } + public int nextDoc() throws IOException { + return scorer.nextDoc(); + } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int docNr) throws IOException { - return scorer.skipTo(docNr); + return scorer.advance(docNr) != NO_MORE_DOCS; } + public int advance(int target) throws IOException { + return scorer.advance(target); + } public Explanation explain(int docNr) throws IOException { return scorer.explain(docNr); } @@ -184,7 +196,7 @@ // once in score(). private float lastDocScore = Float.NaN; public float score() throws IOException { - int doc = doc(); + int doc = docID(); if (doc >= lastScoredDoc) { if (doc > lastScoredDoc) { lastDocScore = super.score(); @@ -208,7 +220,7 @@ // once in score(). private float lastDocScore = Float.NaN; public float score() throws IOException { - int doc = doc(); + int doc = docID(); if (doc >= lastScoredDoc) { if (doc > lastScoredDoc) { lastDocScore = super.score(); @@ -323,24 +335,16 @@ public void score(Collector collector) throws IOException { if (allowDocsOutOfOrder && requiredScorers.size() == 0 && prohibitedScorers.size() < 32) { - // fall back to BooleanScorer, scores documents somewhat out of order - BooleanScorer bs = new BooleanScorer(getSimilarity(), minNrShouldMatch); - Iterator si = optionalScorers.iterator(); - while (si.hasNext()) { - bs.add((Scorer) si.next(), false /* required */, false /* prohibited */); - } - si = prohibitedScorers.iterator(); - while (si.hasNext()) { - bs.add((Scorer) si.next(), false /* required */, true /* prohibited */); - } - bs.score(collector); + new BooleanScorer(getSimilarity(), minNrShouldMatch, optionalScorers, + prohibitedScorers).score(collector); } else { if (countingSumScorer == null) { initCountingSumScorer(); } collector.setScorer(this); - while (countingSumScorer.next()) { - collector.collect(countingSumScorer.doc()); + int doc; + while ((doc = countingSumScorer.nextDoc()) != NO_MORE_DOCS) { + collector.collect(doc); } } } @@ -355,60 +359,57 @@ * @deprecated use {@link #score(Collector, int)} instead. */ protected boolean score(HitCollector hc, int max) throws IOException { - return score(new HitCollectorWrapper(hc), max); + return score(new HitCollectorWrapper(hc), max, docID()); } - /** Expert: Collects matching documents in a range. - *
Note that {@link #next()} must be called once before this method is - * called for the first time. - * @param collector The collector to which all matching documents are passed through. - * @param max Do not score documents past this. - * @return true if more matching documents may remain. - */ - protected boolean score(Collector collector, int max) throws IOException { + protected boolean score(Collector collector, int max, int firstDocID) throws IOException { // null pointer exception when next() was not called before: - int docNr = countingSumScorer.doc(); + int docNr = firstDocID; collector.setScorer(this); while (docNr < max) { collector.collect(docNr); - if (!countingSumScorer.next()) { - return false; - } - docNr = countingSumScorer.doc(); + docNr = countingSumScorer.nextDoc(); } - return true; + return docNr != NO_MORE_DOCS; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return countingSumScorer.doc(); } + public int docID() { + return doc; + } + + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { if (countingSumScorer == null) { initCountingSumScorer(); } - return countingSumScorer.next(); + return doc = countingSumScorer.nextDoc(); } - + public float score() throws IOException { coordinator.nrMatchers = 0; float sum = countingSumScorer.score(); return sum * coordinator.coordFactors[coordinator.nrMatchers]; } - /** Skips to the first match beyond the current whose document number is - * greater than or equal to a given target. - * - *

When this method is used the {@link #explain(int)} method should not be used. - * - * @param target The target document number. - * @return true iff there is such a match. - */ + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { if (countingSumScorer == null) { initCountingSumScorer(); } - return countingSumScorer.skipTo(target); + return doc = countingSumScorer.advance(target); } - + /** Throws an UnsupportedOperationException. * TODO: Implement an explanation of the coordination factor. * @param doc The document number for the explanation. Index: src/java/org/apache/lucene/search/ConjunctionScorer.java =================================================================== --- src/java/org/apache/lucene/search/ConjunctionScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/ConjunctionScorer.java (working copy) @@ -24,76 +24,54 @@ /** Scorer for conjunctions, sets of queries, all of which are required. */ class ConjunctionScorer extends Scorer { + private final Scorer[] scorers; - - private boolean firstTime=true; - private boolean more; private final float coord; - private int lastDoc=-1; + private int lastDoc = -1; public ConjunctionScorer(Similarity similarity, Collection scorers) throws IOException { - this(similarity, (Scorer[])scorers.toArray(new Scorer[scorers.size()])); + this(similarity, (Scorer[]) scorers.toArray(new Scorer[scorers.size()])); } public ConjunctionScorer(Similarity similarity, Scorer[] scorers) throws IOException { super(similarity); this.scorers = scorers; - coord = getSimilarity().coord(this.scorers.length, this.scorers.length); - } - - public int doc() { return lastDoc; } - - public boolean next() throws IOException { - if (firstTime) - return init(0); - else if (more) - more = scorers[(scorers.length-1)].next(); - return doNext(); - } - - private boolean doNext() throws IOException { - int first=0; - Scorer lastScorer = scorers[scorers.length-1]; - Scorer firstScorer; - while (more && (firstScorer=scorers[first]).doc() < (lastDoc=lastScorer.doc())) { - more = firstScorer.skipTo(lastDoc); - lastScorer = firstScorer; - first = (first == (scorers.length-1)) ? 0 : first+1; + coord = similarity.coord(scorers.length, scorers.length); + + for (int i = 0; i < scorers.length; i++) { + if (scorers[i].nextDoc() == NO_MORE_DOCS) { + // If even one of the sub-scorers does not have any documents, this + // scorer should not attempt to do any more work. + lastDoc = NO_MORE_DOCS; + return; + } } - return more; - } - public boolean skipTo(int target) throws IOException { - if (firstTime) - return init(target); - else if (more) - more = scorers[(scorers.length-1)].skipTo(target); - return doNext(); - } - - // Note... most of this could be done in the constructor - // thus skipping a check for firstTime per call to next() and skipTo() - private boolean init(int target) throws IOException { - firstTime=false; - more = scorers.length>1; - for (int i=0; i>1); i++) { + int end = scorers.length - 1; + int max = end >> 1; + for (int i = 0; i < max; i++) { Scorer tmp = scorers[i]; - scorers[i] = scorers[end-i-1]; - scorers[end-i-1] = tmp; + int idx = end - i - 1; + scorers[i] = scorers[idx]; + scorers[idx] = tmp; } + } - return more; + private int doNext() throws IOException { + int first = 0; + int doc = scorers[scorers.length - 1].docID(); + Scorer firstScorer; + while ((firstScorer = scorers[first]).docID() < doc) { + doc = firstScorer.advance(doc); + first = first == scorers.length - 1 ? 0 : first + 1; + } + return doc; } + + public int advance(int target) throws IOException { + if (lastDoc == NO_MORE_DOCS) { + return lastDoc; + } else if (scorers[(scorers.length - 1)].docID() < target) { + scorers[(scorers.length - 1)].advance(target); + } + return lastDoc = doNext(); + } + /** @deprecated use {@link #docID()} instead. */ + public int doc() { return lastDoc; } + + public int docID() { + return lastDoc; + } + + public Explanation explain(int doc) { + throw new UnsupportedOperationException(); + } + + /** @deprecated use {@link #nextDoc()} instead. */ + public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { + if (lastDoc == NO_MORE_DOCS) { + return lastDoc; + } else if (lastDoc == -1) { + return lastDoc = scorers[scorers.length - 1].docID(); + } + scorers[(scorers.length - 1)].nextDoc(); + return lastDoc = doNext(); + } + public float score() throws IOException { float sum = 0.0f; for (int i = 0; i < scorers.length; i++) { @@ -119,8 +143,9 @@ return sum * coord; } - public Explanation explain(int doc) { - throw new UnsupportedOperationException(); + /** @deprecated use {@link #advance(int)} instead. */ + public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; } } Index: src/java/org/apache/lucene/search/ConstantScoreQuery.java =================================================================== --- src/java/org/apache/lucene/search/ConstantScoreQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/ConstantScoreQuery.java (working copy) @@ -84,7 +84,7 @@ public Explanation explain(IndexReader reader, int doc) throws IOException { ConstantScorer cs = (ConstantScorer)scorer(reader); - boolean exists = cs.docIdSetIterator.skipTo(doc) && (cs.docIdSetIterator.doc() == doc); + boolean exists = cs.docIdSetIterator.advance(doc) == doc; ComplexExplanation result = new ComplexExplanation(); @@ -108,7 +108,7 @@ protected class ConstantScorer extends Scorer { final DocIdSetIterator docIdSetIterator; final float theScore; - int doc=-1; + int doc = -1; public ConstantScorer(Similarity similarity, IndexReader reader, Weight w) throws IOException { super(similarity); @@ -116,36 +116,48 @@ docIdSetIterator = filter.getDocIdSet(reader).iterator(); } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - return docIdSetIterator.next(); + return docIdSetIterator.nextDoc() != NO_MORE_DOCS; } + public int nextDoc() throws IOException { + return docIdSetIterator.nextDoc(); + } + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return docIdSetIterator.doc(); } + + public int docID() { + return docIdSetIterator.docID(); + } public float score() throws IOException { return theScore; } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { - return docIdSetIterator.skipTo(target); + return docIdSetIterator.advance(target) != NO_MORE_DOCS; } + public int advance(int target) throws IOException { + return docIdSetIterator.advance(target); + } + public Explanation explain(int doc) throws IOException { throw new UnsupportedOperationException(); } } - protected Weight createWeight(Searcher searcher) { return new ConstantScoreQuery.ConstantWeight(searcher); } - /** Prints a user-readable version of this query. */ - public String toString(String field) - { + public String toString(String field) { return "ConstantScore(" + filter.toString() + (getBoost()==1.0 ? ")" : "^" + getBoost()); } @@ -165,6 +177,3 @@ } } - - - Index: src/java/org/apache/lucene/search/DisjunctionMaxQuery.java =================================================================== --- src/java/org/apache/lucene/search/DisjunctionMaxQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/DisjunctionMaxQuery.java (working copy) @@ -16,14 +16,14 @@ * limitations under the License. */ -import org.apache.lucene.index.IndexReader; - import java.io.IOException; import java.util.ArrayList; +import java.util.Collection; import java.util.Iterator; -import java.util.Collection; import java.util.Set; +import org.apache.lucene.index.IndexReader; + /** * A query that generates the union of documents produced by its subqueries, and that scores each document with the maximum * score for that document as produced by any subquery, plus a tie breaking increment for any additional matching subqueries. @@ -124,13 +124,19 @@ /* Create the scorer used to score our associated DisjunctionMaxQuery */ public Scorer scorer(IndexReader reader) throws IOException { - DisjunctionMaxScorer result = new DisjunctionMaxScorer(tieBreakerMultiplier, similarity); - for (int i = 0 ; i < weights.size(); i++) { - Weight w = (Weight) weights.get(i); + Scorer[] scorers = new Scorer[weights.size()]; + int idx = 0; + for (Iterator iter = weights.iterator(); iter.hasNext();) { + Weight w = (Weight) iter.next(); Scorer subScorer = w.scorer(reader); - if (subScorer == null) return null; - result.add(subScorer); + if (subScorer == null) { + return null; + } else if (subScorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { + scorers[idx++] = subScorer; + } } + if (idx == 0) return null; // all scorers did not have documents + DisjunctionMaxScorer result = new DisjunctionMaxScorer(tieBreakerMultiplier, similarity, scorers, idx); return result; } Index: src/java/org/apache/lucene/search/DisjunctionMaxScorer.java =================================================================== --- src/java/org/apache/lucene/search/DisjunctionMaxScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/DisjunctionMaxScorer.java (working copy) @@ -17,7 +17,6 @@ */ import java.io.IOException; -import java.util.ArrayList; /** * The Scorer for DisjunctionMaxQuery's. The union of all documents generated by the the subquery scorers @@ -27,168 +26,192 @@ */ class DisjunctionMaxScorer extends Scorer { - /* The scorers for subqueries that have remaining docs, kept as a min heap by number of next doc. */ - private ArrayList subScorers = new ArrayList(); + /* The scorers for subqueries that have remaining docs, kept as a min heap by number of next doc. */ + private final Scorer[] subScorers; + private int numScorers; + /* Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result. */ + private final float tieBreakerMultiplier; + private int doc = -1; - /* Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result. */ - private float tieBreakerMultiplier; + /** + * Creates a new instance of DisjunctionMaxScorer + * + * @param tieBreakerMultiplier + * Multiplier applied to non-maximum-scoring subqueries for a + * document as they are summed into the result. + * @param similarity + * -- not used since our definition involves neither coord nor terms + * directly + * @param subScorers + * The sub scorers this Scorer should iterate on + * @param numScorers + * The actual number of scorers to iterate on. Note that the array's + * length may be larger than the actual number of scorers. + */ + public DisjunctionMaxScorer(float tieBreakerMultiplier, + Similarity similarity, Scorer[] subScorers, int numScorers) throws IOException { + super(similarity); - private boolean more = false; // True iff there is a next document - private boolean firstTime = true; // True iff next() has not yet been called + this.tieBreakerMultiplier = tieBreakerMultiplier; + // The passed subScorers array includes only scorers which have documents + // (DisjunctionMaxQuery takes care of that), and their nextDoc() was already + // called. + this.subScorers = subScorers; + this.numScorers = numScorers; + + heapify(); + } - /** Creates a new instance of DisjunctionMaxScorer - * @param tieBreakerMultiplier Multiplier applied to non-maximum-scoring subqueries for a document as they are summed into the result. - * @param similarity -- not used since our definition involves neither coord nor terms directly */ - public DisjunctionMaxScorer(float tieBreakerMultiplier, Similarity similarity) { - super(similarity); - this.tieBreakerMultiplier = tieBreakerMultiplier; - } + /** + * Generate the next document matching our associated DisjunctionMaxQuery. + * + * @return true iff there is a next document + * @deprecated use {@link #nextDoc()} instead. + */ + public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } - /** Add the scorer for a subquery - * @param scorer the scorer of a subquery of our associated DisjunctionMaxQuery - */ - public void add(Scorer scorer) throws IOException { - if (scorer.next()) { // Initialize and retain only if it produces docs - subScorers.add(scorer); - more = true; + public int nextDoc() throws IOException { + if (numScorers == 0) return doc = NO_MORE_DOCS; + while (subScorers[0].docID() == doc) { + if (subScorers[0].nextDoc() != NO_MORE_DOCS) { + heapAdjust(0); + } else { + heapRemoveRoot(); + if (numScorers == 0) { + return doc = NO_MORE_DOCS; } + } } + + return doc = subScorers[0].docID(); + } - /** Generate the next document matching our associated DisjunctionMaxQuery. - * @return true iff there is a next document - */ - public boolean next() throws IOException { - if (!more) return false; - if (firstTime) { - heapify(); - firstTime = false; - return true; // more would have been false if no subScorers had any docs - } - // Increment all generators that generated the last doc and adjust the heap. - int lastdoc = ((Scorer) subScorers.get(0)).doc(); - do { - if (((Scorer) subScorers.get(0)).next()) - heapAdjust(0); - else { - heapRemoveRoot(); - if (subScorers.isEmpty()) return (more = false); - } - } while ( ((Scorer) subScorers.get(0)).doc()==lastdoc ); - return true; - } + /** @deprecated use {@link #docID()} instead. */ + public int doc() { + return subScorers[0].doc(); + } - /** Determine the current document number. Initially invalid, until {@link #next()} is called the first time. - * @return the document number of the currently generated document - */ - public int doc() { - return ((Scorer) subScorers.get(0)).doc(); - } + public int docID() { + return doc; + } - /** Determine the current document score. Initially invalid, until {@link #next()} is called the first time. - * @return the score of the current generated document - */ - public float score() throws IOException { - int doc = ((Scorer) subScorers.get(0)).doc(); - float[] sum = {((Scorer) subScorers.get(0)).score()}, max = {sum[0]}; - int size = subScorers.size(); - scoreAll(1, size, doc, sum, max); - scoreAll(2, size, doc, sum, max); - return max[0] + (sum[0] - max[0])*tieBreakerMultiplier; - } + /** Determine the current document score. Initially invalid, until {@link #next()} is called the first time. + * @return the score of the current generated document + */ + public float score() throws IOException { + int doc = subScorers[0].docID(); + float[] sum = { subScorers[0].score() }, max = { sum[0] }; + int size = numScorers; + scoreAll(1, size, doc, sum, max); + scoreAll(2, size, doc, sum, max); + return max[0] + (sum[0] - max[0]) * tieBreakerMultiplier; + } - // Recursively iterate all subScorers that generated last doc computing sum and max - private void scoreAll(int root, int size, int doc, float[] sum, float[] max) throws IOException { - if (root0 && ((Scorer)subScorers.get(0)).doc()>1)-1; i>=0; i--) - heapAdjust(i); + // Organize subScorers into a min heap with scorers generating the earliest document on top. + private void heapify() { + for (int i = (numScorers >> 1) - 1; i >= 0; i--) { + heapAdjust(i); } + } - /* The subtree of subScorers at root is a min heap except possibly for its root element. - * Bubble the root down as required to make the subtree a heap. - */ - private void heapAdjust(int root) { - Scorer scorer=(Scorer)subScorers.get(root); - int doc=scorer.doc(); - int i=root, size=subScorers.size(); - while (i<=(size>>1)-1) { - int lchild=(i<<1)+1; - Scorer lscorer=(Scorer)subScorers.get(lchild); - int ldoc=lscorer.doc(); - int rdoc=Integer.MAX_VALUE, rchild=(i<<1)+2; - Scorer rscorer=null; - if (rchild> 1) - 1) { + int lchild = (i << 1) + 1; + Scorer lscorer = subScorers[lchild]; + int ldoc = lscorer.docID(); + int rdoc = Integer.MAX_VALUE, rchild = (i << 1) + 2; + Scorer rscorer = null; + if (rchild < numScorers) { + rscorer = subScorers[rchild]; + rdoc = rscorer.docID(); + } + if (ldoc < doc) { + if (rdoc < ldoc) { + subScorers[i] = rscorer; + subScorers[rchild] = scorer; + i = rchild; + } else { + subScorers[i] = lscorer; + subScorers[lchild] = scorer; + i = lchild; } + } else if (rdoc < doc) { + subScorers[i] = rscorer; + subScorers[rchild] = scorer; + i = rchild; + } else { + return; + } } + } - // Remove the root Scorer from subScorers and re-establish it as a heap - private void heapRemoveRoot() { - int size=subScorers.size(); - if (size==1) - subScorers.remove(0); - else { - subScorers.set(0, subScorers.get(size-1)); - subScorers.remove(size-1); - heapAdjust(0); - } + // Remove the root Scorer from subScorers and re-establish it as a heap + private void heapRemoveRoot() { + if (numScorers == 1) { + subScorers[0] = null; + numScorers = 0; + } else { + subScorers[0] = subScorers[numScorers - 1]; + subScorers[numScorers - 1] = null; + --numScorers; + heapAdjust(0); } + } } Index: src/java/org/apache/lucene/search/DisjunctionSumScorer.java =================================================================== --- src/java/org/apache/lucene/search/DisjunctionSumScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/DisjunctionSumScorer.java (working copy) @@ -102,7 +102,7 @@ scorerDocQueue = new ScorerDocQueue(nrScorers); while (si.hasNext()) { Scorer se = (Scorer) si.next(); - if (se.next()) { // doc() method will be used in scorerDocQueue. + if (se.nextDoc() != NO_MORE_DOCS) { // doc() method will be used in scorerDocQueue. scorerDocQueue.insert(se); } } @@ -124,7 +124,7 @@ */ public void score(Collector collector) throws IOException { collector.setScorer(this); - while (next()) { + while (nextDoc() != NO_MORE_DOCS) { collector.collect(currentDoc); } } @@ -139,7 +139,7 @@ * @deprecated use {@link #score(Collector, int)} instead. */ protected boolean score(HitCollector hc, int max) throws IOException { - return score(new HitCollectorWrapper(hc), max); + return score(new HitCollectorWrapper(hc), max, docID()); } /** Expert: Collects matching documents in a range. Hook for optimization. @@ -149,22 +149,29 @@ * @param max Do not score documents past this. * @return true if more matching documents may remain. */ - protected boolean score(Collector collector, int max) throws IOException { + protected boolean score(Collector collector, int max, int firstDocID) throws IOException { + // firstDocID is ignored since nextDoc() sets 'currentDoc' collector.setScorer(this); while (currentDoc < max) { collector.collect(currentDoc); - if (!next()) { + if (nextDoc() == NO_MORE_DOCS) { return false; } } return true; } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - return (scorerDocQueue.size() >= minimumNrMatchers) - && advanceAfterCurrent(); + return nextDoc() != NO_MORE_DOCS; } + public int nextDoc() throws IOException { + if (scorerDocQueue.size() < minimumNrMatchers || !advanceAfterCurrent()) { + currentDoc = NO_MORE_DOCS; + } + return currentDoc; + } /** Advance all subscorers after the current document determined by the * top of the scorerDocQueue. @@ -176,7 +183,7 @@ *
In case there is a match, currentDoc, currentSumScore, * and nrMatchers describe the match. * - * @todo Investigate whether it is possible to use skipTo() when + * TODO: Investigate whether it is possible to use skipTo() when * the minimum number of matchers is bigger than one, ie. try and use the * character of ConjunctionScorer for the minimum number of matchers. * Also delay calling score() on the sub scorers until the minimum number of @@ -190,7 +197,7 @@ currentScore = scorerDocQueue.topScore(); nrMatchers = 1; do { // Until all subscorers are after currentDoc - if (! scorerDocQueue.topNextAndAdjustElsePop()) { + if (!scorerDocQueue.topNextAndAdjustElsePop()) { if (scorerDocQueue.size() == 0) { break; // nothing more to advance, check for last match. } @@ -215,8 +222,13 @@ */ public float score() throws IOException { return currentScore; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return currentDoc; } + public int docID() { + return currentDoc; + } + /** Returns the number of subscorers matching the current document. * Initially invalid, until {@link #next()} is called the first time. */ @@ -224,31 +236,52 @@ return nrMatchers; } - /** Skips to the first match beyond the current whose document number is - * greater than or equal to a given target. - *
When this method is used the {@link #explain(int)} method should not be used. - *
The implementation uses the skipTo() method on the subscorers. - * @param target The target document number. + /** + * Skips to the first match beyond the current whose document number is + * greater than or equal to a given target.
+ * When this method is used the {@link #explain(int)} method should not be + * used.
+ * The implementation uses the skipTo() method on the subscorers. + * + * @param target + * The target document number. * @return true iff there is such a match. + * @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + /** + * Advances to the first match beyond the current whose document number is + * greater than or equal to a given target.
+ * When this method is used the {@link #explain(int)} method should not be + * used.
+ * The implementation uses the skipTo() method on the subscorers. + * + * @param target + * The target document number. + * @return the document whose number is greater than or equal to the given + * target, or -1 if none exist. + */ + public int advance(int target) throws IOException { if (scorerDocQueue.size() < minimumNrMatchers) { - return false; + return currentDoc = NO_MORE_DOCS; } if (target <= currentDoc) { - return true; + return currentDoc; } do { if (scorerDocQueue.topDoc() >= target) { - return advanceAfterCurrent(); - } else if (! scorerDocQueue.topSkipToAndAdjustElsePop(target)) { + return advanceAfterCurrent() ? currentDoc : (currentDoc = NO_MORE_DOCS); + } else if (!scorerDocQueue.topSkipToAndAdjustElsePop(target)) { if (scorerDocQueue.size() < minimumNrMatchers) { - return false; + return currentDoc = NO_MORE_DOCS; } } } while (true); } - + /** @return An explanation for the score of a given document. */ public Explanation explain(int doc) throws IOException { Explanation res = new Explanation(); Index: src/java/org/apache/lucene/search/DocIdSetIterator.java =================================================================== --- src/java/org/apache/lucene/search/DocIdSetIterator.java (revision 780809) +++ src/java/org/apache/lucene/search/DocIdSetIterator.java (working copy) @@ -20,30 +20,130 @@ import java.io.IOException; /** - * This abstract class defines methods to iterate over a set of - * non-decreasing doc ids. + * This abstract class defines methods to iterate over a set of non-decreasing + * doc ids. Note that this class assumes it iterates on doc Ids, and therefore + * {@link #NO_MORE_DOCS} is set to {@value #NO_MORE_DOCS} in order to be used as + * a sentinel object. Implementations of this class are expected to consider + * {@link Integer#MAX_VALUE} as an invalid value. */ public abstract class DocIdSetIterator { - /** Returns the current document number.

This is invalid until {@link - #next()} is called for the first time.*/ - public abstract int doc(); - - /** Moves to the next docId in the set. Returns true, iff - * there is such a docId. */ - public abstract boolean next() throws IOException; - - /** Skips entries to the first beyond the current whose document number is - * greater than or equal to target.

Returns true iff there is such - * an entry.

Behaves as if written:

-     *   boolean skipTo(int target) {
-     *     do {
-     *       if (!next())
-     *         return false;
-     *     } while (target > doc());
-     *     return true;
-     *   }
-     * 
- * Some implementations are considerably more efficient than that. - */ - public abstract boolean skipTo(int target) throws IOException; + + // TODO (3.0): review the javadocs and remove any references to '3.0'. + private int doc = -1; + + /** + * When returned by {@link #nextDoc()}, {@link #advance(int)} and + * {@link #doc()} it means there are no more docs in the iterator. + */ + public static final int NO_MORE_DOCS = Integer.MAX_VALUE; + + /** + * Unsupported anymore. Call {@link #docID()} instead. This method throws + * {@link UnsupportedOperationException} if called. + * + * @deprecated use {@link #docID()} instead. + */ + public int doc() { + throw new UnsupportedOperationException("Call docID() instead."); + } + + /** + * Returns the following: + * + *

+ * NOTE: in 3.0, this method will become abstract. + * + * @since 2.9 + */ + public int docID() { + return doc; + } + + /** + * Unsupported anymore. Call {@link #nextDoc()} instead. This method throws + * {@link UnsupportedOperationException} if called. + * + * @deprecated use {@link #nextDoc()} instead. This will be removed in 3.0 + */ + public boolean next() throws IOException { + throw new UnsupportedOperationException("Call nextDoc() instead."); + } + + /** + * Unsupported anymore. Call {@link #advance(int)} instead. This method throws + * {@link UnsupportedOperationException} if called. + * + * @deprecated use {@link #advance(int)} instead. This will be removed in 3.0 + */ + public boolean skipTo(int target) throws IOException { + throw new UnsupportedOperationException("Call advance() instead."); + } + + /** + * Advances to the next document in the set and returns the doc it is + * currently on, or {@link #NO_MORE_DOCS} if there are no more docs in the + * set.
+ * + * NOTE: in 3.0 this method will become abstract, following the removal + * of {@link #next()}. For backward compatibility it is implemented as: + * + *

+   * public int nextDoc() throws IOException {
+   *   return next() ? doc() : NO_MORE_DOCS;
+   * }
+   * 
+ * + * NOTE: after the iterator has exhausted you should not call this + * method, as it may result in unpredicted behavior. + * + * @since 2.9 + */ + public int nextDoc() throws IOException { + return doc = next() ? doc() : NO_MORE_DOCS; + } + + /** + * Advances to the first beyond the current whose document number is greater + * than or equal to target. Returns the current document number or + * {@link #NO_MORE_DOCS} if there are no more docs in the set. + *

+ * Behaves as if written: + * + *

+   * int advance(int target) {
+   *   int doc;
+   *   while ((doc = nextDoc()) < target) {
+   *   }
+   *   return doc;
+   * }
+   * 
+ * + * Some implementations are considerably more efficient than that. + *

+ * NOTE: certain implemenations may return a different value (each + * time) if called several times in a row with the same target. + *

+ * NOTE: this method may be called with {@value #NO_MORE_DOCS} for + * efficiency by some Scorers. If your implementation cannot efficiently + * determine that it should exhaust, it is recommended that you check for that + * value in each call to this method. + *

+ * NOTE: after the iterator has exhausted you should not call this + * method, as it may result in unpredicted behavior. + *

+ * NOTE: in 3.0 this method will become abstract, following the removal + * of {@link #skipTo(int)}. + * + * @since 2.9 + */ + public int advance(int target) throws IOException { + while (nextDoc() < target) {} + return doc; + } + } Index: src/java/org/apache/lucene/search/FieldCacheRangeFilter.java =================================================================== --- src/java/org/apache/lucene/search/FieldCacheRangeFilter.java (revision 780809) +++ src/java/org/apache/lucene/search/FieldCacheRangeFilter.java (working copy) @@ -158,37 +158,51 @@ protected class RangeMultiFilterIterator extends DocIdSetIterator { private int doc = -1; - + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return doc; } + public int docID() { + return doc; + } + + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() { try { do { doc++; } while (fcsi.order[doc] > inclusiveUpperPoint || fcsi.order[doc] < inclusiveLowerPoint); - return true; } catch (ArrayIndexOutOfBoundsException e) { - doc = Integer.MAX_VALUE; - return false; + doc = NO_MORE_DOCS; } + return doc; } - + + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) { try { doc = target; while (fcsi.order[doc] > inclusiveUpperPoint || fcsi.order[doc] < inclusiveLowerPoint) { doc++; } - return true; } catch (ArrayIndexOutOfBoundsException e) { - doc = Integer.MAX_VALUE; - return false; + doc = NO_MORE_DOCS; } + return doc; } + } } } Index: src/java/org/apache/lucene/search/FieldCacheTermsFilter.java =================================================================== --- src/java/org/apache/lucene/search/FieldCacheTermsFilter.java (revision 780809) +++ src/java/org/apache/lucene/search/FieldCacheTermsFilter.java (working copy) @@ -17,12 +17,11 @@ * limitations under the License. */ +import java.io.IOException; + import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.TermDocs; // for javadoc import org.apache.lucene.util.OpenBitSet; -import java.io.IOException; - /** * A {@link Filter} that only accepts documents whose single * term value in the specified field is contained in the @@ -133,33 +132,44 @@ protected class FieldCacheTermsFilterDocIdSetIterator extends DocIdSetIterator { private int doc = -1; + /** @deprecated use {@link #docID()} instead. */ public int doc() { return doc; } + + public int docID() { + return doc; + } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() { try { - do { - doc++; - } while (!openBitSet.fastGet(fcsi.order[doc])); - return true; + while (!openBitSet.fastGet(fcsi.order[++doc])) {} } catch (ArrayIndexOutOfBoundsException e) { - doc = Integer.MAX_VALUE; - return false; + doc = NO_MORE_DOCS; } + return doc; } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) { try { doc = target; while (!openBitSet.fastGet(fcsi.order[doc])) { doc++; } - return true; } catch (ArrayIndexOutOfBoundsException e) { - doc = Integer.MAX_VALUE; - return false; + doc = NO_MORE_DOCS; } + return doc; } } } Index: src/java/org/apache/lucene/search/FilteredDocIdSetIterator.java =================================================================== --- src/java/org/apache/lucene/search/FilteredDocIdSetIterator.java (revision 780809) +++ src/java/org/apache/lucene/search/FilteredDocIdSetIterator.java (working copy) @@ -25,10 +25,9 @@ * mechanism on an underlying DocIdSetIterator. See {@link * FilteredDocIdSet}. */ - public abstract class FilteredDocIdSetIterator extends DocIdSetIterator { protected DocIdSetIterator _innerIter; - private int _currentDoc; + private int doc; /** * Constructor. @@ -39,7 +38,7 @@ throw new IllegalArgumentException("null iterator"); } _innerIter = innerIter; - _currentDoc = -1; + doc = -1; } /** @@ -50,42 +49,49 @@ */ abstract protected boolean match(int doc); - // @Override + /** @deprecated use {@link #docID()} instead. */ public final int doc() { - return _currentDoc; + return doc; } - // @Override + public int docID() { + return doc; + } + + /** @deprecated use {@link #nextDoc()} instead. */ public final boolean next() throws IOException{ - while (_innerIter.next()) { - int doc = _innerIter.doc(); + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { + while ((doc = _innerIter.nextDoc()) != NO_MORE_DOCS) { if (match(doc)) { - _currentDoc = doc; - return true; + return doc; } } - return false; + return doc; } - - // @Override + + /** @deprecated use {@link #advance(int)} instead. */ public final boolean skipTo(int n) throws IOException{ - boolean flag = _innerIter.skipTo(n); - if (flag) { - int doc = _innerIter.doc(); + return advance(n) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { + doc = _innerIter.advance(target); + if (doc != NO_MORE_DOCS) { if (match(doc)) { - _currentDoc = doc; - return true; + return doc; } else { - while (_innerIter.next()) { - int docid = _innerIter.doc(); - if (match(docid)) { - _currentDoc = docid; - return true; + while ((doc = _innerIter.nextDoc()) != NO_MORE_DOCS) { + if (match(doc)) { + return doc; } } - return false; + return doc; } } - return flag; + return doc; } + } Index: src/java/org/apache/lucene/search/FilteredQuery.java =================================================================== --- src/java/org/apache/lucene/search/FilteredQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/FilteredQuery.java (working copy) @@ -85,7 +85,7 @@ } Filter f = FilteredQuery.this.filter; DocIdSetIterator docIdSetIterator = f.getDocIdSet(ir).iterator(); - if (docIdSetIterator.skipTo(i) && (docIdSetIterator.doc() == i)) { + if (docIdSetIterator.advance(i) == i) { return inner; } else { Explanation result = new Explanation @@ -99,36 +99,52 @@ public Query getQuery() { return FilteredQuery.this; } // return a filtering scorer - public Scorer scorer (IndexReader indexReader) throws IOException { + public Scorer scorer (IndexReader indexReader) throws IOException { final Scorer scorer = weight.scorer(indexReader); final DocIdSetIterator docIdSetIterator = filter.getDocIdSet(indexReader).iterator(); return new Scorer(similarity) { - private boolean advanceToCommon() throws IOException { - while (scorer.doc() != docIdSetIterator.doc()) { - if (scorer.doc() < docIdSetIterator.doc()) { - if (!scorer.skipTo(docIdSetIterator.doc())) { - return false; - } - } else if (!docIdSetIterator.skipTo(scorer.doc())) { - return false; + private int doc = -1; + + private int advanceToCommon(int scorerDoc, int disiDoc) throws IOException { + while (scorerDoc != disiDoc) { + if (scorerDoc < disiDoc) { + scorerDoc = scorer.advance(disiDoc); + } else { + disiDoc = docIdSetIterator.advance(scorerDoc); } } - return true; + return scorerDoc; } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - return docIdSetIterator.next() && scorer.next() && advanceToCommon(); + return nextDoc() != NO_MORE_DOCS; } + public int nextDoc() throws IOException { + int scorerDoc, disiDoc; + return doc = (disiDoc = docIdSetIterator.nextDoc()) != NO_MORE_DOCS + && (scorerDoc = scorer.nextDoc()) != NO_MORE_DOCS + && advanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS ? scorer.docID() : NO_MORE_DOCS; + } + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return scorer.doc(); } - + public int docID() { return doc; } + + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int i) throws IOException { - return docIdSetIterator.skipTo(i) - && scorer.skipTo(docIdSetIterator.doc()) - && advanceToCommon(); + return advance(i) != NO_MORE_DOCS; } + + public int advance(int target) throws IOException { + int disiDoc, scorerDoc; + return doc = (disiDoc = docIdSetIterator.advance(target)) != NO_MORE_DOCS + && (scorerDoc = scorer.advance(disiDoc)) != NO_MORE_DOCS + && advanceToCommon(scorerDoc, disiDoc) != NO_MORE_DOCS ? scorer.docID() : NO_MORE_DOCS; + } public float score() throws IOException { return getBoost() * scorer.score(); } @@ -136,7 +152,7 @@ public Explanation explain (int i) throws IOException { Explanation exp = scorer.explain(i); - if (docIdSetIterator.skipTo(i) && (docIdSetIterator.doc() == i)) { + if (docIdSetIterator.advance(i) == i) { exp.setDescription ("allowed by filter: "+exp.getDescription()); exp.setValue(getBoost() * exp.getValue()); } else { Index: src/java/org/apache/lucene/search/IndexSearcher.java =================================================================== --- src/java/org/apache/lucene/search/IndexSearcher.java (revision 780809) +++ src/java/org/apache/lucene/search/IndexSearcher.java (working copy) @@ -261,28 +261,34 @@ if (scorer == null) return; + int docID = scorer.docID(); + assert docID == -1 || docID == DocIdSetIterator.NO_MORE_DOCS; + if (filter == null) { scorer.score(collector); return; } - DocIdSetIterator filterDocIdIterator = filter.getDocIdSet(reader).iterator(); // CHECKME: use ConjunctionScorer here? + // CHECKME: use ConjunctionScorer here? + DocIdSetIterator filterIter = filter.getDocIdSet(reader).iterator(); - boolean more = filterDocIdIterator.next() && scorer.skipTo(filterDocIdIterator.doc()); - + int filterDoc = filterIter.nextDoc(); + int scorerDoc = scorer.advance(filterDoc); + collector.setScorer(scorer); - while (more) { - int filterDocId = filterDocIdIterator.doc(); - if (filterDocId > scorer.doc() && !scorer.skipTo(filterDocId)) { - more = false; + while (true) { + if (scorerDoc == filterDoc) { + // Check if scorer has exhausted, only before collecting. + if (scorerDoc == DocIdSetIterator.NO_MORE_DOCS) { + break; + } + collector.collect(scorerDoc); + filterDoc = filterIter.nextDoc(); + scorerDoc = scorer.advance(filterDoc); + } else if (scorerDoc > filterDoc) { + filterDoc = filterIter.advance(scorerDoc); } else { - int scorerDocId = scorer.doc(); - if (scorerDocId == filterDocId) { // permitted by filter - collector.collect(scorerDocId); - more = filterDocIdIterator.next(); - } else { - more = filterDocIdIterator.skipTo(scorerDocId); - } + scorerDoc = scorer.advance(filterDoc); } } } Index: src/java/org/apache/lucene/search/MatchAllDocsQuery.java =================================================================== --- src/java/org/apache/lucene/search/MatchAllDocsQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/MatchAllDocsQuery.java (working copy) @@ -47,9 +47,10 @@ final TermDocs termDocs; final float score; final byte[] norms; - - MatchAllScorer(IndexReader reader, Similarity similarity, Weight w, byte[] norms) throws IOException - { + private int doc = -1; + + MatchAllScorer(IndexReader reader, Similarity similarity, Weight w, + byte[] norms) throws IOException { super(similarity); this.termDocs = reader.termDocs(null); score = w.getValue(); @@ -60,26 +61,36 @@ return null; // not called... see MatchAllDocsWeight.explain() } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return termDocs.doc(); } + + public int docID() { + return doc; + } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - return termDocs.next(); + return nextDoc() != NO_MORE_DOCS; } + public int nextDoc() throws IOException { + return doc = termDocs.next() ? termDocs.doc() : NO_MORE_DOCS; + } + public float score() { - if (norms == null) { - return score; - } else { - return score * Similarity.decodeNorm(norms[doc()]); // normalize for field - } + return norms == null ? score : score * Similarity.decodeNorm(norms[docID()]); } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { - return termDocs.skipTo(target); + return advance(target) != NO_MORE_DOCS; } + public int advance(int target) throws IOException { + return doc = termDocs.skipTo(target) ? termDocs.doc() : NO_MORE_DOCS; + } } private class MatchAllDocsWeight implements Weight { Index: src/java/org/apache/lucene/search/NonMatchingScorer.java =================================================================== --- src/java/org/apache/lucene/search/NonMatchingScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/NonMatchingScorer.java (working copy) @@ -23,13 +23,22 @@ class NonMatchingScorer extends Scorer { public NonMatchingScorer() { super(null); } // no similarity used + /** @deprecated use {@link #docID()} instead. */ public int doc() { throw new UnsupportedOperationException(); } + + public int docID() { return NO_MORE_DOCS; } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { return false; } + + public int nextDoc() throws IOException { return NO_MORE_DOCS; } public float score() { throw new UnsupportedOperationException(); } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) { return false; } + + public int advance(int target) { return NO_MORE_DOCS; } public Explanation explain(int doc) { Explanation e = new Explanation(); Index: src/java/org/apache/lucene/search/PhraseScorer.java =================================================================== --- src/java/org/apache/lucene/search/PhraseScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/PhraseScorer.java (working copy) @@ -43,9 +43,8 @@ private float freq; //prhase frequency in current doc as computed by phraseFreq(). - - PhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, Similarity similarity, - byte[] norms) { + PhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, + Similarity similarity, byte[] norms) { super(similarity); this.norms = norms; this.weight = weight; @@ -60,25 +59,37 @@ PhrasePositions pp = new PhrasePositions(tps[i], offsets[i]); if (last != null) { // add next to end of list last.next = pp; - } else + } else { first = pp; + } last = pp; } pq = new PhraseQueue(tps.length); // construct empty pq - + first.doc = -1; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return first.doc; } + + public int docID() { return first.doc; } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { if (firstTime) { init(); firstTime = false; } else if (more) { more = last.next(); // trigger further scanning } - return doNext(); + if (!doNext()) { + first.doc = NO_MORE_DOCS; + } + return first.doc; } // next without initial increment @@ -107,16 +118,25 @@ return norms == null ? raw : raw * Similarity.decodeNorm(norms[first.doc]); // normalize } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { firstTime = false; for (PhrasePositions pp = first; more && pp != null; pp = pp.next) { more = pp.skipTo(target); } - if (more) + if (more) { sort(); // re-sort - return doNext(); + } + if (!doNext()) { + first.doc = NO_MORE_DOCS; + } + return first.doc; } - + /** * For a document containing all the phrase query terms, compute the * frequency of the phrase in that document. @@ -127,16 +147,19 @@ protected abstract float phraseFreq() throws IOException; private void init() throws IOException { - for (PhrasePositions pp = first; more && pp != null; pp = pp.next) + for (PhrasePositions pp = first; more && pp != null; pp = pp.next) { more = pp.next(); - if(more) + } + if (more) { sort(); + } } private void sort() { pq.clear(); - for (PhrasePositions pp = first; pp != null; pp = pp.next) - pq.put(pp); + for (PhrasePositions pp = first; pp != null; pp = pp.next) { + pq.add(pp); + } pqToList(); } @@ -163,9 +186,8 @@ public Explanation explain(final int doc) throws IOException { Explanation tfExplanation = new Explanation(); - while (next() && doc() < doc) {} - - float phraseFreq = (doc() == doc) ? freq : 0.0f; + int d = advance(doc); + float phraseFreq = (d == doc) ? freq : 0.0f; tfExplanation.setValue(getSimilarity().tf(phraseFreq)); tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")"); Index: src/java/org/apache/lucene/search/ReqExclScorer.java =================================================================== --- src/java/org/apache/lucene/search/ReqExclScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/ReqExclScorer.java (working copy) @@ -29,76 +29,78 @@ class ReqExclScorer extends Scorer { private Scorer reqScorer; private DocIdSetIterator exclDisi; + private int doc = -1; /** Construct a ReqExclScorer. * @param reqScorer The scorer that must match, except where * @param exclDisi indicates exclusion. */ - public ReqExclScorer( - Scorer reqScorer, - DocIdSetIterator exclDisi) { + public ReqExclScorer(Scorer reqScorer, DocIdSetIterator exclDisi) { super(null); // No similarity used. this.reqScorer = reqScorer; this.exclDisi = exclDisi; } - private boolean firstTime = true; - + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - if (firstTime) { - if (! exclDisi.next()) { - exclDisi = null; // exhausted at start - } - firstTime = false; - } + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { if (reqScorer == null) { - return false; + return doc; } - if (! reqScorer.next()) { + doc = reqScorer.nextDoc(); + if (doc == NO_MORE_DOCS) { reqScorer = null; // exhausted, nothing left - return false; + return doc; } if (exclDisi == null) { - return true; // reqScorer.next() already returned true + return doc; } - return toNonExcluded(); + return doc = toNonExcluded(); } /** Advance to non excluded doc. *
On entry: *

* Advances reqScorer a non excluded required doc, if any. * @return true iff there is a non excluded required doc. */ - private boolean toNonExcluded() throws IOException { - int exclDoc = exclDisi.doc(); + private int toNonExcluded() throws IOException { + int exclDoc = exclDisi.docID(); + int reqDoc = reqScorer.docID(); // may be excluded do { - int reqDoc = reqScorer.doc(); // may be excluded if (reqDoc < exclDoc) { - return true; // reqScorer advanced to before exclScorer, ie. not excluded + return reqDoc; // reqScorer advanced to before exclScorer, ie. not excluded } else if (reqDoc > exclDoc) { - if (! exclDisi.skipTo(reqDoc)) { + exclDoc = exclDisi.advance(reqDoc); + if (exclDoc == NO_MORE_DOCS) { exclDisi = null; // exhausted, no more exclusions - return true; + return reqDoc; } - exclDoc = exclDisi.doc(); if (exclDoc > reqDoc) { - return true; // not excluded + return reqDoc; // not excluded } } - } while (reqScorer.next()); + } while ((reqDoc = reqScorer.nextDoc()) != NO_MORE_DOCS); reqScorer = null; // exhausted, nothing left - return false; + return NO_MORE_DOCS; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return reqScorer.doc(); // reqScorer may be null when next() or skipTo() already return false } + + public int docID() { + return doc; + } /** Returns the score of the current document matching the query. * Initially invalid, until {@link #next()} is called the first time. @@ -108,35 +110,28 @@ return reqScorer.score(); // reqScorer may be null when next() or skipTo() already return false } - /** Skips to the first match beyond the current whose document number is - * greater than or equal to a given target. - *
When this method is used the {@link #explain(int)} method should not be used. - * @param target The target document number. - * @return true iff there is such a match. - */ + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { - if (firstTime) { - firstTime = false; - if (! exclDisi.skipTo(target)) { - exclDisi = null; // exhausted - } - } + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { if (reqScorer == null) { - return false; + return doc = NO_MORE_DOCS; } if (exclDisi == null) { - return reqScorer.skipTo(target); + return doc = reqScorer.advance(target); } - if (! reqScorer.skipTo(target)) { + if (reqScorer.advance(target) == NO_MORE_DOCS) { reqScorer = null; - return false; + return doc = NO_MORE_DOCS; } - return toNonExcluded(); + return doc = toNonExcluded(); } - + public Explanation explain(int doc) throws IOException { Explanation res = new Explanation(); - if (exclDisi.skipTo(doc) && (exclDisi.doc() == doc)) { + if (exclDisi.advance(doc) == doc) { res.setDescription("excluded"); } else { res.setDescription("not excluded"); Index: src/java/org/apache/lucene/search/ReqOptSumScorer.java =================================================================== --- src/java/org/apache/lucene/search/ReqOptSumScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/ReqOptSumScorer.java (working copy) @@ -43,44 +43,52 @@ this.optScorer = optScorer; } - private boolean firstTimeOptScorer = true; - + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { return reqScorer.next(); } + public int nextDoc() throws IOException { + return reqScorer.nextDoc(); + } + + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { return reqScorer.skipTo(target); } + public int advance(int target) throws IOException { + return reqScorer.advance(target); + } + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return reqScorer.doc(); } + public int docID() { + return reqScorer.docID(); + } + /** Returns the score of the current document matching the query. * Initially invalid, until {@link #next()} is called the first time. * @return The score of the required scorer, eventually increased by the score * of the optional scorer when it also matches the current document. */ public float score() throws IOException { - int curDoc = reqScorer.doc(); + int curDoc = reqScorer.docID(); float reqScore = reqScorer.score(); - if (firstTimeOptScorer) { - firstTimeOptScorer = false; - if (! optScorer.skipTo(curDoc)) { - optScorer = null; - return reqScore; - } - } else if (optScorer == null) { + if (optScorer == null) { return reqScore; - } else if ((optScorer.doc() < curDoc) && (! optScorer.skipTo(curDoc))) { + } + + int optScorerDoc = optScorer.docID(); + if (optScorerDoc < curDoc && (optScorerDoc = optScorer.advance(curDoc)) == NO_MORE_DOCS) { optScorer = null; return reqScore; } - // assert (optScorer != null) && (optScorer.doc() >= curDoc); - return (optScorer.doc() == curDoc) - ? reqScore + optScorer.score() - : reqScore; + + return optScorerDoc == curDoc ? reqScore + optScorer.score() : reqScore; } /** Explain the score of a document. Index: src/java/org/apache/lucene/search/ScoreCachingWrappingScorer.java =================================================================== --- src/java/org/apache/lucene/search/ScoreCachingWrappingScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/ScoreCachingWrappingScorer.java (working copy) @@ -1,83 +1,98 @@ -package org.apache.lucene.search; - -/** - * 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. - */ - -import java.io.IOException; - -/** - * A {@link Scorer} which wraps another scorer and caches the score of the - * current document. Successive calls to {@link #score()} will return the same - * result and will not invoke the wrapped Scorer's score() method, unless the - * current document has changed.
- * This class might be useful due to the changes done to the {@link Collector} - * interface, in which the score is not computed for a document by default, only - * if the collector requests it. Some collectors may need to use the score in - * several places, however all they have in hand is a {@link Scorer} object, and - * might end up computing the score of a document more than once. - */ -public class ScoreCachingWrappingScorer extends Scorer { - - private Scorer scorer; - private int curDoc = -1; - private float curScore; - - /** Creates a new instance by wrapping the given scorer. */ - public ScoreCachingWrappingScorer(Scorer scorer) { - super(scorer.getSimilarity()); - this.scorer = scorer; - } - - protected boolean score(Collector collector, int max) throws IOException { - return scorer.score(collector, max); - } - - public Similarity getSimilarity() { - return scorer.getSimilarity(); - } - - public Explanation explain(int doc) throws IOException { - return scorer.explain(doc); - } - - public float score() throws IOException { - int doc = scorer.doc(); - if (doc != curDoc) { - curScore = scorer.score(); - curDoc = doc; - } - - return curScore; - } - - public int doc() { - return scorer.doc(); - } - - public boolean next() throws IOException { - return scorer.next(); - } - - public void score(Collector collector) throws IOException { - scorer.score(collector); - } - - public boolean skipTo(int target) throws IOException { - return scorer.skipTo(target); - } - -} +package org.apache.lucene.search; + +/** + * 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. + */ + +import java.io.IOException; + +/** + * A {@link Scorer} which wraps another scorer and caches the score of the + * current document. Successive calls to {@link #score()} will return the same + * result and will not invoke the wrapped Scorer's score() method, unless the + * current document has changed.
+ * This class might be useful due to the changes done to the {@link Collector} + * interface, in which the score is not computed for a document by default, only + * if the collector requests it. Some collectors may need to use the score in + * several places, however all they have in hand is a {@link Scorer} object, and + * might end up computing the score of a document more than once. + */ +public class ScoreCachingWrappingScorer extends Scorer { + + private Scorer scorer; + private int curDoc = -1; + private float curScore; + + /** Creates a new instance by wrapping the given scorer. */ + public ScoreCachingWrappingScorer(Scorer scorer) { + super(scorer.getSimilarity()); + this.scorer = scorer; + } + + protected boolean score(Collector collector, int max, int firstDocID) throws IOException { + return scorer.score(collector, max, firstDocID); + } + + public Similarity getSimilarity() { + return scorer.getSimilarity(); + } + + public Explanation explain(int doc) throws IOException { + return scorer.explain(doc); + } + + public float score() throws IOException { + int doc = scorer.docID(); + if (doc != curDoc) { + curScore = scorer.score(); + curDoc = doc; + } + + return curScore; + } + + /** @deprecated use {@link #docID()} instead. */ + public int doc() { + return scorer.doc(); + } + + public int docID() { + return scorer.docID(); + } + + /** @deprecated use {@link #nextDoc()} instead. */ + public boolean next() throws IOException { + return scorer.next(); + } + + public int nextDoc() throws IOException { + return scorer.nextDoc(); + } + + public void score(Collector collector) throws IOException { + scorer.score(collector); + } + + /** @deprecated use {@link #advance(int)} instead. */ + public boolean skipTo(int target) throws IOException { + return scorer.skipTo(target); + } + + public int advance(int target) throws IOException { + return scorer.advance(target); + } + +} Index: src/java/org/apache/lucene/search/Scorer.java =================================================================== --- src/java/org/apache/lucene/search/Scorer.java (revision 780809) +++ src/java/org/apache/lucene/search/Scorer.java (working copy) @@ -71,8 +71,9 @@ */ public void score(Collector collector) throws IOException { collector.setScorer(this); - while (next()) { - collector.collect(doc()); + int doc; + while ((doc = nextDoc()) != NO_MORE_DOCS) { + collector.collect(doc); } } @@ -86,26 +87,33 @@ * @deprecated use {@link #score(Collector, int)} instead. */ protected boolean score(HitCollector hc, int max) throws IOException { - return score(new HitCollectorWrapper(hc), max); + return score(new HitCollectorWrapper(hc), max, docID()); } - /** Expert: Collects matching documents in a range. Hook for optimization. - * Note that {@link #next()} must be called once before this method is called - * for the first time. - * @param collector The collector to which all matching documents are passed. - * @param max Do not score documents past this. + /** + * Expert: Collects matching documents in a range. Hook for optimization. + * Note, firstDocID is added to ensure that {@link #nextDoc()} + * was called before this method. + * + * @param collector + * The collector to which all matching documents are passed. + * @param max + * Do not score documents past this. + * @param firstDocID + * The first document ID (ensures {@link #nextDoc()} is called before + * this method. * @return true if more matching documents may remain. */ - protected boolean score(Collector collector, int max) throws IOException { + protected boolean score(Collector collector, int max, int firstDocID) throws IOException { collector.setScorer(this); - while (doc() < max) { - collector.collect(doc()); - if (!next()) - return false; + int doc = firstDocID; + while (doc < max) { + collector.collect(doc); + doc = nextDoc(); } - return true; + return doc == NO_MORE_DOCS; } - + /** Returns the score of the current document matching the query. * Initially invalid, until {@link #next()} or {@link #skipTo(int)} * is called the first time, or when called from within Index: src/java/org/apache/lucene/search/TermScorer.java =================================================================== --- src/java/org/apache/lucene/search/TermScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/TermScorer.java (working copy) @@ -31,7 +31,7 @@ private TermDocs termDocs; private byte[] norms; private float weightValue; - private int doc; + private int doc = -1; private final int[] docs = new int[32]; // buffered doc numbers private final int[] freqs = new int[32]; // buffered term freqs @@ -65,16 +65,16 @@ } public void score(Collector c) throws IOException { - next(); - score(c, Integer.MAX_VALUE); + score(c, Integer.MAX_VALUE, nextDoc()); } /** @deprecated use {@link #score(Collector, int)} instead. */ protected boolean score(HitCollector c, int end) throws IOException { - return score(new HitCollectorWrapper(c), end); + return score(new HitCollectorWrapper(c), end, doc); } - protected boolean score(Collector c, int end) throws IOException { + // firstDocID is ignored since nextDoc() sets 'doc' + protected boolean score(Collector c, int end, int firstDocID) throws IOException { c.setScorer(this); while (doc < end) { // for docs in window c.collect(doc); // collect score @@ -94,17 +94,31 @@ return true; } - /** Returns the current document number matching the query. - * Initially invalid, until {@link #next()} is called the first time. - */ + /** @deprecated use {@link #docID()} instead. */ public int doc() { return doc; } + + public int docID() { return doc; } - /** Advances to the next document matching the query. - *
The iterator over the matching documents is buffered using + /** + * Advances to the next document matching the query.
+ * The iterator over the matching documents is buffered using * {@link TermDocs#read(int[],int[])}. + * * @return true iff there is another document matching the query. + * @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + /** + * Advances to the next document matching the query.
+ * The iterator over the matching documents is buffered using + * {@link TermDocs#read(int[],int[])}. + * + * @return the document matching the query or -1 if there are no more documents. + */ + public int nextDoc() throws IOException { pointer++; if (pointer >= pointerMax) { pointerMax = termDocs.read(docs, freqs); // refill buffer @@ -112,15 +126,15 @@ pointer = 0; } else { termDocs.close(); // close stream - doc = Integer.MAX_VALUE; // set to sentinel value - return false; + return doc = NO_MORE_DOCS; } } doc = docs[pointer]; - return true; + return doc; } - + public float score() { + assert doc != -1; int f = freqs[pointer]; float raw = // compute tf(f)*weight f < SCORE_CACHE_SIZE // check cache @@ -130,18 +144,34 @@ return norms == null ? raw : raw * SIM_NORM_DECODER[norms[doc] & 0xFF]; // normalize for field } - /** Skips to the first match beyond the current whose document number is - * greater than or equal to a given target. - *
The implementation uses {@link TermDocs#skipTo(int)}. - * @param target The target document number. + /** + * Skips to the first match beyond the current whose document number is + * greater than or equal to a given target.
+ * The implementation uses {@link TermDocs#skipTo(int)}. + * + * @param target + * The target document number. * @return true iff there is such a match. + * @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + /** + * Advances to the first match beyond the current whose document number is + * greater than or equal to a given target.
+ * The implementation uses {@link TermDocs#skipTo(int)}. + * + * @param target + * The target document number. + * @return the matching document or -1 if none exist. + */ + public int advance(int target) throws IOException { // first scan in cache for (pointer++; pointer < pointerMax; pointer++) { if (docs[pointer] >= target) { - doc = docs[pointer]; - return true; + return doc = docs[pointer]; } } @@ -153,11 +183,11 @@ docs[pointer] = doc = termDocs.doc(); freqs[pointer] = termDocs.freq(); } else { - doc = Integer.MAX_VALUE; + doc = NO_MORE_DOCS; } - return result; + return doc; } - + /** Returns an explanation of the score for a document. *
When this method is used, the {@link #next()} method * and the {@link #score(HitCollector)} method should not be used. Index: src/java/org/apache/lucene/search/function/CustomScoreQuery.java =================================================================== --- src/java/org/apache/lucene/search/function/CustomScoreQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/function/CustomScoreQuery.java (working copy) @@ -367,41 +367,53 @@ this.vScores = new float[valSrcScorers.length]; } - /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */ + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - boolean hasNext = subQueryScorer.next(); - if (hasNext) { - for(int i = 0; i < valSrcScorers.length; i++) { - valSrcScorers[i].skipTo(subQueryScorer.doc()); + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { + int doc = subQueryScorer.nextDoc(); + if (doc != NO_MORE_DOCS) { + for (int i = 0; i < valSrcScorers.length; i++) { + valSrcScorers[i].advance(doc); } } - return hasNext; + return doc; } - /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc() */ + /** @deprecated use {@link #docID()} instead. */ public int doc() { return subQueryScorer.doc(); } + public int docID() { + return subQueryScorer.docID(); + } + /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */ public float score() throws IOException { - for(int i = 0; i < valSrcScorers.length; i++) { + for (int i = 0; i < valSrcScorers.length; i++) { vScores[i] = valSrcScorers[i].score(); } - return qWeight * customScore(subQueryScorer.doc(), subQueryScorer.score(), vScores); + return qWeight * customScore(subQueryScorer.docID(), subQueryScorer.score(), vScores); } - /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */ + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { - boolean hasNext = subQueryScorer.skipTo(target); - if (hasNext) { - for (int i = 0; i < valSrcScorers.length; i++) { - valSrcScorers[i].skipTo(subQueryScorer.doc()); + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { + int doc = subQueryScorer.advance(target); + if (doc != NO_MORE_DOCS) { + for (int i = 0; i < valSrcScorers.length; i++) { + valSrcScorers[i].advance(doc); } } - return hasNext; + return doc; } - + /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */ public Explanation explain(int doc) throws IOException { Explanation subQueryExpl = weight.subQueryWeight.explain(reader,doc); Index: src/java/org/apache/lucene/search/function/ValueSourceQuery.java =================================================================== --- src/java/org/apache/lucene/search/function/ValueSourceQuery.java (revision 780809) +++ src/java/org/apache/lucene/search/function/ValueSourceQuery.java (working copy) @@ -115,6 +115,7 @@ private final float qWeight; private final DocValues vals; private final TermDocs termDocs; + private int doc = -1; // constructor private ValueSourceScorer(Similarity similarity, IndexReader reader, ValueSourceWeight w) throws IOException { @@ -126,26 +127,37 @@ termDocs = reader.termDocs(null); } - /*(non-Javadoc) @see org.apache.lucene.search.Scorer#next() */ + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { return termDocs.next(); } - /*(non-Javadoc) @see org.apache.lucene.search.Scorer#doc() - */ + public int nextDoc() throws IOException { + return doc = termDocs.next() ? termDocs.doc() : NO_MORE_DOCS; + } + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return termDocs.doc(); } + public int docID() { + return doc; + } + /*(non-Javadoc) @see org.apache.lucene.search.Scorer#score() */ public float score() throws IOException { return qWeight * vals.floatVal(termDocs.doc()); } - /*(non-Javadoc) @see org.apache.lucene.search.Scorer#skipTo(int) */ + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { return termDocs.skipTo(target); } + + public int advance(int target) throws IOException { + return doc = termDocs.skipTo(target) ? termDocs.doc() : NO_MORE_DOCS; + } /*(non-Javadoc) @see org.apache.lucene.search.Scorer#explain(int) */ public Explanation explain(int doc) throws IOException { Index: src/java/org/apache/lucene/search/spans/SpanScorer.java =================================================================== --- src/java/org/apache/lucene/search/spans/SpanScorer.java (revision 780809) +++ src/java/org/apache/lucene/search/spans/SpanScorer.java (working copy) @@ -33,6 +33,7 @@ protected byte[] norms; protected float value; + /** @deprecated not needed anymore */ protected boolean firstTime = true; protected boolean more = true; @@ -46,33 +47,46 @@ this.norms = norms; this.weight = weight; this.value = weight.getValue(); - doc = -1; + if (this.spans.next()) { + doc = -1; + } else { + doc = NO_MORE_DOCS; + more = false; + } } + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() throws IOException { - if (firstTime) { - more = spans.next(); - firstTime = false; + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { + if (!setFreqCurrentDoc()) { + doc = NO_MORE_DOCS; } - return setFreqCurrentDoc(); + return doc; } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) throws IOException { - if (firstTime) { - more = spans.skipTo(target); - firstTime = false; + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { + if (!more) { + return doc = NO_MORE_DOCS; } - if (! more) { - return false; - } if (spans.doc() < target) { // setFreqCurrentDoc() leaves spans.doc() ahead more = spans.skipTo(target); } - return setFreqCurrentDoc(); + if (!setFreqCurrentDoc()) { + doc = NO_MORE_DOCS; + } + return doc; } - + protected boolean setFreqCurrentDoc() throws IOException { - if (! more) { + if (!more) { return false; } doc = spans.doc(); @@ -85,7 +99,10 @@ return true; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { return doc; } + + public int docID() { return doc; } public float score() throws IOException { float raw = getSimilarity().tf(freq) * value; // raw score @@ -95,9 +112,9 @@ public Explanation explain(final int doc) throws IOException { Explanation tfExplanation = new Explanation(); - skipTo(doc); + int expDoc = advance(doc); - float phraseFreq = (doc() == doc) ? freq : 0.0f; + float phraseFreq = (expDoc == doc) ? freq : 0.0f; tfExplanation.setValue(getSimilarity().tf(phraseFreq)); tfExplanation.setDescription("tf(phraseFreq=" + phraseFreq + ")"); Index: src/java/org/apache/lucene/util/DocIdBitSet.java =================================================================== --- src/java/org/apache/lucene/util/DocIdBitSet.java (revision 780809) +++ src/java/org/apache/lucene/util/DocIdBitSet.java (working copy) @@ -18,6 +18,7 @@ */ import java.util.BitSet; + import org.apache.lucene.search.DocIdSet; import org.apache.lucene.search.DocIdSetIterator; @@ -50,28 +51,40 @@ this.docId = -1; } + /** @deprecated use {@link #docID()} instead. */ public int doc() { assert docId != -1; return docId; } + public int docID() { + return docId; + } + + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() { // (docId + 1) on next line requires -1 initial value for docNr: - return checkNextDocId(bitSet.nextSetBit(docId + 1)); + return nextDoc() != NO_MORE_DOCS; } + + public int nextDoc() { + // (docId + 1) on next line requires -1 initial value for docNr: + int d = bitSet.nextSetBit(docId + 1); + // -1 returned by BitSet.nextSetBit() when exhausted + docId = d == -1 ? NO_MORE_DOCS : d; + return docId; + } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int skipDocNr) { - return checkNextDocId( bitSet.nextSetBit(skipDocNr)); + return advance(skipDocNr) != NO_MORE_DOCS; } - private boolean checkNextDocId(int d) { - if (d == -1) { // -1 returned by BitSet.nextSetBit() when exhausted - docId = Integer.MAX_VALUE; - return false; - } else { - docId = d; - return true; - } + public int advance(int target) { + int d = bitSet.nextSetBit(target); + // -1 returned by BitSet.nextSetBit() when exhausted + docId = d == -1 ? NO_MORE_DOCS : d; + return docId; } } } Index: src/java/org/apache/lucene/util/OpenBitSetDISI.java =================================================================== --- src/java/org/apache/lucene/util/OpenBitSetDISI.java (revision 780809) +++ src/java/org/apache/lucene/util/OpenBitSetDISI.java (working copy) @@ -47,8 +47,10 @@ * constructor. */ public void inPlaceOr(DocIdSetIterator disi) throws IOException { - while (disi.next() && (disi.doc() < size())) { - fastSet(disi.doc()); + int doc; + long size = size(); + while ((doc = disi.nextDoc()) < size) { + fastSet(doc); } } @@ -60,8 +62,8 @@ */ public void inPlaceAnd(DocIdSetIterator disi) throws IOException { int bitSetDoc = nextSetBit(0); - while ((bitSetDoc != -1) && disi.skipTo(bitSetDoc)) { - int disiDoc = disi.doc(); + int disiDoc; + while (bitSetDoc != -1 && (disiDoc = disi.advance(bitSetDoc)) != DocIdSetIterator.NO_MORE_DOCS) { clear(bitSetDoc, disiDoc); bitSetDoc = nextSetBit(disiDoc + 1); } @@ -77,8 +79,10 @@ * constructor. */ public void inPlaceNot(DocIdSetIterator disi) throws IOException { - while (disi.next() && (disi.doc() < size())) { - fastClear(disi.doc()); + int doc; + long size = size(); + while ((doc = disi.nextDoc()) < size) { + fastClear(doc); } } @@ -89,8 +93,10 @@ * constructor. */ public void inPlaceXor(DocIdSetIterator disi) throws IOException { - while (disi.next() && (disi.doc() < size())) { - fastFlip(disi.doc()); + int doc; + long size = size(); + while ((doc = disi.nextDoc()) < size) { + fastFlip(doc); } } } Index: src/java/org/apache/lucene/util/OpenBitSetIterator.java =================================================================== --- src/java/org/apache/lucene/util/OpenBitSetIterator.java (revision 780809) +++ src/java/org/apache/lucene/util/OpenBitSetIterator.java (working copy) @@ -17,8 +17,6 @@ package org.apache.lucene.util; -import java.io.IOException; - import org.apache.lucene.search.DocIdSetIterator; /** An iterator to iterate over set bits in an OpenBitSet. @@ -35,7 +33,34 @@ // should be faster than accessing an array for each index, and // the total array size is kept smaller (256*sizeof(int))=1K protected final static int[] bitlist={ - 0x0,0x1,0x2,0x21,0x3,0x31,0x32,0x321,0x4,0x41,0x42,0x421,0x43,0x431,0x432,0x4321,0x5,0x51,0x52,0x521,0x53,0x531,0x532,0x5321,0x54,0x541,0x542,0x5421,0x543,0x5431,0x5432,0x54321,0x6,0x61,0x62,0x621,0x63,0x631,0x632,0x6321,0x64,0x641,0x642,0x6421,0x643,0x6431,0x6432,0x64321,0x65,0x651,0x652,0x6521,0x653,0x6531,0x6532,0x65321,0x654,0x6541,0x6542,0x65421,0x6543,0x65431,0x65432,0x654321,0x7,0x71,0x72,0x721,0x73,0x731,0x732,0x7321,0x74,0x741,0x742,0x7421,0x743,0x7431,0x7432,0x74321,0x75,0x751,0x752,0x7521,0x753,0x7531,0x7532,0x75321,0x754,0x7541,0x7542,0x75421,0x7543,0x75431,0x75432,0x754321,0x76,0x761,0x762,0x7621,0x763,0x7631,0x7632,0x76321,0x764,0x7641,0x7642,0x76421,0x7643,0x76431,0x76432,0x764321,0x765,0x7651,0x7652,0x76521,0x7653,0x76531,0x76532,0x765321,0x7654,0x76541,0x76542,0x765421,0x76543,0x765431,0x765432,0x7654321,0x8,0x81,0x82,0x821,0x83,0x831,0x832,0x8321,0x84,0x841,0x842,0x8421,0x843,0x8431,0x8432,0x84321,0x85,0x851,0x852,0x8521,0x853,0x8531,0x8532,0x85321,0x854,0x8541,0x8542,0x85421,0x8543,0x85431,0x85432,0x854321,0x86,0x861,0x862,0x8621,0x863,0x8631,0x8632,0x86321,0x864,0x8641,0x8642,0x86421,0x8643,0x86431,0x86432,0x864321,0x865,0x8651,0x8652,0x86521,0x8653,0x86531,0x86532,0x865321,0x8654,0x86541,0x86542,0x865421,0x86543,0x865431,0x865432,0x8654321,0x87,0x871,0x872,0x8721,0x873,0x8731,0x8732,0x87321,0x874,0x8741,0x8742,0x87421,0x8743,0x87431,0x87432,0x874321,0x875,0x8751,0x8752,0x87521,0x8753,0x87531,0x87532,0x875321,0x8754,0x87541,0x87542,0x875421,0x87543,0x875431,0x875432,0x8754321,0x876,0x8761,0x8762,0x87621,0x8763,0x87631,0x87632,0x876321,0x8764,0x87641,0x87642,0x876421,0x87643,0x876431,0x876432,0x8764321,0x8765,0x87651,0x87652,0x876521,0x87653,0x876531,0x876532,0x8765321,0x87654,0x876541,0x876542,0x8765421,0x876543,0x8765431,0x8765432,0x87654321 + 0x0, 0x1, 0x2, 0x21, 0x3, 0x31, 0x32, 0x321, 0x4, 0x41, 0x42, 0x421, 0x43, + 0x431, 0x432, 0x4321, 0x5, 0x51, 0x52, 0x521, 0x53, 0x531, 0x532, 0x5321, + 0x54, 0x541, 0x542, 0x5421, 0x543, 0x5431, 0x5432, 0x54321, 0x6, 0x61, 0x62, + 0x621, 0x63, 0x631, 0x632, 0x6321, 0x64, 0x641, 0x642, 0x6421, 0x643, + 0x6431, 0x6432, 0x64321, 0x65, 0x651, 0x652, 0x6521, 0x653, 0x6531, 0x6532, + 0x65321, 0x654, 0x6541, 0x6542, 0x65421, 0x6543, 0x65431, 0x65432, 0x654321, + 0x7, 0x71, 0x72, 0x721, 0x73, 0x731, 0x732, 0x7321, 0x74, 0x741, 0x742, + 0x7421, 0x743, 0x7431, 0x7432, 0x74321, 0x75, 0x751, 0x752, 0x7521, 0x753, + 0x7531, 0x7532, 0x75321, 0x754, 0x7541, 0x7542, 0x75421, 0x7543, 0x75431, + 0x75432, 0x754321, 0x76, 0x761, 0x762, 0x7621, 0x763, 0x7631, 0x7632, + 0x76321, 0x764, 0x7641, 0x7642, 0x76421, 0x7643, 0x76431, 0x76432, 0x764321, + 0x765, 0x7651, 0x7652, 0x76521, 0x7653, 0x76531, 0x76532, 0x765321, 0x7654, + 0x76541, 0x76542, 0x765421, 0x76543, 0x765431, 0x765432, 0x7654321, 0x8, + 0x81, 0x82, 0x821, 0x83, 0x831, 0x832, 0x8321, 0x84, 0x841, 0x842, 0x8421, + 0x843, 0x8431, 0x8432, 0x84321, 0x85, 0x851, 0x852, 0x8521, 0x853, 0x8531, + 0x8532, 0x85321, 0x854, 0x8541, 0x8542, 0x85421, 0x8543, 0x85431, 0x85432, + 0x854321, 0x86, 0x861, 0x862, 0x8621, 0x863, 0x8631, 0x8632, 0x86321, 0x864, + 0x8641, 0x8642, 0x86421, 0x8643, 0x86431, 0x86432, 0x864321, 0x865, 0x8651, + 0x8652, 0x86521, 0x8653, 0x86531, 0x86532, 0x865321, 0x8654, 0x86541, + 0x86542, 0x865421, 0x86543, 0x865431, 0x865432, 0x8654321, 0x87, 0x871, + 0x872, 0x8721, 0x873, 0x8731, 0x8732, 0x87321, 0x874, 0x8741, 0x8742, + 0x87421, 0x8743, 0x87431, 0x87432, 0x874321, 0x875, 0x8751, 0x8752, 0x87521, + 0x8753, 0x87531, 0x87532, 0x875321, 0x8754, 0x87541, 0x87542, 0x875421, + 0x87543, 0x875431, 0x875432, 0x8754321, 0x876, 0x8761, 0x8762, 0x87621, + 0x8763, 0x87631, 0x87632, 0x876321, 0x8764, 0x87641, 0x87642, 0x876421, + 0x87643, 0x876431, 0x876432, 0x8764321, 0x8765, 0x87651, 0x87652, 0x876521, + 0x87653, 0x876531, 0x876532, 0x8765321, 0x87654, 0x876541, 0x876542, + 0x8765421, 0x876543, 0x8765431, 0x8765432, 0x87654321 }; /***** the python code that generated bitlist def bits2int(val): @@ -56,14 +81,13 @@ // for efficiency, or have a common root interface? (or // maybe both? could ask for a SetBitsIterator, etc... - private final long[] arr; private final int words; private int i=-1; private long word; private int wordShift; private int indexArray; - private int curDocId; + private int curDocId = -1; public OpenBitSetIterator(OpenBitSet obs) { this(obs.getBits(), obs.getNumWords()); @@ -104,50 +128,24 @@ } ******/ + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() { - if (indexArray==0) { - if (word!=0) { - word >>>= 8; - wordShift += 8; - } - - while (word==0) { - if (++i >= words) { - curDocId = -1; - return false; - } - word = arr[i]; - wordShift =-1; // loop invariant code motion should move this - } - - // after the first time, should I go with a linear search, or - // stick with the binary search in shift? - shift(); - } - - int bitIndex = (indexArray & 0x0f) + wordShift; - indexArray >>>= 4; - // should i<<6 be cached as a separate variable? - // it would only save one cycle in the best circumstances. - curDocId = (i<<6) + bitIndex; - return true; + return nextDoc() != NO_MORE_DOCS; } - /** Moves iterator to the next doc and returns its id; - returns -1 when this iterator is exhausted. */ public int nextDoc() { - if (indexArray==0) { - if (word!=0) { + if (indexArray == 0) { + if (word != 0) { word >>>= 8; wordShift += 8; } - while (word==0) { + while (word == 0) { if (++i >= words) { - return curDocId = -1; + return curDocId = NO_MORE_DOCS; } word = arr[i]; - wordShift =-1; // loop invariant code motion should move this + wordShift = -1; // loop invariant code motion should move this } // after the first time, should I go with a linear search, or @@ -162,27 +160,30 @@ return curDocId = (i<<6) + bitIndex; } + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int target) { - indexArray=0; + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) { + indexArray = 0; i = target >> 6; - if (i>=words) { - word =0; // setup so next() will also return -1 - curDocId = -1; - return false; + if (i >= words) { + word = 0; // setup so next() will also return -1 + return curDocId = NO_MORE_DOCS; } wordShift = target & 0x3f; word = arr[i] >>> wordShift; - if (word !=0) { + if (word != 0) { wordShift--; // compensate for 1 based arrIndex } else { - while (word ==0) { + while (word == 0) { if (++i >= words) { - curDocId = -1; - return false; + return curDocId = NO_MORE_DOCS; } word = arr[i]; } - wordShift =-1; + wordShift = -1; } shift(); @@ -191,44 +192,16 @@ indexArray >>>= 4; // should i<<6 be cached as a separate variable? // it would only save one cycle in the best circumstances. - curDocId = (i<<6) + bitIndex; - return true; - } - - /** Behaves like {@link #skipTo(int)} and returns the docId the iterator - * skipped to; returns -1 if no valid document could be skipped to. */ - public int next(int fromIndex) { - indexArray=0; - i = fromIndex >> 6; - if (i>=words) { - word =0; // setup so next() will also return -1 - return curDocId = -1; - } - wordShift = fromIndex & 0x3f; - word = arr[i] >>> wordShift; - if (word !=0) { - wordShift--; // compensate for 1 based arrIndex - } else { - while (word ==0) { - if (++i >= words) { - return curDocId = -1; - } - word = arr[i]; - } - wordShift =-1; - } - - shift(); - - int bitIndex = (indexArray & 0x0f) + wordShift; - indexArray >>>= 4; - // should i<<6 be cached as a separate variable? - // it would only save one cycle in the best circumstances. return curDocId = (i<<6) + bitIndex; } - + + /** @deprecated use {@link #docID()} instead. */ public int doc() { - return this.curDocId; + return curDocId; } + public int docID() { + return curDocId; + } + } Index: src/java/org/apache/lucene/util/ScorerDocQueue.java =================================================================== --- src/java/org/apache/lucene/util/ScorerDocQueue.java (revision 780809) +++ src/java/org/apache/lucene/util/ScorerDocQueue.java (working copy) @@ -20,6 +20,8 @@ /* Derived from org.apache.lucene.util.PriorityQueue of March 2005 */ import java.io.IOException; + +import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.search.Scorer; /** A ScorerDocQueue maintains a partial ordering of its Scorers such that the @@ -35,14 +37,14 @@ Scorer scorer; int doc; - HeapedScorerDoc(Scorer s) { this(s, s.doc()); } + HeapedScorerDoc(Scorer s) { this(s, s.docID()); } HeapedScorerDoc(Scorer scorer, int doc) { this.scorer = scorer; this.doc = doc; } - void adjust() { doc = scorer.doc(); } + void adjust() { doc = scorer.docID(); } } private HeapedScorerDoc topHSD; // same as heap[1], only for speed @@ -79,7 +81,7 @@ put(scorer); return true; } else { - int docNr = scorer.doc(); + int docNr = scorer.docID(); if ((size > 0) && (! (docNr < topHSD.doc))) { // heap[1] is top() heap[1] = new HeapedScorerDoc(scorer, docNr); downHeap(); @@ -113,16 +115,16 @@ } public final boolean topNextAndAdjustElsePop() throws IOException { - return checkAdjustElsePop( topHSD.scorer.next()); + return checkAdjustElsePop(topHSD.scorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS); } public final boolean topSkipToAndAdjustElsePop(int target) throws IOException { - return checkAdjustElsePop( topHSD.scorer.skipTo(target)); + return checkAdjustElsePop(topHSD.scorer.advance(target) != DocIdSetIterator.NO_MORE_DOCS); } private boolean checkAdjustElsePop(boolean cond) { if (cond) { // see also adjustTop - topHSD.doc = topHSD.scorer.doc(); + topHSD.doc = topHSD.scorer.docID(); } else { // see also popNoResult heap[1] = heap[size]; // move last to first heap[size] = null; Index: src/java/org/apache/lucene/util/SortedVIntList.java =================================================================== --- src/java/org/apache/lucene/util/SortedVIntList.java (revision 780809) +++ src/java/org/apache/lucene/util/SortedVIntList.java (working copy) @@ -24,10 +24,15 @@ import org.apache.lucene.search.DocIdSetIterator; /** - * Store and iterate sorted integers in compressed form in RAM. - *
The code for compressing the differences between ascending integers was - * borrowed from {@link org.apache.lucene.store.IndexInput} and - * {@link org.apache.lucene.store.IndexOutput}. + * Stores and iterate on sorted integers in compressed form in RAM.
+ * The code for compressing the differences between ascending integers was + * borrowed from {@link org.apache.lucene.store.IndexInput} and + * {@link org.apache.lucene.store.IndexOutput}. + *

+ * NOTE: this class assumes the stored integers are doc Ids (hence why it + * extends {@link DocIdSet}). Therefore its {@link #iterator()} assumes {@value + * DocIdSetIterator#NO_MORE_DOCS} can be used as sentinel. If you intent to use + * this value, then make sure it's not used during search flow. */ public class SortedVIntList extends DocIdSet { /** When a BitSet has fewer than 1 in BITS2VINTLIST_SIZE bits set, @@ -99,8 +104,9 @@ */ public SortedVIntList(DocIdSetIterator docIdSetIterator) throws IOException { SortedVIntListBuilder builder = new SortedVIntListBuilder(); - while (docIdSetIterator.next()) { - builder.addInt(docIdSetIterator.doc()); + int doc; + while ((doc = docIdSetIterator.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + builder.addInt(doc); } builder.done(); } @@ -181,6 +187,7 @@ return new DocIdSetIterator() { int bytePos = 0; int lastInt = 0; + int doc = -1; private void advance() { // See org.apache.lucene.store.IndexInput.readVInt() @@ -192,26 +199,43 @@ } } + /** @deprecated use {@link #docID()} instead. */ public int doc() {return lastInt;} + public int docID() { + return doc; + } + + /** @deprecated use {@link #nextDoc()} instead. */ public boolean next() { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() { if (bytePos >= lastBytePos) { - return false; + doc = NO_MORE_DOCS; } else { advance(); - return true; + doc = lastInt; } + return doc; } - + + /** @deprecated use {@link #advance(int)} instead. */ public boolean skipTo(int docNr) { + return advance(docNr) != NO_MORE_DOCS; + } + + public int advance(int target) { while (bytePos < lastBytePos) { advance(); - if (lastInt >= docNr) { // No skipping to docNr available. - return true; + if (lastInt >= target) { + return doc = lastInt; } } - return false; + return doc = NO_MORE_DOCS; } + }; } } Index: src/test/org/apache/lucene/search/JustCompileSearch.java =================================================================== --- src/test/org/apache/lucene/search/JustCompileSearch.java (revision 780809) +++ src/test/org/apache/lucene/search/JustCompileSearch.java (working copy) @@ -1,580 +1,613 @@ -package org.apache.lucene.search; - -/** - * 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. - */ - -import java.io.IOException; - -import org.apache.lucene.document.Document; -import org.apache.lucene.document.FieldSelector; -import org.apache.lucene.index.CorruptIndexException; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermPositions; -import org.apache.lucene.util.PriorityQueue; - -/** - * Holds all implementations of classes in the o.a.l.search package as a - * back-compatibility test. It does not run any tests per-se, however if - * someone adds a method to an interface or abstract method to an abstract - * class, one of the implementations here will fail to compile and so we know - * back-compat policy was violated. - */ -final class JustCompileSearch { - - private static final String UNSUPPORTED_MSG = "unsupported: used for back-compat testing only !"; - - static final class JustCompileSearchable implements Searchable { - - public void close() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Document doc(int i) throws CorruptIndexException, IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Document doc(int n, FieldSelector fieldSelector) - throws CorruptIndexException, IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int docFreq(Term term) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int[] docFreqs(Term[] terms) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Explanation explain(Weight weight, int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int maxDoc() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Query rewrite(Query query) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void search(Weight weight, Filter filter, HitCollector results) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void search(Weight weight, Filter filter, Collector collector) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public TopDocs search(Weight weight, Filter filter, int n) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileSearcher extends Searcher { - - public void close() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Document doc(int i) throws CorruptIndexException, IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int docFreq(Term term) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Explanation explain(Weight weight, int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int maxDoc() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Query rewrite(Query query) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void search(Weight weight, Filter filter, HitCollector results) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void search(Weight weight, Filter filter, Collector results) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public TopDocs search(Weight weight, Filter filter, int n) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Document doc(int n, FieldSelector fieldSelector) - throws CorruptIndexException, IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileCollector extends Collector { - - public void collect(int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void setNextReader(IndexReader reader, int docBase) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void setScorer(Scorer scorer) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileDocIdSet extends DocIdSet { - - public DocIdSetIterator iterator() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileDocIdSetIterator extends DocIdSetIterator { - - public int doc() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean next() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean skipTo(int target) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileFieldCache implements FieldCache { - - public Object getAuto(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public byte[] getBytes(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public byte[] getBytes(IndexReader reader, String field, ByteParser parser) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - /** @deprecated */ - public Comparable[] getCustom(IndexReader reader, String field, - SortComparator comparator) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float[] getFloats(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float[] getFloats(IndexReader reader, String field, - FloatParser parser) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int[] getInts(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int[] getInts(IndexReader reader, String field, IntParser parser) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public short[] getShorts(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public short[] getShorts(IndexReader reader, String field, - ShortParser parser) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public StringIndex getStringIndex(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public String[] getStrings(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileExtendedFieldCache implements ExtendedFieldCache { - - public double[] getDoubles(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public double[] getDoubles(IndexReader reader, String field, - DoubleParser parser) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public long[] getLongs(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public long[] getLongs(IndexReader reader, String field, LongParser parser) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Object getAuto(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public byte[] getBytes(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public byte[] getBytes(IndexReader reader, String field, ByteParser parser) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - /** @deprecated */ - public Comparable[] getCustom(IndexReader reader, String field, - SortComparator comparator) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float[] getFloats(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float[] getFloats(IndexReader reader, String field, - FloatParser parser) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int[] getInts(IndexReader reader, String field) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int[] getInts(IndexReader reader, String field, IntParser parser) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public short[] getShorts(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public short[] getShorts(IndexReader reader, String field, - ShortParser parser) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public StringIndex getStringIndex(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public String[] getStrings(IndexReader reader, String field) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileExtendedFieldCacheLongParser implements ExtendedFieldCache.LongParser { - - public long parseLong(String string) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileExtendedFieldCacheDoubleParser implements ExtendedFieldCache.DoubleParser { - - public double parseDouble(String string) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileFieldComparator extends FieldComparator { - - public int compare(int slot1, int slot2) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int compareBottom(int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void copy(int slot, int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void setBottom(int slot) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int sortType() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Comparable value(int slot) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileFieldComparatorSource extends FieldComparatorSource { - - public FieldComparator newComparator(String fieldname, int numHits, - int sortPos, boolean reversed) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileFilter extends Filter { - // Filter is just an abstract class with no abstract methods. However it is - // still added here in case someone will add abstract methods in the future. - } - - static final class JustCompileFilteredDocIdSet extends FilteredDocIdSet { - - public JustCompileFilteredDocIdSet(DocIdSet innerSet) { - super(innerSet); - } - - protected boolean match(int docid) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileFilteredDocIdSetIterator extends FilteredDocIdSetIterator { - - public JustCompileFilteredDocIdSetIterator(DocIdSetIterator innerIter) { - super(innerIter); - } - - protected boolean match(int doc) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileFilteredTermEnum extends FilteredTermEnum { - - public float difference() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - protected boolean endEnum() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - protected boolean termCompare(Term term) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileMultiTermQuery extends MultiTermQuery { - - protected FilteredTermEnum getEnum(IndexReader reader) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompilePhraseScorer extends PhraseScorer { - - JustCompilePhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, - Similarity similarity, byte[] norms) { - super(weight, tps, offsets, similarity, norms); - } - - protected float phraseFreq() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileQuery extends Query { - - public String toString(String field) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileScorer extends Scorer { - - protected JustCompileScorer(Similarity similarity) { - super(similarity); - } - - public Explanation explain(int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float score() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int doc() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean next() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean skipTo(int target) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileSimilarity extends Similarity { - - public float coord(int overlap, int maxOverlap) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float idf(int docFreq, int numDocs) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float lengthNorm(String fieldName, int numTokens) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float queryNorm(float sumOfSquaredWeights) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float sloppyFreq(int distance) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float tf(float freq) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileSpanFilter extends SpanFilter { - - public SpanFilterResult bitSpans(IndexReader reader) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileTopDocsCollector extends TopDocsCollector { - - protected JustCompileTopDocsCollector(PriorityQueue pq) { - super(pq); - } - - public void collect(int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void setNextReader(IndexReader reader, int docBase) - throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void setScorer(Scorer scorer) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileWeight implements Weight { - - public Explanation explain(IndexReader reader, int doc) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Query getQuery() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float getValue() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public void normalize(float norm) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Scorer scorer(IndexReader reader) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public float sumOfSquaredWeights() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - -} +package org.apache.lucene.search; + +/** + * 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. + */ + +import java.io.IOException; + +import org.apache.lucene.document.Document; +import org.apache.lucene.document.FieldSelector; +import org.apache.lucene.index.CorruptIndexException; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.Term; +import org.apache.lucene.index.TermPositions; +import org.apache.lucene.util.PriorityQueue; + +/** + * Holds all implementations of classes in the o.a.l.search package as a + * back-compatibility test. It does not run any tests per-se, however if + * someone adds a method to an interface or abstract method to an abstract + * class, one of the implementations here will fail to compile and so we know + * back-compat policy was violated. + */ +final class JustCompileSearch { + + private static final String UNSUPPORTED_MSG = "unsupported: used for back-compat testing only !"; + + static final class JustCompileSearchable implements Searchable { + + public void close() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Document doc(int i) throws CorruptIndexException, IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Document doc(int n, FieldSelector fieldSelector) + throws CorruptIndexException, IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int docFreq(Term term) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int[] docFreqs(Term[] terms) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Explanation explain(Weight weight, int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int maxDoc() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Query rewrite(Query query) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void search(Weight weight, Filter filter, HitCollector results) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void search(Weight weight, Filter filter, Collector collector) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public TopDocs search(Weight weight, Filter filter, int n) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileSearcher extends Searcher { + + public void close() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Document doc(int i) throws CorruptIndexException, IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int docFreq(Term term) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Explanation explain(Weight weight, int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int maxDoc() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Query rewrite(Query query) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void search(Weight weight, Filter filter, HitCollector results) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void search(Weight weight, Filter filter, Collector results) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public TopDocs search(Weight weight, Filter filter, int n) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public TopFieldDocs search(Weight weight, Filter filter, int n, Sort sort) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Document doc(int n, FieldSelector fieldSelector) + throws CorruptIndexException, IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileCollector extends Collector { + + public void collect(int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void setNextReader(IndexReader reader, int docBase) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void setScorer(Scorer scorer) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileDocIdSet extends DocIdSet { + + public DocIdSetIterator iterator() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileDocIdSetIterator extends DocIdSetIterator { + + /** @deprecated delete in 3.0 */ + public int doc() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int docID() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated delete in 3.0 */ + public boolean next() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated delete in 3.0 */ + public boolean skipTo(int target) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int nextDoc() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int advance(int target) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + } + + static final class JustCompileFieldCache implements FieldCache { + + public Object getAuto(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public byte[] getBytes(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public byte[] getBytes(IndexReader reader, String field, ByteParser parser) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated */ + public Comparable[] getCustom(IndexReader reader, String field, + SortComparator comparator) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float[] getFloats(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float[] getFloats(IndexReader reader, String field, + FloatParser parser) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int[] getInts(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int[] getInts(IndexReader reader, String field, IntParser parser) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public short[] getShorts(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public short[] getShorts(IndexReader reader, String field, + ShortParser parser) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public StringIndex getStringIndex(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public String[] getStrings(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileExtendedFieldCache implements ExtendedFieldCache { + + public double[] getDoubles(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public double[] getDoubles(IndexReader reader, String field, + DoubleParser parser) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public long[] getLongs(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public long[] getLongs(IndexReader reader, String field, LongParser parser) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Object getAuto(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public byte[] getBytes(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public byte[] getBytes(IndexReader reader, String field, ByteParser parser) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated */ + public Comparable[] getCustom(IndexReader reader, String field, + SortComparator comparator) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float[] getFloats(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float[] getFloats(IndexReader reader, String field, + FloatParser parser) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int[] getInts(IndexReader reader, String field) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int[] getInts(IndexReader reader, String field, IntParser parser) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public short[] getShorts(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public short[] getShorts(IndexReader reader, String field, + ShortParser parser) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public StringIndex getStringIndex(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public String[] getStrings(IndexReader reader, String field) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileExtendedFieldCacheLongParser implements ExtendedFieldCache.LongParser { + + public long parseLong(String string) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileExtendedFieldCacheDoubleParser implements ExtendedFieldCache.DoubleParser { + + public double parseDouble(String string) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileFieldComparator extends FieldComparator { + + public int compare(int slot1, int slot2) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int compareBottom(int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void copy(int slot, int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void setBottom(int slot) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void setNextReader(IndexReader reader, int docBase, int numSlotsFull) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int sortType() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Comparable value(int slot) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileFieldComparatorSource extends FieldComparatorSource { + + public FieldComparator newComparator(String fieldname, int numHits, + int sortPos, boolean reversed) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileFilter extends Filter { + // Filter is just an abstract class with no abstract methods. However it is + // still added here in case someone will add abstract methods in the future. + } + + static final class JustCompileFilteredDocIdSet extends FilteredDocIdSet { + + public JustCompileFilteredDocIdSet(DocIdSet innerSet) { + super(innerSet); + } + + protected boolean match(int docid) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileFilteredDocIdSetIterator extends FilteredDocIdSetIterator { + + public JustCompileFilteredDocIdSetIterator(DocIdSetIterator innerIter) { + super(innerIter); + } + + protected boolean match(int doc) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileFilteredTermEnum extends FilteredTermEnum { + + public float difference() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + protected boolean endEnum() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + protected boolean termCompare(Term term) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileMultiTermQuery extends MultiTermQuery { + + protected FilteredTermEnum getEnum(IndexReader reader) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompilePhraseScorer extends PhraseScorer { + + JustCompilePhraseScorer(Weight weight, TermPositions[] tps, int[] offsets, + Similarity similarity, byte[] norms) { + super(weight, tps, offsets, similarity, norms); + } + + protected float phraseFreq() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileQuery extends Query { + + public String toString(String field) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileScorer extends Scorer { + + protected JustCompileScorer(Similarity similarity) { + super(similarity); + } + + protected boolean score(Collector collector, int max, int firstDocID) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Explanation explain(int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float score() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated delete in 3.0 */ + public int doc() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int docID() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated delete in 3.0. */ + public boolean next() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + /** @deprecated delete in 3.0. */ + public boolean skipTo(int target) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int nextDoc() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int advance(int target) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + } + + static final class JustCompileSimilarity extends Similarity { + + public float coord(int overlap, int maxOverlap) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float idf(int docFreq, int numDocs) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float lengthNorm(String fieldName, int numTokens) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float queryNorm(float sumOfSquaredWeights) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float sloppyFreq(int distance) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float tf(float freq) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileSpanFilter extends SpanFilter { + + public SpanFilterResult bitSpans(IndexReader reader) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileTopDocsCollector extends TopDocsCollector { + + protected JustCompileTopDocsCollector(PriorityQueue pq) { + super(pq); + } + + public void collect(int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void setNextReader(IndexReader reader, int docBase) + throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void setScorer(Scorer scorer) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileWeight implements Weight { + + public Explanation explain(IndexReader reader, int doc) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Query getQuery() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float getValue() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public void normalize(float norm) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Scorer scorer(IndexReader reader) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public float sumOfSquaredWeights() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + +} Index: src/test/org/apache/lucene/search/QueryUtils.java =================================================================== --- src/test/org/apache/lucene/search/QueryUtils.java (revision 780809) +++ src/test/org/apache/lucene/search/QueryUtils.java (working copy) @@ -1,13 +1,13 @@ package org.apache.lucene.search; -import junit.framework.TestCase; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import junit.framework.Assert; + import org.apache.lucene.index.IndexReader; /** @@ -56,17 +56,17 @@ } public static void checkEqual(Query q1, Query q2) { - TestCase.assertEquals(q1, q2); - TestCase.assertEquals(q1.hashCode(), q2.hashCode()); + Assert.assertEquals(q1, q2); + Assert.assertEquals(q1.hashCode(), q2.hashCode()); } public static void checkUnequal(Query q1, Query q2) { - TestCase.assertTrue(!q1.equals(q2)); - TestCase.assertTrue(!q2.equals(q1)); + Assert.assertTrue(!q1.equals(q2)); + Assert.assertTrue(!q2.equals(q1)); // possible this test can fail on a hash collision... if that // happens, please change test to use a different example. - TestCase.assertTrue(q1.hashCode() != q2.hashCode()); + Assert.assertTrue(q1.hashCode() != q2.hashCode()); } /** deep check that explanations of a query 'score' correctly */ @@ -169,8 +169,9 @@ try { int op = order[(opidx[0]++)%order.length]; //System.out.println(op==skip_op ? "skip("+(sdoc[0]+1)+")":"next()"); - boolean more = op==skip_op ? scorer.skipTo(sdoc[0]+1) : scorer.next(); - sdoc[0] = scorer.doc(); + boolean more = op == skip_op ? scorer.advance(sdoc[0] + 1) != DocIdSetIterator.NO_MORE_DOCS + : scorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS; + sdoc[0] = scorer.docID(); float scorerScore = scorer.score(); float scorerScore2 = scorer.score(); float scoreDiff = Math.abs(score-scorerScore); @@ -204,8 +205,9 @@ // make sure next call to scorer is false. int op = order[(opidx[0]++)%order.length]; //System.out.println(op==skip_op ? "last: skip()":"last: next()"); - boolean more = op==skip_op ? scorer.skipTo(sdoc[0]+1) : scorer.next(); - TestCase.assertFalse(more); + boolean more = (op == skip_op ? scorer.advance(sdoc[0] + 1) : scorer + .nextDoc()) != DocIdSetIterator.NO_MORE_DOCS; + Assert.assertFalse(more); } } @@ -228,11 +230,11 @@ for (int i=lastDoc[0]+1; i<=doc; i++) { Weight w = q.weight(s); Scorer scorer = w.scorer(s.getIndexReader()); - TestCase.assertTrue("query collected "+doc+" but skipTo("+i+") says no more docs!",scorer.skipTo(i)); - TestCase.assertEquals("query collected "+doc+" but skipTo("+i+") got to "+scorer.doc(),doc,scorer.doc()); + Assert.assertTrue("query collected "+doc+" but skipTo("+i+") says no more docs!",scorer.advance(i) != DocIdSetIterator.NO_MORE_DOCS); + Assert.assertEquals("query collected "+doc+" but skipTo("+i+") got to "+scorer.docID(),doc,scorer.docID()); float skipToScore = scorer.score(); - TestCase.assertEquals("unstable skipTo("+i+") score!",skipToScore,scorer.score(),maxDiff); - TestCase.assertEquals("query assigned doc "+doc+" a score of <"+score+"> but skipTo("+i+") has <"+skipToScore+">!",score,skipToScore,maxDiff); + Assert.assertEquals("unstable skipTo("+i+") score!",skipToScore,scorer.score(),maxDiff); + Assert.assertEquals("query assigned doc "+doc+" a score of <"+score+"> but skipTo("+i+") has <"+skipToScore+">!",score,skipToScore,maxDiff); } lastDoc[0] = doc; } catch (IOException e) { @@ -245,8 +247,8 @@ }); Weight w = q.weight(s); Scorer scorer = w.scorer(s.getIndexReader()); - boolean more = scorer.skipTo(lastDoc[0]+1); + boolean more = scorer.advance(lastDoc[0] + 1) != DocIdSetIterator.NO_MORE_DOCS; if (more) - TestCase.assertFalse("query's last doc was "+lastDoc[0]+" but skipTo("+(lastDoc[0]+1)+") got to "+scorer.doc(),more); + Assert.assertFalse("query's last doc was "+lastDoc[0]+" but skipTo("+(lastDoc[0]+1)+") got to "+scorer.docID(),more); } } Index: src/test/org/apache/lucene/search/TestBoolean2.java =================================================================== --- src/test/org/apache/lucene/search/TestBoolean2.java (revision 780809) +++ src/test/org/apache/lucene/search/TestBoolean2.java (working copy) @@ -18,23 +18,18 @@ */ -import org.apache.lucene.store.RAMDirectory; +import java.util.Random; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.Term; - import org.apache.lucene.analysis.WhitespaceAnalyzer; - import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; - +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.Term; +import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; -import org.apache.lucene.queryParser.ParseException; - +import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.LuceneTestCase; -import java.util.Random; - /** Test BooleanQuery2 against BooleanQuery by overriding the standard query parser. * This also tests the scoring order of BooleanQuery. */ @@ -158,13 +153,14 @@ int tot=0; + BooleanQuery q1 = null; try { // increase number of iterations for more complete testing for (int i=0; i<1000; i++) { int level = rnd.nextInt(3); - BooleanQuery q1 = randBoolQuery(new Random(rnd.nextLong()), level, field, vals, null); - + q1 = randBoolQuery(new Random(rnd.nextLong()), level, field, vals, null); + // Can't sort by relevance since floating point numbers may not quite // match up. Sort sort = Sort.INDEXORDER; @@ -181,6 +177,10 @@ CheckHits.checkEqual(q1, hits1, hits2); } + } catch (Exception e) { + // For easier debugging + System.out.println("failed query: " + q1); + throw e; } finally { // even when a test fails. BooleanQuery.setAllowDocsOutOfOrder(false); } Index: src/test/org/apache/lucene/search/TestBooleanScorer.java =================================================================== --- src/test/org/apache/lucene/search/TestBooleanScorer.java (revision 780809) +++ src/test/org/apache/lucene/search/TestBooleanScorer.java (working copy) @@ -18,6 +18,7 @@ */ import java.io.IOException; +import java.util.Arrays; import org.apache.lucene.analysis.WhitespaceAnalyzer; import org.apache.lucene.document.Document; @@ -74,5 +75,41 @@ } + public void testEmptyBucketWithMoreDocs() throws Exception { + // This test checks the logic of nextDoc() when all sub scorers have docs + // beyond the first bucket (for example). Currently, the code relies on the + // 'more' variable to work properly, and this test ensures that if the logic + // changes, we have a test to back it up. + + Similarity sim = Similarity.getDefault(); + Scorer[] scorers = new Scorer[] {new Scorer(sim) { + private int doc = -1; + public Explanation explain(int doc) throws IOException { return null; } + public float score() throws IOException { return 0; } + /** @deprecated delete in 3.0. */ + public int doc() { return 3000; } + public int docID() { return doc; } + /** @deprecated delete in 3.0 */ + public boolean next() throws IOException { return nextDoc() != NO_MORE_DOCS; } + + public int nextDoc() throws IOException { + return doc = doc == -1 ? 3000 : NO_MORE_DOCS; + } + /** @deprecated delete in 3.0 */ + public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { + return doc = target <= 3000 ? 3000 : NO_MORE_DOCS; + } + + }}; + BooleanScorer bs = new BooleanScorer(sim, 1, Arrays.asList(scorers), null); + + assertEquals("should have received 3000", 3000, bs.nextDoc()); + assertEquals("should have received NO_MORE_DOCS", DocIdSetIterator.NO_MORE_DOCS, bs.nextDoc()); + } + } Index: src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java =================================================================== --- src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java (revision 780809) +++ src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java (working copy) @@ -136,10 +136,9 @@ final Weight dw = dq.weight(s); final Scorer ds = dw.scorer(r); - final boolean skipOk = ds.skipTo(3); + final boolean skipOk = ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS; if (skipOk) { - fail("firsttime skipTo found a match? ... " + - r.document(ds.doc()).get("id")); + fail("firsttime skipTo found a match? ... " + r.document(ds.docID()).get("id")); } } @@ -152,8 +151,8 @@ final Weight dw = dq.weight(s); final Scorer ds = dw.scorer(r); - assertTrue("firsttime skipTo found no match", ds.skipTo(3)); - assertEquals("found wrong docid", "d4", r.document(ds.doc()).get("id")); + assertTrue("firsttime skipTo found no match", ds.advance(3) != DocIdSetIterator.NO_MORE_DOCS); + assertEquals("found wrong docid", "d4", r.document(ds.docID()).get("id")); } Index: src/test/org/apache/lucene/search/TestDocIdSet.java =================================================================== --- src/test/org/apache/lucene/search/TestDocIdSet.java (revision 780809) +++ src/test/org/apache/lucene/search/TestDocIdSet.java (working copy) @@ -34,28 +34,38 @@ public DocIdSetIterator iterator() { return new DocIdSetIterator() { - int docid=-1; - //@Override + int docid = -1; + + /** @deprecated use {@link #docID()} instead. */ public int doc() { return docid; } + public int docID() { + return docid; + } + + /** @deprecated use {@link #nextDoc()} instead. */ + public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + //@Override - public boolean next() throws IOException { + public int nextDoc() throws IOException { docid++; - return (docid doc()); - - return true; + return advance(target) != NO_MORE_DOCS; } + + //@Override + public int advance(int target) throws IOException { + while (nextDoc() < target) {} + return docid; + } }; } }; @@ -70,10 +80,11 @@ DocIdSetIterator iter = filteredSet.iterator(); ArrayList/**/ list = new ArrayList/**/(); - if (iter.skipTo(3)) { - list.add(new Integer(iter.doc())); - while(iter.next()) { - list.add(new Integer(iter.doc())); + int doc = iter.advance(3); + if (doc != DocIdSetIterator.NO_MORE_DOCS) { + list.add(Integer.valueOf(doc)); + while((doc = iter.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + list.add(Integer.valueOf(doc)); } } Index: src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java =================================================================== --- src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java (revision 780809) +++ src/test/org/apache/lucene/search/TestPositiveScoresOnlyCollector.java (working copy) @@ -1,85 +1,98 @@ -package org.apache.lucene.search; - -/** - * 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. - */ - -import java.io.IOException; - -import org.apache.lucene.util.LuceneTestCase; - -public class TestPositiveScoresOnlyCollector extends LuceneTestCase { - - private static final class SimpleScorer extends Scorer { - private int idx = -1; - - public SimpleScorer() { - super(null); - } - - public Explanation explain(int doc) throws IOException { return null; } - - public float score() throws IOException { - return idx == scores.length ? Float.NaN : scores[idx]; - } - - public int doc() { return idx; } - - public boolean next() throws IOException { - return ++idx == scores.length; - } - - public boolean skipTo(int target) throws IOException { - idx = target; - return idx >= scores.length; - } - } - - // The scores must have positive as well as negative values - private static final float[] scores = new float[] { 0.7767749f, -1.7839992f, - 8.9925785f, 7.9608946f, -0.07948637f, 2.6356435f, 7.4950366f, 7.1490803f, - -8.108544f, 4.961808f, 2.2423935f, -7.285586f, 4.6699767f }; - - public void testNegativeScores() throws Exception { - - // The Top*Collectors previously filtered out documents with <= scores. This - // behavior has changed. This test checks that if PositiveOnlyScoresFilter - // wraps one of these collectors, documents with <= 0 scores are indeed - // filtered. - - int numPositiveScores = 0; - for (int i = 0; i < scores.length; i++) { - if (scores[i] > 0) { - ++numPositiveScores; - } - } - - Scorer s = new SimpleScorer(); - TopDocsCollector tdc = TopScoreDocCollector.create(scores.length, true); - Collector c = new PositiveScoresOnlyCollector(tdc); - c.setScorer(s); - while (!s.next()) { - c.collect(0); - } - TopDocs td = tdc.topDocs(); - ScoreDoc[] sd = td.scoreDocs; - assertEquals(numPositiveScores, td.totalHits); - for (int i = 0; i < sd.length; i++) { - assertTrue("only positive scores should return: " + sd[i].score, sd[i].score > 0); - } - } - -} +package org.apache.lucene.search; + +/** + * 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. + */ + +import java.io.IOException; + +import org.apache.lucene.util.LuceneTestCase; + +public class TestPositiveScoresOnlyCollector extends LuceneTestCase { + + private static final class SimpleScorer extends Scorer { + private int idx = -1; + + public SimpleScorer() { + super(null); + } + + public Explanation explain(int doc) throws IOException { return null; } + + public float score() throws IOException { + return idx == scores.length ? Float.NaN : scores[idx]; + } + + /** @deprecated use {@link #docID()} instead. */ + public int doc() { return idx; } + + public int docID() { return idx; } + + /** @deprecated use {@link #nextDoc()} instead. */ + public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { + return ++idx != scores.length ? idx : NO_MORE_DOCS; + } + + /** @deprecated use {@link #advance(int)} instead. */ + public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { + idx = target; + return idx < scores.length ? idx : NO_MORE_DOCS; + } + } + + // The scores must have positive as well as negative values + private static final float[] scores = new float[] { 0.7767749f, -1.7839992f, + 8.9925785f, 7.9608946f, -0.07948637f, 2.6356435f, 7.4950366f, 7.1490803f, + -8.108544f, 4.961808f, 2.2423935f, -7.285586f, 4.6699767f }; + + public void testNegativeScores() throws Exception { + + // The Top*Collectors previously filtered out documents with <= scores. This + // behavior has changed. This test checks that if PositiveOnlyScoresFilter + // wraps one of these collectors, documents with <= 0 scores are indeed + // filtered. + + int numPositiveScores = 0; + for (int i = 0; i < scores.length; i++) { + if (scores[i] > 0) { + ++numPositiveScores; + } + } + + Scorer s = new SimpleScorer(); + TopDocsCollector tdc = TopScoreDocCollector.create(scores.length, true); + Collector c = new PositiveScoresOnlyCollector(tdc); + c.setScorer(s); + while (s.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { + c.collect(0); + } + TopDocs td = tdc.topDocs(); + ScoreDoc[] sd = td.scoreDocs; + assertEquals(numPositiveScores, td.totalHits); + for (int i = 0; i < sd.length; i++) { + assertTrue("only positive scores should return: " + sd[i].score, sd[i].score > 0); + } + } + +} Index: src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java =================================================================== --- src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java (revision 780809) +++ src/test/org/apache/lucene/search/TestScoreCachingWrappingScorer.java (working copy) @@ -1,111 +1,126 @@ -package org.apache.lucene.search; - -/** - * 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. - */ - -import java.io.IOException; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.util.LuceneTestCase; - -public class TestScoreCachingWrappingScorer extends LuceneTestCase { - - private static final class SimpleScorer extends Scorer { - private int idx = 0; - private int doc = -1; - - public SimpleScorer() { - super(null); - } - - public Explanation explain(int doc) throws IOException { return null; } - - public float score() throws IOException { - // advance idx on purpose, so that consecutive calls to score will get - // different results. This is to emulate computation of a score. If - // ScoreCachingWrappingScorer is used, this should not be called more than - // once per document. - return idx == scores.length ? Float.NaN : scores[idx++]; - } - - public int doc() { return doc; } - - public boolean next() throws IOException { - return ++doc == scores.length; - } - - public boolean skipTo(int target) throws IOException { - doc = target; - return doc >= scores.length; - } - } - - private static final class ScoreCachingCollector extends Collector { - - private int idx = 0; - private Scorer scorer; - float[] mscores; - - public ScoreCachingCollector(int numToCollect) { - mscores = new float[numToCollect]; - } - - public void collect(int doc) throws IOException { - // just a sanity check to avoid IOOB. - if (idx == mscores.length) { - return; - } - - // just call score() a couple of times and record the score. - mscores[idx] = scorer.score(); - mscores[idx] = scorer.score(); - mscores[idx] = scorer.score(); - ++idx; - } - - public void setNextReader(IndexReader reader, int docBase) - throws IOException { - } - - public void setScorer(Scorer scorer) throws IOException { - this.scorer = new ScoreCachingWrappingScorer(scorer); - } - - } - - private static final float[] scores = new float[] { 0.7767749f, 1.7839992f, - 8.9925785f, 7.9608946f, 0.07948637f, 2.6356435f, 7.4950366f, 7.1490803f, - 8.108544f, 4.961808f, 2.2423935f, 7.285586f, 4.6699767f }; - - public void testGetScores() throws Exception { - - Scorer s = new SimpleScorer(); - ScoreCachingCollector scc = new ScoreCachingCollector(scores.length); - scc.setScorer(s); - - // We need to iterate on the scorer so that its doc() advances. - while (!s.next()) { - scc.collect(s.doc()); - } - - for (int i = 0; i < scores.length; i++) { - assertEquals(scores[i], scc.mscores[i], 0f); - } - - } - -} +package org.apache.lucene.search; + +/** + * 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. + */ + +import java.io.IOException; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.util.LuceneTestCase; + +public class TestScoreCachingWrappingScorer extends LuceneTestCase { + + private static final class SimpleScorer extends Scorer { + private int idx = 0; + private int doc = -1; + + public SimpleScorer() { + super(null); + } + + public Explanation explain(int doc) throws IOException { return null; } + + public float score() throws IOException { + // advance idx on purpose, so that consecutive calls to score will get + // different results. This is to emulate computation of a score. If + // ScoreCachingWrappingScorer is used, this should not be called more than + // once per document. + return idx == scores.length ? Float.NaN : scores[idx++]; + } + + /** @deprecated use {@link #docID()} instead. */ + public int doc() { return doc; } + + public int docID() { return doc; } + + /** @deprecated use {@link #nextDoc()} instead. */ + public boolean next() throws IOException { + return nextDoc() != NO_MORE_DOCS; + } + + public int nextDoc() throws IOException { + return ++doc < scores.length ? doc : NO_MORE_DOCS; + } + + /** @deprecated use {@link #advance(int)} instead. */ + public boolean skipTo(int target) throws IOException { + return advance(target) != NO_MORE_DOCS; + } + + public int advance(int target) throws IOException { + doc = target; + return doc < scores.length ? doc : NO_MORE_DOCS; + } + + } + + private static final class ScoreCachingCollector extends Collector { + + private int idx = 0; + private Scorer scorer; + float[] mscores; + + public ScoreCachingCollector(int numToCollect) { + mscores = new float[numToCollect]; + } + + public void collect(int doc) throws IOException { + // just a sanity check to avoid IOOB. + if (idx == mscores.length) { + return; + } + + // just call score() a couple of times and record the score. + mscores[idx] = scorer.score(); + mscores[idx] = scorer.score(); + mscores[idx] = scorer.score(); + ++idx; + } + + public void setNextReader(IndexReader reader, int docBase) + throws IOException { + } + + public void setScorer(Scorer scorer) throws IOException { + this.scorer = new ScoreCachingWrappingScorer(scorer); + } + + } + + private static final float[] scores = new float[] { 0.7767749f, 1.7839992f, + 8.9925785f, 7.9608946f, 0.07948637f, 2.6356435f, 7.4950366f, 7.1490803f, + 8.108544f, 4.961808f, 2.2423935f, 7.285586f, 4.6699767f }; + + public void testGetScores() throws Exception { + + Scorer s = new SimpleScorer(); + ScoreCachingCollector scc = new ScoreCachingCollector(scores.length); + scc.setScorer(s); + + // We need to iterate on the scorer so that its doc() advances. + int doc; + while ((doc = s.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) { + scc.collect(doc); + } + + for (int i = 0; i < scores.length; i++) { + assertEquals(scores[i], scc.mscores[i], 0f); + } + + } + +} Index: src/test/org/apache/lucene/search/TestSpanQueryFilter.java =================================================================== --- src/test/org/apache/lucene/search/TestSpanQueryFilter.java (revision 780809) +++ src/test/org/apache/lucene/search/TestSpanQueryFilter.java (working copy) @@ -16,7 +16,9 @@ * limitations under the License. */ -import org.apache.lucene.util.LuceneTestCase; +import java.util.Iterator; +import java.util.List; + import org.apache.lucene.analysis.SimpleAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; @@ -27,11 +29,8 @@ import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.English; +import org.apache.lucene.util.LuceneTestCase; -import java.util.BitSet; -import java.util.Iterator; -import java.util.List; - public class TestSpanQueryFilter extends LuceneTestCase { @@ -77,7 +76,7 @@ int getDocIdSetSize(DocIdSet docIdSet) throws Exception { int size = 0; DocIdSetIterator it = docIdSet.iterator(); - while (it.next()) { + while (it.nextDoc() != DocIdSetIterator.NO_MORE_DOCS) { size++; } return size; @@ -85,7 +84,7 @@ public void assertContainsDocId(String msg, DocIdSet docIdSet, int docId) throws Exception { DocIdSetIterator it = docIdSet.iterator(); - assertTrue(msg, it.skipTo(docId)); - assertTrue(msg, it.doc() == docId); + assertTrue(msg, it.advance(docId) != DocIdSetIterator.NO_MORE_DOCS); + assertTrue(msg, it.docID() == docId); } } Index: src/test/org/apache/lucene/search/TestTermScorer.java =================================================================== --- src/test/org/apache/lucene/search/TestTermScorer.java (revision 780809) +++ src/test/org/apache/lucene/search/TestTermScorer.java (working copy) @@ -134,11 +134,11 @@ TermScorer ts = new TermScorer(weight, indexReader.termDocs(allTerm), indexSearcher.getSimilarity(), indexReader.norms(FIELD)); - assertTrue("next did not return a doc", ts.next() == true); + assertTrue("next did not return a doc", ts.nextDoc() != DocIdSetIterator.NO_MORE_DOCS); assertTrue("score is not correct", ts.score() == 1.6931472f); - assertTrue("next did not return a doc", ts.next() == true); + assertTrue("next did not return a doc", ts.nextDoc() != DocIdSetIterator.NO_MORE_DOCS); assertTrue("score is not correct", ts.score() == 1.6931472f); - assertTrue("next returned a doc and it should not have", ts.next() == false); + assertTrue("next returned a doc and it should not have", ts.nextDoc() == DocIdSetIterator.NO_MORE_DOCS); } public void testSkipTo() throws Exception { @@ -151,7 +151,7 @@ TermScorer ts = new TermScorer(weight, indexReader.termDocs(allTerm), indexSearcher.getSimilarity(), indexReader.norms(FIELD)); - assertTrue("Didn't skip", ts.skipTo(3) == true); + assertTrue("Didn't skip", ts.advance(3) != DocIdSetIterator.NO_MORE_DOCS); //The next doc should be doc 5 assertTrue("doc should be number 5", ts.doc() == 5); } Index: src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java =================================================================== --- src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java (revision 780809) +++ src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java (working copy) @@ -1,112 +1,125 @@ -package org.apache.lucene.search.spans; - -/** - * 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. - */ - -import java.io.IOException; -import java.util.Collection; - -import org.apache.lucene.index.IndexReader; - -/** - * Holds all implementations of classes in the o.a.l.s.spans package as a - * back-compatibility test. It does not run any tests per-se, however if - * someone adds a method to an interface or abstract method to an abstract - * class, one of the implementations here will fail to compile and so we know - * back-compat policy was violated. - */ -final class JustCompileSearchSpans { - - private static final String UNSUPPORTED_MSG = "unsupported: used for back-compat testing only !"; - - static final class JustCompileSpans implements Spans { - - public int doc() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int end() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean next() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean skipTo(int target) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int start() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompileSpanQuery extends SpanQuery { - - public String getField() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Spans getSpans(IndexReader reader) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public Collection getTerms() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public String toString(String field) { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - - static final class JustCompilePayloadSpans implements PayloadSpans { - - public Collection getPayload() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean isPayloadAvailable() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int doc() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int end() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean next() throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public boolean skipTo(int target) throws IOException { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - public int start() { - throw new UnsupportedOperationException(UNSUPPORTED_MSG); - } - - } - -} +package org.apache.lucene.search.spans; + +/** + * 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. + */ + +import java.io.IOException; +import java.util.Collection; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.search.Similarity; +import org.apache.lucene.search.Weight; + +/** + * Holds all implementations of classes in the o.a.l.s.spans package as a + * back-compatibility test. It does not run any tests per-se, however if + * someone adds a method to an interface or abstract method to an abstract + * class, one of the implementations here will fail to compile and so we know + * back-compat policy was violated. + */ +final class JustCompileSearchSpans { + + private static final String UNSUPPORTED_MSG = "unsupported: used for back-compat testing only !"; + + static final class JustCompileSpans implements Spans { + + public int doc() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int end() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public boolean next() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public boolean skipTo(int target) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int start() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileSpanQuery extends SpanQuery { + + public String getField() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Spans getSpans(IndexReader reader) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public Collection getTerms() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public String toString(String field) { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompilePayloadSpans implements PayloadSpans { + + public Collection getPayload() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public boolean isPayloadAvailable() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int doc() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int end() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public boolean next() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public boolean skipTo(int target) throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + public int start() { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + + } + + static final class JustCompileSpanScorer extends SpanScorer { + + protected JustCompileSpanScorer(Spans spans, Weight weight, + Similarity similarity, byte[] norms) throws IOException { + super(spans, weight, similarity, norms); + } + + protected boolean setFreqCurrentDoc() throws IOException { + throw new UnsupportedOperationException(UNSUPPORTED_MSG); + } + } +} Index: src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java =================================================================== --- src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java (revision 780809) +++ src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java (working copy) @@ -165,8 +165,7 @@ SpanNearQuery q = makeQuery(); Weight w = q.createWeight(searcher); Scorer s = w.scorer(searcher.getIndexReader()); - assertEquals(true, s.skipTo(1)); - assertEquals(1, s.doc()); + assertEquals(1, s.advance(1)); } /** * not a direct test of NearSpans, but a demonstration of how/when Index: src/test/org/apache/lucene/search/spans/TestSpans.java =================================================================== --- src/test/org/apache/lucene/search/spans/TestSpans.java (revision 780809) +++ src/test/org/apache/lucene/search/spans/TestSpans.java (working copy) @@ -17,6 +17,7 @@ * limitations under the License. */ +import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.CheckHits; @@ -392,11 +393,11 @@ Scorer spanScorer = snq.weight(searcher).scorer(searcher.getIndexReader()); - assertTrue("first doc", spanScorer.next()); - assertEquals("first doc number", spanScorer.doc(), 11); + assertTrue("first doc", spanScorer.nextDoc() != DocIdSetIterator.NO_MORE_DOCS); + assertEquals("first doc number", spanScorer.docID(), 11); float score = spanScorer.score(); assertTrue("first doc score should be zero, " + score, score == 0.0f); - assertTrue("no second doc", ! spanScorer.next()); + assertTrue("no second doc", spanScorer.nextDoc() == DocIdSetIterator.NO_MORE_DOCS); } // LUCENE-1404 Index: src/test/org/apache/lucene/util/TestOpenBitSet.java =================================================================== --- src/test/org/apache/lucene/util/TestOpenBitSet.java (revision 780809) +++ src/test/org/apache/lucene/util/TestOpenBitSet.java (working copy) @@ -20,6 +20,8 @@ import java.util.Random; import java.util.BitSet; +import org.apache.lucene.search.DocIdSetIterator; + /** * @version $Id$ */ @@ -55,12 +57,8 @@ OpenBitSetIterator iterator = new OpenBitSetIterator(b); do { aa = a.nextSetBit(aa+1); - if (rand.nextBoolean()) - iterator.next(); - else - iterator.skipTo(bb+1); - bb = iterator.doc(); - assertEquals(aa,bb); + bb = rand.nextBoolean() ? iterator.nextDoc() : iterator.advance(bb + 1); + assertEquals(aa == -1 ? DocIdSetIterator.NO_MORE_DOCS : aa, bb); } while (aa>=0); } @@ -69,11 +67,8 @@ OpenBitSetIterator iterator = new OpenBitSetIterator(b); do { aa = a.nextSetBit(aa+1); - if (rand.nextBoolean()) - bb = iterator.nextDoc(); - else - bb = iterator.next(bb+1); - assertEquals(aa,bb); + bb = rand.nextBoolean() ? iterator.nextDoc() : iterator.advance(bb + 1); + assertEquals(aa == -1 ? DocIdSetIterator.NO_MORE_DOCS : aa, bb); } while (aa>=0); } Index: src/test/org/apache/lucene/util/TestSortedVIntList.java =================================================================== --- src/test/org/apache/lucene/util/TestSortedVIntList.java (revision 780809) +++ src/test/org/apache/lucene/util/TestSortedVIntList.java (working copy) @@ -42,10 +42,10 @@ } DocIdSetIterator m = vintList.iterator(); for (int i = 0; i < ints.length; i++) { - assertTrue("No end of Matcher at: " + i, m.next()); - assertEquals(ints[i], m.doc()); + assertTrue("No end of Matcher at: " + i, m.nextDoc() != DocIdSetIterator.NO_MORE_DOCS); + assertEquals(ints[i], m.docID()); } - assertTrue("End of Matcher", (! m.next())); + assertTrue("End of Matcher", m.nextDoc() == DocIdSetIterator.NO_MORE_DOCS); } void tstVIntList( @@ -143,9 +143,6 @@ public void test02() { tstInts(new int[] {0}); } - public void test03() { - tstInts(new int[] {0,Integer.MAX_VALUE}); - } public void test04a() { tstInts(new int[] {0, VB2 - 1}); } Index: tags/lucene_2_4_back_compat_tests_20090601a/src/java/org/apache/lucene/util/OpenBitSetIterator.java =================================================================== --- tags/lucene_2_4_back_compat_tests_20090601a/src/java/org/apache/lucene/util/OpenBitSetIterator.java (revision 780962) +++ tags/lucene_2_4_back_compat_tests_20090601a/src/java/org/apache/lucene/util/OpenBitSetIterator.java (working copy) @@ -197,7 +197,7 @@ /** Behaves like {@link #skipTo(int)} and returns the docId the iterator * skipped to; returns -1 if no valid document could be skipped to. */ - public int next(int fromIndex) { + public int advance(int fromIndex) { indexArray=0; i = fromIndex >> 6; if (i>=words) { Index: tags/lucene_2_4_back_compat_tests_20090601a/src/test/org/apache/lucene/util/TestOpenBitSet.java =================================================================== --- tags/lucene_2_4_back_compat_tests_20090601a/src/test/org/apache/lucene/util/TestOpenBitSet.java (revision 780962) +++ tags/lucene_2_4_back_compat_tests_20090601a/src/test/org/apache/lucene/util/TestOpenBitSet.java (working copy) @@ -62,7 +62,7 @@ else iterator.skipTo(bb+1); bb = iterator.doc(); - assertEquals(aa,bb); + assertEquals(aa == -1 ? Integer.MAX_VALUE : aa,bb); } while (aa>=0); } @@ -74,8 +74,8 @@ if (rand.nextBoolean()) bb = iterator.nextDoc(); else - bb = iterator.next(bb+1); - assertEquals(aa,bb); + bb = iterator.advance(bb + 1); + assertEquals(aa == -1 ? Integer.MAX_VALUE : aa,bb); } while (aa>=0); } Index: tags/lucene_2_4_back_compat_tests_20090601a/src/test/org/apache/lucene/util/TestSortedVIntList.java =================================================================== --- tags/lucene_2_4_back_compat_tests_20090601a/src/test/org/apache/lucene/util/TestSortedVIntList.java (revision 780962) +++ tags/lucene_2_4_back_compat_tests_20090601a/src/test/org/apache/lucene/util/TestSortedVIntList.java (working copy) @@ -143,9 +143,6 @@ public void test02() { tstInts(new int[] {0}); } - public void test03() { - tstInts(new int[] {0,Integer.MAX_VALUE}); - } public void test04a() { tstInts(new int[] {0, VB2 - 1}); }