You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2012/08/13 04:25:21 UTC

svn commit: r1372243 [1/2] - in /lucene/dev/trunk: lucene/ lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/ lucene/core/src/java/org/apache/lucene/codecs/ lucene/core/src/java/org/apache/lucene/codecs/bloom/ lucene/core/src/java/org/apache...

Author: rmuir
Date: Mon Aug 13 02:25:19 2012
New Revision: 1372243

URL: http://svn.apache.org/viewvc?rev=1372243&view=rev
Log:
remove FieldsEnum and replace with Iterator<String>

Added:
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java   (with props)
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/UnmodifiableIterator.java   (with props)
Removed:
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/FieldsEnum.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/MultiFieldsEnum.java
Modified:
    lucene/dev/trunk/lucene/CHANGES.txt
    lucene/dev/trunk/lucene/MIGRATE.txt
    lucene/dev/trunk/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/TestPerfTasksLogic.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTermsReader.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTreeTermsReader.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/FieldsConsumer.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/TermVectorsWriter.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/bloom/BloomFilteringPostingsFormat.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40TermVectorsReader.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/MemoryPostingsFormat.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldPostingsFormat.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextFieldsReader.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextTermVectorsReader.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CoalescedDeletes.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocValues.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/Fields.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/FilterAtomicReader.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/MultiFields.java
    lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/ParallelAtomicReader.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestCodecs.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDoc.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDocCount.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestFilterAtomicReader.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestParallelTermEnum.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPostingsFormat.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPrefixCodedTerms.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSumDocFreq.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestTermVectors.java
    lucene/dev/trunk/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
    lucene/dev/trunk/lucene/misc/src/java/org/apache/lucene/misc/HighFreqTerms.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/asserting/AssertingPostingsFormat.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/ramonly/RAMOnlyPostingsFormat.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/FieldFilterAtomicReader.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java

Modified: lucene/dev/trunk/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/CHANGES.txt?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/CHANGES.txt (original)
+++ lucene/dev/trunk/lucene/CHANGES.txt Mon Aug 13 02:25:19 2012
@@ -27,6 +27,10 @@ API Changes
   otherwise returns the current payload. You can now call it multiple
   times per position if you want. (Robert Muir)
 
+* Removed FieldsEnum. Fields API instead implements Iterable<String>
+  and exposes Iterator, so you can iterate over field names with
+  for (String field : fields) instead.  (Robert Muir)
+
 Bug Fixes
 
 * LUCENE-4297: BooleanScorer2 would multiply the coord() factor

Modified: lucene/dev/trunk/lucene/MIGRATE.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/MIGRATE.txt?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/MIGRATE.txt (original)
+++ lucene/dev/trunk/lucene/MIGRATE.txt Mon Aug 13 02:25:19 2012
@@ -9,7 +9,7 @@ enumeration APIs.  Here are the major ch
     by the BytesRef class (which provides an offset + length "slice"
     into an existing byte[]).
 
-  * Fields are separately enumerated (FieldsEnum) from the terms
+  * Fields are separately enumerated (Fields.iterator()) from the terms
     within each field (TermEnum).  So instead of this:
 
         TermEnum termsEnum = ...;
@@ -20,10 +20,8 @@ enumeration APIs.  Here are the major ch
 
     Do this:
 
