Index: src/java/org/apache/lucene/index/TermsEnum.java =================================================================== --- src/java/org/apache/lucene/index/TermsEnum.java (revision 908452) +++ src/java/org/apache/lucene/index/TermsEnum.java (working copy) @@ -112,4 +112,40 @@ * method many times, so it's best to cache a single * instance & reuse it. */ public abstract BytesRef.Comparator getComparator() throws IOException; + + /** An empty TermsEnum for quickly returning an empty instance e.g. + * in {@link org.apache.lucene.search.MultiTermQuery} */ + public static final TermsEnum EMPTY = new TermsEnum() { + @Override + public SeekStatus seek(BytesRef term) { return SeekStatus.END; } + + @Override + public SeekStatus seek(long ord) { return SeekStatus.END; } + + @Override + public BytesRef term() { return null; } + + @Override + public BytesRef.Comparator getComparator() { + // return an unused dummy to prevent NPE + return BytesRef.getUTF8SortedAsUTF16Comparator(); + } + + @Override + public int docFreq() { return -1; } + + @Override + public long ord() { return -1; } + + @Override + public DocsEnum docs(Bits bits, DocsEnum reuse) { return null; } + + @Override + public DocsAndPositionsEnum docsAndPositions(Bits bits, DocsAndPositionsEnum reuse) { + return null; + } + + @Override + public BytesRef next() { return null; } + }; } Index: src/java/org/apache/lucene/search/AutomatonQuery.java =================================================================== --- src/java/org/apache/lucene/search/AutomatonQuery.java (revision 908452) +++ src/java/org/apache/lucene/search/AutomatonQuery.java (working copy) @@ -73,15 +73,14 @@ protected TermsEnum getTermsEnum(IndexReader reader) throws IOException { // matches nothing if (BasicOperations.isEmpty(automaton)) { - // nocommit -- should we just return null? singleton? - return new EmptyTermsEnum(); + return TermsEnum.EMPTY; } // matches all possible strings if (BasicOperations.isTotal(automaton)) { final Terms terms = MultiFields.getTerms(reader, getField()); // nocommit -- should we just return null? singleton? - return (terms != null) ? terms.iterator() : new EmptyTermsEnum(); + return (terms != null) ? terms.iterator() : TermsEnum.EMPTY; } // matches a fixed string in singleton representation Index: src/java/org/apache/lucene/search/EmptyTermsEnum.java =================================================================== --- src/java/org/apache/lucene/search/EmptyTermsEnum.java (revision 908452) +++ src/java/org/apache/lucene/search/EmptyTermsEnum.java (working copy) @@ -1,57 +0,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 org.apache.lucene.util.BytesRef; -import org.apache.lucene.index.TermsEnum; - -/** - * Subclass of {@code FilteredTermsEnum} that is always empty. - *

- * This can be used by {@link MultiTermQuery}s (if no terms can ever match the query), - * but want to preserve MultiTermQuery semantics such as - * {@link MultiTermQuery#rewriteMethod}. - */ -public final class EmptyTermsEnum extends FilteredTermsEnum { - - /** - * Creates a new EmptyTermsEnum. - */ - public EmptyTermsEnum() { - super((TermsEnum) null); - } - - @Override - /** Always returns {@link AcceptStatus#END}. */ - protected AcceptStatus accept(BytesRef term) { - return AcceptStatus.END; - } - - /** Always returns {@link SeekStatus#END}. */ - @Override - public SeekStatus seek(BytesRef term) { - return SeekStatus.END; - } - - /** Always returns {@link SeekStatus#END}. */ - @Override - public SeekStatus seek(long ord) { - return SeekStatus.END; - } - -} Index: src/java/org/apache/lucene/search/NumericRangeQuery.java =================================================================== --- src/java/org/apache/lucene/search/NumericRangeQuery.java (revision 908452) +++ src/java/org/apache/lucene/search/NumericRangeQuery.java (working copy) @@ -304,7 +304,7 @@ protected TermsEnum getTermsEnum(final IndexReader reader) throws IOException { // very strange: java.lang.Number itsself is not Comparable, but all subclasses used here are return (min != null && max != null && ((Comparable) min).compareTo(max) > 0) ? - new EmptyTermsEnum() : + TermsEnum.EMPTY : new NumericRangeTermsEnum(reader); } Index: src/java/org/apache/lucene/search/PrefixQuery.java =================================================================== --- src/java/org/apache/lucene/search/PrefixQuery.java (revision 908452) +++ src/java/org/apache/lucene/search/PrefixQuery.java (working copy) @@ -53,7 +53,7 @@ protected TermsEnum getTermsEnum(IndexReader reader) throws IOException { if (prefix.text().length() == 0) { final Terms terms = MultiFields.getTerms(reader, getField()); - return (terms != null) ? terms.iterator() : new EmptyTermsEnum(); + return (terms != null) ? terms.iterator() : TermsEnum.EMPTY; } return new PrefixTermsEnum(reader, prefix); } Index: src/java/org/apache/lucene/search/TermRangeQuery.java =================================================================== --- src/java/org/apache/lucene/search/TermRangeQuery.java (revision 908452) +++ src/java/org/apache/lucene/search/TermRangeQuery.java (working copy) @@ -138,13 +138,13 @@ @Override protected TermsEnum getTermsEnum(IndexReader reader) throws IOException { if (collator == null && lowerTerm != null && upperTerm != null && lowerTerm.compareTo(upperTerm) > 0) { - return new EmptyTermsEnum(); + return TermsEnum.EMPTY; } if ((lowerTerm == null || (collator == null && includeLower && "".equals(lowerTerm))) && upperTerm == null) { // NOTE: debateably, the caller should never pass in a // multi reader... final Terms terms = MultiFields.getTerms(reader, field); - return (terms != null) ? terms.iterator() : new EmptyTermsEnum(); + return (terms != null) ? terms.iterator() : TermsEnum.EMPTY; } return new TermRangeTermsEnum(reader, field, lowerTerm, upperTerm, includeLower, includeUpper, collator); Index: src/test/org/apache/lucene/search/TestAutomatonQuery.java =================================================================== --- src/test/org/apache/lucene/search/TestAutomatonQuery.java (revision 908452) +++ src/test/org/apache/lucene/search/TestAutomatonQuery.java (working copy) @@ -25,6 +25,7 @@ import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; +import org.apache.lucene.index.TermsEnum; import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.Version; @@ -218,7 +219,7 @@ .makeEmpty()); // not yet available: assertTrue(aq.getEnum(searcher.getIndexReader()) // instanceof EmptyTermEnum); - assertTrue(aq.getTermsEnum(searcher.getIndexReader()) instanceof EmptyTermsEnum); + assertSame(TermsEnum.EMPTY, aq.getTermsEnum(searcher.getIndexReader())); assertEquals(0, automatonQueryNrHits(aq)); } }