pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / src / java / org / apache / lucene / search / MultiTermQueryWrapperFilter.java
1 package org.apache.lucene.search;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.io.IOException;
21
22 import org.apache.lucene.index.IndexReader;
23 import org.apache.lucene.index.Term;
24 import org.apache.lucene.index.TermDocs;
25 import org.apache.lucene.index.TermEnum;
26 import org.apache.lucene.util.FixedBitSet;
27
28 /**
29  * A wrapper for {@link MultiTermQuery}, that exposes its
30  * functionality as a {@link Filter}.
31  * <P>
32  * <code>MultiTermQueryWrapperFilter</code> is not designed to
33  * be used by itself. Normally you subclass it to provide a Filter
34  * counterpart for a {@link MultiTermQuery} subclass.
35  * <P>
36  * For example, {@link TermRangeFilter} and {@link PrefixFilter} extend
37  * <code>MultiTermQueryWrapperFilter</code>.
38  * This class also provides the functionality behind
39  * {@link MultiTermQuery#CONSTANT_SCORE_FILTER_REWRITE};
40  * this is why it is not abstract.
41  */
42 public class MultiTermQueryWrapperFilter<Q extends MultiTermQuery> extends Filter {
43     
44   protected final Q query;
45
46   /**
47    * Wrap a {@link MultiTermQuery} as a Filter.
48    */
49   protected MultiTermQueryWrapperFilter(Q query) {
50       this.query = query;
51   }
52   
53   @Override
54   public String toString() {
55     // query.toString should be ok for the filter, too, if the query boost is 1.0f
56     return query.toString();
57   }
58
59   @Override
60   public final boolean equals(final Object o) {
61     if (o==this) return true;
62     if (o==null) return false;
63     if (this.getClass().equals(o.getClass())) {
64       return this.query.equals( ((MultiTermQueryWrapperFilter)o).query );
65     }
66     return false;
67   }
68
69   @Override
70   public final int hashCode() {
71     return query.hashCode();
72   }
73   
74   /**
75    * Expert: Return the number of unique terms visited during execution of the filter.
76    * If there are many of them, you may consider using another filter type
77    * or optimize your total term count in index.
78    * <p>This method is not thread safe, be sure to only call it when no filter is running!
79    * If you re-use the same filter instance for another
80    * search, be sure to first reset the term counter
81    * with {@link #clearTotalNumberOfTerms}.
82    * @see #clearTotalNumberOfTerms
83    * @deprecated Don't use this method, as its not thread safe and useless.
84    */
85   @Deprecated
86   public int getTotalNumberOfTerms() {
87     return query.getTotalNumberOfTerms();
88   }
89   
90   /**
91    * Expert: Resets the counting of unique terms.
92    * Do this before executing the filter.
93    * @see #getTotalNumberOfTerms
94    * @deprecated Don't use this method, as its not thread safe and useless.
95    */
96   @Deprecated
97   public void clearTotalNumberOfTerms() {
98     query.clearTotalNumberOfTerms();
99   }
100   
101   /**
102    * Returns a DocIdSet with documents that should be
103    * permitted in search results.
104    */
105   @Override
106   public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
107     final TermEnum enumerator = query.getEnum(reader);
108     try {
109       // if current term in enum is null, the enum is empty -> shortcut
110       if (enumerator.term() == null)
111         return DocIdSet.EMPTY_DOCIDSET;
112       // else fill into a FixedBitSet
113       final FixedBitSet bitSet = new FixedBitSet(reader.maxDoc());
114       final int[] docs = new int[32];
115       final int[] freqs = new int[32];
116       TermDocs termDocs = reader.termDocs();
117       try {
118         int termCount = 0;
119         do {
120           Term term = enumerator.term();
121           if (term == null)
122             break;
123           termCount++;
124           termDocs.seek(term);
125           while (true) {
126             final int count = termDocs.read(docs, freqs);
127             if (count != 0) {
128               for(int i=0;i<count;i++) {
129                 bitSet.set(docs[i]);
130               }
131             } else {
132               break;
133             }
134           }
135         } while (enumerator.next());
136
137         query.incTotalNumberOfTerms(termCount);
138
139       } finally {
140         termDocs.close();
141       }
142       return bitSet;
143     } finally {
144       enumerator.close();
145     }
146   }
147
148 }