Index: src/java/org/apache/lucene/search/FilteredDocIdSet.java =================================================================== --- src/java/org/apache/lucene/search/FilteredDocIdSet.java (revision 0) +++ src/java/org/apache/lucene/search/FilteredDocIdSet.java (revision 0) @@ -0,0 +1,57 @@ +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. + */ + +/** + * Abstract decorator class for a DocIdSet implementation that provides filtering/validation + * mechanism on a given DocIdSet. + * @see DocIdSet + */ +public abstract class FilteredDocIdSet extends DocIdSet{ + private final DocIdSet _innerSet; + + /** + * Constructor. + * @param innerSet Underlying DocIdSet + */ + public FilteredDocIdSet(DocIdSet innerSet){ + _innerSet = innerSet; + } + + /** + * Validation method to determine whether a docid should be in the result set. + * @param docid docid to be tested + * @return true if input docid should be in the result set, false otherwise. + */ + protected abstract boolean match(int docid); + + /** + * Implementation of the contract to build a DocIdSetIterator. + * @see DocIdSetIterator + * @see FilteredDocIdSetIterator + */ + @Override + public DocIdSetIterator iterator() { + return new FilteredDocIdSetIterator(_innerSet.iterator()){ + protected boolean match(int docid) + { + return FilteredDocIdSet.this.match(docid); + } + }; + } +} Index: src/java/org/apache/lucene/search/FilteredDocIdSetIterator.java =================================================================== --- src/java/org/apache/lucene/search/FilteredDocIdSetIterator.java (revision 0) +++ src/java/org/apache/lucene/search/FilteredDocIdSetIterator.java (revision 0) @@ -0,0 +1,89 @@ +package org.apache.lucene.search; + +import java.io.IOException; + +/** + * 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. + */ + +/** + * Abstract decorator class of a DocIdSetIterator implementation that provides filter/validation + * mechanism on an underlying DocIdSetIterator. + */ +public abstract class FilteredDocIdSetIterator extends DocIdSetIterator{ + protected DocIdSetIterator _innerIter; + private int _currentDoc; + + /** + * Constructor. + * @param innerIter Underlying DocIdSetIterator. + */ + public FilteredDocIdSetIterator(DocIdSetIterator innerIter){ + if (innerIter == null){ + throw new IllegalArgumentException("null iterator"); + } + _innerIter=innerIter; + _currentDoc=-1; + } + + /** + * Validation method to determine whether a docid should be in the result set. + * @param docid docid to be tested + * @return true if input docid should be in the result set, false otherwise. + * @see #FilteredDocIdSetIterator(DocIdSetIterator). + */ + abstract protected boolean match(int doc); + + @Override + public final int doc() { + return _currentDoc; + } + + @Override + public final boolean next() throws IOException{ + while(_innerIter.next()){ + int doc=_innerIter.doc(); + if (match(doc)){ + _currentDoc=doc; + return true; + } + } + return false; + } + + @Override + public final boolean skipTo(int n) throws IOException{ + boolean flag=_innerIter.skipTo(n); + if (flag){ + int doc=_innerIter.doc(); + if (match(doc)){ + _currentDoc=doc; + return true; + } + else{ + while(_innerIter.next()){ + int docid=_innerIter.doc(); + if (match(docid)){ + _currentDoc=docid; + return true; + } + } + return false; + } + } + return flag; + } +} Index: src/test/org/apache/lucene/search/TestDocIdSet.java =================================================================== --- src/test/org/apache/lucene/search/TestDocIdSet.java (revision 0) +++ src/test/org/apache/lucene/search/TestDocIdSet.java (revision 0) @@ -0,0 +1,78 @@ +package org.apache.lucene.search; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; + +import junit.framework.TestCase; + +public class TestDocIdSet extends TestCase { + public void testFilteredDocIdSet() throws Exception + { + final int maxdoc=10; + final DocIdSet innerSet = new DocIdSet(){ + + @Override + public DocIdSetIterator iterator() { + return new DocIdSetIterator() + { + int docid=-1; + @Override + public int doc() { + return docid; + } + + @Override + public boolean next() throws IOException { + docid++; + return (docid doc()); + return true; + } + }; + } + }; + + + DocIdSet filteredSet = new FilteredDocIdSet(innerSet){ + @Override + protected boolean match(int docid) { + return docid%2 == 0; //validate only even docids + } + }; + + DocIdSetIterator iter = filteredSet.iterator(); + ArrayList list = new ArrayList(); + if (iter.skipTo(3)) + { + list.add(iter.doc()); + while(iter.next()) + { + list.add(iter.doc()); + } + } + + int[] docs = new int[list.size()]; + int c=0; + Iterator intIter = list.iterator(); + while(intIter.hasNext()){ + docs[c++] = intIter.next(); + } + int[] answer = new int[]{4,6,8}; + boolean same = Arrays.equals(answer, docs); + if (!same) + { + System.out.println("answer: "+Arrays.toString(answer)); + System.out.println("gotten: "+Arrays.toString(docs)); + fail(); + } + } +}