-        FieldsEnum fieldsEnum = ...;
-        String field;
-        while((field = fieldsEnum.next()) != null) {
-            TermsEnum termsEnum = fieldsEnum.terms();
+        for(String field : fields) {
+            TermsEnum termsEnum = fields.terms(field);
             BytesRef text;
             while((text = termsEnum.next()) != null) {
               System.out.println("field=" + field + "; text=" + text.utf8ToString());

Modified: lucene/dev/trunk/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/TestPerfTasksLogic.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/TestPerfTasksLogic.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/TestPerfTasksLogic.java (original)
+++ lucene/dev/trunk/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/TestPerfTasksLogic.java Mon Aug 13 02:25:19 2012
@@ -43,7 +43,6 @@ import org.apache.lucene.facet.taxonomy.
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -493,13 +492,13 @@ public class TestPerfTasksLogic extends 
 
     int totalTokenCount2 = 0;
 
-    FieldsEnum fields = MultiFields.getFields(reader).iterator();
-    String fieldName = null;
-    while((fieldName = fields.next()) != null) {
+    Fields fields = MultiFields.getFields(reader);
+
+    for (String fieldName : fields) {
       if (fieldName.equals(DocMaker.ID_FIELD) || fieldName.equals(DocMaker.DATE_MSEC_FIELD) || fieldName.equals(DocMaker.TIME_SEC_FIELD)) {
         continue;
       }
-      Terms terms = fields.terms();
+      Terms terms = fields.terms(fieldName);
       if (terms == null) {
         continue;
       }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTermsReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTermsReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTermsReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTermsReader.java Mon Aug 13 02:25:19 2012
@@ -27,7 +27,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
@@ -40,6 +39,7 @@ import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.DoubleBarrelLRUCache;
+import org.apache.lucene.util.UnmodifiableIterator;
 
 /** Handles a terms dict, but decouples all details of
  *  doc/freqs/positions reading to an instance of {@link
@@ -184,8 +184,8 @@ public class BlockTermsReader extends Fi
   }
 
   @Override
-  public FieldsEnum iterator() {
-    return new TermFieldsEnum();
+  public Iterator<String> iterator() {
+    return new UnmodifiableIterator<String>(fields.keySet().iterator());
   }
 
   @Override
@@ -199,32 +199,6 @@ public class BlockTermsReader extends Fi
     return fields.size();
   }
 
-  // Iterates through all fields
-  private class TermFieldsEnum extends FieldsEnum {
-    final Iterator<FieldReader> it;
-    FieldReader current;
-
-    TermFieldsEnum() {
-      it = fields.values().iterator();
-    }
-
-    @Override
-    public String next() {
-      if (it.hasNext()) {
-        current = it.next();
-        return current.fieldInfo.name;
-      } else {
-        current = null;
-        return null;
-      }
-    }
-    
-    @Override
-    public Terms terms() throws IOException {
-      return current;
-    }
-  }
-
   private class FieldReader extends Terms {
     final long numTerms;
     final FieldInfo fieldInfo;

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTreeTermsReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTreeTermsReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTreeTermsReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/BlockTreeTermsReader.java Mon Aug 13 02:25:19 2012
@@ -31,7 +31,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
@@ -46,6 +45,7 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.StringHelper;
+import org.apache.lucene.util.UnmodifiableIterator;
 import org.apache.lucene.util.automaton.CompiledAutomaton;
 import org.apache.lucene.util.automaton.RunAutomaton;
 import org.apache.lucene.util.automaton.Transition;
@@ -199,8 +199,8 @@ public class BlockTreeTermsReader extend
   }
 
   @Override
-  public FieldsEnum iterator() {
-    return new TermFieldsEnum();
+  public Iterator<String> iterator() {
+    return new UnmodifiableIterator<String>(fields.keySet().iterator());
   }
 
   @Override
@@ -214,32 +214,6 @@ public class BlockTreeTermsReader extend
     return fields.size();
   }
 
-  // Iterates through all fields
-  private class TermFieldsEnum extends FieldsEnum {
-    final Iterator<FieldReader> it;
-    FieldReader current;
-
-    TermFieldsEnum() {
-      it = fields.values().iterator();
-    }
-
-    @Override
-    public String next() {
-      if (it.hasNext()) {
-        current = it.next();
-        return current.fieldInfo.name;
-      } else {
-        current = null;
-        return null;
-      }
-    }
-    
-    @Override
-    public Terms terms() throws IOException {
-      return current;
-    }
-  }
-
   // for debugging
   String brToString(BytesRef b) {
     if (b == null) {

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/FieldsConsumer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/FieldsConsumer.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/FieldsConsumer.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/FieldsConsumer.java Mon Aug 13 02:25:19 2012
@@ -22,7 +22,6 @@ import java.io.IOException;
 
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.MergeState;
 import org.apache.lucene.index.SegmentWriteState; // javadocs
 import org.apache.lucene.index.Terms;
@@ -53,13 +52,10 @@ public abstract class FieldsConsumer imp
   public abstract void close() throws IOException;
 
   public void merge(MergeState mergeState, Fields fields) throws IOException {
-    FieldsEnum fieldsEnum = fields.iterator();
-    assert fieldsEnum != null;
-    String field;
-    while((field = fieldsEnum.next()) != null) {
+    for (String field : fields) {
       mergeState.fieldInfo = mergeState.fieldInfos.fieldInfo(field);
       assert mergeState.fieldInfo != null : "FieldInfo for field is null: "+ field;
-      Terms terms = fieldsEnum.terms();
+      Terms terms = fields.terms(field);
       if (terms != null) {
         final TermsConsumer termsConsumer = addField(mergeState.fieldInfo);
         termsConsumer.merge(mergeState, terms.iterator(null));

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/TermVectorsWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/TermVectorsWriter.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/TermVectorsWriter.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/TermVectorsWriter.java Mon Aug 13 02:25:19 2012
@@ -26,7 +26,6 @@ import org.apache.lucene.index.DocsAndPo
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.MergeState;
 import org.apache.lucene.index.PayloadProcessorProvider.PayloadProcessor;
 import org.apache.lucene.index.PayloadProcessorProvider.ReaderPayloadProcessor;
@@ -211,8 +210,6 @@ public abstract class TermVectorsWriter 
     }
     startDocument(numFields);
     
-    final FieldsEnum fieldsEnum = vectors.iterator();
-    String fieldName;
     String lastFieldName = null;
     
     TermsEnum termsEnum = null;
@@ -221,13 +218,13 @@ public abstract class TermVectorsWriter 
     final ReaderPayloadProcessor readerPayloadProcessor = mergeState.currentReaderPayloadProcessor;
     PayloadProcessor payloadProcessor = null;
 
-    while((fieldName = fieldsEnum.next()) != null) {
+    for(String fieldName : vectors) {
       final FieldInfo fieldInfo = mergeState.fieldInfos.fieldInfo(fieldName);
 
       assert lastFieldName == null || fieldName.compareTo(lastFieldName) > 0: "lastFieldName=" + lastFieldName + " fieldName=" + fieldName;
       lastFieldName = fieldName;
 
-      final Terms terms = fieldsEnum.terms();
+      final Terms terms = vectors.terms(fieldName);
       if (terms == null) {
         // FieldsEnum shouldn't lie...
         continue;

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/bloom/BloomFilteringPostingsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/bloom/BloomFilteringPostingsFormat.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/bloom/BloomFilteringPostingsFormat.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/bloom/BloomFilteringPostingsFormat.java Mon Aug 13 02:25:19 2012
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -35,7 +36,6 @@ import org.apache.lucene.codecs.TermsCon
 import org.apache.lucene.index.DocsAndPositionsEnum;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
@@ -44,7 +44,6 @@ import org.apache.lucene.index.TermsEnum
 import org.apache.lucene.store.DataOutput;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
-import org.apache.lucene.util.AttributeSource;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.FuzzySet;
@@ -187,9 +186,8 @@ public class BloomFilteringPostingsForma
       
     }
     
-    public FieldsEnum iterator() throws IOException {
-      return new BloomFilteredFieldsEnum(delegateFieldsProducer.iterator(),
-          bloomsByFieldName);
+    public Iterator<String> iterator() {
+      return delegateFieldsProducer.iterator();
     }
     
     public void close() throws IOException {
@@ -217,44 +215,6 @@ public class BloomFilteringPostingsForma
       return delegateFieldsProducer.getUniqueTermCount();
     }
     
-    // Not all fields in a segment may be subject to a bloom filter. This class
-    // wraps Terms objects appropriately if a filtering request is present
-    class BloomFilteredFieldsEnum extends FieldsEnum {
-      private FieldsEnum delegateFieldsEnum;
-      private HashMap<String,FuzzySet> bloomsByFieldName;
-      private String currentFieldName;
-      
-      public BloomFilteredFieldsEnum(FieldsEnum iterator,
-          HashMap<String,FuzzySet> bloomsByFieldName) {
-        this.delegateFieldsEnum = iterator;
-        this.bloomsByFieldName = bloomsByFieldName;
-      }
-      
-      public AttributeSource attributes() {
-        return delegateFieldsEnum.attributes();
-      }
-      
-      public String next() throws IOException {
-        currentFieldName = delegateFieldsEnum.next();
-        return currentFieldName;
-      }
-      
-      public Terms terms() throws IOException {
-        FuzzySet filter = bloomsByFieldName.get(currentFieldName);
-        if (filter == null) {
-          return delegateFieldsEnum.terms();
-        } else {
-          Terms result = delegateFieldsEnum.terms();
-          if (result == null) {
-            return null;
-          }
-          // wrap the terms object with a bloom filter
-          return new BloomFilteredTerms(result, filter);
-        }
-      }
-      
-    }
-    
     class BloomFilteredTerms extends Terms {
       private Terms delegateTerms;
       private FuzzySet filter;

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40TermVectorsReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40TermVectorsReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40TermVectorsReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40TermVectorsReader.java Mon Aug 13 02:25:19 2012
@@ -21,7 +21,9 @@ import java.io.IOException;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 
 import org.apache.lucene.codecs.CodecUtil;
 import org.apache.lucene.codecs.TermVectorsReader;
@@ -30,7 +32,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.SegmentInfo;
 import org.apache.lucene.index.Terms;
@@ -249,9 +250,8 @@ public class Lucene40TermVectorsReader e
     }
     
     @Override
-    public FieldsEnum iterator() throws IOException {
-
-      return new FieldsEnum() {
+    public Iterator<String> iterator() {
+      return new Iterator<String>() {
         private int fieldUpto;
 
         @Override
@@ -259,13 +259,18 @@ public class Lucene40TermVectorsReader e
           if (fieldNumbers != null && fieldUpto < fieldNumbers.length) {
             return fieldInfos.fieldInfo(fieldNumbers[fieldUpto++]).name;
           } else {
-            return null;
+            throw new NoSuchElementException();
           }
         }
 
         @Override
-        public Terms terms() throws IOException {
-          return TVFields.this.terms(fieldInfos.fieldInfo(fieldNumbers[fieldUpto-1]).name);
+        public boolean hasNext() {
+          return fieldNumbers != null && fieldUpto < fieldNumbers.length;
+        }
+
+        @Override
+        public void remove() {
+          throw new UnsupportedOperationException();
         }
       };
     }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java Mon Aug 13 02:25:19 2012
@@ -32,7 +32,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.OrdTermState;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
@@ -44,6 +43,7 @@ import org.apache.lucene.store.RAMOutput
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.UnmodifiableIterator;
 import org.apache.lucene.util.automaton.CompiledAutomaton;
 import org.apache.lucene.util.automaton.RunAutomaton;
 import org.apache.lucene.util.automaton.Transition;
@@ -124,36 +124,14 @@ public class DirectPostingsFormat extend
     private final Map<String,DirectField> fields = new TreeMap<String,DirectField>();
 
     public DirectFields(SegmentReadState state, Fields fields, int minSkipCount, int lowFreqCutoff) throws IOException {
-      FieldsEnum fieldsEnum = fields.iterator();
-      String field;
-      while ((field = fieldsEnum.next()) != null) {
-        this.fields.put(field, new DirectField(state, field, fieldsEnum.terms(), minSkipCount, lowFreqCutoff));
+      for (String field : fields) {
+        this.fields.put(field, new DirectField(state, field, fields.terms(field), minSkipCount, lowFreqCutoff));
       }
     }
 
     @Override
-    public FieldsEnum iterator() {
-
-      final Iterator<Map.Entry<String,DirectField>> iter = fields.entrySet().iterator();
-
-      return new FieldsEnum() {
-        Map.Entry<String,DirectField> current;
-        
-        @Override
-        public String next() {
-          if (iter.hasNext()) {
-            current = iter.next();
-            return current.getKey();
-          } else {
-            return null;
-          }
-        }
-
-        @Override
-        public Terms terms() {
-          return current.getValue();
-        }
-      };
+    public Iterator<String> iterator() {
+      return new UnmodifiableIterator<String>(fields.keySet().iterator());
     }
 
     @Override

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/MemoryPostingsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/MemoryPostingsFormat.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/MemoryPostingsFormat.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/memory/MemoryPostingsFormat.java Mon Aug 13 02:25:19 2012
@@ -34,7 +34,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
@@ -49,6 +48,7 @@ import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IntsRef;
+import org.apache.lucene.util.UnmodifiableIterator;
 import org.apache.lucene.util.fst.Builder;
 import org.apache.lucene.util.fst.ByteSequenceOutputs;
 import org.apache.lucene.util.fst.BytesRefFSTEnum;
@@ -862,24 +862,8 @@ public class MemoryPostingsFormat extend
 
     return new FieldsProducer() {
       @Override
-      public FieldsEnum iterator() {
-        final Iterator<TermsReader> iter = fields.values().iterator();
-
-        return new FieldsEnum() {
-
-          private TermsReader current;
-
-          @Override
-          public String next() {
-            current = iter.next();
-            return current.field.name;
-          }
-
-          @Override
-          public Terms terms() {
-            return current;
-          }
-        };
+      public Iterator<String> iterator() {
+        return new UnmodifiableIterator<String>(fields.keySet().iterator());
       }
 
       @Override

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldPostingsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldPostingsFormat.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldPostingsFormat.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/perfield/PerFieldPostingsFormat.java Mon Aug 13 02:25:19 2012
@@ -30,11 +30,11 @@ import org.apache.lucene.codecs.FieldsPr
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.TermsConsumer;
 import org.apache.lucene.index.FieldInfo;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.SegmentWriteState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.UnmodifiableIterator;
 
 /**
  * Enables per field format support.
@@ -197,34 +197,9 @@ public abstract class PerFieldPostingsFo
       }
     }
 
-    private final class FieldsIterator extends FieldsEnum {
-      private final Iterator<String> it;
-      private String current;
-
-      public FieldsIterator() {
-        it = fields.keySet().iterator();
-      }
-
-      @Override
-      public String next() {
-        if (it.hasNext()) {
-          current = it.next();
-        } else {
-          current = null;
-        }
-
-        return current;
-      }
-
-      @Override
-      public Terms terms() throws IOException {
-        return fields.get(current).terms(current);
-      }
-    }
-
     @Override
-    public FieldsEnum iterator() throws IOException {
-      return new FieldsIterator();
+    public Iterator<String> iterator() {
+      return new UnmodifiableIterator<String>(fields.keySet().iterator());
     }
 
     @Override

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextFieldsReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextFieldsReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextFieldsReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextFieldsReader.java Mon Aug 13 02:25:19 2012
@@ -20,7 +20,10 @@ package org.apache.lucene.codecs.simplet
 import java.io.IOException;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
 
 import org.apache.lucene.codecs.FieldsProducer;
 import org.apache.lucene.index.DocsAndPositionsEnum;
@@ -28,7 +31,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.FieldInfos;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.SegmentReadState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -41,6 +43,7 @@ import org.apache.lucene.util.IntsRef;
 import org.apache.lucene.util.OpenBitSet;
 import org.apache.lucene.util.StringHelper;
 import org.apache.lucene.util.UnicodeUtil;
+import org.apache.lucene.util.UnmodifiableIterator;
 import org.apache.lucene.util.fst.Builder;
 import org.apache.lucene.util.fst.BytesRefFSTEnum;
 import org.apache.lucene.util.fst.FST;
@@ -49,7 +52,7 @@ import org.apache.lucene.util.fst.Positi
 import org.apache.lucene.util.fst.Util;
 
 class SimpleTextFieldsReader extends FieldsProducer {
-
+  private final TreeMap<String,Long> fields;
   private final IndexInput in;
   private final FieldInfos fieldInfos;
 
@@ -67,35 +70,22 @@ class SimpleTextFieldsReader extends Fie
     in = state.dir.openInput(SimpleTextPostingsFormat.getPostingsFileName(state.segmentInfo.name, state.segmentSuffix), state.context);
    
     fieldInfos = state.fieldInfos;
+    fields = readFields((IndexInput)in.clone());
   }
-
-  private class SimpleTextFieldsEnum extends FieldsEnum {
-    private final IndexInput in;
-    private final BytesRef scratch = new BytesRef(10);
-    private String current;
-
-    public SimpleTextFieldsEnum() {
-      this.in = (IndexInput) SimpleTextFieldsReader.this.in.clone();
-    }
-
-    @Override
-    public String next() throws IOException {
-      while(true) {
-        SimpleTextUtil.readLine(in, scratch);
-        if (scratch.equals(END)) {
-          current = null;
-          return null;
-        }
-        if (StringHelper.startsWith(scratch, FIELD)) {
-          return current = new String(scratch.bytes, scratch.offset + FIELD.length, scratch.length - FIELD.length, "UTF-8");
-        }
+  
+  private TreeMap<String,Long> readFields(IndexInput in) throws IOException {
+    BytesRef scratch = new BytesRef(10);
+    TreeMap<String,Long> fields = new TreeMap<String,Long>();
+    
+    while (true) {
+      SimpleTextUtil.readLine(in, scratch);
+      if (scratch.equals(END)) {
+        return fields;
+      } else if (StringHelper.startsWith(scratch, FIELD)) {
+        String fieldName = new String(scratch.bytes, scratch.offset + FIELD.length, scratch.length - FIELD.length, "UTF-8");
+        fields.put(fieldName, in.getFilePointer());
       }
     }
-
-    @Override
-    public Terms terms() throws IOException {
-      return SimpleTextFieldsReader.this.terms(current);
-    }
   }
 
   private class SimpleTextTermsEnum extends TermsEnum {
@@ -617,8 +607,8 @@ class SimpleTextFieldsReader extends Fie
   }
 
   @Override
-  public FieldsEnum iterator() throws IOException {
-    return new SimpleTextFieldsEnum();
+  public Iterator<String> iterator() {
+    return new UnmodifiableIterator<String>(fields.keySet().iterator());
   }
 
   private final Map<String,Terms> termsCache = new HashMap<String,Terms>();
@@ -627,15 +617,13 @@ class SimpleTextFieldsReader extends Fie
   synchronized public Terms terms(String field) throws IOException {
     Terms terms = termsCache.get(field);
     if (terms == null) {
-      SimpleTextFieldsEnum fe = (SimpleTextFieldsEnum) iterator();
-      String fieldUpto;
-      while((fieldUpto = fe.next()) != null) {
-        if (fieldUpto.equals(field)) {
-          terms = new SimpleTextTerms(field, fe.in.getFilePointer());
-          break;
-        }
+      Long fp = fields.get(field);
+      if (fp == null) {
+        return null;
+      } else {
+        terms = new SimpleTextTerms(field, fp);
+        termsCache.put(field, terms);
       }
-      termsCache.put(field, terms);
     }
     return terms;
   }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextTermVectorsReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextTermVectorsReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextTermVectorsReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextTermVectorsReader.java Mon Aug 13 02:25:19 2012
@@ -29,7 +29,6 @@ import org.apache.lucene.codecs.TermVect
 import org.apache.lucene.index.DocsAndPositionsEnum;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.SegmentInfo;
 import org.apache.lucene.index.Terms;
@@ -45,6 +44,7 @@ import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.StringHelper;
 import org.apache.lucene.util.UnicodeUtil;
+import org.apache.lucene.util.UnmodifiableIterator;
 
 import static org.apache.lucene.codecs.simpletext.SimpleTextTermVectorsWriter.*;
 
@@ -240,26 +240,8 @@ public class SimpleTextTermVectorsReader
     }
 
     @Override
-    public FieldsEnum iterator() throws IOException {
-      return new FieldsEnum() {
-        private Iterator<Map.Entry<String,SimpleTVTerms>> iterator = fields.entrySet().iterator();
-        private Map.Entry<String,SimpleTVTerms> current = null;
-        
-        @Override
-        public String next() {
-          if (!iterator.hasNext()) {
-            return null;
-          } else {
-            current = iterator.next();
-            return current.getKey();
-          }
-        }
-
-        @Override
-        public Terms terms() {
-          return current.getValue();
-        }
-      };
+    public Iterator<String> iterator() {
+      return new UnmodifiableIterator<String>(fields.keySet().iterator());
     }
 
     @Override

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java Mon Aug 13 02:25:19 2012
@@ -685,12 +685,7 @@ public class CheckIndex {
     DocsAndPositionsEnum postings = null;
     
     String lastField = null;
-    final FieldsEnum fieldsEnum = fields.iterator();
-    while(true) {
-      final String field = fieldsEnum.next();
-      if (field == null) {
-        break;
-      }
+    for (String field : fields) {
       // MultiFieldsEnum relies upon this order...
       if (lastField != null && field.compareTo(lastField) <= 0) {
         throw new RuntimeException("fields out of order: lastField=" + lastField + " field=" + field);
@@ -713,7 +708,7 @@ public class CheckIndex {
       // assert fields.terms(field) != null;
       computedFieldCount++;
       
-      final Terms terms = fieldsEnum.terms();
+      final Terms terms = fields.terms(field);
       if (terms == null) {
         continue;
       }
@@ -987,11 +982,7 @@ public class CheckIndex {
         // only happen if it's a ghost field (field with
         // no terms, eg there used to be terms but all
         // docs got deleted and then merged away):
-        // make sure TermsEnum is empty:
-        final Terms fieldTerms2 = fieldsEnum.terms();
-        if (fieldTerms2 != null && fieldTerms2.iterator(null).next() != null) {
-          throw new RuntimeException("Fields.terms(field=" + field + ") returned null yet the field appears to have terms");
-        }
+        
       } else {
         if (fieldTerms instanceof BlockTreeTermsReader.FieldReader) {
           final BlockTreeTermsReader.Stats stats = ((BlockTreeTermsReader.FieldReader) fieldTerms).computeStats();
@@ -1402,9 +1393,7 @@ public class CheckIndex {
             status.docCount++;
           }
 
-          FieldsEnum fieldsEnum = tfv.iterator();
-          String field = null;
-          while((field = fieldsEnum.next()) != null) {
+          for(String field : tfv) {
             if (doStats) {
               status.totVectors++;
             }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CoalescedDeletes.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CoalescedDeletes.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CoalescedDeletes.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/CoalescedDeletes.java Mon Aug 13 02:25:19 2012
@@ -24,7 +24,7 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.lucene.search.Query;
-import org.apache.lucene.util.PriorityQueue;
+import org.apache.lucene.util.MergedIterator;
 import org.apache.lucene.index.BufferedDeletesStream.QueryAndLimit;
 
 class CoalescedDeletes {
@@ -48,13 +48,14 @@ class CoalescedDeletes {
 
  public Iterable<Term> termsIterable() {
    return new Iterable<Term>() {
+     @SuppressWarnings("unchecked")
      @Override
      public Iterator<Term> iterator() {
-       ArrayList<Iterator<Term>> subs = new ArrayList<Iterator<Term>>(iterables.size());
-       for (Iterable<Term> iterable : iterables) {
-         subs.add(iterable.iterator());
+       Iterator<Term> subs[] = new Iterator[iterables.size()];
+       for (int i = 0; i < iterables.size(); i++) {
+         subs[i] = iterables.get(i).iterator();
        }
-       return mergedIterator(subs);
+       return new MergedIterator<Term>(subs);
      }
    };
   }
@@ -86,106 +87,4 @@ class CoalescedDeletes {
       }
     };
   }
-  
-  /** provides a merged view across multiple iterators */
-  static Iterator<Term> mergedIterator(final List<Iterator<Term>> iterators) {
-    return new Iterator<Term>() {
-      Term current;
-      TermMergeQueue queue = new TermMergeQueue(iterators.size());
-      SubIterator[] top = new SubIterator[iterators.size()];
-      int numTop;
-      
-      {
-        int index = 0;
-        for (Iterator<Term> iterator : iterators) {
-          if (iterator.hasNext()) {
-            SubIterator sub = new SubIterator();
-            sub.current = iterator.next();
-            sub.iterator = iterator;
-            sub.index = index++;
-            queue.add(sub);
-          }
-        }
-      }
-      
-      public boolean hasNext() {
-        if (queue.size() > 0) {
-          return true;
-        }
-        
-        for (int i = 0; i < numTop; i++) {
-          if (top[i].iterator.hasNext()) {
-            return true;
-          }
-        }
-        return false;
-      }
-      
-      public Term next() {
-        // restore queue
-        pushTop();
-        
-        // gather equal top fields
-        if (queue.size() > 0) {
-          pullTop();
-        } else {
-          current = null;
-        }
-        return current;
-      }
-      
-      public void remove() {
-        throw new UnsupportedOperationException();
-      }
-      
-      private void pullTop() {
-        // extract all subs from the queue that have the same top term
-        assert numTop == 0;
-        while (true) {
-          top[numTop++] = queue.pop();
-          if (queue.size() == 0
-              || !(queue.top()).current.equals(top[0].current)) {
-            break;
-          }
-        }
-        current = top[0].current;
-      }
-      
-      private void pushTop() {
-        // call next() on each top, and put back into queue
-        for (int i = 0; i < numTop; i++) {
-          if (top[i].iterator.hasNext()) {
-            top[i].current = top[i].iterator.next();
-            queue.add(top[i]);
-          } else {
-            // no more terms
-            top[i].current = null;
-          }
-        }
-        numTop = 0;
-      }
-    };
-  }
-  
-  private static class SubIterator {
-    Iterator<Term> iterator;
-    Term current;
-    int index;
-  }
-  
-  private static class TermMergeQueue extends PriorityQueue<SubIterator> {
-    TermMergeQueue(int size) {
-      super(size);
-    }
-
-    @Override
-    protected boolean lessThan(SubIterator a, SubIterator b) {
-      final int cmp = a.current.compareTo(b.current);
-      if (cmp != 0) {
-        return cmp < 0;
-      } else {
-        return a.index < b.index;
-      }
-    }
-  }
 }

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocValues.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocValues.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocValues.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/DocValues.java Mon Aug 13 02:25:19 2012
@@ -105,7 +105,7 @@ public abstract class DocValues implemen
    * <p>
    * {@link Source} instances obtained from this method are closed / released
    * from the cache once this {@link DocValues} instance is closed by the
-   * {@link IndexReader}, {@link Fields} or {@link FieldsEnum} the
+   * {@link IndexReader}, {@link Fields} or the
    * {@link DocValues} was created from.
    */
   public Source getSource() throws IOException {

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/Fields.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/Fields.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/Fields.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/Fields.java Mon Aug 13 02:25:19 2012
@@ -18,15 +18,16 @@ package org.apache.lucene.index;
  */
 
 import java.io.IOException;
+import java.util.Iterator;
 
 /** Flex API for access to fields and terms
  *  @lucene.experimental */
 
-public abstract class Fields {
+public abstract class Fields implements Iterable<String> {
 
   /** Returns an iterator that will step through all fields
    *  names.  This will not return null.  */
-  public abstract FieldsEnum iterator() throws IOException;
+  public abstract Iterator<String> iterator();
 
   /** Get the {@link Terms} for this field.  This will return
    *  null if the field does not exist. */
@@ -45,12 +46,7 @@ public abstract class Fields {
   // TODO: deprecate?
   public long getUniqueTermCount() throws IOException {
     long numTerms = 0;
-    FieldsEnum it = iterator();
-    while(true) {
-      String field = it.next();
-      if (field == null) {
-        break;
-      }
+    for (String field : this) {
       Terms terms = terms(field);
       if (terms != null) {
         final long termCount = terms.size();

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/FilterAtomicReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/FilterAtomicReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/FilterAtomicReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/FilterAtomicReader.java Mon Aug 13 02:25:19 2012
@@ -24,6 +24,7 @@ import org.apache.lucene.util.automaton.
 
 import java.io.IOException;
 import java.util.Comparator;
+import java.util.Iterator;
 
 /**  A <code>FilterAtomicReader</code> contains another AtomicReader, which it
  * uses as its basic source of data, possibly transforming the data along the
@@ -46,7 +47,7 @@ public class FilterAtomicReader extends 
     }
 
     @Override
-    public FieldsEnum iterator() throws IOException {
+    public Iterator<String> iterator() {
       return in.iterator();
     }
 
@@ -127,29 +128,6 @@ public class FilterAtomicReader extends 
   }
 
   /** Base class for filtering {@link TermsEnum} implementations. */
-  public static class FilterFieldsEnum extends FieldsEnum {
-    protected final FieldsEnum in;
-    public FilterFieldsEnum(FieldsEnum in) {
-      this.in = in;
-    }
-
-    @Override
-    public String next() throws IOException {
-      return in.next();
-    }
-
-    @Override
-    public Terms terms() throws IOException {
-      return in.terms();
-    }
-    
-    @Override
-    public AttributeSource attributes() {
-      return in.attributes();
-    }
-  }
-
-  /** Base class for filtering {@link TermsEnum} implementations. */
   public static class FilterTermsEnum extends TermsEnum {
     protected final TermsEnum in;
 

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/MultiFields.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/MultiFields.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/MultiFields.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/MultiFields.java Mon Aug 13 02:25:19 2012
@@ -19,6 +19,7 @@ package org.apache.lucene.index;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Collection;
@@ -27,6 +28,7 @@ import java.util.concurrent.ConcurrentHa
 
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.MergedIterator;
 
 /**
  * Exposes flex API, merged from flex API of sub-segments.
@@ -180,22 +182,14 @@ public final class MultiFields extends F
     this.subSlices = subSlices;
   }
 
+  @SuppressWarnings("unchecked")
   @Override
-  public FieldsEnum iterator() throws IOException {
-
-    final List<FieldsEnum> fieldsEnums = new ArrayList<FieldsEnum>();
-    final List<ReaderSlice> fieldsSlices = new ArrayList<ReaderSlice>();
+  public Iterator<String> iterator() {
+    Iterator<String> subIterators[] = new Iterator[subs.length];
     for(int i=0;i<subs.length;i++) {
-      fieldsEnums.add(subs[i].iterator());
-      fieldsSlices.add(subSlices[i]);
-    }
-    if (fieldsEnums.size() == 0) {
-      return FieldsEnum.EMPTY;
-    } else {
-      return new MultiFieldsEnum(this,
-                                 fieldsEnums.toArray(FieldsEnum.EMPTY_ARRAY),
-                                 fieldsSlices.toArray(ReaderSlice.EMPTY_ARRAY));
+      subIterators[i] = subs[i].iterator();
     }
+    return new MergedIterator<String>(subIterators);
   }
 
   @Override

Modified: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/ParallelAtomicReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/ParallelAtomicReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/ParallelAtomicReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/index/ParallelAtomicReader.java Mon Aug 13 02:25:19 2012
@@ -27,6 +27,7 @@ import java.util.SortedMap;
 import java.util.TreeMap;
 
 import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.UnmodifiableIterator;
 
 
 /** An {@link AtomicReader} which reads multiple, parallel indexes.  Each index
@@ -121,12 +122,10 @@ public final class ParallelAtomicReader 
     for (final AtomicReader reader : this.parallelReaders) {
       final Fields readerFields = reader.fields();
       if (readerFields != null) {
-        final FieldsEnum it = readerFields.iterator();
-        String name;
-        while ((name = it.next()) != null) {
+        for (String field : readerFields) {
           // only add if the reader responsible for that field name is the current:
-          if (fieldToReader.get(name) == reader) {
-            this.fields.addField(name, it.terms());
+          if (fieldToReader.get(field) == reader) {
+            this.fields.addField(field, readerFields.terms(field));
           }
         }
       }
@@ -151,33 +150,6 @@ public final class ParallelAtomicReader 
     return buffer.append(')').toString();
   }
   
-  private final class ParallelFieldsEnum extends FieldsEnum {
-    private String currentField;
-    private final Iterator<String> keys;
-    private final ParallelFields fields;
-    
-    ParallelFieldsEnum(ParallelFields fields) {
-      this.fields = fields;
-      keys = fields.fields.keySet().iterator();
-    }
-    
-    @Override
-    public String next() {
-      if (keys.hasNext()) {
-        currentField = keys.next();
-      } else {
-        currentField = null;
-      }
-      return currentField;
-    }
-    
-    @Override
-    public Terms terms() {
-      return fields.terms(currentField);
-    }
-    
-  }
-  
   // Single instance of this, per ParallelReader instance
   private final class ParallelFields extends Fields {
     final Map<String,Terms> fields = new TreeMap<String,Terms>();
@@ -190,8 +162,8 @@ public final class ParallelAtomicReader 
     }
     
     @Override
-    public FieldsEnum iterator() {
-      return new ParallelFieldsEnum(this);
+    public Iterator<String> iterator() {
+      return new UnmodifiableIterator<String>(fields.keySet().iterator());
     }
     
     @Override

Added: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java?rev=1372243&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java (added)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java Mon Aug 13 02:25:19 2012
@@ -0,0 +1,148 @@
+package org.apache.lucene.util;
+
+/*
+ * 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 java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Provides a merged sorted view from several sorted iterators, each
+ * iterating over a unique set of elements.
+ * <p>
+ * If an element appears in multiple iterators, it is deduplicated,
+ * that is this iterator returns the sorted union of elements.
+ * <p>
+ * Caveats:
+ * <ul>
+ *   <li>The behavior is undefined if the iterators are not actually 
+ *       sorted according to their comparator, or if a single iterator
+ *       contains duplicates.
+ *   <li>Null elements are unsupported.
+ *   <li>When an element E is a duplicate across multiple iterators,
+ *       only one is returned, but it is undefined which one: not
+ *       guaranteed to be a stable sort.
+ * </ul>
+ * @lucene.internal
+ */
+public class MergedIterator<T extends Comparable<T>> implements Iterator<T> {
+  private T current;
+  private final TermMergeQueue<T> queue; 
+  private final SubIterator<T>[] top;
+  private int numTop;
+  
+  @SuppressWarnings("unchecked")
+  public MergedIterator(Iterator<T>... iterators) {
+    queue = new TermMergeQueue<T>(iterators.length);
+    top = new SubIterator[iterators.length];
+    int index = 0;
+    for (Iterator<T> iterator : iterators) {
+      if (iterator.hasNext()) {
+        SubIterator<T> sub = new SubIterator<T>();
+        sub.current = iterator.next();
+        sub.iterator = iterator;
+        sub.index = index++;
+        queue.add(sub);
+      }
+    }
+  }
+  
+  @Override
+  public boolean hasNext() {
+    if (queue.size() > 0) {
+      return true;
+    }
+    
+    for (int i = 0; i < numTop; i++) {
+      if (top[i].iterator.hasNext()) {
+        return true;
+      }
+    }
+    return false;
+  }
+  
+  @Override
+  public T next() {
+    // restore queue
+    pushTop();
+    
+    // gather equal top elements
+    if (queue.size() > 0) {
+      pullTop();
+    } else {
+      current = null;
+    }
+    if (current == null) {
+      throw new NoSuchElementException();
+    }
+    return current;
+  }
+  
+  @Override
+  public void remove() {
+    throw new UnsupportedOperationException();
+  }
+  
+  private void pullTop() {
+    // extract all subs from the queue that have the same top element
+    assert numTop == 0;
+    while (true) {
+      top[numTop++] = queue.pop();
+      if (queue.size() == 0
+          || !(queue.top()).current.equals(top[0].current)) {
+        break;
+      }
+    }
+    current = top[0].current;
+  }
+  
+  private void pushTop() {
+    // call next() on each top, and put back into queue
+    for (int i = 0; i < numTop; i++) {
+      if (top[i].iterator.hasNext()) {
+        top[i].current = top[i].iterator.next();
+        queue.add(top[i]);
+      } else {
+        // no more elements
+        top[i].current = null;
+      }
+    }
+    numTop = 0;
+  }
+  
+  private static class SubIterator<I extends Comparable<I>> {
+    Iterator<I> iterator;
+    I current;
+    int index;
+  }
+  
+  private static class TermMergeQueue<C extends Comparable<C>> extends PriorityQueue<SubIterator<C>> {
+    TermMergeQueue(int size) {
+      super(size);
+    }
+    
+    @Override
+    protected boolean lessThan(SubIterator<C> a, SubIterator<C> b) {
+      final int cmp = a.current.compareTo(b.current);
+      if (cmp != 0) {
+        return cmp < 0;
+      } else {
+        return a.index < b.index;
+      }
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/UnmodifiableIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/UnmodifiableIterator.java?rev=1372243&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/UnmodifiableIterator.java (added)
+++ lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/util/UnmodifiableIterator.java Mon Aug 13 02:25:19 2012
@@ -0,0 +1,46 @@
+package org.apache.lucene.util;
+
+/*
+ * 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 java.util.Iterator;
+
+/**
+ * Wraps an iterator to ensure its unmodifiable
+ */
+public class UnmodifiableIterator<T> implements Iterator<T> {
+  private final Iterator<T> in;
+  
+  public UnmodifiableIterator(Iterator<T> in) {
+    this.in = in;
+  }
+
+  @Override
+  public boolean hasNext() {
+    return in.hasNext();
+  }
+
+  @Override
+  public T next() {
+    return in.next();
+  }
+
+  @Override
+  public void remove() {
+    throw new UnsupportedOperationException();
+  }
+}

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestCodecs.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestCodecs.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestCodecs.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestCodecs.java Mon Aug 13 02:25:19 2012
@@ -20,6 +20,7 @@ package org.apache.lucene.index;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.codecs.Codec;
@@ -258,9 +259,10 @@ public class TestCodecs extends LuceneTe
 
     final FieldsProducer reader = codec.postingsFormat().fieldsProducer(new SegmentReadState(dir, si, fieldInfos, newIOContext(random()), DirectoryReader.DEFAULT_TERMS_INDEX_DIVISOR));
 
-    final FieldsEnum fieldsEnum = reader.iterator();
-    assertNotNull(fieldsEnum.next());
-    final Terms terms2 = fieldsEnum.terms();
+    final Iterator<String> fieldsEnum = reader.iterator();
+    String fieldName = fieldsEnum.next();
+    assertNotNull(fieldName);
+    final Terms terms2 = reader.terms(fieldName);
     assertNotNull(terms2);
 
     final TermsEnum termsEnum = terms2.iterator(null);
@@ -286,7 +288,7 @@ public class TestCodecs extends LuceneTe
       assertEquals(termsEnum.seekCeil(new BytesRef(terms[i].text2)), TermsEnum.SeekStatus.FOUND);
     }
 
-    assertNull(fieldsEnum.next());
+    assertFalse(fieldsEnum.hasNext());
     reader.close();
     dir.close();
   }

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java Mon Aug 13 02:25:19 2012
@@ -612,20 +612,20 @@ public void testFilesOpenClose() throws 
     }
     
     // check dictionary and posting lists
-    FieldsEnum fenum1 = MultiFields.getFields(index1).iterator();
-    FieldsEnum fenum2 = MultiFields.getFields(index2).iterator();
-    String field1 = null;
+    Fields fields1 = MultiFields.getFields(index1);
+    Fields fields2 = MultiFields.getFields(index2);
+    Iterator<String> fenum2 = fields2.iterator();
     Bits liveDocs = MultiFields.getLiveDocs(index1);
-    while((field1=fenum1.next()) != null) {
+    for (String field1 : fields1) {
       assertEquals("Different fields", field1, fenum2.next());
-      Terms terms1 = fenum1.terms();
+      Terms terms1 = fields1.terms(field1);
       if (terms1 == null) {
-        assertNull(fenum2.terms());
+        assertNull(fields2.terms(field1));
         continue;
       }
       TermsEnum enum1 = terms1.iterator(null);
 
-      Terms terms2 = fenum2.terms();
+      Terms terms2 = fields2.terms(field1);
       assertNotNull(terms2);
       TermsEnum enum2 = terms2.iterator(null);
 
@@ -644,6 +644,7 @@ public void testFilesOpenClose() throws 
         }
       }
     }
+    assertFalse(fenum2.hasNext());
   }
 
   public void testGetIndexCommit() throws IOException {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDoc.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDoc.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDoc.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDoc.java Mon Aug 13 02:25:19 2012
@@ -32,7 +32,6 @@ import java.util.LinkedList;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -236,10 +235,9 @@ public class TestDoc extends LuceneTestC
       for (int i = 0; i < reader.numDocs(); i++)
         out.println(reader.document(i));
 
-      FieldsEnum fis = reader.fields().iterator();
-      String field = fis.next();
-      while(field != null)  {
-        Terms terms = fis.terms();
+      Fields fields = reader.fields();
+      for (String field : fields)  {
+        Terms terms = fields.terms(field);
         assertNotNull(terms);
         TermsEnum tis = terms.iterator(null);
         while(tis.next() != null) {
@@ -259,7 +257,6 @@ public class TestDoc extends LuceneTestC
             out.println("");
           }
         }
-        field = fis.next();
       }
       reader.close();
     }

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDocCount.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDocCount.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDocCount.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDocCount.java Mon Aug 13 02:25:19 2012
@@ -61,9 +61,7 @@ public class TestDocCount extends Lucene
     if (fields == null) {
       return;
     }
-    FieldsEnum e = fields.iterator();
-    String field;
-    while ((field = e.next()) != null) {
+    for (String field : fields) {
       Terms terms = fields.terms(field);
       if (terms == null) {
         continue;

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java Mon Aug 13 02:25:19 2012
@@ -173,15 +173,15 @@ public class TestDuelingCodecs extends L
     }
     assertFieldStatistics(leftFields, rightFields);
     
-    FieldsEnum leftEnum = leftFields.iterator();
-    FieldsEnum rightEnum = rightFields.iterator();
+    Iterator<String> leftEnum = leftFields.iterator();
+    Iterator<String> rightEnum = rightFields.iterator();
     
-    String field;
-    while ((field = leftEnum.next()) != null) {
+    while (leftEnum.hasNext()) {
+      String field = leftEnum.next();
       assertEquals(info, field, rightEnum.next());
-      assertTerms(leftEnum.terms(), rightEnum.terms(), deep);
+      assertTerms(leftFields.terms(field), rightFields.terms(field), deep);
     }
-    assertNull(rightEnum.next());
+    assertFalse(rightEnum.hasNext());
   }
   
   /** 
@@ -525,9 +525,7 @@ public class TestDuelingCodecs extends L
       return;
     }
     
-    FieldsEnum fieldsEnum = leftFields.iterator();
-    String field;
-    while ((field = fieldsEnum.next()) != null) {
+    for (String field : leftFields) {
       DocValues leftNorms = MultiDocValues.getNormDocValues(leftReader, field);
       DocValues rightNorms = MultiDocValues.getNormDocValues(rightReader, field);
       if (leftNorms != null && rightNorms != null) {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestFilterAtomicReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestFilterAtomicReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestFilterAtomicReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestFilterAtomicReader.java Mon Aug 13 02:25:19 2012
@@ -40,10 +40,7 @@ public class TestFilterAtomicReader exte
       TestFields(Fields in) {
         super(in);
       }
-      @Override
-      public FieldsEnum iterator() throws IOException {
-        return new TestFieldsEnum(super.iterator());
-      }
+
       @Override
       public Terms terms(String field) throws IOException {
         return new TestTerms(super.terms(field));
@@ -61,17 +58,6 @@ public class TestFilterAtomicReader exte
       }
     }
 
-    private static class TestFieldsEnum extends FilterFieldsEnum {
-      TestFieldsEnum(FieldsEnum in) {
-        super(in);
-      }
-
-      @Override
-      public Terms terms() throws IOException {
-        return new TestTerms(super.terms());
-      }
-    }
-
     private static class TestTermsEnum extends FilterTermsEnum {
       public TestTermsEnum(TermsEnum in) {
         super(in);
@@ -194,7 +180,6 @@ public class TestFilterAtomicReader exte
     checkOverrideMethods(FilterAtomicReader.class);
     checkOverrideMethods(FilterAtomicReader.FilterFields.class);
     checkOverrideMethods(FilterAtomicReader.FilterTerms.class);
-    checkOverrideMethods(FilterAtomicReader.FilterFieldsEnum.class);
     checkOverrideMethods(FilterAtomicReader.FilterTermsEnum.class);
     checkOverrideMethods(FilterAtomicReader.FilterDocsEnum.class);
     checkOverrideMethods(FilterAtomicReader.FilterDocsAndPositionsEnum.class);

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestParallelTermEnum.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestParallelTermEnum.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestParallelTermEnum.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestParallelTermEnum.java Mon Aug 13 02:25:19 2012
@@ -18,6 +18,7 @@ package org.apache.lucene.index;
  */
 
 import java.io.IOException;
+import java.util.Iterator;
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
@@ -94,20 +95,21 @@ public class TestParallelTermEnum extend
 
     Bits liveDocs = pr.getLiveDocs();
 
-    FieldsEnum fe = pr.fields().iterator();
+    Fields fields = pr.fields();
+    Iterator<String> fe = fields.iterator();
 
     String f = fe.next();
     assertEquals("field1", f);
-    checkTerms(fe.terms(), liveDocs, "brown", "fox", "jumps", "quick", "the");
+    checkTerms(fields.terms(f), liveDocs, "brown", "fox", "jumps", "quick", "the");
 
     f = fe.next();
     assertEquals("field2", f);
-    checkTerms(fe.terms(), liveDocs, "brown", "fox", "jumps", "quick", "the");
+    checkTerms(fields.terms(f), liveDocs, "brown", "fox", "jumps", "quick", "the");
 
     f = fe.next();
     assertEquals("field3", f);
-    checkTerms(fe.terms(), liveDocs, "dog", "fox", "jumps", "lazy", "over", "the");
+    checkTerms(fields.terms(f), liveDocs, "dog", "fox", "jumps", "lazy", "over", "the");
 
-    assertNull(fe.next());
+    assertFalse(fe.hasNext());
   }
 }

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPostingsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPostingsFormat.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPostingsFormat.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPostingsFormat.java Mon Aug 13 02:25:19 2012
@@ -23,8 +23,10 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.TreeMap;
 
@@ -889,6 +891,26 @@ public class TestPostingsFormat extends 
       }
     }
   }
+  
+  private void testFields(Fields fields) throws Exception {
+    Iterator<String> iterator = fields.iterator();
+    while (iterator.hasNext()) {
+      String field = iterator.next();
+      try {
+        iterator.remove();
+        fail("Fields.iterator() allows for removal");
+      } catch (UnsupportedOperationException expected) {
+        // expected;
+      }
+    }
+    assertFalse(iterator.hasNext());
+    try {
+      iterator.next();
+      fail("Fields.iterator() doesn't throw NoSuchElementException when past the end");
+    } catch (NoSuchElementException expected) {
+      // expected
+    }
+  }
 
   public void test() throws Exception {
     Directory dir = newFSDirectory(_TestUtil.getTempDir("testPostingsFormat"));
@@ -898,6 +920,7 @@ public class TestPostingsFormat extends 
 
     FieldsProducer fieldsProducer = buildIndex(dir, IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS, indexPayloads);
 
+    testFields(fieldsProducer);
     //testTerms(fieldsProducer, EnumSet.noneOf(Option.class), IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
     //testTerms(fieldsProducer, EnumSet.of(Option.LIVE_DOCS), IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
     //testTerms(fieldsProducer, EnumSet.of(Option.TERM_STATE, Option.LIVE_DOCS, Option.PARTIAL_DOC_CONSUME, Option.PARTIAL_POS_CONSUME), IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPrefixCodedTerms.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPrefixCodedTerms.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPrefixCodedTerms.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestPrefixCodedTerms.java Mon Aug 13 02:25:19 2012
@@ -25,6 +25,7 @@ import java.util.Set;
 import java.util.TreeSet;
 
 import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.MergedIterator;
 import org.apache.lucene.util._TestUtil;
 
 public class TestPrefixCodedTerms extends LuceneTestCase {
@@ -67,17 +68,20 @@ public class TestPrefixCodedTerms extend
     assertFalse(expected.hasNext());
   }
   
+  @SuppressWarnings("unchecked")
   public void testMergeEmpty() {
     List<Iterator<Term>> subs = Collections.emptyList();
-    assertFalse(CoalescedDeletes.mergedIterator(subs).hasNext());
+    Iterator<Term> merged = new MergedIterator<Term>(subs.toArray(new Iterator[0]));
+    assertFalse(merged.hasNext());
 
     subs = new ArrayList<Iterator<Term>>();
     subs.add(new PrefixCodedTerms.Builder().finish().iterator());
     subs.add(new PrefixCodedTerms.Builder().finish().iterator());
-    Iterator<Term> merged = CoalescedDeletes.mergedIterator(subs);
+    merged = new MergedIterator<Term>(subs.toArray(new Iterator[0]));
     assertFalse(merged.hasNext());
   }
 
+  @SuppressWarnings("unchecked")
   public void testMergeOne() {
     Term t1 = new Term("foo", "a");
     PrefixCodedTerms.Builder b1 = new PrefixCodedTerms.Builder();
@@ -93,13 +97,14 @@ public class TestPrefixCodedTerms extend
     subs.add(pb1.iterator());
     subs.add(pb2.iterator());
     
-    Iterator<Term> merged = CoalescedDeletes.mergedIterator(subs);
+    Iterator<Term> merged = new MergedIterator<Term>(subs.toArray(new Iterator[0]));
     assertTrue(merged.hasNext());
     assertEquals(t1, merged.next());
     assertTrue(merged.hasNext());
     assertEquals(t2, merged.next());
   }
 
+  @SuppressWarnings("unchecked")
   public void testMergeRandom() {
     PrefixCodedTerms pb[] = new PrefixCodedTerms[_TestUtil.nextInt(random(), 2, 10)];
     Set<Term> superSet = new TreeSet<Term>();
@@ -126,7 +131,7 @@ public class TestPrefixCodedTerms extend
     }
     
     Iterator<Term> expected = superSet.iterator();
-    Iterator<Term> actual = CoalescedDeletes.mergedIterator(subs);
+    Iterator<Term> actual = new MergedIterator<Term>(subs.toArray(new Iterator[0]));
     while (actual.hasNext()) {
       assertTrue(expected.hasNext());
       assertEquals(expected.next(), actual.next());

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java Mon Aug 13 02:25:19 2012
@@ -114,10 +114,9 @@ public class TestSegmentReader extends L
   } 
   
   public void testTerms() throws IOException {
-    FieldsEnum fields = MultiFields.getFields(reader).iterator();
-    String field;
-    while((field = fields.next()) != null) {
-      Terms terms = fields.terms();
+    Fields fields = MultiFields.getFields(reader);
+    for (String field : fields) {
+      Terms terms = fields.terms(field);
       assertNotNull(terms);
       TermsEnum termsEnum = terms.iterator(null);
       while(termsEnum.next() != null) {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java Mon Aug 13 02:25:19 2012
@@ -396,13 +396,11 @@ public class TestStressIndexing2 extends
         Fields tv1 = r1.getTermVectors(id1);
         System.out.println("  d1=" + tv1);
         if (tv1 != null) {
-          FieldsEnum fieldsEnum = tv1.iterator();
-          String field;
           DocsAndPositionsEnum dpEnum = null;
           DocsEnum dEnum = null;
-          while ((field=fieldsEnum.next()) != null) {
+          for (String field : tv1) {
             System.out.println("    " + field + ":");
-            Terms terms3 = fieldsEnum.terms();
+            Terms terms3 = tv1.terms(field);
             assertNotNull(terms3);
             TermsEnum termsEnum3 = terms3.iterator(null);
             BytesRef term2;
@@ -430,13 +428,11 @@ public class TestStressIndexing2 extends
         Fields tv2 = r2.getTermVectors(id2);
         System.out.println("  d2=" + tv2);
         if (tv2 != null) {
-          FieldsEnum fieldsEnum = tv2.iterator();
-          String field;
           DocsAndPositionsEnum dpEnum = null;
           DocsEnum dEnum = null;
-          while ((field=fieldsEnum.next()) != null) {
+          for (String field : tv2) {
             System.out.println("    " + field + ":");
-            Terms terms3 = fieldsEnum.terms();
+            Terms terms3 = tv2.terms(field);
             assertNotNull(terms3);
             TermsEnum termsEnum3 = terms3.iterator(null);
             BytesRef term2;
@@ -469,8 +465,11 @@ public class TestStressIndexing2 extends
 
     // Verify postings
     //System.out.println("TEST: create te1");
-    final FieldsEnum fields1 = MultiFields.getFields(r1).iterator();
-    final FieldsEnum fields2 = MultiFields.getFields(r2).iterator();
+    final Fields fields1 = MultiFields.getFields(r1);
+    final Iterator<String> fields1Enum = fields1.iterator();
+    final Fields fields2 = MultiFields.getFields(r2);
+    final Iterator<String> fields2Enum = fields2.iterator();
+
 
     String field1=null, field2=null;
     TermsEnum termsEnum1 = null;
@@ -489,16 +488,15 @@ public class TestStressIndexing2 extends
       for(;;) {
         len1=0;
         if (termsEnum1 == null) {
-          field1 = fields1.next();
-          if (field1 == null) {
+          if (!fields1Enum.hasNext()) {
             break;
-          } else {
-            Terms terms = fields1.terms();
-            if (terms == null) {
-              continue;
-            }
-            termsEnum1 = terms.iterator(null);
           }
+          field1 = fields1Enum.next();
+          Terms terms = fields1.terms(field1);
+          if (terms == null) {
+            continue;
+          }
+          termsEnum1 = terms.iterator(null);
         }
         term1 = termsEnum1.next();
         if (term1 == null) {
@@ -523,16 +521,15 @@ public class TestStressIndexing2 extends
       for(;;) {
         len2=0;
         if (termsEnum2 == null) {
-          field2 = fields2.next();
-          if (field2 == null) {
+          if (!fields2Enum.hasNext()) {
             break;
-          } else {
-            Terms terms = fields2.terms();
-            if (terms == null) {
-              continue;
-            }
-            termsEnum2 = terms.iterator(null);
           }
+          field2 = fields2Enum.next();
+          Terms terms = fields2.terms(field2);
+          if (terms == null) {
+            continue;
+          }
+          termsEnum2 = terms.iterator(null);
         }
         term2 = termsEnum2.next();
         if (term2 == null) {
@@ -605,18 +602,17 @@ public class TestStressIndexing2 extends
     }
     assertTrue(d2 != null);
 
-    FieldsEnum fieldsEnum1 = d1.iterator();
-    FieldsEnum fieldsEnum2 = d2.iterator();
-    String field1;
-    while ((field1 = fieldsEnum1.next()) != null) {
+    Iterator<String> fieldsEnum2 = d2.iterator();
+
+    for (String field1 : d1) {
       String field2 = fieldsEnum2.next();
       assertEquals(field1, field2);
 
-      Terms terms1 = fieldsEnum1.terms();
+      Terms terms1 = d1.terms(field1);
       assertNotNull(terms1);
       TermsEnum termsEnum1 = terms1.iterator(null);
 
-      Terms terms2 = fieldsEnum2.terms();
+      Terms terms2 = d2.terms(field2);
       assertNotNull(terms2);
       TermsEnum termsEnum2 = terms2.iterator(null);
 
@@ -689,7 +685,7 @@ public class TestStressIndexing2 extends
 
       assertNull(termsEnum2.next());
     }
-    assertNull(fieldsEnum2.next());
+    assertFalse(fieldsEnum2.hasNext());
   }
 
   private class IndexingThread extends Thread {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSumDocFreq.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSumDocFreq.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSumDocFreq.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestSumDocFreq.java Mon Aug 13 02:25:19 2012
@@ -74,9 +74,8 @@ public class TestSumDocFreq extends Luce
   private void assertSumDocFreq(IndexReader ir) throws Exception {
     // compute sumDocFreq across all fields
     Fields fields = MultiFields.getFields(ir);
-    FieldsEnum fieldEnum = fields.iterator();
-    String f = null;
-    while ((f = fieldEnum.next()) != null) {
+
+    for (String f : fields) {
       Terms terms = fields.terms(f);
       long sumDocFreq = terms.getSumDocFreq();
       if (sumDocFreq == -1) {

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java Mon Aug 13 02:25:19 2012
@@ -23,7 +23,6 @@ import org.apache.lucene.analysis.MockAn
 import org.apache.lucene.document.*;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Terms;
@@ -179,9 +178,8 @@ class MultiThreadTermVectorsReader imple
   }
   
   private void verifyVectors(Fields vectors, int num) throws IOException {
-    FieldsEnum fieldsEnum = vectors.iterator();
-    while(fieldsEnum.next() != null) {
-      Terms terms = fieldsEnum.terms();
+    for (String field : vectors) {
+      Terms terms = vectors.terms(field);
       assert terms != null;
       verifyVector(terms.iterator(null), num);
     }

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestTermVectors.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestTermVectors.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestTermVectors.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestTermVectors.java Mon Aug 13 02:25:19 2012
@@ -19,6 +19,7 @@ package org.apache.lucene.search;
 
 import java.io.IOException;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.lucene.analysis.MockAnalyzer;
@@ -124,13 +125,13 @@ public class TestTermVectors extends Luc
     assertEquals(4, v.size());
     String[] expectedFields = new String[]{"a", "b", "c", "x"};
     int[] expectedPositions = new int[]{1, 2, 0};
-    FieldsEnum fieldsEnum = v.iterator();
+    Iterator<String> fieldsEnum = v.iterator();
     for(int i=0;i<expectedFields.length;i++) {
       assertEquals(expectedFields[i], fieldsEnum.next());
       assertEquals(3, v.terms(expectedFields[i]).size());
 
       DocsAndPositionsEnum dpEnum = null;
-      Terms terms = fieldsEnum.terms();
+      Terms terms = v.terms(expectedFields[i]);
       assertNotNull(terms);
       TermsEnum termsEnum = terms.iterator(null);
       assertEquals("content", termsEnum.next().utf8ToString());
@@ -251,11 +252,11 @@ public class TestTermVectors extends Luc
     writer.close();
     IndexSearcher knownSearcher = newSearcher(reader);
     knownSearcher.setSimilarity(new DefaultSimilarity());
-    FieldsEnum fields = MultiFields.getFields(knownSearcher.reader).iterator();
+    Fields fields = MultiFields.getFields(knownSearcher.reader);
     
     DocsEnum docs = null;
-    while(fields.next() != null) {
-      Terms terms = fields.terms();
+    for (String fieldName : fields) {
+      Terms terms = fields.terms(fieldName);
       assertNotNull(terms); // NOTE: kinda sketchy assumptions, but ideally we would fix fieldsenum api... 
       TermsEnum termsEnum = terms.iterator(null);
 

Modified: lucene/dev/trunk/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java?rev=1372243&r1=1372242&r2=1372243&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java (original)
+++ lucene/dev/trunk/lucene/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java Mon Aug 13 02:25:19 2012
@@ -25,6 +25,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
+import java.util.NoSuchElementException;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
@@ -42,7 +43,6 @@ import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfos;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.Fields;
-import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.OrdTermState;
 import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.TermState;
@@ -718,22 +718,27 @@ public class MemoryIndex {
 
     private class MemoryFields extends Fields {
       @Override
-      public FieldsEnum iterator() {
-        return new FieldsEnum() {
+      public Iterator<String> iterator() {
+        return new Iterator<String>() {
           int upto = -1;
 
           @Override
           public String next() {
             upto++;
             if (upto >= sortedFields.length) {
-              return null;
+              throw new NoSuchElementException();
             }
             return sortedFields[upto].getKey();
           }
 
           @Override
-          public Terms terms() {
-            return MemoryFields.this.terms(sortedFields[upto].getKey());
+          public boolean hasNext() {
+            return upto+1 < sortedFields.length;
+          }
+
+          @Override
+          public void remove() {
+            throw new UnsupportedOperationException();
           }
         };
       }