add --shared
[pylucene.git] / lucene-java-3.4.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    */
84   public int getTotalNumberOfTerms() {
85     return query.getTotalNumberOfTerms();
86   }
87   
88   /**
89    * Expert: Resets the counting of unique terms.
90    * Do this before executing the filter.
91    * @see #getTotalNumberOfTerms
92    */
93   public void clearTotalNumberOfTerms() {
94     query.clearTotalNumberOfTerms();
95   }
96   
97   /**
98    * Returns a DocIdSet with documents that should be
99    * permitted in search results.
100    */
101   @Override
102   public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
103     final TermEnum enumerator = query.getEnum(reader);
104     try {
105       // if current term in enum is null, the enum is empty -> shortcut
106       if (enumerator.term() == null)
107         return DocIdSet.EMPTY_DOCIDSET;
108       // else fill into a FixedBitSet
109       final FixedBitSet bitSet = new FixedBitSet(reader.maxDoc());
110       final int[] docs = new int[32];
111       final int[] freqs = new int[32];
112       TermDocs termDocs = reader.termDocs();
113       try {
114         int termCount = 0;
115         do {
116           Term term = enumerator.term();
117           if (term == null)
118             break;
119           termCount++;
120           termDocs.seek(term);
121           while (true) {
122             final int count = termDocs.read(docs, freqs);
123             if (count != 0) {
124               for(int i=0;i<count;i++) {
125                 bitSet.set(docs[i]);
126               }
127             } else {
128               break;
129             }
130           }
131         } while (enumerator.next());
132
133         query.incTotalNumberOfTerms(termCount);
134
135       } finally {
136         termDocs.close();
137       }
138       return bitSet;
139     } finally {
140       enumerator.close();
141     }
142   }
143
144 }