From 290355e80ce88f7f3c84e2c545380fee36f34aee Mon Sep 17 00:00:00 2001 From: Uwe Schindler Date: Sun, 19 Aug 2012 09:16:24 +0000 Subject: [PATCH] Fix javadocs of Fields.size(), use FilteredIterator from StoredFields branch. Return -1 for Fields.size() in FieldFilterAtomicReader. If this breaks some test, we found a bug and have to change test to respect -1 (which is valid return value) git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1374713 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/lucene/index/Fields.java | 7 +- .../apache/lucene/util/FilterIterator.java | 72 +++++++++++++++++++ .../lucene/index/FieldFilterAtomicReader.java | 53 ++------------ 3 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 lucene/core/src/java/org/apache/lucene/util/FilterIterator.java diff --git a/lucene/core/src/java/org/apache/lucene/index/Fields.java b/lucene/core/src/java/org/apache/lucene/index/Fields.java index 4ea80152919..0e2e726691d 100644 --- a/lucene/core/src/java/org/apache/lucene/index/Fields.java +++ b/lucene/core/src/java/org/apache/lucene/index/Fields.java @@ -33,10 +33,9 @@ public abstract class Fields implements Iterable { * null if the field does not exist. */ public abstract Terms terms(String field) throws IOException; - /** Returns the number of terms for all fields, or -1 if this - * measure isn't stored by the codec. Note that, just like - * other term measures, this measure does not take deleted - * documents into account. */ + /** Returns the number of fields or -1 if the number of + * distinct field names is unknown. If >= 0, + * {@link #iterator} will return as many field names. */ public abstract int size() throws IOException; /** Returns the number of terms for all fields, or -1 if this diff --git a/lucene/core/src/java/org/apache/lucene/util/FilterIterator.java b/lucene/core/src/java/org/apache/lucene/util/FilterIterator.java new file mode 100644 index 00000000000..f562448b783 --- /dev/null +++ b/lucene/core/src/java/org/apache/lucene/util/FilterIterator.java @@ -0,0 +1,72 @@ +package org.apache.lucene.util; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * 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. + */ + +/** + * An {@link Iterator} implementation that filters elements with a boolean predicate. + * @see #predicateFunction + */ +public abstract class FilterIterator implements Iterator { + + private final Iterator iterator; + private T next = null; + private boolean nextIsSet = false; + + /** returns true, if this element should be returned by {@link next()}. */ + protected abstract boolean predicateFunction(T object); + + public FilterIterator(Iterator baseIterator) { + this.iterator = baseIterator; + } + + public final boolean hasNext() { + return nextIsSet || setNext(); + } + + public final T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + assert nextIsSet; + try { + return next; + } finally { + nextIsSet = false; + next = null; + } + } + + public final void remove() { + throw new UnsupportedOperationException(); + } + + private boolean setNext() { + while (iterator.hasNext()) { + final T object = iterator.next(); + if (predicateFunction(object)) { + next = object; + nextIsSet = true; + return true; + } + } + return false; + } +} diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/FieldFilterAtomicReader.java b/lucene/test-framework/src/java/org/apache/lucene/index/FieldFilterAtomicReader.java index 3c98870a302..6744e2bda9a 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/index/FieldFilterAtomicReader.java +++ b/lucene/test-framework/src/java/org/apache/lucene/index/FieldFilterAtomicReader.java @@ -20,9 +20,10 @@ package org.apache.lucene.index; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; -import java.util.NoSuchElementException; import java.util.Set; +import org.apache.lucene.util.FilterIterator; + /** * A {@link FilterAtomicReader} that exposes only a subset * of fields from the underlying wrapped reader. @@ -139,56 +140,16 @@ public final class FieldFilterAtomicReader extends FilterAtomicReader { @Override public int size() { - // TODO: add faster implementation! - int c = 0; - final Iterator it = iterator(); - while (it.hasNext()) { - it.next(); - c++; - } - return c; + // this information is not cheap, return -1 like MultiFields does: + return -1; } @Override public Iterator iterator() { - final Iterator in = super.iterator(); - return new Iterator() { - private String cached = null; - + return new FilterIterator(super.iterator()) { @Override - public String next() { - if (cached != null) { - String next = cached; - cached = null; - return next; - } else { - String next = doNext(); - if (next == null) { - throw new NoSuchElementException(); - } else { - return next; - } - } - } - - @Override - public boolean hasNext() { - return cached != null || (cached = doNext()) != null; - } - - private String doNext() { - while (in.hasNext()) { - String field = in.next(); - if (hasField(field)) { - return field; - } - } - return null; - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); + protected boolean predicateFunction(String field) { + return hasField(field); } }; }