001: package org.apache.lucene.search;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import org.apache.lucene.search.Filter;
021: import org.apache.lucene.index.Term;
022: import org.apache.lucene.index.IndexReader;
023: import org.apache.lucene.index.TermEnum;
024: import org.apache.lucene.index.TermDocs;
025:
026: import java.util.BitSet;
027: import java.io.IOException;
028:
029: /**
030: *
031: * @version $Id$
032: */
033: public class PrefixFilter extends Filter {
034: protected final Term prefix;
035:
036: public PrefixFilter(Term prefix) {
037: this .prefix = prefix;
038: }
039:
040: public Term getPrefix() {
041: return prefix;
042: }
043:
044: public BitSet bits(IndexReader reader) throws IOException {
045: final BitSet bitSet = new BitSet(reader.maxDoc());
046: new PrefixGenerator(prefix) {
047: public void handleDoc(int doc) {
048: bitSet.set(doc);
049: }
050: }.generate(reader);
051: return bitSet;
052: }
053:
054: /** Prints a user-readable version of this query. */
055: public String toString() {
056: StringBuffer buffer = new StringBuffer();
057: buffer.append("PrefixFilter(");
058: buffer.append(prefix.toString());
059: buffer.append(")");
060: return buffer.toString();
061: }
062: }
063:
064: // keep this protected until I decide if it's a good way
065: // to separate id generation from collection (or should
066: // I just reuse hitcollector???)
067: interface IdGenerator {
068: public void generate(IndexReader reader) throws IOException;
069:
070: public void handleDoc(int doc);
071: }
072:
073: abstract class PrefixGenerator implements IdGenerator {
074: protected final Term prefix;
075:
076: PrefixGenerator(Term prefix) {
077: this .prefix = prefix;
078: }
079:
080: public void generate(IndexReader reader) throws IOException {
081: TermEnum enumerator = reader.terms(prefix);
082: TermDocs termDocs = reader.termDocs();
083:
084: try {
085:
086: String prefixText = prefix.text();
087: String prefixField = prefix.field();
088: do {
089: Term term = enumerator.term();
090: if (term != null && term.text().startsWith(prefixText)
091: && term.field() == prefixField) // interned comparison
092: {
093: termDocs.seek(term);
094: while (termDocs.next()) {
095: handleDoc(termDocs.doc());
096: }
097: } else {
098: break;
099: }
100: } while (enumerator.next());
101: } finally {
102: termDocs.close();
103: enumerator.close();
104: }
105: }
106: }
|