LUCENE-3312: Final merge before reintegrate

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/branches/lucene3312@1379940 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lucene/analysis/uima/src/test/org/apache/lucene/analysis/uima/UIMABaseAnalyzerTest.java b/lucene/analysis/uima/src/test/org/apache/lucene/analysis/uima/UIMABaseAnalyzerTest.java
index 6961e15..e51e5af 100644
--- a/lucene/analysis/uima/src/test/org/apache/lucene/analysis/uima/UIMABaseAnalyzerTest.java
+++ b/lucene/analysis/uima/src/test/org/apache/lucene/analysis/uima/UIMABaseAnalyzerTest.java
@@ -25,6 +25,7 @@
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MatchAllDocsQuery;
 import org.apache.lucene.search.TopDocs;
@@ -79,7 +80,7 @@
     IndexSearcher indexSearcher = new IndexSearcher(directoryReader);
     TopDocs result = indexSearcher.search(new MatchAllDocsQuery(), 1);
     assertTrue(result.totalHits > 0);
-    Document d = indexSearcher.doc(result.scoreDocs[0].doc);
+    StoredDocument d = indexSearcher.doc(result.scoreDocs[0].doc);
     assertNotNull(d);
     assertNotNull(d.getField("title"));
     assertEquals(dummyTitle, d.getField("title").stringValue());
@@ -99,7 +100,7 @@
     directoryReader = DirectoryReader.open(dir);
     indexSearcher = new IndexSearcher(directoryReader);
     result = indexSearcher.search(new MatchAllDocsQuery(), 2);
-    Document d1 = indexSearcher.doc(result.scoreDocs[1].doc);
+    StoredDocument d1 = indexSearcher.doc(result.scoreDocs[1].doc);
     assertNotNull(d1);
     assertNotNull(d1.getField("title"));
     assertEquals(dogmasTitle, d1.getField("title").stringValue());
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
index 9401427..5e471b1 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
@@ -226,11 +226,12 @@
 
     final DocState ds = getDocState();
     final Document doc = reuseFields ? ds.doc : new Document();
-    doc.getFields().clear();
+    doc.clear();
     
     // Set ID_FIELD
     FieldType ft = new FieldType(valType);
     ft.setIndexed(true);
+    ft.setStored(true);
 
     Field idField = ds.getField(ID_FIELD, ft);
     int id;
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/BenchmarkHighlighter.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/BenchmarkHighlighter.java
index fd229d0..d1a3abf 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/BenchmarkHighlighter.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/BenchmarkHighlighter.java
@@ -20,11 +20,12 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 
 /**
  * Abstract class for benchmarking highlighting performance
  */
 public abstract class BenchmarkHighlighter {
   public abstract int doHighlight( IndexReader reader, int doc, String field,
-      Document document, Analyzer analyzer, String text ) throws Exception ;
+      StoredDocument document, Analyzer analyzer, String text ) throws Exception ;
 }
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
index f1cce8a..c768b98 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
@@ -32,6 +32,8 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.TopDocs;
 import org.apache.lucene.search.MultiTermQuery;
@@ -96,7 +98,7 @@
 
     // optionally warm and add num docs traversed to count
     if (withWarm()) {
-      Document doc = null;
+      StoredDocument doc = null;
       Bits liveDocs = MultiFields.getLiveDocs(reader);
       for (int m = 0; m < reader.maxDoc(); m++) {
         if (null == liveDocs || liveDocs.get(m)) {
@@ -142,7 +144,7 @@
           System.out.println("numDocs() = " + reader.numDocs());
           for(int i=0;i<hits.scoreDocs.length;i++) {
             final int docID = hits.scoreDocs[i].doc;
-            final Document doc = reader.document(docID);
+            final StoredDocument doc = reader.document(docID);
             System.out.println("  " + i + ": doc=" + docID + " score=" + hits.scoreDocs[i].score + " " + printHitsField + " =" + doc.get(printHitsField));
           }
         }
@@ -163,7 +165,7 @@
               int id = scoreDocs[m].doc;
               res++;
               if (retrieve) {
-                Document document = retrieveDoc(reader, id);
+                StoredDocument document = retrieveDoc(reader, id);
                 res += document != null ? 1 : 0;
                 if (numHighlight > 0 && m < numHighlight) {
                   Collection<String> fieldsToHighlight = getFieldsToHighlight(document);
@@ -193,7 +195,7 @@
   }
 
 
-  protected Document retrieveDoc(IndexReader ir, int id) throws IOException {
+  protected StoredDocument retrieveDoc(IndexReader ir, int id) throws IOException {
     return ir.document(id);
   }
 
@@ -296,10 +298,10 @@
    * @param document The Document
    * @return A Collection of Field names (Strings)
    */
-  protected Collection<String> getFieldsToHighlight(Document document) {
-    List<IndexableField> fields = document.getFields();
+  protected Collection<String> getFieldsToHighlight(StoredDocument document) {
+    List<StorableField> fields = document.getFields();
     Set<String> result = new HashSet<String>(fields.size());
-    for (final IndexableField f : fields) {
+    for (final StorableField f : fields) {
       result.add(f.name());
     }
     return result;
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
index 62b8205..2bdb080 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
@@ -26,6 +26,7 @@
 import org.apache.lucene.benchmark.byTask.PerfRunData;
 import org.apache.lucene.benchmark.byTask.feeds.DocMaker;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.document.IntField;
 import org.apache.lucene.document.LongField;
 import org.apache.lucene.document.FloatField;
@@ -68,7 +69,7 @@
 
   @Override
   public int doLogic() throws Exception {
-    List<IndexableField> fields = doc.getFields();
+    List<Field> fields = doc.getFields();
     Analyzer analyzer = getRunData().getAnalyzer();
     int tokenCount = 0;
     for(final IndexableField field : fields) {
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetHighlightTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetHighlightTask.java
index 8af944b..8e3d87e 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetHighlightTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetHighlightTask.java
@@ -22,6 +22,7 @@
 import org.apache.lucene.benchmark.byTask.PerfRunData;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.highlight.Highlighter;
 import org.apache.lucene.search.highlight.QueryScorer;
@@ -101,7 +102,7 @@
     return new BenchmarkHighlighter(){
       @Override
       public int doHighlight(IndexReader reader, int doc, String field,
-          Document document, Analyzer analyzer, String text) throws Exception {
+          StoredDocument document, Analyzer analyzer, String text) throws Exception {
         TokenStream ts = TokenSources.getAnyTokenStream(reader, doc, field, document, analyzer);
         TextFragment[] frag = highlighter.getBestTextFragments(ts, text, mergeContiguous, maxFrags);
         return frag != null ? frag.length : 0;
@@ -110,7 +111,7 @@
   }
 
   @Override
-  protected Collection<String> getFieldsToHighlight(Document document) {
+  protected Collection<String> getFieldsToHighlight(StoredDocument document) {
     Collection<String> result = super.getFieldsToHighlight(document);
     //if stored is false, then result will be empty, in which case just get all the param fields
     if (paramFields.isEmpty() == false && result.isEmpty() == false) {
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java
index a7858ab..406e994 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java
@@ -25,6 +25,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.DocumentStoredFieldVisitor;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 
 /**
  * Search and Traverse and Retrieve docs task using a
@@ -54,7 +55,7 @@
 
 
   @Override
-  protected Document retrieveDoc(IndexReader ir, int id) throws IOException {
+  protected StoredDocument retrieveDoc(IndexReader ir, int id) throws IOException {
     if (fieldsToLoad == null) {
       return ir.document(id);
     } else {
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetVectorHighlightTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetVectorHighlightTask.java
index 2a897ec..4993aff 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetVectorHighlightTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetVectorHighlightTask.java
@@ -21,6 +21,7 @@
 import org.apache.lucene.benchmark.byTask.PerfRunData;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.vectorhighlight.FastVectorHighlighter;
 import org.apache.lucene.search.vectorhighlight.FieldQuery;
@@ -99,7 +100,7 @@
     return new BenchmarkHighlighter(){
       @Override
       public int doHighlight(IndexReader reader, int doc, String field,
-          Document document, Analyzer analyzer, String text) throws Exception {
+          StoredDocument document, Analyzer analyzer, String text) throws Exception {
         final FieldQuery fq = highlighter.getFieldQuery( myq, reader);
         String[] fragments = highlighter.getBestFragments(fq, reader, doc, field, fragSize, maxFrags);
         return fragments != null ? fragments.length : 0;
@@ -108,7 +109,7 @@
   }
 
   @Override
-  protected Collection<String> getFieldsToHighlight(Document document) {
+  protected Collection<String> getFieldsToHighlight(StoredDocument document) {
     Collection<String> result = super.getFieldsToHighlight(document);
     //if stored is false, then result will be empty, in which case just get all the param fields
     if (paramFields.isEmpty() == false && result.isEmpty() == false) {
diff --git a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java
index 05188d6..e4e5b51 100644
--- a/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java
+++ b/lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java
@@ -33,6 +33,7 @@
 import org.apache.lucene.benchmark.byTask.utils.StreamUtils;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 
 /**
  * A task which writes documents, one line per document. Each line is in the
@@ -172,7 +173,7 @@
 
     boolean sufficient = !checkSufficientFields;
     for (int i=0; i<fieldsToWrite.length; i++) {
-      IndexableField f = doc.getField(fieldsToWrite[i]);
+      StorableField f = doc.getField(fieldsToWrite[i]);
       String text = f == null ? "" : matcher.reset(f.stringValue()).replaceAll(" ").trim();
       sb.append(text).append(SEP);
       sufficient |= text.length()>0 && sufficientFields[i];
diff --git a/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/CountingHighlighterTestTask.java b/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/CountingHighlighterTestTask.java
index a6e0293..3d5bb8a 100644
--- a/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/CountingHighlighterTestTask.java
+++ b/lucene/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/CountingHighlighterTestTask.java
@@ -28,6 +28,7 @@
 import org.apache.lucene.search.Query;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 
 import java.io.IOException;
 
@@ -44,8 +45,8 @@
   }
 
   @Override
-  protected Document retrieveDoc(IndexReader ir, int id) throws IOException {
-    Document document = ir.document(id);
+  protected StoredDocument retrieveDoc(IndexReader ir, int id) throws IOException {
+    StoredDocument document = ir.document(id);
     if (document != null) {
       numDocsRetrieved++;
     }
@@ -57,7 +58,7 @@
     highlighter = new Highlighter(new SimpleHTMLFormatter(), new QueryScorer(q));
     return new BenchmarkHighlighter() {
       @Override
-      public int doHighlight(IndexReader reader, int doc, String field, Document document, Analyzer analyzer, String text) throws Exception {
+      public int doHighlight(IndexReader reader, int doc, String field, StoredDocument document, Analyzer analyzer, String text) throws Exception {
         TokenStream ts = TokenSources.getAnyTokenStream(reader, doc, field, document, analyzer);
         TextFragment[] frag = highlighter.getBestTextFragments(ts, text, mergeContiguous, maxFrags);
         numHighlightedResults += frag != null ? frag.length : 0;
diff --git a/lucene/core/src/java/org/apache/lucene/analysis/package.html b/lucene/core/src/java/org/apache/lucene/analysis/package.html
index b298263..b829f13 100644
--- a/lucene/core/src/java/org/apache/lucene/analysis/package.html
+++ b/lucene/core/src/java/org/apache/lucene/analysis/package.html
@@ -168,7 +168,7 @@
 <ul>
   <li>
     At indexing, as a consequence of 
-    {@link org.apache.lucene.index.IndexWriter#addDocument(Iterable) addDocument(doc)},
+    {@link org.apache.lucene.index.IndexWriter#addDocument(IndexDocument) addDocument(doc)},
     the Analyzer in effect for indexing is invoked for each indexed field of the added document.
   </li>
   <li>
@@ -241,7 +241,7 @@
 </p>
 <h3>Field Section Boundaries</h3>
 <p>
-  When {@link org.apache.lucene.document.Document#add(org.apache.lucene.index.IndexableField) document.add(field)}
+  When {@link org.apache.lucene.document.Document#add(org.apache.lucene.document.Field) document.add(field)}
   is called multiple times for the same field name, we could say that each such call creates a new 
   section for that field in that document. 
   In fact, a separate call to 
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/DocValuesConsumer.java b/lucene/core/src/java/org/apache/lucene/codecs/DocValuesConsumer.java
index 4e1e536..c052dc3 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/DocValuesConsumer.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/DocValuesConsumer.java
@@ -28,21 +28,23 @@
 import org.apache.lucene.document.PackedLongDocValuesField;
 import org.apache.lucene.document.ShortDocValuesField;
 import org.apache.lucene.document.SortedBytesDocValuesField;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.document.StraightBytesDocValuesField;
 import org.apache.lucene.index.AtomicReader;
 import org.apache.lucene.index.DocValues.Source;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.index.MergeState;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 
 /**
- * Abstract API that consumes {@link IndexableField}s.
+ * Abstract API that consumes {@link StorableField}s.
  * {@link DocValuesConsumer} are always associated with a specific field and
  * segments. Concrete implementations of this API write the given
- * {@link IndexableField} into a implementation specific format depending on
+ * {@link StorableField} into a implementation specific format depending on
  * the fields meta-data.
  * 
  * @lucene.experimental
@@ -53,7 +55,7 @@
 
   protected abstract Type getType();
   /**
-   * Adds the given {@link IndexableField} instance to this
+   * Adds the given {@link StorableField} instance to this
    * {@link DocValuesConsumer}
    * 
    * @param docID
@@ -64,7 +66,7 @@
    * @throws IOException
    *           if an {@link IOException} occurs
    */
-  public abstract void add(int docID, IndexableField value)
+  public abstract void add(int docID, StorableField value)
       throws IOException;
 
   /**
@@ -73,7 +75,7 @@
    * @param docCount
    *          the total number of documents in this {@link DocValuesConsumer}.
    *          Must be greater than or equal the last given docID to
-   *          {@link #add(int, IndexableField)}.
+   *          {@link #add(int, StorableField)}.
    * @throws IOException
    */
   public abstract void finish(int docCount) throws IOException;
@@ -136,7 +138,7 @@
     assert source != null;
     int docID = docBase;
     final Type type = getType();
-    final Field scratchField;
+    final StoredField scratchField;
     switch(type) {
     case VAR_INTS:
       scratchField = new PackedLongDocValuesField("", (long) 0);
@@ -202,7 +204,7 @@
    * ID must always be greater than the previous ID or <tt>0</tt> if called the
    * first time.
    */
-  protected void mergeDoc(Field scratchField, Source source, int docID, int sourceDoc)
+  protected void mergeDoc(StoredField scratchField, Source source, int docID, int sourceDoc)
       throws IOException {
     switch(getType()) {
     case BYTES_FIXED_DEREF:
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java
index 7e67b50..3541da8 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/StoredFieldsWriter.java
@@ -19,13 +19,13 @@
 import java.io.Closeable;
 import java.io.IOException;
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.index.AtomicReader;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
-import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MergeState;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.util.Bits;
+import org.apache.lucene.index.AtomicReader;
 
 /**
  * Codec API for writing stored fields:
@@ -33,7 +33,7 @@
  * <ol>
  *   <li>For every document, {@link #startDocument(int)} is called,
  *       informing the Codec how many fields will be written.
- *   <li>{@link #writeField(FieldInfo, IndexableField)} is called for 
+ *   <li>{@link #writeField(FieldInfo, StorableField)} is called for 
  *       each field in the document.
  *   <li>After all documents have been written, {@link #finish(FieldInfos, int)} 
  *       is called for verification/sanity-checks.
@@ -45,14 +45,14 @@
 public abstract class StoredFieldsWriter implements Closeable {
   
   /** Called before writing the stored fields of the document.
-   *  {@link #writeField(FieldInfo, IndexableField)} will be called
+   *  {@link #writeField(FieldInfo, StorableField)} will be called
    *  <code>numStoredFields</code> times. Note that this is
    *  called even if the document has no stored fields, in
    *  this case <code>numStoredFields</code> will be zero. */
   public abstract void startDocument(int numStoredFields) throws IOException;
   
   /** Writes a single stored field. */
-  public abstract void writeField(FieldInfo info, IndexableField field) throws IOException;
+  public abstract void writeField(FieldInfo info, StorableField field) throws IOException;
 
   /** Aborts writing entirely, implementation should remove
    *  any partially-written files, etc. */
@@ -69,7 +69,7 @@
   /** Merges in the stored fields from the readers in 
    *  <code>mergeState</code>. The default implementation skips
    *  over deleted documents, and uses {@link #startDocument(int)},
-   *  {@link #writeField(FieldInfo, IndexableField)}, and {@link #finish(FieldInfos, int)},
+   *  {@link #writeField(FieldInfo, StorableField)}, and {@link #finish(FieldInfos, int)},
    *  returning the number of documents that were written.
    *  Implementations can override this method for more sophisticated
    *  merging (bulk-byte copying, etc). */
@@ -89,7 +89,7 @@
         // on the fly?
         // NOTE: it's very important to first assign to doc then pass it to
         // fieldsWriter.addDocument; see LUCENE-1282
-        Document doc = reader.document(i);
+        StoredDocument doc = reader.document(i);
         addDocument(doc, mergeState.fieldInfos);
         docCount++;
         mergeState.checkAbort.work(300);
@@ -100,20 +100,16 @@
   }
   
   /** sugar method for startDocument() + writeField() for every stored field in the document */
-  protected final void addDocument(Iterable<? extends IndexableField> doc, FieldInfos fieldInfos) throws IOException {
+  protected final void addDocument(Iterable<? extends StorableField> doc, FieldInfos fieldInfos) throws IOException {
     int storedCount = 0;
-    for (IndexableField field : doc) {
-      if (field.fieldType().stored()) {
-        storedCount++;
-      }
+    for (StorableField field : doc) {
+      storedCount++;
     }
     
     startDocument(storedCount);
 
-    for (IndexableField field : doc) {
-      if (field.fieldType().stored()) {
+    for (StorableField field : doc) {
         writeField(fieldInfos.fieldInfo(field.name()), field);
-      }
     }
   }
 }
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java
index fa90993..3e5a0a0 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/Lucene40StoredFieldsWriter.java
@@ -29,6 +29,8 @@
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MergeState;
 import org.apache.lucene.index.SegmentReader;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -131,7 +133,7 @@
         IndexFileNames.segmentFileName(segment, "", FIELDS_INDEX_EXTENSION));
   }
 
-  public void writeField(FieldInfo info, IndexableField field) throws IOException {
+  public void writeField(FieldInfo info, StorableField field) throws IOException {
     fieldsStream.writeVInt(info.number);
     int bits = 0;
     final BytesRef bytes;
@@ -297,7 +299,7 @@
         // on the fly?
         // NOTE: it's very important to first assign to doc then pass it to
         // fieldsWriter.addDocument; see LUCENE-1282
-        Document doc = reader.document(j);
+        StoredDocument doc = reader.document(j);
         addDocument(doc, mergeState.fieldInfos);
         docCount++;
         mergeState.checkAbort.work(300);
@@ -324,7 +326,7 @@
       for (; docCount < maxDoc; docCount++) {
         // NOTE: it's very important to first assign to doc then pass it to
         // fieldsWriter.addDocument; see LUCENE-1282
-        Document doc = reader.document(docCount);
+        StoredDocument doc = reader.document(docCount);
         addDocument(doc, mergeState.fieldInfos);
         mergeState.checkAbort.work(300);
       }
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
index 8b533f3..5613d8e 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Bytes.java
@@ -30,6 +30,7 @@
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.DataOutput;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
@@ -420,7 +421,7 @@
     }
 
     @Override
-    public void add(int docID, IndexableField value) throws IOException {
+    public void add(int docID, StorableField value) throws IOException {
       BytesRef bytes = value.binaryValue();
       assert bytes != null;
       if (bytes.length == 0) { // default value - skip it
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java
index bc072ad..0ba456a 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/FixedStraightBytesImpl.java
@@ -22,12 +22,12 @@
 import org.apache.lucene.codecs.lucene40.values.Bytes.BytesReaderBase;
 import org.apache.lucene.codecs.lucene40.values.Bytes.BytesSourceBase;
 import org.apache.lucene.codecs.lucene40.values.Bytes.BytesWriterBase;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.document.StraightBytesDocValuesField;
-import org.apache.lucene.document.Field;
 import org.apache.lucene.index.DocValues.Source;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -74,7 +74,7 @@
     }
     
     @Override
-    public void add(int docID, IndexableField value) throws IOException {
+    public void add(int docID, StorableField value) throws IOException {
       final BytesRef bytes = value.binaryValue();
       assert bytes != null;
       assert lastDocID < docID;
@@ -201,7 +201,7 @@
     }
     
     @Override
-    protected void mergeDoc(Field scratchField, Source source, int docID, int sourceDoc) throws IOException {
+    protected void mergeDoc(StoredField scratchField, Source source, int docID, int sourceDoc) throws IOException {
       assert lastDocID < docID;
       setMergeBytes(source, sourceDoc);
       if (size == -1) {
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Floats.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Floats.java
index c8a96fd..e8724a3 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Floats.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Floats.java
@@ -24,6 +24,7 @@
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -88,7 +89,7 @@
     }
     
     @Override
-    public void add(int docID, IndexableField value) throws IOException {
+    public void add(int docID, StorableField value) throws IOException {
       template.toBytes(value.numericValue().doubleValue(), bytesRef);
       bytesSpareField.setBytesValue(bytesRef);
       super.add(docID, bytesSpareField);
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Ints.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Ints.java
index 2d937f6..33ef01f 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Ints.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/Ints.java
@@ -25,6 +25,7 @@
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -112,7 +113,7 @@
     }
     
     @Override
-    public void add(int docID, IndexableField value) throws IOException {
+    public void add(int docID, StorableField value) throws IOException {
       template.toBytes(value.numericValue().longValue(), bytesRef);
       bytesSpareField.setBytesValue(bytesRef);
       super.add(docID, bytesSpareField);
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
index 557d21e..4f27653 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/PackedIntValues.java
@@ -26,6 +26,7 @@
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexFileNames;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -126,7 +127,7 @@
     }
     
     @Override
-    public void add(int docID, IndexableField docValue) throws IOException {
+    public void add(int docID, StorableField docValue) throws IOException {
       final long v = docValue.numericValue().longValue();
       assert lastDocId < docID;
       if (!started) {
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
index 126c11d..7efe24c 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene40/values/VarStraightBytesImpl.java
@@ -22,11 +22,11 @@
 import org.apache.lucene.codecs.lucene40.values.Bytes.BytesReaderBase;
 import org.apache.lucene.codecs.lucene40.values.Bytes.BytesSourceBase;
 import org.apache.lucene.codecs.lucene40.values.Bytes.BytesWriterBase;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.index.DocValues.Source;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.DocValues;
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -86,7 +86,7 @@
     }
 
     @Override
-    public void add(int docID, IndexableField value) throws IOException {
+    public void add(int docID, StorableField value) throws IOException {
       final BytesRef bytes = value.binaryValue();
       assert bytes != null;
       assert !merge;
@@ -156,7 +156,7 @@
     }
     
     @Override
-    protected void mergeDoc(Field scratchField, Source source, int docID, int sourceDoc) throws IOException {
+    protected void mergeDoc(StoredField scratchField, Source source, int docID, int sourceDoc) throws IOException {
       assert merge;
       assert lastDocID < docID;
       source.getBytes(sourceDoc, bytesRef);
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesConsumer.java b/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesConsumer.java
index f662b22..96aac28 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesConsumer.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextDocValuesConsumer.java
@@ -21,7 +21,7 @@
 import org.apache.lucene.codecs.DocValuesConsumer;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.IndexFileNames;
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexOutput;
@@ -72,7 +72,7 @@
   }
 
   @Override
-  public void add(int docID, IndexableField value) throws IOException {
+  public void add(int docID, StorableField value) throws IOException {
     assert docID >= 0;
     final int ord, vSize;
     switch (type) {
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsWriter.java
index 3d38879..6a9b223 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/simpletext/SimpleTextStoredFieldsWriter.java
@@ -23,7 +23,7 @@
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfos;
 import org.apache.lucene.index.IndexFileNames;
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexOutput;
@@ -89,7 +89,7 @@
   }
 
   @Override
-  public void writeField(FieldInfo info, IndexableField field) throws IOException {
+  public void writeField(FieldInfo info, StorableField field) throws IOException {
     write(FIELD);
     write(Integer.toString(info.number));
     newLine();
diff --git a/lucene/core/src/java/org/apache/lucene/document/ByteDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/ByteDocValuesField.java
index 076af30..74e2142 100644
--- a/lucene/core/src/java/org/apache/lucene/document/ByteDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/ByteDocValuesField.java
@@ -36,7 +36,7 @@
  * @see DocValues for further information
  * */
 
-public class ByteDocValuesField extends Field {
+public class ByteDocValuesField extends StoredField {
 
   /**
    * Type for 8-bit byte DocValues.
diff --git a/lucene/core/src/java/org/apache/lucene/document/DerefBytesDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/DerefBytesDocValuesField.java
index bc846a4..98755d6 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DerefBytesDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DerefBytesDocValuesField.java
@@ -41,7 +41,7 @@
  * @see DocValues for further information
  * */
 
-public class DerefBytesDocValuesField extends Field {
+public class DerefBytesDocValuesField extends StoredField {
 
   // TODO: ideally indexer figures out var vs fixed on its own!?
   /**
diff --git a/lucene/core/src/java/org/apache/lucene/document/Document.java b/lucene/core/src/java/org/apache/lucene/document/Document.java
index da8424b..f9ec493 100644
--- a/lucene/core/src/java/org/apache/lucene/document/Document.java
+++ b/lucene/core/src/java/org/apache/lucene/document/Document.java
@@ -19,11 +19,15 @@
 
 import java.util.*;
 
+import org.apache.lucene.index.IndexDocument;
 import org.apache.lucene.index.IndexReader;  // for javadoc
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.IndexSearcher;  // for javadoc
 import org.apache.lucene.search.ScoreDoc; // for javadoc
 import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.FilterIterator;
 
 /** Documents are the unit of indexing and search.
  *
@@ -38,18 +42,36 @@
  * ScoreDoc#doc} or {@link IndexReader#document(int)}.
  */
 
-public final class Document implements Iterable<IndexableField> {
+public final class Document implements IndexDocument{
 
-  private final List<IndexableField> fields = new ArrayList<IndexableField>();
+  private final List<Field> fields = new ArrayList<Field>();
 
   /** Constructs a new document with no fields. */
   public Document() {}
+  
 
-  @Override
-  public Iterator<IndexableField> iterator() {
-    return fields.iterator();
-  }
+  /**
+  * Creates a Document from StoredDocument so it that can be used e.g. for another
+  * round of indexing.
+  *
+  */
+  public Document(StoredDocument storedDoc) {
+    for (StorableField field : storedDoc.getFields()) {
+      Field newField = new Field(field.name(), (FieldType) field.fieldType());
+     
+      newField.fieldsData = field.stringValue();
+      if (newField.fieldsData == null) 
+        newField.fieldsData = field.numericValue();
+      if (newField.fieldsData == null) 
+        newField.fieldsData = field.binaryValue();
+      if (newField.fieldsData == null) 
+        newField.fieldsData = field.readerValue();
+     
+      add(newField);
+    }
+ }
 
+  
   /**
    * <p>Adds a field to a document.  Several fields may be added with
    * the same name.  In this case, if the fields are indexed, their text is
@@ -60,7 +82,7 @@
    * a document has to be deleted from an index and a new changed version of that
    * document has to be added.</p>
    */
-  public final void add(IndexableField field) {
+  public final void add(Field field) {
     fields.add(field);
   }
   
@@ -75,9 +97,9 @@
    * document has to be added.</p>
    */
   public final void removeField(String name) {
-    Iterator<IndexableField> it = fields.iterator();
+    Iterator<Field> it = fields.iterator();
     while (it.hasNext()) {
-      IndexableField field = it.next();
+      Field field = it.next();
       if (field.name().equals(name)) {
         it.remove();
         return;
@@ -95,9 +117,9 @@
    * document has to be added.</p>
    */
   public final void removeFields(String name) {
-    Iterator<IndexableField> it = fields.iterator();
+    Iterator<Field> it = fields.iterator();
     while (it.hasNext()) {
-      IndexableField field = it.next();
+      Field field = it.next();
       if (field.name().equals(name)) {
         it.remove();
       }
@@ -116,7 +138,10 @@
   */
   public final BytesRef[] getBinaryValues(String name) {
     final List<BytesRef> result = new ArrayList<BytesRef>();
-    for (IndexableField field : fields) {
+    Iterator<Field> it = storedFieldsIterator();
+    
+    while (it.hasNext()) {
+      StorableField field = it.next();
       if (field.name().equals(name)) {
         final BytesRef bytes = field.binaryValue();
         if (bytes != null) {
@@ -138,7 +163,10 @@
   * @return a <code>byte[]</code> containing the binary field value or <code>null</code>
   */
   public final BytesRef getBinaryValue(String name) {
-    for (IndexableField field : fields) {
+    Iterator<Field> it = storedFieldsIterator();
+    
+    while (it.hasNext()) {
+      StorableField field = it.next();
       if (field.name().equals(name)) {
         final BytesRef bytes = field.binaryValue();
         if (bytes != null) {
@@ -153,8 +181,8 @@
    * null.  If multiple fields exists with this name, this method returns the
    * first value added.
    */
-  public final IndexableField getField(String name) {
-    for (IndexableField field : fields) {
+  public final Field getField(String name) {
+    for (Field field : fields) {
       if (field.name().equals(name)) {
         return field;
       }
@@ -170,15 +198,15 @@
    * @param name the name of the field
    * @return a <code>Fieldable[]</code> array
    */
-  public IndexableField[] getFields(String name) {
-    List<IndexableField> result = new ArrayList<IndexableField>();
-    for (IndexableField field : fields) {
+  public Field[] getFields(String name) {
+    List<Field> result = new ArrayList<Field>();
+    for (Field field : fields) {
       if (field.name().equals(name)) {
         result.add(field);
       }
     }
 
-    return result.toArray(new IndexableField[result.size()]);
+    return result.toArray(new Field[result.size()]);
   }
   
   /** Returns a List of all the fields in a document.
@@ -186,9 +214,11 @@
    * <i>not</i> available in documents retrieved from the
    * index, e.g. {@link IndexSearcher#doc(int)} or {@link
    * IndexReader#document(int)}.
+   * 
+   * @return an immutable <code>List[Field]</code> 
    */
-  public final List<IndexableField> getFields() {
-    return fields;
+  public final List<Field> getFields() {
+    return Collections.unmodifiableList(fields);
   }
   
    private final static String[] NO_STRINGS = new String[0];
@@ -205,7 +235,10 @@
    */
   public final String[] getValues(String name) {
     List<String> result = new ArrayList<String>();
-    for (IndexableField field : fields) {
+    Iterator<Field> it = storedFieldsIterator();
+    
+    while (it.hasNext()) {
+      StorableField field = it.next();
       if (field.name().equals(name) && field.stringValue() != null) {
         result.add(field.stringValue());
       }
@@ -227,7 +260,10 @@
    * the actual numeric field instance back, use {@link #getField}.
    */
   public final String get(String name) {
-    for (IndexableField field : fields) {
+    Iterator<Field> it = storedFieldsIterator();
+    
+    while (it.hasNext()) {
+      StorableField field = it.next();
       if (field.name().equals(name) && field.stringValue() != null) {
         return field.stringValue();
       }
@@ -249,4 +285,50 @@
     buffer.append(">");
     return buffer.toString();
   }
+
+  /** Obtains all indexed fields in document */
+  @Override
+  public Iterable<? extends IndexableField> indexableFields() {
+    return new Iterable<Field>() {
+      @Override
+      public Iterator<Field> iterator() {
+        return Document.this.indexedFieldsIterator();
+      }
+    };
+  }
+
+
+  /** Obtains all stored fields in document. */
+  @Override
+  public Iterable<? extends StorableField> storableFields() {
+    return new Iterable<Field>() {
+      @Override
+      public Iterator<Field> iterator() {
+        return Document.this.storedFieldsIterator();
+      }
+    };
+  }
+
+  private Iterator<Field> storedFieldsIterator() {
+    return new FilterIterator<Field>(fields.iterator()) {
+      @Override
+      protected boolean predicateFunction(Field field) {
+        return field.type.stored();
+      }
+    };
+  }
+  
+  private Iterator<Field> indexedFieldsIterator() {
+    return new FilterIterator<Field>(fields.iterator()) {
+      @Override
+      protected boolean predicateFunction(Field field) {
+        return field.type.indexed();
+      }
+    };
+  }
+
+  /** Removes all the fields from document. */
+  public void clear() {
+    fields.clear();
+  }
 }
diff --git a/lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java b/lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java
index 2f79c41..111fd25 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DocumentStoredFieldVisitor.java
@@ -23,6 +23,7 @@
 
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.StoredFieldVisitor;
 
 /** A {@link StoredFieldVisitor} that creates a {@link
@@ -35,7 +36,7 @@
  * @lucene.experimental */
 
 public class DocumentStoredFieldVisitor extends StoredFieldVisitor {
-  private final Document doc = new Document();
+  private final StoredDocument doc = new StoredDocument();
   private final Set<String> fieldsToAdd;
 
   /** Load only fields named in the provided <code>Set&lt;String&gt;</code>. */
@@ -68,7 +69,7 @@
     ft.setIndexed(fieldInfo.isIndexed());
     ft.setOmitNorms(fieldInfo.omitsNorms());
     ft.setIndexOptions(fieldInfo.getIndexOptions());
-    doc.add(new Field(fieldInfo.name, value, ft));
+    doc.add(new StoredField(fieldInfo.name, value, ft));
   }
 
   @Override
@@ -98,12 +99,9 @@
 
   /**
    * Retrieve the visited document.
-   * @return Document populated with stored fields. Note that only
-   *         the stored information in the field instances is valid,
-   *         data such as boosts, indexing options, term vector options,
-   *         etc is not set.
+   * @return StoredDocument populated with stored fields.
    */
-  public Document getDocument() {
+  public StoredDocument getDocument() {
     return doc;
   }
 }
diff --git a/lucene/core/src/java/org/apache/lucene/document/DoubleDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/DoubleDocValuesField.java
index bb4d1f5..6b21cf3 100644
--- a/lucene/core/src/java/org/apache/lucene/document/DoubleDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/DoubleDocValuesField.java
@@ -36,7 +36,7 @@
  * @see DocValues for further information
  * */
 
-public class DoubleDocValuesField extends Field {
+public class DoubleDocValuesField extends StoredField {
 
   /**
    * Type for 64-bit double DocValues.
diff --git a/lucene/core/src/java/org/apache/lucene/document/Field.java b/lucene/core/src/java/org/apache/lucene/document/Field.java
index 2a2ec60..011187d 100644
--- a/lucene/core/src/java/org/apache/lucene/document/Field.java
+++ b/lucene/core/src/java/org/apache/lucene/document/Field.java
@@ -30,6 +30,7 @@
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexableFieldType;
 import org.apache.lucene.index.Norm; // javadocs
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.index.FieldInvertState; // javadocs
 
@@ -58,12 +59,13 @@
  * Field it is used in.  It is strongly recommended that no
  * changes be made after Field instantiation.
  */
-public class Field implements IndexableField {
+public class Field implements IndexableField, StorableField {
 
   /**
    * Field's type
    */
   protected final FieldType type;
+
   /**
    * Field's name
    */
diff --git a/lucene/core/src/java/org/apache/lucene/document/FieldType.java b/lucene/core/src/java/org/apache/lucene/document/FieldType.java
index a476411..8f4b6c9 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FieldType.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FieldType.java
@@ -27,7 +27,7 @@
 /**
  * Describes the properties of a field.
  */
-public class FieldType implements IndexableFieldType {
+public class FieldType implements IndexableFieldType  {
 
   /** Data type of the numeric value
    * @since 3.2
@@ -52,10 +52,10 @@
   private boolean storeTermVectorPayloads;
   private boolean omitNorms;
   private IndexOptions indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
-  private DocValues.Type docValueType;
   private NumericType numericType;
   private boolean frozen;
   private int numericPrecisionStep = NumericUtils.PRECISION_STEP_DEFAULT;
+  private DocValues.Type docValueType;
 
   /**
    * Create a new mutable FieldType with all of the properties from <code>ref</code>
@@ -300,29 +300,6 @@
   }
 
   /**
-   * Set's the field's DocValues.Type
-   * @param type DocValues type, or null if no DocValues should be stored.
-   * @throws IllegalStateException if this FieldType is frozen against
-   *         future modifications.
-   * @see #docValueType()
-   */
-  public void setDocValueType(DocValues.Type type) {
-    checkIfFrozen();
-    docValueType = type;
-  }
-  
-  /**
-   * {@inheritDoc}
-   * <p>
-   * The default is <code>null</code> (no docValues) 
-   * @see #setDocValueType(DocValues.Type)
-   */
-  @Override
-  public DocValues.Type docValueType() {
-    return docValueType;
-  }
-
-  /**
    * Specifies the field's numeric type.
    * @param type numeric type, or null if the field has no numeric type.
    * @throws IllegalStateException if this FieldType is frozen against
@@ -423,4 +400,30 @@
     
     return result.toString();
   }
+  
+  /* from StorableFieldType */
+  
+  /**
+   * {@inheritDoc}
+   * <p>
+   * The default is <code>null</code> (no docValues) 
+   * @see #setDocValueType(DocValues.Type)
+   */
+  @Override
+  public DocValues.Type docValueType() {
+    return docValueType;
+  }
+
+  /**
+   * Set's the field's DocValues.Type
+   * @param type DocValues type, or null if no DocValues should be stored.
+   * @throws IllegalStateException if this FieldType is frozen against
+   *         future modifications.
+   * @see #docValueType()
+   */
+  public void setDocValueType(DocValues.Type type) {
+    checkIfFrozen();
+    docValueType = type;
+    this.stored = true;
+  }
 }
diff --git a/lucene/core/src/java/org/apache/lucene/document/FloatDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/FloatDocValuesField.java
index dd4f1c2..bf66370 100644
--- a/lucene/core/src/java/org/apache/lucene/document/FloatDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/FloatDocValuesField.java
@@ -35,7 +35,7 @@
  * @see DocValues for further information
  * */
 
-public class FloatDocValuesField extends Field {
+public class FloatDocValuesField extends StoredField {
 
   /**
    * Type for 32-bit float DocValues.
diff --git a/lucene/core/src/java/org/apache/lucene/document/IntDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/IntDocValuesField.java
index 28914bc..a06012c 100644
--- a/lucene/core/src/java/org/apache/lucene/document/IntDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/IntDocValuesField.java
@@ -35,7 +35,7 @@
  * @see DocValues for further information
  * */
 
-public class IntDocValuesField extends Field {
+public class IntDocValuesField extends StoredField {
 
   /**
    * Type for 32-bit integer DocValues.
diff --git a/lucene/core/src/java/org/apache/lucene/document/LongDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/LongDocValuesField.java
index e3484bd..e023331 100644
--- a/lucene/core/src/java/org/apache/lucene/document/LongDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/LongDocValuesField.java
@@ -35,7 +35,7 @@
  * @see DocValues for further information
  * */
 
-public class LongDocValuesField extends Field {
+public class LongDocValuesField extends StoredField {
 
   /**
    * Type for 64-bit long DocValues.
diff --git a/lucene/core/src/java/org/apache/lucene/document/PackedLongDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/PackedLongDocValuesField.java
index 8d3f2ba..93908dd 100644
--- a/lucene/core/src/java/org/apache/lucene/document/PackedLongDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/PackedLongDocValuesField.java
@@ -39,7 +39,7 @@
  * @see DocValues for further information
  * */
 
-public class PackedLongDocValuesField extends Field {
+public class PackedLongDocValuesField extends StoredField {
 
   /**
    * Type for packed long DocValues.
@@ -47,6 +47,7 @@
   public static final FieldType TYPE = new FieldType();
   static {
     TYPE.setDocValueType(DocValues.Type.VAR_INTS);
+    TYPE.setStored(true);
     TYPE.freeze();
   }
 
diff --git a/lucene/core/src/java/org/apache/lucene/document/ShortDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/ShortDocValuesField.java
index 45dafc9..cb33876 100644
--- a/lucene/core/src/java/org/apache/lucene/document/ShortDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/ShortDocValuesField.java
@@ -36,7 +36,7 @@
  * @see DocValues for further information
  * */
 
-public class ShortDocValuesField extends Field {
+public class ShortDocValuesField extends StoredField {
 
   /**
    * Type for 16-bit short DocValues.
diff --git a/lucene/core/src/java/org/apache/lucene/document/SortedBytesDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/SortedBytesDocValuesField.java
index 594e26d..a5ec57b 100644
--- a/lucene/core/src/java/org/apache/lucene/document/SortedBytesDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/SortedBytesDocValuesField.java
@@ -37,7 +37,7 @@
  * @see DocValues for further information
  * */
 
-public class SortedBytesDocValuesField extends Field {
+public class SortedBytesDocValuesField extends StoredField {
 
   // TODO: ideally indexer figures out var vs fixed on its own!?
   /**
diff --git a/lucene/core/src/java/org/apache/lucene/document/StoredField.java b/lucene/core/src/java/org/apache/lucene/document/StoredField.java
index 6ffa81a..d0fc08d 100644
--- a/lucene/core/src/java/org/apache/lucene/document/StoredField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/StoredField.java
@@ -1,6 +1,7 @@
 package org.apache.lucene.document;
 
 import org.apache.lucene.index.IndexReader; // javadocs
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.IndexSearcher; // javadocs
 import org.apache.lucene.util.BytesRef;
 
@@ -24,7 +25,7 @@
 /** A field whose value is stored so that {@link
  *  IndexSearcher#doc} and {@link IndexReader#document} will
  *  return the field and its value. */
-public final class StoredField extends Field {
+public class StoredField extends Field {
 
   /**
    * Type for a stored-only field.
@@ -37,6 +38,31 @@
   }
 
   /**
+   * Expert: allows you to customize the {@link
+   * FieldType}.
+   * @param name field name
+   * @param type custom {@link FieldType} for this field
+   * @throws IllegalArgumentException if the field name is null.
+   */
+  protected StoredField(String name, FieldType type) {
+    super(name, type);
+  }
+  
+  /**
+   * Expert: allows you to customize the {@link
+   * FieldType}.
+   * <p>NOTE: the provided byte[] is not copied so be sure
+   * not to change it until you're done with this field.
+   * @param name field name
+   * @param bytes byte array pointing to binary content (not copied)
+   * @param type custom {@link FieldType} for this field
+   * @throws IllegalArgumentException if the field name is null.
+   */
+  public StoredField(String name, BytesRef bytes, FieldType type) {
+    super(name, bytes, type);
+  }
+  
+  /**
    * Create a stored-only field with the given binary value.
    * <p>NOTE: the provided byte[] is not copied so be sure
    * not to change it until you're done with this field.
@@ -83,6 +109,18 @@
   public StoredField(String name, String value) {
     super(name, value, TYPE);
   }
+  
+  /**
+   * Expert: allows you to customize the {@link
+   * FieldType}.
+   * @param name field name
+   * @param value string value
+   * @param type custom {@link FieldType} for this field
+   * @throws IllegalArgumentException if the field name or value is null.
+   */
+  public StoredField(String name, String value, FieldType type) {
+    super(name, value, type);
+  }
 
   // TODO: not great but maybe not a big problem?
   /**
diff --git a/lucene/core/src/java/org/apache/lucene/document/StraightBytesDocValuesField.java b/lucene/core/src/java/org/apache/lucene/document/StraightBytesDocValuesField.java
index cdca59b..f93d6b3 100644
--- a/lucene/core/src/java/org/apache/lucene/document/StraightBytesDocValuesField.java
+++ b/lucene/core/src/java/org/apache/lucene/document/StraightBytesDocValuesField.java
@@ -40,7 +40,7 @@
  * @see DocValues for further information
  * */
 
-public class StraightBytesDocValuesField extends Field {
+public class StraightBytesDocValuesField extends StoredField {
 
   // TODO: ideally indexer figures out var vs fixed on its own!?
   /**
diff --git a/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java b/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java
index 0daf83d..f964aa5d 100644
--- a/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java
+++ b/lucene/core/src/java/org/apache/lucene/index/CheckIndex.java
@@ -1180,7 +1180,7 @@
       for (int j = 0; j < info.info.getDocCount(); ++j) {
         // Intentionally pull even deleted documents to
         // make sure they too are not corrupt:
-        Document doc = reader.document(j);
+        StoredDocument doc = reader.document(j);
         if (liveDocs == null || liveDocs.get(j)) {
           status.docCount++;
           status.totFields += doc.getFields().size();
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java b/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java
index 0929970..0853ed3 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocFieldProcessor.java
@@ -28,6 +28,7 @@
 import org.apache.lucene.codecs.DocValuesConsumer;
 import org.apache.lucene.codecs.FieldInfosWriter;
 import org.apache.lucene.codecs.PerDocConsumer;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.DocumentsWriterPerThread.DocState;
 import org.apache.lucene.index.TypePromoter.TypeCompatibility;
 import org.apache.lucene.store.IOContext;
@@ -218,58 +219,21 @@
     // seen before (eg suddenly turning on norms or
     // vectors, etc.):
 
-    for(IndexableField field : docState.doc) {
+    for(IndexableField field : docState.doc.indexableFields()) {
       final String fieldName = field.name();
+      IndexableFieldType ft = field.fieldType();
 
-      // Make sure we have a PerField allocated
-      final int hashPos = fieldName.hashCode() & hashMask;
-      DocFieldProcessorPerField fp = fieldHash[hashPos];
-      while(fp != null && !fp.fieldInfo.name.equals(fieldName)) {
-        fp = fp.next;
-      }
-
-      if (fp == null) {
-
-        // TODO FI: we need to genericize the "flags" that a
-        // field holds, and, how these flags are merged; it
-        // needs to be more "pluggable" such that if I want
-        // to have a new "thing" my Fields can do, I can
-        // easily add it
-        FieldInfo fi = fieldInfos.addOrUpdate(fieldName, field.fieldType());
-
-        fp = new DocFieldProcessorPerField(this, fi);
-        fp.next = fieldHash[hashPos];
-        fieldHash[hashPos] = fp;
-        totalFieldCount++;
-
-        if (totalFieldCount >= fieldHash.length/2) {
-          rehash();
-        }
-      } else {
-        fieldInfos.addOrUpdate(fp.fieldInfo.name, field.fieldType());
-      }
-
-      if (thisFieldGen != fp.lastGen) {
-
-        // First time we're seeing this field for this doc
-        fp.fieldCount = 0;
-
-        if (fieldCount == fields.length) {
-          final int newSize = fields.length*2;
-          DocFieldProcessorPerField newArray[] = new DocFieldProcessorPerField[newSize];
-          System.arraycopy(fields, 0, newArray, 0, fieldCount);
-          fields = newArray;
-        }
-
-        fields[fieldCount++] = fp;
-        fp.lastGen = thisFieldGen;
-      }
+      DocFieldProcessorPerField fp = processField(fieldInfos, thisFieldGen, fieldName, ft);
 
       fp.addField(field);
+    }
+    for (StorableField field: docState.doc.storableFields()) {
+      final String fieldName = field.name();
+      IndexableFieldType ft = field.fieldType();
 
-      if (field.fieldType().stored()) {
-        fieldsWriter.addField(field, fp.fieldInfo);
-      }
+      DocFieldProcessorPerField fp = processField(fieldInfos, thisFieldGen, fieldName, ft);
+      fieldsWriter.addField(field, fp.fieldInfo);
+      
       final DocValues.Type dvType = field.fieldType().docValueType();
       if (dvType != null) {
         DocValuesConsumerHolder docValuesConsumer = docValuesConsumer(dvType,
@@ -313,6 +277,54 @@
     }
   }
 
+  private DocFieldProcessorPerField processField(FieldInfos.Builder fieldInfos,
+      final int thisFieldGen, final String fieldName, IndexableFieldType ft) {
+    // Make sure we have a PerField allocated
+    final int hashPos = fieldName.hashCode() & hashMask;
+    DocFieldProcessorPerField fp = fieldHash[hashPos];
+    while(fp != null && !fp.fieldInfo.name.equals(fieldName)) {
+      fp = fp.next;
+    }
+
+    if (fp == null) {
+
+      // TODO FI: we need to genericize the "flags" that a
+      // field holds, and, how these flags are merged; it
+      // needs to be more "pluggable" such that if I want
+      // to have a new "thing" my Fields can do, I can
+      // easily add it
+      FieldInfo fi = fieldInfos.addOrUpdate(fieldName, ft);
+
+      fp = new DocFieldProcessorPerField(this, fi);
+      fp.next = fieldHash[hashPos];
+      fieldHash[hashPos] = fp;
+      totalFieldCount++;
+
+      if (totalFieldCount >= fieldHash.length/2) {
+        rehash();
+      }
+    } else {
+      fieldInfos.addOrUpdate(fp.fieldInfo.name, ft);
+    }
+
+    if (thisFieldGen != fp.lastGen) {
+
+      // First time we're seeing this field for this doc
+      fp.fieldCount = 0;
+
+      if (fieldCount == fields.length) {
+        final int newSize = fields.length*2;
+        DocFieldProcessorPerField newArray[] = new DocFieldProcessorPerField[newSize];
+        System.arraycopy(fields, 0, newArray, 0, fieldCount);
+        fields = newArray;
+      }
+
+      fields[fieldCount++] = fp;
+      fp.lastGen = thisFieldGen;
+    }
+    return fp;
+  }
+
   private static final Comparator<DocFieldProcessorPerField> fieldsComp = new Comparator<DocFieldProcessorPerField>() {
     public int compare(DocFieldProcessorPerField o1, DocFieldProcessorPerField o2) {
       return o1.fieldInfo.name.compareTo(o2.fieldInfo.name);
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java b/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java
index 044d4ed..0e22a01 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocInverterPerField.java
@@ -75,7 +75,7 @@
       // TODO FI: this should be "genericized" to querying
       // consumer if it wants to see this particular field
       // tokenized.
-      if (fieldType.indexed() && doInvert) {
+      if (doInvert) {
         final boolean analyzed = fieldType.tokenized() && docState.analyzer != null;
         
         // if the field omits norms, the boost cannot be indexed.
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
index d913f77..42c386c 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriter.java
@@ -321,7 +321,7 @@
     return maybeMerge;
   }
 
-  boolean updateDocuments(final Iterable<? extends Iterable<? extends IndexableField>> docs, final Analyzer analyzer,
+  boolean updateDocuments(final Iterable<? extends IndexDocument> docs, final Analyzer analyzer,
                           final Term delTerm) throws IOException {
     boolean maybeMerge = preUpdate();
 
@@ -352,7 +352,7 @@
     return postUpdate(flushingDWPT, maybeMerge);
   }
 
-  boolean updateDocument(final Iterable<? extends IndexableField> doc, final Analyzer analyzer,
+  boolean updateDocument(final IndexDocument doc, final Analyzer analyzer,
       final Term delTerm) throws IOException {
 
     boolean maybeMerge = preUpdate();
diff --git a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java
index 62ed5e9..9c25290 100644
--- a/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java
+++ b/lucene/core/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java
@@ -94,7 +94,7 @@
     InfoStream infoStream;
     Similarity similarity;
     int docID;
-    Iterable<? extends IndexableField> doc;
+    IndexDocument doc;
     String maxTermPrefix;
 
     DocState(DocumentsWriterPerThread docWriter, InfoStream infoStream) {
@@ -225,7 +225,7 @@
     return retval;
   }
 
-  public void updateDocument(Iterable<? extends IndexableField> doc, Analyzer analyzer, Term delTerm) throws IOException {
+  public void updateDocument(IndexDocument doc, Analyzer analyzer, Term delTerm) throws IOException {
     assert writer.testPoint("DocumentsWriterPerThread addDocument start");
     assert deleteQueue != null;
     docState.doc = doc;
@@ -278,7 +278,7 @@
     }
   }
   
-  public int updateDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer analyzer, Term delTerm) throws IOException {
+  public int updateDocuments(Iterable<? extends IndexDocument> docs, Analyzer analyzer, Term delTerm) throws IOException {
     assert writer.testPoint("DocumentsWriterPerThread addDocuments start");
     assert deleteQueue != null;
     docState.analyzer = analyzer;
@@ -290,7 +290,7 @@
     }
     int docCount = 0;
     try {
-      for(Iterable<? extends IndexableField> doc : docs) {
+      for(IndexDocument doc : docs) {
         docState.doc = doc;
         docState.docID = numDocsInRAM;
         docCount++;
diff --git a/lucene/core/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java b/lucene/core/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java
index f85f1c8..118d35a 100644
--- a/lucene/core/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java
+++ b/lucene/core/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java
@@ -103,12 +103,7 @@
 
   @Override
   boolean start(IndexableField[] fields, int count) {
-    for(int i=0;i<count;i++) {
-      if (fields[i].fieldType().indexed()) {
-        return true;
-      }
-    }
-    return false;
+    return true;
   }
 
   @Override
diff --git a/lucene/core/src/java/org/apache/lucene/index/GeneralField.java b/lucene/core/src/java/org/apache/lucene/index/GeneralField.java
new file mode 100644
index 0000000..cb07f03
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/index/GeneralField.java
@@ -0,0 +1,33 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.
+ */
+
+/** Represents a single field in lucene document. Further generalizations
+ * are {@link IndexableField} and {@link StorableField} interfaces.  
+ *
+ *  @lucene.experimental */
+
+public interface GeneralField {
+
+  /** Field name */
+  public String name();
+
+  /** {@link IndexableFieldType} describing the properties
+   * of this field. */
+  public IndexableFieldType fieldType();
+}
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexDocument.java b/lucene/core/src/java/org/apache/lucene/index/IndexDocument.java
new file mode 100644
index 0000000..b8bde65
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexDocument.java
@@ -0,0 +1,31 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.
+ */
+
+/**
+ * Elementary interface used for indexing an document.
+ * @lucene.internal
+ */
+public interface IndexDocument {
+
+  /** Obtains all indexable fields in document */
+  public Iterable<? extends IndexableField> indexableFields();
+  
+  /** Obtains all storable fields in document */
+  public Iterable<? extends StorableField> storableFields();
+}
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexReader.java b/lucene/core/src/java/org/apache/lucene/index/IndexReader.java
index 86c0e02..e982e62 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexReader.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexReader.java
@@ -342,7 +342,7 @@
   // TODO: we need a separate StoredField, so that the
   // Document returned here contains that class not
   // IndexableField
-  public final Document document(int docID) throws IOException {
+  public final StoredDocument document(int docID) throws IOException {
     final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor();
     document(docID, visitor);
     return visitor.getDocument();
@@ -353,8 +353,10 @@
    * fields.  Note that this is simply sugar for {@link
    * DocumentStoredFieldVisitor#DocumentStoredFieldVisitor(Set)}.
    */
-  public final Document document(int docID, Set<String> fieldsToLoad) throws IOException {
-    final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(fieldsToLoad);
+  public final StoredDocument document(int docID, Set<String> fieldsToLoad)
+      throws IOException {
+    final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(
+        fieldsToLoad);
     document(docID, visitor);
     return visitor.getDocument();
   }
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
index 8df850b..8139c86 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexWriter.java
@@ -69,10 +69,10 @@
   new index if there is not already an index at the provided path
   and otherwise open the existing index.</p>
 
-  <p>In either case, documents are added with {@link #addDocument(Iterable)
+  <p>In either case, documents are added with {@link #addDocument(IndexDocument)
   addDocument} and removed with {@link #deleteDocuments(Term)} or {@link
   #deleteDocuments(Query)}. A document can be updated with {@link
-  #updateDocument(Term, Iterable) updateDocument} (which just deletes
+  #updateDocument(Term, IndexDocument) updateDocument} (which just deletes
   and then adds the entire document). When finished adding, deleting 
   and updating documents, {@link #close() close} should be called.</p>
 
@@ -1099,7 +1099,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void addDocument(Iterable<? extends IndexableField> doc) throws IOException {
+  public void addDocument(IndexDocument doc) throws IOException {
     addDocument(doc, analyzer);
   }
 
@@ -1107,7 +1107,7 @@
    * Adds a document to this index, using the provided analyzer instead of the
    * value of {@link #getAnalyzer()}.
    *
-   * <p>See {@link #addDocument(Iterable)} for details on
+   * <p>See {@link #addDocument(IndexDocument)} for details on
    * index and IndexWriter state after an Exception, and
    * flushing/merging temporary free space requirements.</p>
    *
@@ -1118,7 +1118,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void addDocument(Iterable<? extends IndexableField> doc, Analyzer analyzer) throws IOException {
+  public void addDocument(IndexDocument doc, Analyzer analyzer) throws IOException {
     updateDocument(null, doc, analyzer);
   }
 
@@ -1143,7 +1143,7 @@
    * perhaps to obtain better index compression), in which case
    * you may need to fully re-index your documents at that time.
    *
-   * <p>See {@link #addDocument(Iterable)} for details on
+   * <p>See {@link #addDocument(IndexDocument)} for details on
    * index and IndexWriter state after an Exception, and
    * flushing/merging temporary free space requirements.</p>
    *
@@ -1163,7 +1163,7 @@
    *
    * @lucene.experimental
    */
-  public void addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
+  public void addDocuments(Iterable<? extends IndexDocument> docs) throws IOException {
     addDocuments(docs, analyzer);
   }
 
@@ -1178,7 +1178,7 @@
    *
    * @lucene.experimental
    */
-  public void addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer analyzer) throws IOException {
+  public void addDocuments(Iterable<? extends IndexDocument> docs, Analyzer analyzer) throws IOException {
     updateDocuments(null, docs, analyzer);
   }
 
@@ -1195,7 +1195,7 @@
    *
    * @lucene.experimental
    */
-  public void updateDocuments(Term delTerm, Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
+  public void updateDocuments(Term delTerm, Iterable<? extends IndexDocument> docs) throws IOException {
     updateDocuments(delTerm, docs, analyzer);
   }
 
@@ -1213,7 +1213,7 @@
    *
    * @lucene.experimental
    */
-  public void updateDocuments(Term delTerm, Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer analyzer) throws IOException {
+  public void updateDocuments(Term delTerm, Iterable<? extends IndexDocument> docs, Analyzer analyzer) throws IOException {
     ensureOpen();
     try {
       boolean success = false;
@@ -1410,7 +1410,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void updateDocument(Term term, Iterable<? extends IndexableField> doc) throws IOException {
+  public void updateDocument(Term term, IndexDocument doc) throws IOException {
     ensureOpen();
     updateDocument(term, doc, getAnalyzer());
   }
@@ -1433,7 +1433,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void updateDocument(Term term, Iterable<? extends IndexableField> doc, Analyzer analyzer)
+  public void updateDocument(Term term, IndexDocument doc, Analyzer analyzer)
       throws IOException {
     ensureOpen();
     try {
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexableField.java b/lucene/core/src/java/org/apache/lucene/index/IndexableField.java
index 2df6f00..062dc8c 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexableField.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexableField.java
@@ -35,15 +35,19 @@
  *
  *  @lucene.experimental */
 
-public interface IndexableField {
+public interface IndexableField extends GeneralField {
 
-  /** Field name */
-  public String name();
+  /**
+   * Creates the TokenStream used for indexing this field.  If appropriate,
+   * implementations should use the given Analyzer to create the TokenStreams.
+   *
+   * @param analyzer Analyzer that should be used to create the TokenStreams from
+   * @return TokenStream value for indexing the document.  Should always return
+   *         a non-null value if the field is to be indexed
+   * @throws IOException Can be thrown while creating the TokenStream
+   */
+  public TokenStream tokenStream(Analyzer analyzer) throws IOException;
 
-  /** {@link IndexableFieldType} describing the properties
-   * of this field. */
-  public IndexableFieldType fieldType();
-  
   /** 
    * Returns the field's index-time boost.
    * <p>
@@ -65,27 +69,4 @@
    * @see DefaultSimilarity#encodeNormValue(float)
    */
   public float boost();
-
-  /** Non-null if this field has a binary value */
-  public BytesRef binaryValue();
-
-  /** Non-null if this field has a string value */
-  public String stringValue();
-
-  /** Non-null if this field has a Reader value */
-  public Reader readerValue();
-
-  /** Non-null if this field has a numeric value */
-  public Number numericValue();
-
-  /**
-   * Creates the TokenStream used for indexing this field.  If appropriate,
-   * implementations should use the given Analyzer to create the TokenStreams.
-   *
-   * @param analyzer Analyzer that should be used to create the TokenStreams from
-   * @return TokenStream value for indexing the document.  Should always return
-   *         a non-null value if the field is to be indexed
-   * @throws IOException Can be thrown while creating the TokenStream
-   */
-  public TokenStream tokenStream(Analyzer analyzer) throws IOException;
 }
diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java b/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java
index 91f2efe..6a72431 100644
--- a/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java
+++ b/lucene/core/src/java/org/apache/lucene/index/IndexableFieldType.java
@@ -31,7 +31,7 @@
 
   /** True if the field's value should be stored */
   public boolean stored();
-
+  
   /** 
    * True if this field's value should be analyzed by the
    * {@link Analyzer}.
@@ -95,5 +95,5 @@
    * DocValues {@link DocValues.Type}: if non-null then the field's value
    * will be indexed into docValues.
    */
-  public DocValues.Type docValueType();
+  public DocValues.Type docValueType();  
 }
diff --git a/lucene/core/src/java/org/apache/lucene/index/Norm.java b/lucene/core/src/java/org/apache/lucene/index/Norm.java
index 4f338c3..8baecff 100644
--- a/lucene/core/src/java/org/apache/lucene/index/Norm.java
+++ b/lucene/core/src/java/org/apache/lucene/index/Norm.java
@@ -26,13 +26,14 @@
 import org.apache.lucene.document.PackedLongDocValuesField;
 import org.apache.lucene.document.ShortDocValuesField;
 import org.apache.lucene.document.SortedBytesDocValuesField;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.document.StraightBytesDocValuesField;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.BytesRef;
 
 /**
- * Stores the normalization value computed in
+ * Stores the normalization value with {@link StorableField} computed in
  * {@link Similarity#computeNorm(FieldInvertState, Norm)} per field.
  * Normalization values must be consistent within a single field, different
  * value types are not permitted within a single field. All values set must be
@@ -43,13 +44,13 @@
  * @lucene.internal
  */
 public final class Norm  {
-  private Field field;
+  private StoredField field;
   private BytesRef spare;
   
   /**
-   * Returns the {@link IndexableField} representation for this norm
+   * Returns the {@link StorableField} representation for this norm
    */
-  public IndexableField field() {
+  public StorableField field() {
     return field;
   }
   
diff --git a/lucene/core/src/java/org/apache/lucene/index/NormsConsumerPerField.java b/lucene/core/src/java/org/apache/lucene/index/NormsConsumerPerField.java
index 6532330..a936c37 100644
--- a/lucene/core/src/java/org/apache/lucene/index/NormsConsumerPerField.java
+++ b/lucene/core/src/java/org/apache/lucene/index/NormsConsumerPerField.java
@@ -51,7 +51,7 @@
       similarity.computeNorm(fieldState, norm);
       
       if (norm.type() != null) {
-        IndexableField field = norm.field();
+        StorableField field = norm.field();
         // some similarity might not compute any norms
         DocValuesConsumer consumer = getConsumer(norm.type());
         consumer.add(docState.docID, field);
diff --git a/lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java b/lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java
index ebae93a..6ce2d6f 100644
--- a/lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java
+++ b/lucene/core/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java
@@ -26,6 +26,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.Version;
@@ -67,13 +68,13 @@
       int numDocs = r.numDocs();
       // index is allowed to have exactly one document or 0.
       if (numDocs == 1) {
-        Document doc = r.document(r.maxDoc() - 1);
+        StoredDocument doc = r.document(r.maxDoc() - 1);
         if (doc.getField(SNAPSHOTS_ID) == null) {
           throw new IllegalStateException("directory is not a valid snapshots store!");
         }
-        doc.removeField(SNAPSHOTS_ID);
-        for (IndexableField f : doc) {
-          snapshots.put(f.name(), f.stringValue());
+        for (StorableField f : doc) {
+          if (!f.name().equals(SNAPSHOTS_ID))
+            snapshots.put(f.name(), f.stringValue());
         }
       } else if (numDocs != 0) {
         throw new IllegalStateException(
@@ -184,14 +185,12 @@
   private void persistSnapshotInfos(String id, String segment) throws IOException {
     writer.deleteAll();
     Document d = new Document();
-    FieldType ft = new FieldType();
-    ft.setStored(true);
-    d.add(new Field(SNAPSHOTS_ID, "", ft));
+    d.add(new StoredField(SNAPSHOTS_ID, ""));
     for (Entry<String, String> e : super.getSnapshots().entrySet()) {
-      d.add(new Field(e.getKey(), e.getValue(), ft));
+      d.add(new StoredField(e.getKey(), e.getValue()));
     }
     if (id != null) {
-      d.add(new Field(id, segment, ft));
+      d.add(new StoredField(id, segment));
     }
     writer.addDocument(d);
     writer.commit();
diff --git a/lucene/core/src/java/org/apache/lucene/index/StorableField.java b/lucene/core/src/java/org/apache/lucene/index/StorableField.java
new file mode 100644
index 0000000..136fd17
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/index/StorableField.java
@@ -0,0 +1,42 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.io.Reader;
+
+import org.apache.lucene.util.BytesRef;
+
+/** Represents a single stored field in lucene document. These fields
+ * are contained in document retrieved from IndexReader.
+ *
+ *  @lucene.experimental */
+
+public interface StorableField extends GeneralField {
+
+  /** Non-null if this field has a binary value */
+  public BytesRef binaryValue();
+
+  /** Non-null if this field has a string value */
+  public String stringValue();
+
+  /** Non-null if this field has a Reader value */
+  public Reader readerValue();
+
+  /** Non-null if this field has a numeric value */
+  public Number numericValue(); 
+}
diff --git a/lucene/core/src/java/org/apache/lucene/index/StorableFieldType.java b/lucene/core/src/java/org/apache/lucene/index/StorableFieldType.java
new file mode 100644
index 0000000..a948387
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/index/StorableFieldType.java
@@ -0,0 +1,31 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.
+ */
+
+// TODO: Move some properties from IndexableFieldType here, those regarding stored fields. 
+
+/** 
+ * Describes the properties of a stored field.
+ * @lucene.experimental 
+ */
+public interface StorableFieldType {
+
+  /** DocValues type; if non-null then the field's value
+   *  will be indexed into docValues */
+  public DocValues.Type docValueType();
+}
diff --git a/lucene/core/src/java/org/apache/lucene/index/StoredDocument.java b/lucene/core/src/java/org/apache/lucene/index/StoredDocument.java
new file mode 100644
index 0000000..50b06e7
--- /dev/null
+++ b/lucene/core/src/java/org/apache/lucene/index/StoredDocument.java
@@ -0,0 +1,191 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.DoubleField;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.FloatField;
+import org.apache.lucene.document.IntField;
+import org.apache.lucene.document.LongField;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.util.BytesRef;
+
+/** 
+* StoredDocument is retrieved from IndexReader containing only stored fields from indexed {@link IndexDocument}.
+*/
+public class StoredDocument implements Iterable<StorableField>{
+  
+  private final List<StorableField> fields = new ArrayList<StorableField>();
+  
+  
+  public final void add(StorableField field) {
+    fields.add(field);
+  }
+  
+  public StorableField[] getFields(String name) {
+    List<StorableField> result = new ArrayList<StorableField>();
+    for (StorableField field : fields) {
+      if (field.name().equals(name)) {
+        result.add(field);
+      }
+    }
+  
+    return result.toArray(new StorableField[result.size()]);
+  }
+  
+  /** Returns a field with the given name if any exist in this document, or
+   * null.  If multiple fields exists with this name, this method returns the
+   * first value added.
+   */
+  public final StorableField getField(String name) {
+    for (StorableField field : fields) {
+      if (field.name().equals(name)) {
+        return field;
+      }
+    }
+    return null;
+  }
+  
+
+  /** Returns a List of all the fields in a document.
+   * <p>Note that fields which are <i>not</i> stored are
+   * <i>not</i> available in documents retrieved from the
+   * index, e.g. {@link IndexSearcher#doc(int)} or {@link
+   * IndexReader#document(int)}.
+   * 
+   * @return an immutable <code>List[StorableField]</code> 
+   */
+  public final List<StorableField> getFields() {
+    return fields;
+  }
+  
+  @Override
+  public Iterator<StorableField> iterator() {
+    return this.fields.iterator();
+  }
+  
+  /**
+   * Returns an array of byte arrays for of the fields that have the name specified
+   * as the method parameter.  This method returns an empty
+   * array when there are no matching fields.  It never
+   * returns null.
+   *
+   * @param name the name of the field
+   * @return a <code>byte[][]</code> of binary field values
+   */
+   public final BytesRef[] getBinaryValues(String name) {
+     final List<BytesRef> result = new ArrayList<BytesRef>();
+     for (StorableField field : fields) {
+       if (field.name().equals(name)) {
+         final BytesRef bytes = field.binaryValue();
+         if (bytes != null) {
+           result.add(bytes);
+         }
+       }
+     }
+   
+     return result.toArray(new BytesRef[result.size()]);
+   }
+   
+   /**
+   * Returns an array of bytes for the first (or only) field that has the name
+   * specified as the method parameter. This method will return <code>null</code>
+   * if no binary fields with the specified name are available.
+   * There may be non-binary fields with the same name.
+   *
+   * @param name the name of the field.
+   * @return a <code>byte[]</code> containing the binary field value or <code>null</code>
+   */
+   public final BytesRef getBinaryValue(String name) {
+     for (StorableField field : fields) {
+       if (field.name().equals(name)) {
+         final BytesRef bytes = field.binaryValue();
+         if (bytes != null) {
+           return bytes;
+         }
+       }
+     }
+     return null;
+   }
+   private final static String[] NO_STRINGS = new String[0];
+  
+   /**
+    * Returns an array of values of the field specified as the method parameter.
+    * This method returns an empty array when there are no
+    * matching fields.  It never returns null.
+    * For {@link IntField}, {@link LongField}, {@link
+    * FloatField} and {@link DoubleField} it returns the string value of the number. If you want
+    * the actual numeric field instances back, use {@link #getFields}.
+    * @param name the name of the field
+    * @return a <code>String[]</code> of field values
+    */
+   public final String[] getValues(String name) {
+     List<String> result = new ArrayList<String>();
+     for (StorableField field : fields) {
+       if (field.name().equals(name) && field.stringValue() != null) {
+         result.add(field.stringValue());
+       }
+     }
+     
+     if (result.size() == 0) {
+       return NO_STRINGS;
+     }
+     
+     return result.toArray(new String[result.size()]);
+   }
+  
+   /** Returns the string value of the field with the given name if any exist in
+    * this document, or null.  If multiple fields exist with this name, this
+    * method returns the first value added. If only binary fields with this name
+    * exist, returns null.
+    * For {@link IntField}, {@link LongField}, {@link
+    * FloatField} and {@link DoubleField} it returns the string value of the number. If you want
+    * the actual numeric field instance back, use {@link #getField}.
+    */
+   public final String get(String name) {
+     for (StorableField field : fields) {
+       if (field.name().equals(name) && field.stringValue() != null) {
+         return field.stringValue();
+       }
+     }
+     return null;
+   }
+
+  /** Prints the fields of a document for human consumption. */
+  @Override
+  public final String toString() {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append("StoredDocument<");
+    for (int i = 0; i < fields.size(); i++) {
+      StorableField field = fields.get(i);
+      buffer.append(field.toString());
+      if (i != fields.size()-1)
+        buffer.append(" ");
+    }
+    buffer.append(">");
+    return buffer.toString();
+  }
+}
diff --git a/lucene/core/src/java/org/apache/lucene/index/StoredFieldsConsumer.java b/lucene/core/src/java/org/apache/lucene/index/StoredFieldsConsumer.java
index 3241d38..b22c48a 100644
--- a/lucene/core/src/java/org/apache/lucene/index/StoredFieldsConsumer.java
+++ b/lucene/core/src/java/org/apache/lucene/index/StoredFieldsConsumer.java
@@ -44,12 +44,12 @@
   }
 
   private int numStoredFields;
-  private IndexableField[] storedFields;
+  private StorableField[] storedFields;
   private FieldInfo[] fieldInfos;
 
   public void reset() {
     numStoredFields = 0;
-    storedFields = new IndexableField[1];
+    storedFields = new StorableField[1];
     fieldInfos = new FieldInfo[1];
   }
 
@@ -126,10 +126,10 @@
     assert docWriter.writer.testPoint("StoredFieldsWriter.finishDocument end");
   }
 
-  public void addField(IndexableField field, FieldInfo fieldInfo) {
+  public void addField(StorableField field, FieldInfo fieldInfo) {
     if (numStoredFields == storedFields.length) {
       int newSize = ArrayUtil.oversize(numStoredFields + 1, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
-      IndexableField[] newArray = new IndexableField[newSize];
+      StorableField[] newArray = new StorableField[newSize];
       System.arraycopy(storedFields, 0, newArray, 0, numStoredFields);
       storedFields = newArray;
       
diff --git a/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java b/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
index 68ffa73..503b22f 100644
--- a/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
+++ b/lucene/core/src/java/org/apache/lucene/search/IndexSearcher.java
@@ -39,6 +39,7 @@
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.ReaderUtil;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
@@ -181,7 +182,7 @@
   }
 
   /** Sugar for <code>.getIndexReader().document(docID)</code> */
-  public Document doc(int docID) throws IOException {
+  public StoredDocument doc(int docID) throws IOException {
     return reader.document(docID);
   }
 
@@ -191,7 +192,7 @@
   }
 
   /** Sugar for <code>.getIndexReader().document(docID, fieldsToLoad)</code> */
-  public final Document document(int docID, Set<String> fieldsToLoad) throws IOException {
+  public final StoredDocument document(int docID, Set<String> fieldsToLoad) throws IOException {
     return reader.document(docID, fieldsToLoad);
   }
 
diff --git a/lucene/core/src/java/org/apache/lucene/search/NRTManager.java b/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
index bda7b95..cfe8028 100644
--- a/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
+++ b/lucene/core/src/java/org/apache/lucene/search/NRTManager.java
@@ -27,6 +27,7 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexDocument;
 import org.apache.lucene.index.SegmentInfoPerCommit;
 import org.apache.lucene.index.IndexReader; // javadocs
 import org.apache.lucene.index.IndexWriter;
@@ -154,25 +155,25 @@
       this.writer = writer;
     }
 
-    public long updateDocument(Term t, Iterable<? extends IndexableField> d, Analyzer a) throws IOException {
+    public long updateDocument(Term t, IndexDocument d, Analyzer a) throws IOException {
       writer.updateDocument(t, d, a);
       // Return gen as of when indexing finished:
       return indexingGen.get();
     }
 
-    public long updateDocument(Term t, Iterable<? extends IndexableField> d) throws IOException {
+    public long updateDocument(Term t, IndexDocument d) throws IOException {
       writer.updateDocument(t, d);
       // Return gen as of when indexing finished:
       return indexingGen.get();
     }
 
-    public long updateDocuments(Term t, Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer a) throws IOException {
+    public long updateDocuments(Term t, Iterable<? extends IndexDocument> docs, Analyzer a) throws IOException {
       writer.updateDocuments(t, docs, a);
       // Return gen as of when indexing finished:
       return indexingGen.get();
     }
 
-    public long updateDocuments(Term t, Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
+    public long updateDocuments(Term t, Iterable<? extends IndexDocument> docs) throws IOException {
       writer.updateDocuments(t, docs);
       // Return gen as of when indexing finished:
       return indexingGen.get();
@@ -208,25 +209,25 @@
       return indexingGen.get();
     }
 
-    public long addDocument(Iterable<? extends IndexableField> d, Analyzer a) throws IOException {
+    public long addDocument(IndexDocument d, Analyzer a) throws IOException {
       writer.addDocument(d, a);
       // Return gen as of when indexing finished:
       return indexingGen.get();
     }
 
-    public long addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer a) throws IOException {
+    public long addDocuments(Iterable<? extends IndexDocument> docs, Analyzer a) throws IOException {
       writer.addDocuments(docs, a);
       // Return gen as of when indexing finished:
       return indexingGen.get();
     }
 
-    public long addDocument(Iterable<? extends IndexableField> d) throws IOException {
+    public long addDocument(IndexDocument d) throws IOException {
       writer.addDocument(d);
       // Return gen as of when indexing finished:
       return indexingGen.get();
     }
 
-    public long addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
+    public long addDocuments(Iterable<? extends IndexDocument> docs) throws IOException {
       writer.addDocuments(docs);
       // Return gen as of when indexing finished:
       return indexingGen.get();
diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java b/lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java
index 9213b05..a88cf78 100644
--- a/lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java
+++ b/lucene/core/src/java/org/apache/lucene/util/packed/BulkOperation.java
@@ -178,4 +178,4 @@
       return iterations;
     }
   }
-}
+}
\ No newline at end of file
diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java b/lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java
index 57cf0df..df9c1ef 100644
--- a/lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java
+++ b/lucene/core/src/java/org/apache/lucene/util/packed/Packed64SingleBlock.java
@@ -581,4 +581,4 @@
 
   }
 
-}
+}
\ No newline at end of file
diff --git a/lucene/core/src/java/overview.html b/lucene/core/src/java/overview.html
index 14929b9..ac04192 100644
--- a/lucene/core/src/java/overview.html
+++ b/lucene/core/src/java/overview.html
@@ -130,7 +130,7 @@
 
 <li>
 Create an {@link org.apache.lucene.index.IndexWriter IndexWriter}
-and add documents to it with {@link org.apache.lucene.index.IndexWriter#addDocument(Iterable) addDocument()};</li>
+and add documents to it with {@link org.apache.lucene.index.IndexWriter#addDocument(org.apache.lucene.index.IndexDocument) addDocument()};</li>
 
 <li>
 Call <a href="../queryparser/org/apache/lucene/queryparser/classic/QueryParserBase.html#parse(java.lang.String)">QueryParser.parse()</a>
diff --git a/lucene/core/src/test/org/apache/lucene/TestDemo.java b/lucene/core/src/test/org/apache/lucene/TestDemo.java
index 9f36dfe..717b753 100644
--- a/lucene/core/src/test/org/apache/lucene/TestDemo.java
+++ b/lucene/core/src/test/org/apache/lucene/TestDemo.java
@@ -25,6 +25,7 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.*;
@@ -64,7 +65,7 @@
     assertEquals(1, hits.totalHits);
     // Iterate through the results:
     for (int i = 0; i < hits.scoreDocs.length; i++) {
-      Document hitDoc = isearcher.doc(hits.scoreDocs[i].doc);
+      StoredDocument hitDoc = isearcher.doc(hits.scoreDocs[i].doc);
       assertEquals(text, hitDoc.get("fieldname"));
     }
 
diff --git a/lucene/core/src/test/org/apache/lucene/TestSearch.java b/lucene/core/src/test/org/apache/lucene/TestSearch.java
index 98ee9c9..235f45b 100644
--- a/lucene/core/src/test/org/apache/lucene/TestSearch.java
+++ b/lucene/core/src/test/org/apache/lucene/TestSearch.java
@@ -110,7 +110,7 @@
 
         out.println(hits.length + " total results");
         for (int i = 0 ; i < hits.length && i < 10; i++) {
-          Document d = searcher.doc(hits[i].doc);
+          StoredDocument d = searcher.doc(hits[i].doc);
           out.println(i + " " + hits[i].score + " " + d.get("contents"));
         }
       }
diff --git a/lucene/core/src/test/org/apache/lucene/TestSearchForDuplicates.java b/lucene/core/src/test/org/apache/lucene/TestSearchForDuplicates.java
index eecf92a..ad1f06e 100644
--- a/lucene/core/src/test/org/apache/lucene/TestSearchForDuplicates.java
+++ b/lucene/core/src/test/org/apache/lucene/TestSearchForDuplicates.java
@@ -127,7 +127,7 @@
     out.println(hits.length + " total results\n");
     for (int i = 0 ; i < hits.length; i++) {
       if ( i < 10 || (i > 94 && i < 105) ) {
-        Document d = searcher.doc(hits[i].doc);
+        StoredDocument d = searcher.doc(hits[i].doc);
         out.println(i + " " + d.get(ID_FIELD));
       }
     }
@@ -137,7 +137,7 @@
     assertEquals("total results", expectedCount, hits.length);
     for (int i = 0 ; i < hits.length; i++) {
       if (i < 10 || (i > 94 && i < 105) ) {
-        Document d = searcher.doc(hits[i].doc);
+        StoredDocument d = searcher.doc(hits[i].doc);
         assertEquals("check " + i, String.valueOf(i), d.get(ID_FIELD));
       }
     }
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/appending/TestAppendingCodec.java b/lucene/core/src/test/org/apache/lucene/codecs/appending/TestAppendingCodec.java
index f963366..d5ccd2e 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/appending/TestAppendingCodec.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/appending/TestAppendingCodec.java
@@ -32,6 +32,7 @@
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum.SeekStatus;
 import org.apache.lucene.index.TermsEnum;
@@ -128,7 +129,7 @@
     writer.close();
     IndexReader reader = DirectoryReader.open(dir, 1);
     assertEquals(2, reader.numDocs());
-    Document doc2 = reader.document(0);
+    StoredDocument doc2 = reader.document(0);
     assertEquals(text, doc2.get("f"));
     Fields fields = MultiFields.getFields(reader);
     Terms terms = fields.terms("f");
diff --git a/lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java b/lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java
index c8fcd9e..4aa02a8 100644
--- a/lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java
+++ b/lucene/core/src/test/org/apache/lucene/codecs/lucene40/values/TestDocValues.java
@@ -28,12 +28,14 @@
 import org.apache.lucene.codecs.lucene40.values.Bytes;
 import org.apache.lucene.codecs.lucene40.values.Floats;
 import org.apache.lucene.codecs.lucene40.values.Ints;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.DocValues.SortedSource;
 import org.apache.lucene.index.DocValues.Source;
 import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.index.DocValues;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexableFieldType;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Counter;
@@ -438,22 +440,12 @@
     return getSource(values).asSortedSource();
   }
   
-  public static class DocValueHolder implements IndexableField {
+  public static class DocValueHolder implements StorableField {
     BytesRef bytes;
     Number numberValue;
     Comparator<BytesRef> comp;
 
     @Override
-    public TokenStream tokenStream(Analyzer a) {
-      return null;
-    }
-
-    @Override
-    public float boost() {
-      return 0.0f;
-    }
-
-    @Override
     public String name() {
       return "test";
     }
@@ -479,7 +471,7 @@
     }
 
     @Override
-    public IndexableFieldType fieldType() {
+    public FieldType fieldType() {
       return null;
     }
   }
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestBinaryDocument.java b/lucene/core/src/test/org/apache/lucene/document/TestBinaryDocument.java
index 67d1ad9..c001f82 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestBinaryDocument.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestBinaryDocument.java
@@ -3,6 +3,7 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
@@ -37,8 +38,8 @@
   {
     FieldType ft = new FieldType();
     ft.setStored(true);
-    IndexableField binaryFldStored = new StoredField("binaryStored", binaryValStored.getBytes("UTF-8"));
-    IndexableField stringFldStored = new Field("stringStored", binaryValStored, ft);
+    StoredField binaryFldStored = new StoredField("binaryStored", binaryValStored.getBytes("UTF-8"));
+    Field stringFldStored = new Field("stringStored", binaryValStored, ft);
 
     Document doc = new Document();
     
@@ -56,7 +57,7 @@
     
     /** open a reader and fetch the document */ 
     IndexReader reader = writer.getReader();
-    Document docFromReader = reader.document(0);
+    StoredDocument docFromReader = reader.document(0);
     assertTrue(docFromReader != null);
     
     /** fetch the binary stored field and compare it's content with the original one */
@@ -75,8 +76,8 @@
   }
   
   public void testCompressionTools() throws Exception {
-    IndexableField binaryFldCompressed = new StoredField("binaryCompressed", CompressionTools.compress(binaryValCompressed.getBytes("UTF-8")));
-    IndexableField stringFldCompressed = new StoredField("stringCompressed", CompressionTools.compressString(binaryValCompressed));
+    StoredField binaryFldCompressed = new StoredField("binaryCompressed", CompressionTools.compress(binaryValCompressed.getBytes("UTF-8")));
+    StoredField stringFldCompressed = new StoredField("stringCompressed", CompressionTools.compressString(binaryValCompressed));
     
     Document doc = new Document();
     
@@ -90,7 +91,7 @@
     
     /** open a reader and fetch the document */ 
     IndexReader reader = writer.getReader();
-    Document docFromReader = reader.document(0);
+    StoredDocument docFromReader = reader.document(0);
     assertTrue(docFromReader != null);
     
     /** fetch the binary compressed field and compare it's content with the original one */
diff --git a/lucene/core/src/test/org/apache/lucene/document/TestDocument.java b/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
index 5d32a82..07d035f 100644
--- a/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
+++ b/lucene/core/src/test/org/apache/lucene/document/TestDocument.java
@@ -18,6 +18,7 @@
  */
 
 import java.io.StringReader;
+import java.util.List;
 
 import org.apache.lucene.analysis.EmptyTokenizer;
 import org.apache.lucene.analysis.MockAnalyzer;
@@ -27,6 +28,8 @@
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -50,9 +53,9 @@
     
     FieldType ft = new FieldType();
     ft.setStored(true);
-    IndexableField stringFld = new Field("string", binaryVal, ft);
-    IndexableField binaryFld = new StoredField("binary", binaryVal.getBytes("UTF-8"));
-    IndexableField binaryFld2 = new StoredField("binary", binaryVal2.getBytes("UTF-8"));
+    Field stringFld = new Field("string", binaryVal, ft);
+    StoredField binaryFld = new StoredField("binary", binaryVal.getBytes("UTF-8"));
+    StoredField binaryFld2 = new StoredField("binary", binaryVal2.getBytes("UTF-8"));
     
     doc.add(stringFld);
     doc.add(binaryFld);
@@ -124,7 +127,7 @@
                                        // siltenlty ignored
     assertEquals(0, doc.getFields().size());
   }
-  
+
   public void testConstructorExceptions() {
     FieldType ft = new FieldType();
     ft.setStored(true);
@@ -147,6 +150,34 @@
       // expected exception
     }
   }
+
+  public void testClearDocument() {
+    Document doc = makeDocumentWithFields();
+    assertEquals(8, doc.getFields().size());
+    doc.clear();
+    assertEquals(0, doc.getFields().size());
+  }
+
+  public void testGetFieldsImmutable() {
+    Document doc = makeDocumentWithFields();
+    assertEquals(8, doc.getFields().size());
+    List<Field> fields = doc.getFields();
+    try {
+      fields.add( new StringField("name", "value", Field.Store.NO) );
+      fail("Document.getFields() should return immutable List");
+    }
+    catch (UnsupportedOperationException e) {
+      // OK
+    }
+
+    try {
+      fields.clear();
+      fail("Document.getFields() should return immutable List");
+    }
+    catch (UnsupportedOperationException e) {
+      // OK
+    }
+  }
   
   /**
    * Tests {@link Document#getValues(String)} method for a brand new Document
@@ -179,7 +210,7 @@
     ScoreDoc[] hits = searcher.search(query, null, 1000).scoreDocs;
     assertEquals(1, hits.length);
     
-    doAssert(searcher.doc(hits[0].doc), true);
+    doAssert(searcher.doc(hits[0].doc));
     writer.close();
     reader.close();
     dir.close();
@@ -214,11 +245,14 @@
     return doc;
   }
   
+  private void doAssert(StoredDocument doc) {
+    doAssert(new Document(doc), true);
+  }
   private void doAssert(Document doc, boolean fromIndex) {
-    IndexableField[] keywordFieldValues = doc.getFields("keyword");
-    IndexableField[] textFieldValues = doc.getFields("text");
-    IndexableField[] unindexedFieldValues = doc.getFields("unindexed");
-    IndexableField[] unstoredFieldValues = doc.getFields("unstored");
+    StorableField[] keywordFieldValues = doc.getFields("keyword");
+    StorableField[] textFieldValues = doc.getFields("text");
+    StorableField[] unindexedFieldValues = doc.getFields("unindexed");
+    StorableField[] unstoredFieldValues = doc.getFields("unstored");
     
     assertTrue(keywordFieldValues.length == 2);
     assertTrue(textFieldValues.length == 2);
@@ -268,7 +302,7 @@
     assertEquals(3, hits.length);
     int result = 0;
     for (int i = 0; i < 3; i++) {
-      Document doc2 = searcher.doc(hits[i].doc);
+      StoredDocument doc2 = searcher.doc(hits[i].doc);
       Field f = (Field) doc2.getField("id");
       if (f.stringValue().equals("id1")) result |= 1;
       else if (f.stringValue().equals("id2")) result |= 2;
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java b/lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java
index fcbd414..33e51a8 100755
--- a/lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestAddIndexes.java
@@ -1247,7 +1247,7 @@
     w.close();
     assertEquals(2, r3.numDocs());
     for(int docID=0;docID<2;docID++) {
-      Document d = r3.document(docID);
+      StoredDocument d = r3.document(docID);
       if (d.get("id").equals("1")) {
         assertEquals("doc1 field1", d.get("f1"));
       } else {
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java b/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
index 7b7e3d2..e6c5c8b 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
@@ -329,13 +329,13 @@
 
     for(int i=0;i<35;i++) {
       if (liveDocs.get(i)) {
-        Document d = reader.document(i);
-        List<IndexableField> fields = d.getFields();
+        StoredDocument d = reader.document(i);
+        List<StorableField> fields = d.getFields();
         boolean isProxDoc = d.getField("content3") == null;
         if (isProxDoc) {
           final int numFields = is40Index ? 7 : 5;
           assertEquals(numFields, fields.size());
-          IndexableField f =  d.getField("id");
+          StorableField f =  d.getField("id");
           assertEquals(""+i, f.stringValue());
 
           f = d.getField("utf8");
@@ -406,7 +406,7 @@
     ScoreDoc[] hits = searcher.search(new TermQuery(new Term(new String("content"), "aaa")), null, 1000).scoreDocs;
 
     // First document should be #0
-    Document d = searcher.getIndexReader().document(hits[0].doc);
+    StoredDocument d = searcher.getIndexReader().document(hits[0].doc);
     assertEquals("didn't get the right document first", "0", d.get("id"));
 
     doTestHits(hits, 34, searcher.getIndexReader());
@@ -459,7 +459,7 @@
     IndexReader reader = DirectoryReader.open(dir);
     IndexSearcher searcher = new IndexSearcher(reader);
     ScoreDoc[] hits = searcher.search(new TermQuery(new Term("content", "aaa")), null, 1000).scoreDocs;
-    Document d = searcher.getIndexReader().document(hits[0].doc);
+    StoredDocument d = searcher.getIndexReader().document(hits[0].doc);
     assertEquals("wrong first document", "0", d.get("id"));
     doTestHits(hits, 44, searcher.getIndexReader());
     reader.close();
@@ -485,7 +485,7 @@
     IndexSearcher searcher = new IndexSearcher(reader);
     ScoreDoc[] hits = searcher.search(new TermQuery(new Term("content", "aaa")), null, 1000).scoreDocs;
     assertEquals("wrong number of hits", 34, hits.length);
-    Document d = searcher.doc(hits[0].doc);
+    StoredDocument d = searcher.doc(hits[0].doc);
     assertEquals("wrong first document", "0", d.get("id"));
     reader.close();
 
@@ -757,7 +757,7 @@
       for (int id=10; id<15; id++) {
         ScoreDoc[] hits = searcher.search(NumericRangeQuery.newIntRange("trieInt", 4, Integer.valueOf(id), Integer.valueOf(id), true, true), 100).scoreDocs;
         assertEquals("wrong number of hits", 1, hits.length);
-        Document d = searcher.doc(hits[0].doc);
+        StoredDocument d = searcher.doc(hits[0].doc);
         assertEquals(String.valueOf(id), d.get("id"));
         
         hits = searcher.search(NumericRangeQuery.newLongRange("trieLong", 4, Long.valueOf(id), Long.valueOf(id), true, true), 100).scoreDocs;
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java b/lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java
index d503615..cd69b64 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestCustomNorms.java
@@ -74,7 +74,7 @@
     assertEquals(Type.FLOAT_32, normValues.getType());
     float[] norms = (float[]) source.getArray();
     for (int i = 0; i < open.maxDoc(); i++) {
-      Document document = open.document(i);
+      StoredDocument document = open.document(i);
       float expected = Float.parseFloat(document.get(floatTestField));
       assertEquals(expected, norms[i], 0.0f);
     }
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java b/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
index 1954ff3..f1dd366 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReader.java
@@ -61,10 +61,10 @@
     assertTrue(reader != null);
     assertTrue(reader instanceof StandardDirectoryReader);
     
-    Document newDoc1 = reader.document(0);
+    StoredDocument newDoc1 = reader.document(0);
     assertTrue(newDoc1 != null);
     assertTrue(DocHelper.numFields(newDoc1) == DocHelper.numFields(doc1) - DocHelper.unstored.size());
-    Document newDoc2 = reader.document(1);
+    StoredDocument newDoc2 = reader.document(1);
     assertTrue(newDoc2 != null);
     assertTrue(DocHelper.numFields(newDoc2) == DocHelper.numFields(doc2) - DocHelper.unstored.size());
     Terms vector = reader.getTermVectors(0).terms(DocHelper.TEXT_FIELD_2_KEY);
@@ -386,11 +386,11 @@
       writer.addDocument(doc);
       writer.close();
       DirectoryReader reader = DirectoryReader.open(dir);
-      Document doc2 = reader.document(reader.maxDoc() - 1);
-      IndexableField[] fields = doc2.getFields("bin1");
+      StoredDocument doc2 = reader.document(reader.maxDoc() - 1);
+      StorableField[] fields = doc2.getFields("bin1");
       assertNotNull(fields);
       assertEquals(1, fields.length);
-      IndexableField b1 = fields[0];
+      StorableField b1 = fields[0];
       assertTrue(b1.binaryValue() != null);
       BytesRef bytesRef = b1.binaryValue();
       assertEquals(bin.length, bytesRef.length);
@@ -595,13 +595,13 @@
     // check stored fields
     for (int i = 0; i < index1.maxDoc(); i++) {
       if (liveDocs1 == null || liveDocs1.get(i)) {
-        Document doc1 = index1.document(i);
-        Document doc2 = index2.document(i);
-        List<IndexableField> field1 = doc1.getFields();
-        List<IndexableField> field2 = doc2.getFields();
+        StoredDocument doc1 = index1.document(i);
+        StoredDocument doc2 = index2.document(i);
+        List<StorableField> field1 = doc1.getFields();
+        List<StorableField> field2 = doc2.getFields();
         assertEquals("Different numbers of fields for doc " + i + ".", field1.size(), field2.size());
-        Iterator<IndexableField> itField1 = field1.iterator();
-        Iterator<IndexableField> itField2 = field2.iterator();
+        Iterator<StorableField> itField1 = field1.iterator();
+        Iterator<StorableField> itField2 = field2.iterator();
         while (itField1.hasNext()) {
           Field curField1 = (Field) itField1.next();
           Field curField2 = (Field) itField2.next();
@@ -1082,7 +1082,7 @@
     Set<String> fieldsToLoad = new HashSet<String>();
     assertEquals(0, r.document(0, fieldsToLoad).getFields().size());
     fieldsToLoad.add("field1");
-    Document doc2 = r.document(0, fieldsToLoad);
+    StoredDocument doc2 = r.document(0, fieldsToLoad);
     assertEquals(1, doc2.getFields().size());
     assertEquals("foobar", doc2.get("field1"));
     r.close();
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java b/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java
index c230866..6db930a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestDirectoryReaderReopen.java
@@ -122,7 +122,7 @@
           if (i>0) {
             int k = i-1;
             int n = j + k*M;
-            Document prevItereationDoc = reader.document(n);
+            StoredDocument prevItereationDoc = reader.document(n);
             assertNotNull(prevItereationDoc);
             String id = prevItereationDoc.get("id");
             assertEquals(k+"_"+j, id);
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java b/lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java
index 9ca5250..22b2360 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestDocTermOrds.java
@@ -122,7 +122,7 @@
     for(int id=0;id<NUM_DOCS;id++) {
       Document doc = new Document();
 
-      doc.add(new IntField("id", id, Field.Store.NO));
+      doc.add(new IntField("id", id, Field.Store.YES));
       
       final int termCount = _TestUtil.nextInt(random(), 0, 20*RANDOM_MULTIPLIER);
       while(ordsForDocSet.size() < termCount) {
@@ -219,7 +219,7 @@
     for(int id=0;id<NUM_DOCS;id++) {
       Document doc = new Document();
 
-      doc.add(new IntField("id", id, Field.Store.NO));
+      doc.add(new IntField("id", id, Field.Store.YES));
       
       final int termCount = _TestUtil.nextInt(random(), 0, 20*RANDOM_MULTIPLIER);
       while(ordsForDocSet.size() < termCount) {
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDocValuesTypeCompatibility.java b/lucene/core/src/test/org/apache/lucene/index/TestDocValuesTypeCompatibility.java
index 618e057..cdba1c2 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestDocValuesTypeCompatibility.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestDocValuesTypeCompatibility.java
@@ -24,6 +24,7 @@
 import org.apache.lucene.document.DerefBytesDocValuesField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.DoubleDocValuesField;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FloatDocValuesField;
 import org.apache.lucene.document.IntDocValuesField;
 import org.apache.lucene.document.LongDocValuesField;
@@ -67,7 +68,7 @@
   }
   
   @SuppressWarnings("fallthrough")
-  public IndexableField getRandomIntsField(Type maxType, boolean force) {
+  public Field getRandomIntsField(Type maxType, boolean force) {
     switch (maxType) {
     
       case VAR_INTS:
@@ -120,7 +121,7 @@
     
   }
   @SuppressWarnings("fallthrough")
-  public IndexableField getRandomFloatField(Type maxType, boolean force) {
+  public Field getRandomFloatField(Type maxType, boolean force) {
     switch (maxType) {
     
       case FLOAT_64:
@@ -161,7 +162,7 @@
       iwc.setRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH);
       iwc.setRAMPerThreadHardLimitMB(2000);
       IndexWriter writer = new IndexWriter(dir, iwc);
-      IndexableField[] fields = new IndexableField[] {
+      Field[] fields = new Field[] {
           new DoubleDocValuesField("f", 1.0), new IntDocValuesField("f", 1),
           new ShortDocValuesField("f", (short) 1),
           new ByteDocValuesField("f", (byte) 1)};
@@ -194,7 +195,7 @@
       IndexWriter writer = new IndexWriter(dir, iwc);
       boolean mustBeFixed = random().nextBoolean();
       int maxSize = 2 + random().nextInt(15);
-      IndexableField bytesField = getRandomBytesField(mustBeFixed, maxSize,
+      Field bytesField = getRandomBytesField(mustBeFixed, maxSize,
           true);
       addDoc(writer, bytesField);
       for (int j = 0; j < numDocs; j++) {
@@ -207,7 +208,7 @@
     }
   }
   
-  public IndexableField getRandomBytesField(boolean mustBeFixed, int maxSize,
+  public Field getRandomBytesField(boolean mustBeFixed, int maxSize,
       boolean mustBeVariableIfNotFixed) {
     int size = mustBeFixed ? maxSize : random().nextInt(maxSize) + 1;
     StringBuilder s = new StringBuilder();
@@ -256,16 +257,16 @@
     dir.close();
   }
   
-  private void addDoc(IndexWriter writer, IndexableField... fields)
+  private void addDoc(IndexWriter writer, Field... fields)
       throws IOException {
     Document doc = new Document();
-    for (IndexableField indexableField : fields) {
+    for (Field indexableField : fields) {
       doc.add(indexableField);
     }
     writer.addDocument(doc);
   }
   
-  public IndexableField getRandomIndexableDVField() {
+  public Field getRandomIndexableDVField() {
     int size = random().nextInt(100) + 1;
     StringBuilder s = new StringBuilder();
     for (int i = 0; i < size; i++) {
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDocumentWriter.java b/lucene/core/src/test/org/apache/lucene/index/TestDocumentWriter.java
index eade9ab..eb9e1bb 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestDocumentWriter.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestDocumentWriter.java
@@ -67,11 +67,11 @@
     //After adding the document, we should be able to read it back in
     SegmentReader reader = new SegmentReader(info, DirectoryReader.DEFAULT_TERMS_INDEX_DIVISOR, newIOContext(random()));
     assertTrue(reader != null);
-    Document doc = reader.document(0);
+    StoredDocument doc = reader.document(0);
     assertTrue(doc != null);
 
     //System.out.println("Document: " + doc);
-    IndexableField [] fields = doc.getFields("textField2");
+    StorableField[] fields = doc.getFields("textField2");
     assertTrue(fields != null && fields.length == 1);
     assertTrue(fields[0].stringValue().equals(DocHelper.FIELD_2_TEXT));
     assertTrue(fields[0].fieldType().storeTermVectors());
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java b/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java
index 56f9601..0c9bd4b 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestDuelingCodecs.java
@@ -539,25 +539,25 @@
   public void assertStoredFields(IndexReader leftReader, IndexReader rightReader) throws Exception {
     assert leftReader.maxDoc() == rightReader.maxDoc();
     for (int i = 0; i < leftReader.maxDoc(); i++) {
-      Document leftDoc = leftReader.document(i);
-      Document rightDoc = rightReader.document(i);
+      StoredDocument leftDoc = leftReader.document(i);
+      StoredDocument rightDoc = rightReader.document(i);
       
       // TODO: I think this is bogus because we don't document what the order should be
       // from these iterators, etc. I think the codec/IndexReader should be free to order this stuff
       // in whatever way it wants (e.g. maybe it packs related fields together or something)
       // To fix this, we sort the fields in both documents by name, but
       // we still assume that all instances with same name are in order:
-      Comparator<IndexableField> comp = new Comparator<IndexableField>() {
+      Comparator<StorableField> comp = new Comparator<StorableField>() {
         @Override
-        public int compare(IndexableField arg0, IndexableField arg1) {
+        public int compare(StorableField arg0, StorableField arg1) {
           return arg0.name().compareTo(arg1.name());
         }        
       };
       Collections.sort(leftDoc.getFields(), comp);
       Collections.sort(rightDoc.getFields(), comp);
 
-      Iterator<IndexableField> leftIterator = leftDoc.iterator();
-      Iterator<IndexableField> rightIterator = rightDoc.iterator();
+      Iterator<StorableField> leftIterator = leftDoc.iterator();
+      Iterator<StorableField> rightIterator = rightDoc.iterator();
       while (leftIterator.hasNext()) {
         assertTrue(info, rightIterator.hasNext());
         assertStoredField(leftIterator.next(), rightIterator.next());
@@ -569,7 +569,7 @@
   /** 
    * checks that two stored fields are equivalent 
    */
-  public void assertStoredField(IndexableField leftField, IndexableField rightField) {
+  public void assertStoredField(StorableField leftField, StorableField rightField) {
     assertEquals(info, leftField.name(), rightField.name());
     assertEquals(info, leftField.binaryValue(), rightField.binaryValue());
     assertEquals(info, leftField.stringValue(), rightField.stringValue());
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java b/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java
index 9850a3d..312ae6a 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestFieldInfos.java
@@ -47,7 +47,7 @@
   //Positive test of FieldInfos
     assertTrue(testDoc != null);
     FieldInfos.Builder builder = new FieldInfos.Builder();
-    for (IndexableField field : testDoc) {
+    for (IndexableField field : testDoc.getFields()) {
       builder.addOrUpdate(field.name(), field.fieldType());
     }
     FieldInfos fieldInfos = builder.finish();
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java b/lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java
index d2f02ed..7d5468d 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestFieldsReader.java
@@ -55,7 +55,7 @@
   public static void beforeClass() throws Exception {
     fieldInfos = new FieldInfos.Builder();
     DocHelper.setupDoc(testDoc);
-    for (IndexableField field : testDoc) {
+    for (IndexableField field : testDoc.getFields()) {
       fieldInfos.addOrUpdate(field.name(), field.fieldType());
     }
     dir = newDirectory();
@@ -79,7 +79,7 @@
     assertTrue(dir != null);
     assertTrue(fieldInfos != null);
     IndexReader reader = DirectoryReader.open(dir);
-    Document doc = reader.document(0);
+    StoredDocument doc = reader.document(0);
     assertTrue(doc != null);
     assertTrue(doc.getField(DocHelper.TEXT_FIELD_1_KEY) != null);
 
@@ -104,7 +104,7 @@
 
     DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(DocHelper.TEXT_FIELD_3_KEY);
     reader.document(0, visitor);
-    final List<IndexableField> fields = visitor.getDocument().getFields();
+    final List<StorableField> fields = visitor.getDocument().getFields();
     assertEquals(1, fields.size());
     assertEquals(DocHelper.TEXT_FIELD_3_KEY, fields.get(0).name());
     reader.close();
@@ -279,7 +279,7 @@
       doc.add(sf);
       answers[id] = answer;
       typeAnswers[id] = typeAnswer;
-      FieldType ft = new FieldType(IntField.TYPE_NOT_STORED);
+      FieldType ft = new FieldType(IntField.TYPE_STORED);
       ft.setNumericPrecisionStep(Integer.MAX_VALUE);
       doc.add(new IntField("id", id, ft));
       w.addDocument(doc);
@@ -293,7 +293,7 @@
       final AtomicReader sub = ctx.reader();
       final int[] ids = FieldCache.DEFAULT.getInts(sub, "id", false);
       for(int docID=0;docID<sub.numDocs();docID++) {
-        final Document doc = sub.document(docID);
+        final StoredDocument doc = sub.document(docID);
         final Field f = (Field) doc.getField("nf");
         assertTrue("got f=" + f, f instanceof StoredField);
         assertEquals(answers[ids[docID]], f.numericValue());
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
index e0533b9..c867fed 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriter.java
@@ -908,8 +908,8 @@
     w.close();
 
     IndexReader ir = DirectoryReader.open(dir);
-    Document doc2 = ir.document(0);
-    IndexableField f2 = doc2.getField("binary");
+    StoredDocument doc2 = ir.document(0);
+    StorableField f2 = doc2.getField("binary");
     b = f2.binaryValue().bytes;
     assertTrue(b != null);
     assertEquals(17, b.length, 17);
@@ -1165,8 +1165,8 @@
     w.close();
 
     IndexReader ir = DirectoryReader.open(dir);
-    Document doc2 = ir.document(0);
-    IndexableField f3 = doc2.getField("binary");
+    StoredDocument doc2 = ir.document(0);
+    StorableField f3 = doc2.getField("binary");
     b = f3.binaryValue().bytes;
     assertTrue(b != null);
     assertEquals(17, b.length, 17);
@@ -1207,8 +1207,8 @@
     doc.add(newField("zzz", "1 2 3", customType));
     w.addDocument(doc);
     IndexReader r = w.getReader();
-    Document doc2 = r.document(0);
-    Iterator<IndexableField> it = doc2.getFields().iterator();
+    StoredDocument doc2 = r.document(0);
+    Iterator<StorableField> it = doc2.getFields().iterator();
     assertTrue(it.hasNext());
     Field f = (Field) it.next();
     assertEquals(f.name(), "zzz");
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
index 376974f..cfee991 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
@@ -1559,50 +1559,46 @@
     try {
       doc = new Document();
       // try to boost with norms omitted
-      List<IndexableField> list = new ArrayList<IndexableField>();
-      list.add(new IndexableField() {
-
+      IndexDocument docList = new IndexDocument() {
+        
+        List<IndexableField> list = new ArrayList<IndexableField>();
+        List<StorableField> storedList = new ArrayList<StorableField>();
+        
         @Override
-        public String name() {
-          return "foo";
+        public Iterable<? extends IndexableField> indexableFields() {
+          if (list.size() == 0) {
+            list.add(new IndexableField() {
+              @Override
+              public String name() {
+                return "foo";
+              }
+
+              @Override
+              public IndexableFieldType fieldType() {
+                return StringField.TYPE_NOT_STORED;
+              }
+
+              @Override
+              public float boost() {
+                return 5f;
+              }
+
+              @Override
+              public TokenStream tokenStream(Analyzer analyzer) throws IOException {
+                return null;
+              }
+            });
+          }
+          return list;
         }
 
         @Override
-        public IndexableFieldType fieldType() {
-          return StringField.TYPE_NOT_STORED;
+        public Iterable<? extends StorableField> storableFields() {
+          return storedList;
         }
-
-        @Override
-        public float boost() {
-          return 5f;
-        }
-
-        @Override
-        public BytesRef binaryValue() {
-          return null;
-        }
-
-        @Override
-        public String stringValue() {
-          return "baz";
-        }
-
-        @Override
-        public Reader readerValue() {
-          return null;
-        }
-
-        @Override
-        public Number numericValue() {
-          return null;
-        }
-
-        @Override
-        public TokenStream tokenStream(Analyzer analyzer) throws IOException {
-          return null;
-        }
-      });
-      iw.addDocument(list);
+        
+      };
+      iw.addDocument(docList);
       fail("didn't get any exception, boost silently discarded");
     } catch (UnsupportedOperationException expected) {
       // expected
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterMerging.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterMerging.java
index d07a775..5e87625 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterMerging.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterMerging.java
@@ -84,7 +84,7 @@
     int max = reader.maxDoc();
     for (int i = 0; i < max; i++)
     {
-      Document temp = reader.document(i);
+      StoredDocument temp = reader.document(i);
       //System.out.println("doc "+i+"="+temp.getField("count").stringValue());
       //compare the index doc number to the value that it should be
       if (!temp.getField("count").stringValue().equals((i + startAt) + ""))
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java
index a27c38b..43c31f4 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterReader.java
@@ -141,7 +141,7 @@
 
     String id10 = r1.document(10).getField("id").stringValue();
     
-    Document newDoc = r1.document(10);
+    Document newDoc = new Document(r1.document(10));
     newDoc.removeField("id");
     newDoc.add(newStringField("id", Integer.toString(8000), Field.Store.YES));
     writer.updateDocument(new Term("id", id10), newDoc);
@@ -271,9 +271,9 @@
     assertEquals(100, index2df);
 
     // verify the docs are from different indexes
-    Document doc5 = r1.document(5);
+    StoredDocument doc5 = r1.document(5);
     assertEquals("index1", doc5.get("indexname"));
-    Document doc150 = r1.document(150);
+    StoredDocument doc150 = r1.document(150);
     assertEquals("index2", doc150.get("indexname"));
     r1.close();
     writer.close();
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java
index 950b53f..b0f44f0 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java
@@ -259,7 +259,7 @@
     w.close();
 
     IndexReader ir = DirectoryReader.open(dir);
-    Document doc2 = ir.document(0);
+    StoredDocument doc2 = ir.document(0);
     for(int i=0;i<count;i++) {
       assertEquals("field " + i + " was not indexed correctly", 1, ir.docFreq(new Term("f"+i, utf8Data[2*i+1])));
       assertEquals("field " + i + " is incorrect", utf8Data[2*i+1], doc2.getField("f"+i).stringValue());
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java b/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java
index 6ac4b2d..864b17f 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestIndexableField.java
@@ -24,8 +24,8 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.index.DocValues.Type;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -39,7 +39,7 @@
 
 public class TestIndexableField extends LuceneTestCase {
 
-  private class MyField implements IndexableField {
+  private class MyField implements IndexableField, StorableField {
 
     private final int counter;
     private final IndexableFieldType fieldType = new IndexableFieldType() {
@@ -89,7 +89,7 @@
       }
 
       @Override
-      public DocValues.Type docValueType() {
+      public Type docValueType() {
         return null;
       }
     };
@@ -183,35 +183,100 @@
       final int finalBaseCount = baseCount;
       baseCount += fieldCount-1;
 
-      w.addDocument(new Iterable<IndexableField>() {
+      IndexDocument d = new IndexDocument() {
         @Override
-        public Iterator<IndexableField> iterator() {
-          return new Iterator<IndexableField>() {
-            int fieldUpto;
-
+        public Iterable<? extends IndexableField> indexableFields() {
+          return new Iterable<IndexableField>() {
             @Override
-            public boolean hasNext() {
-              return fieldUpto < fieldCount;
-            }
+            public Iterator<IndexableField> iterator() {
+              return new Iterator<IndexableField>() {
+                int fieldUpto = 0;
+                private IndexableField next;
 
-            @Override
-            public IndexableField next() {
-              assert fieldUpto < fieldCount;
-              if (fieldUpto == 0) {
-                fieldUpto = 1;
-                return newStringField("id", ""+finalDocCount, Field.Store.YES);
-              } else {
-                return new MyField(finalBaseCount + (fieldUpto++-1));
-              }
-            }
+                @Override
+                public boolean hasNext() {
+                  if (fieldUpto >= fieldCount) return false;
 
-            @Override
-            public void remove() {
-              throw new UnsupportedOperationException();
+                  next = null;
+                  if (fieldUpto == 0) {
+                    fieldUpto = 1;
+                    next = newStringField("id", ""+finalDocCount, Field.Store.YES);
+                  } else {
+                    next = new MyField(finalBaseCount + (fieldUpto++-1));
+                  }
+                  
+                  if (next != null && next.fieldType().indexed()) return true;
+                  else return this.hasNext();
+                }
+
+                @Override
+                public IndexableField next() {
+                  assert fieldUpto <= fieldCount;
+                  if (next == null && !hasNext()) {
+                    return null;
+                  }
+                  else {
+                    return next;
+                  }
+                }
+
+                @Override
+                public void remove() {
+                  throw new UnsupportedOperationException();
+                }
+              };
             }
           };
         }
-        });
+
+        @Override
+        public Iterable<? extends StorableField> storableFields() {
+          return new Iterable<StorableField>() {
+            @Override
+            public Iterator<StorableField> iterator() {
+              return new Iterator<StorableField>() {
+                int fieldUpto = 0;
+                private StorableField next = null;
+
+                @Override
+                public boolean hasNext() {
+
+                  if (fieldUpto == fieldCount) return false;
+                  
+                  next = null;
+                  if (fieldUpto == 0) {
+                    fieldUpto = 1;
+                    next = newStringField("id", ""+finalDocCount, Field.Store.YES);
+                  } else {
+                    next = new MyField(finalBaseCount + (fieldUpto++-1));
+                  }
+                  
+                  if (next != null && next.fieldType().stored()) return true;
+                  else return this.hasNext();
+                }
+
+                @Override
+                public StorableField next() {
+                  assert fieldUpto <= fieldCount;
+                  if (next == null && !hasNext()) {
+                    return null;
+                  }
+                  else {
+                    return next;
+                  }
+                }
+
+                @Override
+                public void remove() {
+                  throw new UnsupportedOperationException();
+                }
+              };
+            }
+          };
+        }
+      };
+      
+      w.addDocument(d);
     }
 
     final IndexReader r = w.getReader();
@@ -223,10 +288,11 @@
       if (VERBOSE) {
         System.out.println("TEST: verify doc id=" + id + " (" + fieldsPerDoc[id] + " fields) counter=" + counter);
       }
+
       final TopDocs hits = s.search(new TermQuery(new Term("id", ""+id)), 1);
       assertEquals(1, hits.totalHits);
       final int docID = hits.scoreDocs[0].doc;
-      final Document doc = s.doc(docID);
+      final StoredDocument doc = s.doc(docID);
       final int endCounter = counter + fieldsPerDoc[id];
       while(counter < endCounter) {
         final String name = "f" + counter;
@@ -245,7 +311,7 @@
 
         // stored:
         if (stored) {
-          IndexableField f = doc.getField(name);
+          StorableField f = doc.getField(name);
           assertNotNull("doc " + id + " doesn't have field f" + counter, f);
           if (binary) {
             assertNotNull("doc " + id + " doesn't have field f" + counter, f);
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestNorms.java b/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
index e734930..368f5c2 100755
--- a/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestNorms.java
@@ -105,7 +105,7 @@
     assertEquals(Type.FIXED_INTS_8, normValues.getType());
     byte[] norms = (byte[]) source.getArray();
     for (int i = 0; i < open.maxDoc(); i++) {
-      Document document = open.document(i);
+      StoredDocument document = open.document(i);
       int expected = Integer.parseInt(document.get(byteTestField));
       assertEquals((byte)expected, norms[i]);
     }
@@ -164,7 +164,7 @@
       assertEquals(Type.FIXED_INTS_8, normValues.getType());
       byte[] norms = (byte[]) source.getArray();
       for (int i = 0; i < mergedReader.maxDoc(); i++) {
-        Document document = mergedReader.document(i);
+        StoredDocument document = mergedReader.document(i);
         int expected = Integer.parseInt(document.get(byteTestField));
         assertEquals((byte) expected, norms[i]);
       }
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestParallelAtomicReader.java b/lucene/core/src/test/org/apache/lucene/index/TestParallelAtomicReader.java
index c7760f6..bfeb332 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestParallelAtomicReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestParallelAtomicReader.java
@@ -224,8 +224,8 @@
     assertEquals(parallelHits.length, singleHits.length);
     for(int i = 0; i < parallelHits.length; i++) {
       assertEquals(parallelHits[i].score, singleHits[i].score, 0.001f);
-      Document docParallel = parallel.doc(parallelHits[i].doc);
-      Document docSingle = single.doc(singleHits[i].doc);
+      StoredDocument docParallel = parallel.doc(parallelHits[i].doc);
+      StoredDocument docSingle = single.doc(singleHits[i].doc);
       assertEquals(docParallel.get("f1"), docSingle.get("f1"));
       assertEquals(docParallel.get("f2"), docSingle.get("f2"));
       assertEquals(docParallel.get("f3"), docSingle.get("f3"));
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java b/lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java
index 499b0cb..9b23ffa 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestParallelCompositeReader.java
@@ -283,8 +283,8 @@
     assertEquals(parallelHits.length, singleHits.length);
     for(int i = 0; i < parallelHits.length; i++) {
       assertEquals(parallelHits[i].score, singleHits[i].score, 0.001f);
-      Document docParallel = parallel.doc(parallelHits[i].doc);
-      Document docSingle = single.doc(singleHits[i].doc);
+      StoredDocument docParallel = parallel.doc(parallelHits[i].doc);
+      StoredDocument docSingle = single.doc(singleHits[i].doc);
       assertEquals(docParallel.get("f1"), docSingle.get("f1"));
       assertEquals(docParallel.get("f2"), docSingle.get("f2"));
       assertEquals(docParallel.get("f3"), docSingle.get("f3"));
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java b/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
index 396a699..1b1ec4d 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestPostingsOffsets.java
@@ -240,7 +240,7 @@
 
     for(int docCount=0;docCount<numDocs;docCount++) {
       Document doc = new Document();
-      doc.add(new IntField("id", docCount, Field.Store.NO));
+      doc.add(new IntField("id", docCount, Field.Store.YES));
       List<Token> tokens = new ArrayList<Token>();
       final int numTokens = atLeast(100);
       //final int numTokens = atLeast(20);
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestRandomStoredFields.java b/lucene/core/src/test/org/apache/lucene/index/TestRandomStoredFields.java
index fc74f90..9247d41 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestRandomStoredFields.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestRandomStoredFields.java
@@ -121,7 +121,7 @@
           }
           TopDocs hits = s.search(new TermQuery(new Term("id", testID)), 1);
           assertEquals(1, hits.totalHits);
-          Document doc = r.document(hits.scoreDocs[0].doc);
+          StoredDocument doc = r.document(hits.scoreDocs[0].doc);
           Document docExp = docs.get(testID);
           for(int i=0;i<fieldCount;i++) {
             assertEquals("doc " + testID + ", field f" + fieldCount + " is wrong", docExp.get("f"+i),  doc.get("f"+i));
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java b/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
index 4376db4..d4607dd 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestRollingUpdates.java
@@ -69,7 +69,7 @@
       if (VERBOSE) {
         System.out.println("  docIter=" + docIter + " id=" + id);
       }
-      ((Field) doc.getField("docid")).setStringValue(myID);
+      doc.getField("docid").setStringValue(myID);
 
       Term idTerm = new Term("docid", myID);
 
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestSegmentMerger.java b/lucene/core/src/test/org/apache/lucene/index/TestSegmentMerger.java
index 306c8ae..3df987c 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestSegmentMerger.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestSegmentMerger.java
@@ -96,11 +96,11 @@
                                                    DirectoryReader.DEFAULT_TERMS_INDEX_DIVISOR, newIOContext(random()));
     assertTrue(mergedReader != null);
     assertTrue(mergedReader.numDocs() == 2);
-    Document newDoc1 = mergedReader.document(0);
+    StoredDocument newDoc1 = mergedReader.document(0);
     assertTrue(newDoc1 != null);
     //There are 2 unstored fields on the document
     assertTrue(DocHelper.numFields(newDoc1) == DocHelper.numFields(doc1) - DocHelper.unstored.size());
-    Document newDoc2 = mergedReader.document(1);
+    StoredDocument newDoc2 = mergedReader.document(1);
     assertTrue(newDoc2 != null);
     assertTrue(DocHelper.numFields(newDoc2) == DocHelper.numFields(doc2) - DocHelper.unstored.size());
 
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java b/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java
index 1407f42..280ab6e 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestSegmentReader.java
@@ -62,13 +62,13 @@
   public void testDocument() throws IOException {
     assertTrue(reader.numDocs() == 1);
     assertTrue(reader.maxDoc() >= 1);
-    Document result = reader.document(0);
+    StoredDocument result = reader.document(0);
     assertTrue(result != null);
     //There are 2 unstored fields on the document that are not preserved across writing
     assertTrue(DocHelper.numFields(result) == DocHelper.numFields(testDoc) - DocHelper.unstored.size());
     
-    List<IndexableField> fields = result.getFields();
-    for (final IndexableField field : fields ) { 
+    List<StorableField> fields = result.getFields();
+    for (final StorableField field : fields ) { 
       assertTrue(field != null);
       assertTrue(DocHelper.nameValues.containsKey(field.name()));
     }
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java b/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java
index ccecbed..363547f 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestStressIndexing2.java
@@ -133,8 +133,8 @@
 
   static Term idTerm = new Term("id","");
   IndexingThread[] threads;
-  static Comparator<IndexableField> fieldNameComparator = new Comparator<IndexableField>() {
-    public int compare(IndexableField o1, IndexableField o2) {
+  static Comparator<GeneralField> fieldNameComparator = new Comparator<GeneralField>() {
+    public int compare(GeneralField o1, GeneralField o2) {
       return o1.name().compareTo(o2.name());
     }
   };
@@ -250,7 +250,7 @@
     Iterator<Document> iter = docs.values().iterator();
     while (iter.hasNext()) {
       Document d = iter.next();
-      ArrayList<IndexableField> fields = new ArrayList<IndexableField>();
+      ArrayList<Field> fields = new ArrayList<Field>();
       fields.addAll(d.getFields());
       // put fields in same order each time
       Collections.sort(fields, fieldNameComparator);
@@ -287,7 +287,7 @@
       Bits liveDocs = sub.getLiveDocs();
       System.out.println("  " + ((SegmentReader) sub).getSegmentInfo());
       for(int docID=0;docID<sub.maxDoc();docID++) {
-        Document doc = sub.document(docID);
+        StoredDocument doc = sub.document(docID);
         if (liveDocs == null || liveDocs.get(docID)) {
           System.out.println("    docID=" + docID + " id:" + doc.get("id"));
         } else {
@@ -573,9 +573,9 @@
     }
   }
 
-  public static void verifyEquals(Document d1, Document d2) {
-    List<IndexableField> ff1 = d1.getFields();
-    List<IndexableField> ff2 = d2.getFields();
+  public static void verifyEquals(StoredDocument d1, StoredDocument d2) {
+    List<StorableField> ff1 = d1.getFields();
+    List<StorableField> ff2 = d2.getFields();
 
     Collections.sort(ff1, fieldNameComparator);
     Collections.sort(ff2, fieldNameComparator);
@@ -583,8 +583,8 @@
     assertEquals(ff1 + " : " + ff2, ff1.size(), ff2.size());
 
     for (int i=0; i<ff1.size(); i++) {
-      IndexableField f1 = ff1.get(i);
-      IndexableField f2 = ff2.get(i);
+      StorableField f1 = ff1.get(i);
+      StorableField f2 = ff2.get(i);
       if (f1.binaryValue() != null) {
         assert(f2.binaryValue() != null);
       } else {
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestStressNRT.java b/lucene/core/src/test/org/apache/lucene/index/TestStressNRT.java
index 9a78986..2441dfa 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestStressNRT.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestStressNRT.java
@@ -343,12 +343,12 @@
                 if (results.totalHits != 1) {
                   System.out.println("FAIL: hits id:" + id + " val=" + val);
                   for(ScoreDoc sd : results.scoreDocs) {
-                    final Document doc = r.document(sd.doc);
+                    final StoredDocument doc = r.document(sd.doc);
                     System.out.println("  docID=" + sd.doc + " id:" + doc.get("id") + " foundVal=" + doc.get(field));
                   }
                   fail("id=" + id + " reader=" + r + " totalHits=" + results.totalHits);
                 }
-                Document doc = searcher.doc(results.scoreDocs[0].doc);
+                StoredDocument doc = searcher.doc(results.scoreDocs[0].doc);
                 long foundVal = Long.parseLong(doc.get(field));
                 if (foundVal < Math.abs(val)) {
                   fail("foundVal=" + foundVal + " val=" + val + " id=" + id + " reader=" + r);
diff --git a/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java b/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
index c24fb08..5b1ff5e 100644
--- a/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
+++ b/lucene/core/src/test/org/apache/lucene/index/TestTermsEnum.java
@@ -156,7 +156,7 @@
 
   private void addDoc(RandomIndexWriter w, Collection<String> terms, Map<BytesRef,Integer> termToID, int id) throws IOException {
     Document doc = new Document();
-    doc.add(new IntField("id", id, Field.Store.NO));
+    doc.add(new IntField("id", id, Field.Store.YES));
     if (VERBOSE) {
       System.out.println("TEST: addDoc id:" + id + " terms=" + terms);
     }
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java
index 05b9c1b..dd93da5 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java
@@ -22,6 +22,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
@@ -435,7 +436,7 @@
         DecimalFormat f = new DecimalFormat("0.000000", DecimalFormatSymbols.getInstance(Locale.ROOT));
 
         for (int i = 0; i < h.length; i++) {
-            Document d = searcher.doc(h[i].doc);
+            StoredDocument d = searcher.doc(h[i].doc);
             float score = h[i].score;
             System.err.println("#" + i + ": " + f.format(score) + " - " +
                                d.get("id") + " - " + d.get("data"));
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDateSort.java b/lucene/core/src/test/org/apache/lucene/search/TestDateSort.java
index 5639a59..42d08c0 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDateSort.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDateSort.java
@@ -27,6 +27,7 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.store.Directory;
 
 /**
@@ -82,7 +83,7 @@
     String[] actualOrder = new String[5];
     ScoreDoc[] hits = searcher.search(query, null, 1000, sort).scoreDocs;
     for (int i = 0; i < hits.length; i++) {
-      Document document = searcher.doc(hits[i].doc);
+      StoredDocument document = searcher.doc(hits[i].doc);
       String text = document.get(TEXT_FIELD);
       actualOrder[i] = text;
     }
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
index 661a7ad..0a29c6e 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
@@ -29,6 +29,7 @@
 import org.apache.lucene.index.SlowCompositeReaderWrapper;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
@@ -490,7 +491,7 @@
     DecimalFormat f = new DecimalFormat("0.000000000", DecimalFormatSymbols.getInstance(Locale.ROOT));
     
     for (int i = 0; i < h.length; i++) {
-      Document d = searcher.doc(h[i].doc);
+      StoredDocument d = searcher.doc(h[i].doc);
       float score = h[i].score;
       System.err
           .println("#" + i + ": " + f.format(score) + " - " + d.get("id"));
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java b/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java
index 0ad6b9c..d864a44 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestNRTManager.java
@@ -28,6 +28,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexDocument;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -75,7 +76,7 @@
   }
 
   @Override
-  protected void updateDocuments(Term id, List<? extends Iterable<? extends IndexableField>> docs) throws Exception {
+  protected void updateDocuments(Term id, List<? extends IndexDocument> docs) throws Exception {
     final long gen = genWriter.updateDocuments(id, docs);
 
     // Randomly verify the update "took":
@@ -99,7 +100,7 @@
   }
 
   @Override
-  protected void addDocuments(Term id, List<? extends Iterable<? extends IndexableField>> docs) throws Exception {
+  protected void addDocuments(Term id, List<? extends IndexDocument> docs) throws Exception {
     final long gen = genWriter.addDocuments(docs);
     // Randomly verify the add "took":
     if (random().nextInt(20) == 2) {
@@ -121,7 +122,7 @@
   }
 
   @Override
-  protected void addDocument(Term id, Iterable<? extends IndexableField> doc) throws Exception {
+  protected void addDocument(Term id, IndexDocument doc) throws Exception {
     final long gen = genWriter.addDocument(doc);
 
     // Randomly verify the add "took":
@@ -144,7 +145,7 @@
   }
 
   @Override
-  protected void updateDocument(Term id, Iterable<? extends IndexableField> doc) throws Exception {
+  protected void updateDocument(Term id, IndexDocument doc) throws Exception {
     final long gen = genWriter.updateDocument(id, doc);
     // Randomly verify the udpate "took":
     if (random().nextInt(20) == 2) {
@@ -373,7 +374,7 @@
     }
 
     public void updateDocument(Term term,
-        Iterable<? extends IndexableField> doc, Analyzer analyzer)
+        IndexDocument doc, Analyzer analyzer)
         throws IOException {
       super.updateDocument(term, doc, analyzer);
       try {
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java b/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java
index cdb2503..6711f7a 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java
@@ -29,6 +29,7 @@
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.SlowCompositeReaderWrapper;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.store.Directory;
@@ -173,7 +174,7 @@
       ScoreDoc[] sd = topDocs.scoreDocs;
       assertNotNull(sd);
       assertEquals("Score doc count"+type, count, sd.length );
-      Document doc=searcher.doc(sd[0].doc);
+      StoredDocument doc=searcher.doc(sd[0].doc);
       assertEquals("First doc"+type, 2*distance+startOffset, doc.getField(field).numericValue().intValue());
       doc=searcher.doc(sd[sd.length-1].doc);
       assertEquals("Last doc"+type, (1+count)*distance+startOffset, doc.getField(field).numericValue().intValue());
@@ -226,7 +227,7 @@
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertNotNull(sd);
     assertEquals("Score doc count", count, sd.length );
-    Document doc=searcher.doc(sd[0].doc);
+    StoredDocument doc=searcher.doc(sd[0].doc);
     assertEquals("First doc", startOffset, doc.getField(field).numericValue().intValue());
     doc=searcher.doc(sd[sd.length-1].doc);
     assertEquals("Last doc", (count-1)*distance+startOffset, doc.getField(field).numericValue().intValue());
@@ -266,7 +267,7 @@
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertNotNull(sd);
     assertEquals("Score doc count", noDocs-count, sd.length );
-    Document doc=searcher.doc(sd[0].doc);
+    StoredDocument doc=searcher.doc(sd[0].doc);
     assertEquals("First doc", count*distance+startOffset, doc.getField(field).numericValue().intValue());
     doc=searcher.doc(sd[sd.length-1].doc);
     assertEquals("Last doc", (noDocs-1)*distance+startOffset, doc.getField(field).numericValue().intValue());
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java b/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java
index 48a8251..ede30d9 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java
@@ -29,6 +29,7 @@
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.SlowCompositeReaderWrapper;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.store.Directory;
@@ -182,7 +183,7 @@
       ScoreDoc[] sd = topDocs.scoreDocs;
       assertNotNull(sd);
       assertEquals("Score doc count"+type, count, sd.length );
-      Document doc=searcher.doc(sd[0].doc);
+      StoredDocument doc=searcher.doc(sd[0].doc);
       assertEquals("First doc"+type, 2*distance+startOffset, doc.getField(field).numericValue().longValue() );
       doc=searcher.doc(sd[sd.length-1].doc);
       assertEquals("Last doc"+type, (1+count)*distance+startOffset, doc.getField(field).numericValue().longValue() );
@@ -241,7 +242,7 @@
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertNotNull(sd);
     assertEquals("Score doc count", count, sd.length );
-    Document doc=searcher.doc(sd[0].doc);
+    StoredDocument doc=searcher.doc(sd[0].doc);
     assertEquals("First doc", startOffset, doc.getField(field).numericValue().longValue() );
     doc=searcher.doc(sd[sd.length-1].doc);
     assertEquals("Last doc", (count-1)*distance+startOffset, doc.getField(field).numericValue().longValue() );
@@ -286,7 +287,7 @@
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertNotNull(sd);
     assertEquals("Score doc count", noDocs-count, sd.length );
-    Document doc=searcher.doc(sd[0].doc);
+    StoredDocument doc=searcher.doc(sd[0].doc);
     assertEquals("First doc", count*distance+startOffset, doc.getField(field).numericValue().longValue() );
     doc=searcher.doc(sd[sd.length-1].doc);
     assertEquals("Last doc", (noDocs-1)*distance+startOffset, doc.getField(field).numericValue().longValue() );
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
index f59e3de..c40e99d 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestPhraseQuery.java
@@ -74,7 +74,7 @@
     Document doc = new Document();
     doc.add(newTextField("field", "one two three four five", Field.Store.YES));
     doc.add(newTextField("repeated", "this is a repeated field - first part", Field.Store.YES));
-    IndexableField repeatedField = newTextField("repeated", "second part of a repeated field", Field.Store.YES);
+    Field repeatedField = newTextField("repeated", "second part of a repeated field", Field.Store.YES);
     doc.add(repeatedField);
     doc.add(newTextField("palindrome", "one two three two one", Field.Store.YES));
     writer.addDocument(doc);
diff --git a/lucene/core/src/test/org/apache/lucene/search/TestSort.java b/lucene/core/src/test/org/apache/lucene/search/TestSort.java
index 0d54e32..39b05f8 100644
--- a/lucene/core/src/test/org/apache/lucene/search/TestSort.java
+++ b/lucene/core/src/test/org/apache/lucene/search/TestSort.java
@@ -50,6 +50,8 @@
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.FieldValueHitQueue.Entry;
@@ -523,9 +525,9 @@
     boolean fail = false;
     final String fieldSuffix = sort.getSort()[0].getField().endsWith("_fixed") ? "_fixed" : "";
     for (int x = 0; x < n; ++x) {
-      Document doc2 = searcher.doc(result[x].doc);
-      IndexableField[] v = doc2.getFields("tracer" + fieldSuffix);
-      IndexableField[] v2 = doc2.getFields("tracer2" + fieldSuffix);
+      StoredDocument doc2 = searcher.doc(result[x].doc);
+      StorableField[] v = doc2.getFields("tracer" + fieldSuffix);
+      StorableField[] v2 = doc2.getFields("tracer2" + fieldSuffix);
       for (int j = 0; j < v.length; ++j) {
         buff.append(v[j] + "(" + v2[j] + ")(" + result[x].doc+")\n");
         if (last != null) {
@@ -1230,8 +1232,8 @@
     StringBuilder buff = new StringBuilder(10);
     int n = result.length;
     for (int i=0; i<n; ++i) {
-      Document doc = searcher.doc(result[i].doc);
-      IndexableField[] v = doc.getFields("tracer");
+      StoredDocument doc = searcher.doc(result[i].doc);
+      StorableField[] v = doc.getFields("tracer");
       for (int j=0; j<v.length; ++j) {
         buff.append (v[j].stringValue());
       }
diff --git a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java
index dc8a0f0..1431422 100644
--- a/lucene/core/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java
+++ b/lucene/core/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java
@@ -28,6 +28,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.*;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
@@ -160,7 +161,7 @@
       
       int id = topdocs.scoreDocs[i].doc;
       float score = topdocs.scoreDocs[i].score;
-      Document doc = s.doc(id);
+      StoredDocument doc = s.doc(id);
       assertEquals(expectedIds[i], doc.get(FIELD_ID));
       boolean scoreEq = Math.abs(expectedScores[i] - score) < tolerance;
       if (!scoreEq) {
diff --git a/lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java b/lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java
index 0a1bb3c..82cd9ee 100644
--- a/lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java
+++ b/lucene/core/src/test/org/apache/lucene/store/TestRAMDirectory.java
@@ -29,6 +29,7 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.util.English;
@@ -85,7 +86,7 @@
     
     // search for all documents
     for (int i = 0; i < docsToAdd; i++) {
-      Document doc = searcher.doc(i);
+      StoredDocument doc = searcher.doc(i);
       assertTrue(doc.getField("content") != null);
     }
 
diff --git a/lucene/demo/src/java/org/apache/lucene/demo/SearchFiles.java b/lucene/demo/src/java/org/apache/lucene/demo/SearchFiles.java
index b837b65..6d85687 100644
--- a/lucene/demo/src/java/org/apache/lucene/demo/SearchFiles.java
+++ b/lucene/demo/src/java/org/apache/lucene/demo/SearchFiles.java
@@ -29,6 +29,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.queryparser.classic.QueryParser;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -178,7 +179,7 @@
           continue;
         }
 
-        Document doc = searcher.doc(hits[i].doc);
+        StoredDocument doc = searcher.doc(hits[i].doc);
         String path = doc.get("path");
         if (path != null) {
           System.out.println((i+1) + ". " + path);
diff --git a/lucene/demo/src/java/org/apache/lucene/demo/xmlparser/FormBasedXmlQueryDemo.java b/lucene/demo/src/java/org/apache/lucene/demo/xmlparser/FormBasedXmlQueryDemo.java
index 67468e5..9f437b3 100644
--- a/lucene/demo/src/java/org/apache/lucene/demo/xmlparser/FormBasedXmlQueryDemo.java
+++ b/lucene/demo/src/java/org/apache/lucene/demo/xmlparser/FormBasedXmlQueryDemo.java
@@ -41,6 +41,7 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.queryparser.xml.CorePlusExtensionsParser;
 import org.apache.lucene.queryparser.xml.QueryTemplateManager;
 import org.apache.lucene.search.IndexSearcher;
@@ -112,7 +113,7 @@
       //and package the results and forward to JSP
       if (topDocs != null) {
         ScoreDoc[] sd = topDocs.scoreDocs;
-        Document[] results = new Document[sd.length];
+        StoredDocument[] results = new StoredDocument[sd.length];
         for (int i = 0; i < results.length; i++) {
           results[i] = searcher.doc(sd[i].doc);
           request.setAttribute("results", results);
diff --git a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
index 9a41ff3..495f30c 100644
--- a/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
+++ b/lucene/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
@@ -594,7 +594,7 @@
         Document doc = new Document();
         docs.add(doc);
         if (groupValue.group != null) {
-          doc.add(newStringField("group", groupValue.group.utf8ToString(), Field.Store.NO));
+          doc.add(newStringField("group", groupValue.group.utf8ToString(), Field.Store.YES));
         }
         doc.add(newStringField("sort1", groupValue.sort1.utf8ToString(), Field.Store.NO));
         doc.add(newStringField("sort2", groupValue.sort2.utf8ToString(), Field.Store.NO));
diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java
index 9928ce3..b0830be 100644
--- a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java
+++ b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java
@@ -35,6 +35,7 @@
 import org.apache.lucene.index.DocsAndPositionsEnum;
 import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -58,7 +59,7 @@
    *        and get the vector from
    * @param docId The docId to retrieve.
    * @param field The field to retrieve on the document
-   * @param doc The document to fall back on
+   * @param document The document to fall back on
    * @param analyzer The analyzer to use for creating the TokenStream if the
    *        vector doesn't exist
    * @return The {@link org.apache.lucene.analysis.TokenStream} for the
@@ -68,7 +69,7 @@
    */
 
   public static TokenStream getAnyTokenStream(IndexReader reader, int docId,
-      String field, Document doc, Analyzer analyzer) throws IOException {
+      String field, StoredDocument document, Analyzer analyzer) throws IOException {
     TokenStream ts = null;
 
     Fields vectors = reader.getTermVectors(docId);
@@ -81,7 +82,7 @@
 
     // No token info stored so fall back to analyzing raw content
     if (ts == null) {
-      ts = getTokenStream(doc, field, analyzer);
+      ts = getTokenStream(document, field, analyzer);
     }
     return ts;
   }
@@ -291,11 +292,11 @@
   // convenience method
   public static TokenStream getTokenStream(IndexReader reader, int docId,
       String field, Analyzer analyzer) throws IOException {
-    Document doc = reader.document(docId);
+    StoredDocument doc = reader.document(docId);
     return getTokenStream(doc, field, analyzer);
   }
-
-  public static TokenStream getTokenStream(Document doc, String field,
+  
+  public static TokenStream getTokenStream(StoredDocument doc, String field,
       Analyzer analyzer) {
     String contents = doc.get(field);
     if (contents == null) {
diff --git a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
index 67ea75f..3677573 100644
--- a/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
+++ b/lucene/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
@@ -42,6 +42,7 @@
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.Term;
@@ -97,7 +98,7 @@
 
 
     for (int i = 0; i < hits.scoreDocs.length; i++) {
-      Document doc = searcher.doc(hits.scoreDocs[i].doc);
+      StoredDocument doc = searcher.doc(hits.scoreDocs[i].doc);
       String storedField = doc.get(FIELD_NAME);
 
       TokenStream stream = TokenSources.getAnyTokenStream(searcher
@@ -1656,7 +1657,7 @@
 
     TopDocs hits = searcher.search(query, null, 10);
     for( int i = 0; i < hits.totalHits; i++ ){
-      Document doc = searcher.doc( hits.scoreDocs[i].doc );
+      StoredDocument doc = searcher.doc( hits.scoreDocs[i].doc );
       String result = h.getBestFragment( a, "t_text1", doc.get( "t_text1" ));
       if (VERBOSE) System.out.println("result:" +  result);
       assertEquals("more <B>random</B> words for second field", result);
diff --git a/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java b/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
index 6936023..f2c98e7 100644
--- a/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
+++ b/lucene/join/src/test/org/apache/lucene/search/join/TestBlockJoin.java
@@ -119,11 +119,11 @@
     assertEquals(1, group.totalHits);
     assertFalse(Float.isNaN(group.score));
 
-    Document childDoc = s.doc(group.scoreDocs[0].doc);
+    StoredDocument childDoc = s.doc(group.scoreDocs[0].doc);
     //System.out.println("  doc=" + group.scoreDocs[0].doc);
     assertEquals("java", childDoc.get("skill"));
     assertNotNull(group.groupValue);
-    Document parentDoc = s.doc(group.groupValue);
+    StoredDocument parentDoc = s.doc(group.groupValue);
     assertEquals("Lisa", parentDoc.get("name"));
 
 
@@ -247,7 +247,7 @@
     }
   }
   
-  private Document getParentDoc(IndexReader reader, Filter parents, int childDocID) throws IOException {
+  private StoredDocument getParentDoc(IndexReader reader, Filter parents, int childDocID) throws IOException {
     final List<AtomicReaderContext> leaves = reader.leaves();
     final int subIndex = ReaderUtil.subIndex(childDocID, leaves);
     final AtomicReaderContext leaf = leaves.get(subIndex);
@@ -563,7 +563,7 @@
         System.out.println("\nTEST: normal index gets " + results.totalHits + " hits");
         final ScoreDoc[] hits = results.scoreDocs;
         for(int hitIDX=0;hitIDX<hits.length;hitIDX++) {
-          final Document doc = s.doc(hits[hitIDX].doc);
+          final StoredDocument doc = s.doc(hits[hitIDX].doc);
           //System.out.println("  score=" + hits[hitIDX].score + " parentID=" + doc.get("parentID") + " childID=" + doc.get("childID") + " (docID=" + hits[hitIDX].doc + ")");
           System.out.println("  parentID=" + doc.get("parentID") + " childID=" + doc.get("childID") + " (docID=" + hits[hitIDX].doc + ")");
           FieldDoc fd = (FieldDoc) hits[hitIDX];
@@ -617,10 +617,10 @@
             }
 
             assertNotNull(group.groupValue);
-            final Document parentDoc = joinS.doc(group.groupValue);
+            final StoredDocument parentDoc = joinS.doc(group.groupValue);
             System.out.println("  group parentID=" + parentDoc.get("parentID") + " (docID=" + group.groupValue + ")");
             for(int hitIDX=0;hitIDX<group.scoreDocs.length;hitIDX++) {
-              final Document doc = joinS.doc(group.scoreDocs[hitIDX].doc);
+              final StoredDocument doc = joinS.doc(group.scoreDocs[hitIDX].doc);
               //System.out.println("    score=" + group.scoreDocs[hitIDX].score + " childID=" + doc.get("childID") + " (docID=" + group.scoreDocs[hitIDX].doc + ")");
               System.out.println("    childID=" + doc.get("childID") + " child0=" + doc.get("child0") + " (docID=" + group.scoreDocs[hitIDX].doc + ")");
             }
@@ -635,7 +635,7 @@
         TopDocs b = joinS.search(childJoinQuery, 10);
         for (ScoreDoc hit : b.scoreDocs) {
           Explanation explanation = joinS.explain(childJoinQuery, hit.doc);
-          Document document = joinS.doc(hit.doc - 1);
+          StoredDocument document = joinS.doc(hit.doc - 1);
           int childId = Integer.parseInt(document.get("childID"));
           assertTrue(explanation.isMatch());
           assertEquals(hit.score, explanation.getValue(), 0.0f);
@@ -763,7 +763,7 @@
       if (VERBOSE) {
         System.out.println("  " + results2.totalHits + " totalHits:");
         for(ScoreDoc sd : results2.scoreDocs) {
-          final Document doc = s.doc(sd.doc);
+          final StoredDocument doc = s.doc(sd.doc);
           System.out.println("  childID=" + doc.get("childID") + " parentID=" + doc.get("parentID") + " docID=" + sd.doc);
         }
       }
@@ -777,8 +777,8 @@
       if (VERBOSE) {
         System.out.println("  " + joinResults2.totalHits + " totalHits:");
         for(ScoreDoc sd : joinResults2.scoreDocs) {
-          final Document doc = joinS.doc(sd.doc);
-          final Document parentDoc = getParentDoc(joinR, parentsFilter, sd.doc);
+          final StoredDocument doc = joinS.doc(sd.doc);
+          final StoredDocument parentDoc = getParentDoc(joinR, parentsFilter, sd.doc);
           System.out.println("  childID=" + doc.get("childID") + " parentID=" + parentDoc.get("parentID") + " docID=" + sd.doc);
         }
       }
@@ -798,8 +798,8 @@
     for(int hitCount=0;hitCount<results.scoreDocs.length;hitCount++) {
       ScoreDoc hit = results.scoreDocs[hitCount];
       ScoreDoc joinHit = joinResults.scoreDocs[hitCount];
-      Document doc1 = r.document(hit.doc);
-      Document doc2 = joinR.document(joinHit.doc);
+      StoredDocument doc1 = r.document(hit.doc);
+      StoredDocument doc2 = joinR.document(joinHit.doc);
       assertEquals("hit " + hitCount + " differs",
                    doc1.get("childID"), doc2.get("childID"));
       // don't compare scores -- they are expected to differ
@@ -826,14 +826,14 @@
       final GroupDocs<Integer> group = groupDocs[joinGroupUpto++];
       final ScoreDoc[] groupHits = group.scoreDocs;
       assertNotNull(group.groupValue);
-      final Document parentDoc = joinR.document(group.groupValue);
+      final StoredDocument parentDoc = joinR.document(group.groupValue);
       final String parentID = parentDoc.get("parentID");
       //System.out.println("GROUP groupDoc=" + group.groupDoc + " parent=" + parentDoc);
       assertNotNull(parentID);
       assertTrue(groupHits.length > 0);
       for(int hitIDX=0;hitIDX<groupHits.length;hitIDX++) {
-        final Document nonJoinHit = r.document(hits[resultUpto++].doc);
-        final Document joinHit = joinR.document(groupHits[hitIDX].doc);
+        final StoredDocument nonJoinHit = r.document(hits[resultUpto++].doc);
+        final StoredDocument joinHit = joinR.document(groupHits[hitIDX].doc);
         assertEquals(parentID,
                      nonJoinHit.get("parentID"));
         assertEquals(joinHit.get("childID"),
@@ -916,11 +916,11 @@
       final GroupDocs<Integer> group = jobResults.groups[0];
       assertEquals(1, group.totalHits);
 
-      Document childJobDoc = s.doc(group.scoreDocs[0].doc);
+      StoredDocument childJobDoc = s.doc(group.scoreDocs[0].doc);
       //System.out.println("  doc=" + group.scoreDocs[0].doc);
       assertEquals("java", childJobDoc.get("skill"));
       assertNotNull(group.groupValue);
-      Document parentDoc = s.doc(group.groupValue);
+      StoredDocument parentDoc = s.doc(group.groupValue);
       assertEquals("Lisa", parentDoc.get("name"));
     }
 
@@ -933,10 +933,10 @@
     final GroupDocs<Integer> qGroup = qualificationResults.groups[0];
     assertEquals(1, qGroup.totalHits);
 
-    Document childQualificationDoc = s.doc(qGroup.scoreDocs[0].doc);
+    StoredDocument childQualificationDoc = s.doc(qGroup.scoreDocs[0].doc);
     assertEquals("maths", childQualificationDoc.get("qualification"));
     assertNotNull(qGroup.groupValue);
-    Document parentDoc = s.doc(qGroup.groupValue);
+    StoredDocument parentDoc = s.doc(qGroup.groupValue);
     assertEquals("Lisa", parentDoc.get("name"));
 
 
diff --git a/lucene/misc/src/java/org/apache/lucene/document/LazyDocument.java b/lucene/misc/src/java/org/apache/lucene/document/LazyDocument.java
index 06563cd..b99c1bd 100644
--- a/lucene/misc/src/java/org/apache/lucene/document/LazyDocument.java
+++ b/lucene/misc/src/java/org/apache/lucene/document/LazyDocument.java
@@ -25,8 +25,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexableFieldType;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.util.BytesRef;
 
 /** Defers actually loading a field's value until you ask
@@ -38,7 +39,7 @@
   private final int docID;
 
   // null until first field is loaded
-  private Document doc;
+  private StoredDocument doc;
 
   private Map<Integer,Integer> fields = new HashMap<Integer,Integer>();
 
@@ -47,7 +48,7 @@
     this.docID = docID;
   }
 
-  public IndexableField getField(FieldInfo fieldInfo) {  
+  public StorableField getField(FieldInfo fieldInfo) {  
     Integer num = fields.get(fieldInfo.number);
     if (num == null) {
       num = 0;
@@ -59,7 +60,7 @@
     return new LazyField(fieldInfo.name, num);
   }
 
-  private synchronized Document getDocument() {
+  private synchronized StoredDocument getDocument() {
     if (doc == null) {
       try {
         doc = reader.document(docID);
@@ -71,7 +72,7 @@
     return doc;
   }
 
-  private class LazyField implements IndexableField {
+  private class LazyField implements StorableField {
     private String name;
     private int num;
     
@@ -86,11 +87,6 @@
     }
 
     @Override
-    public float boost() {
-      return 1.0f;
-    }
-
-    @Override
     public BytesRef binaryValue() {
       if (num == 0) {
         return getDocument().getField(name).binaryValue();
@@ -134,14 +130,5 @@
         return getDocument().getFields(name)[num].fieldType();
       }
     }
-
-    @Override
-    public TokenStream tokenStream(Analyzer analyzer) throws IOException {
-      if (num == 0) {
-        return getDocument().getField(name).tokenStream(analyzer);
-      } else {
-        return getDocument().getFields(name)[num].tokenStream(analyzer);
-      }
-    }
   }
 }
diff --git a/lucene/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java b/lucene/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java
index 7f15357..9dd6e76 100644
--- a/lucene/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java
+++ b/lucene/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java
@@ -68,7 +68,7 @@
     IndexReader ir;
     ir = DirectoryReader.open(dirs[0]);
     assertTrue(ir.numDocs() - NUM_DOCS / 3 <= 1); // rounding error
-    Document doc = ir.document(0);
+    StoredDocument doc = ir.document(0);
     assertEquals("0", doc.get("id"));
     TermsEnum te = MultiFields.getTerms(ir, "id").iterator(null);
     assertEquals(TermsEnum.SeekStatus.NOT_FOUND, te.seekCeil(new BytesRef("1")));
@@ -113,7 +113,7 @@
     IndexReader ir;
     ir = DirectoryReader.open(dirs[0]);
     assertTrue(ir.numDocs() - NUM_DOCS / 3 <= 1);
-    Document doc = ir.document(0);
+    StoredDocument doc = ir.document(0);
     assertEquals("0", doc.get("id"));
     int start = ir.numDocs();
     ir.close();
diff --git a/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java b/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java
index d8b9776..62b96a9 100644
--- a/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java
+++ b/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java
@@ -26,6 +26,8 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
@@ -715,9 +717,9 @@
 
       // field does not store term vector info
       if (vector == null) {
-        Document d = ir.document(docNum);
-        IndexableField fields[] = d.getFields(fieldName);
-        for (IndexableField field : fields) {
+        StoredDocument d = ir.document(docNum);
+        StorableField[] fields = d.getFields(fieldName);
+        for (StorableField field : fields) {
           final String stringValue = field.stringValue();
           if (stringValue != null) {
             addTermFrequencies(new StringReader(stringValue), termFreqMap, fieldName);
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java
index 23ec531..69473a4 100644
--- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java
+++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java
@@ -26,6 +26,7 @@
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.queryparser.classic.QueryParser;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -100,7 +101,7 @@
     TopDocs td = searcher.search(q, 10);
     ScoreDoc[] sd = td.scoreDocs;
     for (int i = 0; i < sd.length; i++) {
-      Document doc = searcher.doc(sd[i].doc);
+      StoredDocument doc = searcher.doc(sd[i].doc);
       String id = doc.get("id");
       assertTrue(qString + "matched doc#" + id + " not expected", expecteds
           .contains(id));
diff --git a/lucene/queryparser/src/test/org/apache/lucene/queryparser/xml/TestParser.java b/lucene/queryparser/src/test/org/apache/lucene/queryparser/xml/TestParser.java
index e087f64..c60f194 100644
--- a/lucene/queryparser/src/test/org/apache/lucene/queryparser/xml/TestParser.java
+++ b/lucene/queryparser/src/test/org/apache/lucene/queryparser/xml/TestParser.java
@@ -28,6 +28,7 @@
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.DisjunctionMaxQuery;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -232,7 +233,7 @@
       System.out.println("=========" + qType + "============");
       ScoreDoc[] scoreDocs = hits.scoreDocs;
       for (int i = 0; i < Math.min(numDocs, hits.totalHits); i++) {
-        Document ldoc = searcher.doc(scoreDocs[i].doc);
+        StoredDocument ldoc = searcher.doc(scoreDocs[i].doc);
         System.out.println("[" + ldoc.get("date") + "]" + ldoc.get("contents"));
       }
       System.out.println();
diff --git a/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/DuplicateFilterTest.java b/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/DuplicateFilterTest.java
index 827916c..2d9040b 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/DuplicateFilterTest.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/DuplicateFilterTest.java
@@ -87,7 +87,7 @@
     ScoreDoc[] hits = searcher.search(tq, df, 1000).scoreDocs;
 
     for (ScoreDoc hit : hits) {
-      Document d = searcher.doc(hit.doc);
+      StoredDocument d = searcher.doc(hit.doc);
       String url = d.get(KEY_FIELD);
       assertFalse("No duplicate urls should be returned", results.contains(url));
       results.add(url);
@@ -101,7 +101,7 @@
     boolean dupsFound = false;
 
     for (ScoreDoc hit : hits) {
-      Document d = searcher.doc(hit.doc);
+      StoredDocument d = searcher.doc(hit.doc);
       String url = d.get(KEY_FIELD);
       if (!dupsFound)
         dupsFound = results.contains(url);
@@ -118,7 +118,7 @@
     assertTrue("Filtered searching should have found some matches", hits.length > 0);
 
     for (ScoreDoc hit : hits) {
-      Document d = searcher.doc(hit.doc);
+      StoredDocument d = searcher.doc(hit.doc);
       String url = d.get(KEY_FIELD);
       assertFalse("No duplicate urls should be returned", results.contains(url));
       results.add(url);
@@ -132,7 +132,7 @@
     ScoreDoc[] hits = searcher.search(tq, df, 1000).scoreDocs;
     assertTrue("Filtered searching should have found some matches", hits.length > 0);
     for (ScoreDoc hit : hits) {
-      Document d = searcher.doc(hit.doc);
+      StoredDocument d = searcher.doc(hit.doc);
       String url = d.get(KEY_FIELD);
       DocsEnum td = _TestUtil.docs(random(), reader,
                                    KEY_FIELD,
@@ -156,7 +156,7 @@
     ScoreDoc[] hits = searcher.search(tq, df, 1000).scoreDocs;
     assertTrue("Filtered searching should have found some matches", hits.length > 0);
     for (ScoreDoc hit : hits) {
-      Document d = searcher.doc(hit.doc);
+      StoredDocument d = searcher.doc(hit.doc);
       String url = d.get(KEY_FIELD);
       DocsEnum td = _TestUtil.docs(random(), reader,
                                    KEY_FIELD,
diff --git a/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/FuzzyLikeThisQueryTest.java b/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/FuzzyLikeThisQueryTest.java
index dfedd8a..401dc0d 100644
--- a/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/FuzzyLikeThisQueryTest.java
+++ b/lucene/sandbox/src/test/org/apache/lucene/sandbox/queries/FuzzyLikeThisQueryTest.java
@@ -23,6 +23,7 @@
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -88,7 +89,7 @@
     TopDocs topDocs = searcher.search(flt, 1);
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertTrue("score docs must match 1 doc", (sd != null) && (sd.length > 0));
-    Document doc = searcher.doc(sd[0].doc);
+    StoredDocument doc = searcher.doc(sd[0].doc);
     assertEquals("Should match most similar not most rare variant", "2", doc.get("id"));
   }
 
@@ -104,7 +105,7 @@
     TopDocs topDocs = searcher.search(flt, 1);
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertTrue("score docs must match 1 doc", (sd != null) && (sd.length > 0));
-    Document doc = searcher.doc(sd[0].doc);
+    StoredDocument doc = searcher.doc(sd[0].doc);
     assertEquals("Should match most similar when using 2 words", "2", doc.get("id"));
   }
 
@@ -119,7 +120,7 @@
     TopDocs topDocs = searcher.search(flt, 1);
     ScoreDoc[] sd = topDocs.scoreDocs;
     assertTrue("score docs must match 1 doc", (sd != null) && (sd.length > 0));
-    Document doc = searcher.doc(sd[0].doc);
+    StoredDocument doc = searcher.doc(sd[0].doc);
     assertEquals("Should match most similar when using 2 words", "2", doc.get("id"));
   }
 
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java
index 81eadf8..624cd4c 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/SpatialStrategy.java
@@ -19,6 +19,8 @@
 
 import com.spatial4j.core.context.SpatialContext;
 import com.spatial4j.core.shape.Shape;
+
+import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.FunctionQuery;
 import org.apache.lucene.queries.function.ValueSource;
@@ -97,7 +99,7 @@
    *
    * @return Not null nor will it have null elements.
    */
-  public abstract IndexableField[] createIndexableFields(Shape shape);
+  public abstract Field[] createIndexableFields(Shape shape);
 
   /**
    * The value source yields a number that is proportional to the distance between the query shape and indexed data.
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java
index 5c74d19..91af948 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/bbox/BBoxStrategy.java
@@ -92,11 +92,11 @@
   //---------------------------------
 
   @Override
-  public IndexableField[] createIndexableFields(Shape shape) {
+  public Field[] createIndexableFields(Shape shape) {
     Rectangle bbox = shape.getBoundingBox();
     FieldType doubleFieldType = new FieldType(DoubleField.TYPE_NOT_STORED);
     doubleFieldType.setNumericPrecisionStep(precisionStep);
-    IndexableField[] fields = new IndexableField[5];
+    Field[] fields = new Field[5];
     fields[0] = new DoubleField(field_minX, bbox.getMinX(), doubleFieldType);
     fields[1] = new DoubleField(field_maxX, bbox.getMaxX(), doubleFieldType);
     fields[2] = new DoubleField(field_minY, bbox.getMinY(), doubleFieldType);
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
index fdd53d4..70d0eec 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/prefix/PrefixTreeStrategy.java
@@ -63,7 +63,7 @@
   }
 
   @Override
-  public IndexableField[] createIndexableFields(Shape shape) {
+  public Field[] createIndexableFields(Shape shape) {
     int detailLevel = grid.getMaxLevelForPrecision(shape,distErrPct);
     List<Node> cells = grid.getNodes(shape, detailLevel, true);//true=intermediates cells
     //If shape isn't a point, add a full-resolution center-point so that
@@ -79,7 +79,7 @@
     //  http://code.google.com/p/lucene-spatial-playground/issues/detail?id=4
 
     Field field = new Field(getFieldName(), new CellTokenStream(cells.iterator()), FIELD_TYPE);
-    return new IndexableField[]{field};
+    return new Field[]{field};
   }
 
   /* Indexed, tokenized, not stored. */
diff --git a/lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java b/lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java
index 7f420d5..a5e6e80 100644
--- a/lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java
+++ b/lucene/spatial/src/java/org/apache/lucene/spatial/vector/TwoDoublesStrategy.java
@@ -24,6 +24,7 @@
 import com.spatial4j.core.shape.Rectangle;
 import com.spatial4j.core.shape.Shape;
 import org.apache.lucene.document.DoubleField;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.FunctionQuery;
@@ -77,12 +78,12 @@
   }
 
   @Override
-  public IndexableField[] createIndexableFields(Shape shape) {
+  public Field[] createIndexableFields(Shape shape) {
     if( shape instanceof Point ) {
       Point point = (Point)shape;
       FieldType doubleFieldType = new FieldType(DoubleField.TYPE_NOT_STORED);
       doubleFieldType.setNumericPrecisionStep(precisionStep);
-      IndexableField[] f = new IndexableField[2];
+      Field[] f = new Field[2];
       f[0] = new DoubleField(fieldNameX, point.getX(), doubleFieldType);
       f[1] = new DoubleField(fieldNameY, point.getY(), doubleFieldType);
       return f;
@@ -90,7 +91,7 @@
     if( !ignoreIncompatibleGeometry ) {
       throw new IllegalArgumentException( "TwoDoublesStrategy can not index: "+shape );
     }
-    return new IndexableField[0]; // nothing (solr does not support null)
+    return new Field[0]; // nothing (solr does not support null)
   }
 
   @Override
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java b/lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java
index 42d1685..750183e 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/PortedSolr3Test.java
@@ -194,7 +194,7 @@
   private Document newDoc(String id, Shape shape) {
     Document doc = new Document();
     doc.add(new StringField("id", id, Field.Store.YES));
-    for (IndexableField f : strategy.createIndexableFields(shape)) {
+    for (Field f : strategy.createIndexableFields(shape)) {
       doc.add(f);
     }
     if (storeShape)
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java b/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java
index 64392d3..3e578f2 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialExample.java
@@ -124,7 +124,7 @@
     //Potentially more than one shape in this field is supported by some
     // strategies; see the javadocs of the SpatialStrategy impl to see.
     for (Shape shape : shapes) {
-      for (IndexableField f : strategy.createIndexableFields(shape)) {
+      for (Field f : strategy.createIndexableFields(shape)) {
         doc.add(f);
       }
       //store it too; the format is up to you
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java b/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java
index 8d1741d..5909cb1 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/SpatialTestCase.java
@@ -20,6 +20,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
@@ -130,11 +131,11 @@
   protected static class SearchResult {
 
     public float score;
-    public Document document;
+    public StoredDocument document;
 
-    public SearchResult(float score, Document document) {
+    public SearchResult(float score, StoredDocument storedDocument) {
       this.score = score;
-      this.document = document;
+      this.document = storedDocument;
     }
     
     @Override
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java b/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java
index 1e30cbb..5460b99 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/StrategyTestCase.java
@@ -85,7 +85,7 @@
       document.add(new StringField("id", data.id, Field.Store.YES));
       document.add(new StringField("name", data.name, Field.Store.YES));
       Shape shape = ctx.readShape(data.shape);
-      for (IndexableField f : strategy.createIndexableFields(shape)) {
+      for (Field f : strategy.createIndexableFields(shape)) {
         document.add(f);
       }
       if (storeShape)
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java b/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java
index f00d13b..bdfc51f 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestRecursivePrefixTreeStrategy.java
@@ -199,7 +199,7 @@
   private Document newDoc(String id, Shape shape) {
     Document doc = new Document();
     doc.add(new StringField("id", id, Field.Store.YES));
-    for (IndexableField f : strategy.createIndexableFields(shape)) {
+    for (Field f : strategy.createIndexableFields(shape)) {
       doc.add(f);
     }
     if (storeShape)
diff --git a/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java b/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java
index d63cf7e..389d471 100644
--- a/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java
+++ b/lucene/spatial/src/test/org/apache/lucene/spatial/prefix/TestTermQueryPrefixGridStrategy.java
@@ -46,7 +46,7 @@
 
     Document losAngeles = new Document();
     losAngeles.add(new StringField("name", "Los Angeles", Field.Store.YES));
-    for (IndexableField field : prefixGridStrategy.createIndexableFields(point)) {
+    for (Field field : prefixGridStrategy.createIndexableFields(point)) {
       losAngeles.add(field);
     }
     losAngeles.add(new StoredField(prefixGridStrategy.getFieldName(), ctx.toString(point)));
diff --git a/lucene/test-framework/src/java/org/apache/lucene/analysis/CollationTestBase.java b/lucene/test-framework/src/java/org/apache/lucene/analysis/CollationTestBase.java
index 685796f..716303e 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/analysis/CollationTestBase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/analysis/CollationTestBase.java
@@ -34,6 +34,8 @@
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -238,8 +240,8 @@
     StringBuilder buff = new StringBuilder(10);
     int n = result.length;
     for (int i = 0 ; i < n ; ++i) {
-      Document doc = searcher.doc(result[i].doc);
-      IndexableField[] v = doc.getFields("tracer");
+      StoredDocument doc = searcher.doc(result[i].doc);
+      StorableField[] v = doc.getFields("tracer");
       for (int j = 0 ; j < v.length ; ++j) {
         buff.append(v[j].stringValue());
       }
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/DocHelper.java b/lucene/test-framework/src/java/org/apache/lucene/index/DocHelper.java
index 2e0c3e8..da4627d 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/DocHelper.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/DocHelper.java
@@ -290,6 +290,10 @@
   public static int numFields(Document doc) {
     return doc.getFields().size();
   }
+
+  public static int numFields(StoredDocument doc) {
+    return doc.getFields().size();
+  }
   
   public static Document createDocument(int n, String indexName, int numFields) {
     StringBuilder sb = new StringBuilder();
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/RandomIndexWriter.java b/lucene/test-framework/src/java/org/apache/lucene/index/RandomIndexWriter.java
index 5629c0a..b038fba 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/RandomIndexWriter.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/RandomIndexWriter.java
@@ -139,13 +139,13 @@
   
   /**
    * Adds a Document.
-   * @see IndexWriter#addDocument(Iterable)
+   * @see IndexWriter#addDocument(org.apache.lucene.index.IndexDocument)
    */
-  public <T extends IndexableField> void addDocument(final Iterable<T> doc) throws IOException {
+  public <T extends IndexableField> void addDocument(final IndexDocument doc) throws IOException {
     addDocument(doc, w.getAnalyzer());
   }
 
-  public <T extends IndexableField> void addDocument(final Iterable<T> doc, Analyzer a) throws IOException {
+  public <T extends IndexableField> void addDocument(final IndexDocument doc, Analyzer a) throws IOException {
     if (doDocValues && doc instanceof Document) {
       randomPerDocFieldValues((Document) doc);
     }
@@ -154,11 +154,11 @@
       // (but we need to clone them), and only when
       // getReader, commit, etc. are called, we do an
       // addDocuments?  Would be better testing.
-      w.addDocuments(new Iterable<Iterable<T>>() {
+      w.addDocuments(new Iterable<IndexDocument>() {
 
         @Override
-        public Iterator<Iterable<T>> iterator() {
-          return new Iterator<Iterable<T>>() {
+        public Iterator<IndexDocument> iterator() {
+          return new Iterator<IndexDocument>() {
             boolean done;
             
             @Override
@@ -172,7 +172,7 @@
             }
 
             @Override
-            public Iterable<T> next() {
+            public IndexDocument next() {
               if (done) {
                 throw new IllegalStateException();
               }
@@ -273,30 +273,30 @@
     }
   }
   
-  public void addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
+  public void addDocuments(Iterable<? extends IndexDocument> docs) throws IOException {
     w.addDocuments(docs);
     maybeCommit();
   }
 
-  public void updateDocuments(Term delTerm, Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
+  public void updateDocuments(Term delTerm, Iterable<? extends IndexDocument> docs) throws IOException {
     w.updateDocuments(delTerm, docs);
     maybeCommit();
   }
 
   /**
    * Updates a document.
-   * @see IndexWriter#updateDocument(Term, Iterable)
+   * @see IndexWriter#updateDocument(Term, org.apache.lucene.index.IndexDocument)
    */
-  public <T extends IndexableField> void updateDocument(Term t, final Iterable<T> doc) throws IOException {
+  public <T extends IndexableField> void updateDocument(Term t, final IndexDocument doc) throws IOException {
     if (doDocValues) {
       randomPerDocFieldValues((Document) doc);
     }
     if (r.nextInt(5) == 3) {
-      w.updateDocuments(t, new Iterable<Iterable<T>>() {
+      w.updateDocuments(t, new Iterable<IndexDocument>() {
 
         @Override
-        public Iterator<Iterable<T>> iterator() {
-          return new Iterator<Iterable<T>>() {
+        public Iterator<IndexDocument> iterator() {
+          return new Iterator<IndexDocument>() {
             boolean done;
             
             @Override
@@ -310,7 +310,7 @@
             }
 
             @Override
-            public Iterable<T> next() {
+            public IndexDocument next() {
               if (done) {
                 throw new IllegalStateException();
               }
diff --git a/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
index 4f365f3..05527f9 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/index/ThreadedIndexingAndSearchingTestCase.java
@@ -89,19 +89,19 @@
     return in;
   }
 
-  protected void updateDocuments(Term id, List<? extends Iterable<? extends IndexableField>> docs) throws Exception {
+  protected void updateDocuments(Term id, List<? extends IndexDocument> docs) throws Exception {
     writer.updateDocuments(id, docs);
   }
 
-  protected void addDocuments(Term id, List<? extends Iterable<? extends IndexableField>> docs) throws Exception {
+  protected void addDocuments(Term id, List<? extends IndexDocument> docs) throws Exception {
     writer.addDocuments(docs);
   }
 
-  protected void addDocument(Term id, Iterable<? extends IndexableField> doc) throws Exception {
+  protected void addDocument(Term id, IndexDocument doc) throws Exception {
     writer.addDocument(doc);
   }
 
-  protected void updateDocument(Term term, Iterable<? extends IndexableField> doc) throws Exception {
+  protected void updateDocument(Term term, IndexDocument doc) throws Exception {
     writer.updateDocument(term, doc);
   }
 
@@ -464,7 +464,7 @@
         final int inc = Math.max(1, maxDoc/50);
         for(int docID=0;docID<maxDoc;docID += inc) {
           if (liveDocs == null || liveDocs.get(docID)) {
-            final Document doc = reader.document(docID);
+            final StoredDocument doc = reader.document(docID);
             sum += doc.getFields().size();
           }
         }
@@ -564,7 +564,7 @@
               startDocID = docID;
             }
             lastDocID = docID;
-            final Document doc = s.doc(docID);
+            final StoredDocument doc = s.doc(docID);
             assertEquals(subDocs.packID, doc.get("packID"));
           }
 
diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/_TestUtil.java b/lucene/test-framework/src/java/org/apache/lucene/util/_TestUtil.java
index 22837ba..cefdb0f 100644
--- a/lucene/test-framework/src/java/org/apache/lucene/util/_TestUtil.java
+++ b/lucene/test-framework/src/java/org/apache/lucene/util/_TestUtil.java
@@ -797,7 +797,7 @@
   // TODO: is there a pre-existing way to do this!!!
   public static Document cloneDocument(Document doc1) {
     final Document doc2 = new Document();
-    for(IndexableField f : doc1) {
+    for(IndexableField f : doc1.getFields()) {
       final Field field1 = (Field) f;
       final Field field2;
       final DocValues.Type dvType = field1.fieldType().docValueType();
diff --git a/solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java b/solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java
index 88e1ce5..b8ed195 100644
--- a/solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java
+++ b/solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java
@@ -27,7 +27,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.collation.ICUCollationKeyAnalyzer;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermRangeQuery;
@@ -210,7 +212,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java b/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
index 7a5a0fa..b8411ea 100644
--- a/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
@@ -31,6 +31,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queryparser.classic.ParseException;
 import org.apache.lucene.search.*;
@@ -342,7 +343,7 @@
     
     public DocListAndSet getMoreLikeThis( int id, int start, int rows, List<Query> filters, List<InterestingTerm> terms, int flags ) throws IOException
     {
-      Document doc = reader.document(id);
+      StoredDocument doc = reader.document(id);
       rawMLTQuery = mlt.like(id);
       boostedMLTQuery = getBoostedQuery( rawMLTQuery );
       if( terms != null ) {
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
index c539724..219cdbb 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
@@ -133,7 +133,7 @@
       if( style != null && style != ShowStyle.DOC ) {
         throw new SolrException(ErrorCode.BAD_REQUEST, "missing doc param for doc style");
       }
-      Document doc = null;
+      StoredDocument doc = null;
       try {
         doc = reader.document( docId );
       }
@@ -170,7 +170,7 @@
   /**
    * @return a string representing a IndexableField's flags.  
    */
-  private static String getFieldFlags( IndexableField f )
+  private static String getFieldFlags( StorableField f )
   {
     IndexOptions opts = (f == null) ? null : f.fieldType().indexOptions();
 
@@ -239,7 +239,7 @@
     return key;
   }
 
-  private static SimpleOrderedMap<Object> getDocumentFieldsInfo( Document doc, int docId, IndexReader reader,
+  private static SimpleOrderedMap<Object> getDocumentFieldsInfo( StoredDocument doc, int docId, IndexReader reader,
                                                                  IndexSchema schema ) throws IOException
   {
     final CharsRef spare = new CharsRef();
@@ -343,13 +343,13 @@
       if(sfield != null && sfield.indexed() ) {
         // In the pre-4.0 days, this did a veeeery expensive range query. But we can be much faster now,
         // so just do this all the time.
-        Document doc = getFirstLiveDoc(reader, fieldName, terms);
+        StoredDocument doc = getFirstLiveDoc(reader, fieldName, terms);
 
 
         if( doc != null ) {
           // Found a document with this field
           try {
-            IndexableField fld = doc.getField( fieldName );
+            StorableField fld = doc.getField( fieldName );
             if( fld != null ) {
               fieldMap.add("index", getFieldFlags(fld));
             }
@@ -377,7 +377,7 @@
   // Just get a document with the term in it, the first one will do!
   // Is there a better way to do this? Shouldn't actually be very costly
   // to do it this way.
-  private static Document getFirstLiveDoc(AtomicReader reader, String fieldName, Terms terms) throws IOException {
+  private static StoredDocument getFirstLiveDoc(AtomicReader reader, String fieldName, Terms terms) throws IOException {
     DocsEnum docsEnum = null;
     TermsEnum termsEnum = terms.iterator(null);
     BytesRef text;
diff --git a/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java b/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
index 1ecdc9a..c00bd02 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
@@ -19,6 +19,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.client.solrj.SolrResponse;
@@ -167,7 +169,7 @@
 
        int docid = searcher.getFirstMatch(new Term(idField.getName(), idBytes));
        if (docid < 0) continue;
-       Document luceneDocument = searcher.doc(docid);
+       StoredDocument luceneDocument = searcher.doc(docid);
        SolrDocument doc = toSolrDoc(luceneDocument,  req.getSchema());
        if( transformer != null ) {
          transformer.transform(doc, docid);
@@ -234,7 +236,7 @@
 
         int docid = searcher.getFirstMatch(new Term(idField.getName(), idBytes));
         if (docid < 0) return null;
-        Document luceneDocument = searcher.doc(docid);
+        StoredDocument luceneDocument = searcher.doc(docid);
         sid = toSolrInputDocument(luceneDocument, core.getSchema());
       }
     } finally {
@@ -246,9 +248,9 @@
     return sid;
   }
 
-  private static SolrInputDocument toSolrInputDocument(Document doc, IndexSchema schema) {
+  private static SolrInputDocument toSolrInputDocument(StoredDocument doc, IndexSchema schema) {
     SolrInputDocument out = new SolrInputDocument();
-    for( IndexableField f : doc.getFields() ) {
+    for( StorableField f : doc.getFields() ) {
       String fname = f.name();
       SchemaField sf = schema.getFieldOrNull(f.name());
       Object val = null;
@@ -269,9 +271,9 @@
   }
 
 
-  private static SolrDocument toSolrDoc(Document doc, IndexSchema schema) {
+  private static SolrDocument toSolrDoc(StoredDocument doc, IndexSchema schema) {
     SolrDocument out = new SolrDocument();
-    for( IndexableField f : doc.getFields() ) {
+    for( StorableField f : doc.getFields() ) {
       // Make sure multivalued fields are represented as lists
       Object existing = out.get(f.name());
       if (existing == null) {
@@ -301,10 +303,10 @@
     Document doc = DocumentBuilder.toDocument(sdoc, schema);
 
     // copy the stored fields only
-    Document out = new Document();
+    StoredDocument out = new StoredDocument();
     for (IndexableField f : doc.getFields()) {
       if (f.fieldType().stored() ) {
-        out.add(f);
+        out.add((StorableField) f);
       }
     }
 
diff --git a/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java b/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
index 7527f7b..e4d9fc3 100644
--- a/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
+++ b/solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
@@ -34,6 +34,8 @@
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.highlight.*;
 import org.apache.lucene.search.vectorhighlight.BoundaryScanner;
@@ -391,7 +393,7 @@
     DocIterator iterator = docs.iterator();
     for (int i = 0; i < docs.size(); i++) {
       int docId = iterator.nextDoc();
-      Document doc = searcher.doc(docId, fset);
+      StoredDocument doc = searcher.doc(docId, fset);
       NamedList docSummaries = new SimpleOrderedMap();
       for (String fieldName : fieldNames) {
         fieldName = fieldName.trim();
@@ -423,7 +425,7 @@
   }
   
   private void doHighlightingByHighlighter( Query query, SolrQueryRequest req, NamedList docSummaries,
-      int docId, Document doc, String fieldName ) throws IOException {
+      int docId, StoredDocument doc, String fieldName ) throws IOException {
     final SolrIndexSearcher searcher = req.getSearcher();
     final IndexSchema schema = searcher.getSchema();
     
@@ -438,9 +440,9 @@
     // END: Hack
     
     SolrParams params = req.getParams(); 
-    IndexableField[] docFields = doc.getFields(fieldName);
+    StorableField[] docFields = doc.getFields(fieldName);
     List<String> listFields = new ArrayList<String>();
-    for (IndexableField field : docFields) {
+    for (StorableField field : docFields) {
       listFields.add(field.stringValue());
     }
 
@@ -545,7 +547,7 @@
   }
 
   private void doHighlightingByFastVectorHighlighter( FastVectorHighlighter highlighter, FieldQuery fieldQuery,
-      SolrQueryRequest req, NamedList docSummaries, int docId, Document doc,
+      SolrQueryRequest req, NamedList docSummaries, int docId, StoredDocument doc,
       String fieldName ) throws IOException {
     SolrParams params = req.getParams(); 
     SolrFragmentsBuilder solrFb = getSolrFragmentsBuilder( fieldName, params );
@@ -563,12 +565,12 @@
       alternateField( docSummaries, params, doc, fieldName );
   }
   
-  private void alternateField( NamedList docSummaries, SolrParams params, Document doc, String fieldName ){
+  private void alternateField( NamedList docSummaries, SolrParams params, StoredDocument doc, String fieldName ){
     String alternateField = params.getFieldParam(fieldName, HighlightParams.ALTERNATE_FIELD);
     if (alternateField != null && alternateField.length() > 0) {
-      IndexableField[] docFields = doc.getFields(alternateField);
+      StorableField[] docFields = doc.getFields(alternateField);
       List<String> listFields = new ArrayList<String>();
-      for (IndexableField field : docFields) {
+      for (StorableField field : docFields) {
         if (field.binaryValue() == null)
           listFields.add(field.stringValue());
       }
diff --git a/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java b/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
index 253548a..f38a2bd 100755
--- a/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
@@ -21,6 +21,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.params.CommonParams;
@@ -87,10 +89,10 @@
         writeResults(ctx, codec);
         return null; // null means we completely handled it
       }
-      if( o instanceof IndexableField ) {
+      if( o instanceof StorableField ) {
         if(schema == null) schema = solrQueryRequest.getSchema(); 
         
-        IndexableField f = (IndexableField)o;
+        StorableField f = (StorableField)o;
         SchemaField sf = schema.getFieldOrNull(f.name());
         try {
           o = getValue(sf, f);
@@ -138,7 +140,7 @@
       context.iterator = ids.iterator();
       for (int i = 0; i < sz; i++) {
         int id = context.iterator.nextDoc();
-        Document doc = searcher.doc(id, fnames);
+        StoredDocument doc = searcher.doc(id, fnames);
         SolrDocument sdoc = getDoc(doc);
         if( transformer != null ) {
           transformer.transform(sdoc, id);
@@ -168,9 +170,9 @@
       writeResultsBody( ctx, codec );
     }
 
-    public SolrDocument getDoc(Document doc) {
+    public SolrDocument getDoc(StoredDocument doc) {
       SolrDocument solrDoc = new SolrDocument();
-      for (IndexableField f : doc) {
+      for (StorableField f : doc) {
         String fieldName = f.name();
         if( !returnFields.wantsField(fieldName) ) 
           continue;
@@ -198,7 +200,7 @@
       return solrDoc;
     }
     
-    public Object getValue(SchemaField sf, IndexableField f) throws Exception {
+    public Object getValue(SchemaField sf, StorableField f) throws Exception {
       FieldType ft = null;
       if(sf != null) ft =sf.getType();
       
diff --git a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
index bb64aad..08630c6 100644
--- a/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
+++ b/solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
@@ -23,6 +23,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
@@ -123,8 +125,8 @@
     } else if (val instanceof String) {
       writeStr(name, val.toString(), true);
       // micro-optimization... using toString() avoids a cast first
-    } else if (val instanceof IndexableField) {
-      IndexableField f = (IndexableField)val;
+    } else if (val instanceof StorableField) {
+      StorableField f = (StorableField)val;
       SchemaField sf = schema.getFieldOrNull( f.name() );
       if( sf != null ) {
         sf.getType().write(this, name, f);
@@ -155,8 +157,8 @@
       writeBool(name, val.toString());
     } else if (val instanceof Date) {
       writeDate(name,(Date)val);
-    } else if (val instanceof Document) {
-      SolrDocument doc = toSolrDocument( (Document)val );
+    } else if (val instanceof StoredDocument) {
+      SolrDocument doc = toSolrDocument( (StoredDocument)val );
       DocTransformer transformer = returnFields.getTransformer();
       if( transformer != null ) {
         TransformContext context = new TransformContext();
@@ -224,10 +226,10 @@
     writeEndDocumentList();
   }
 
-  public final SolrDocument toSolrDocument( Document doc )
+  public final SolrDocument toSolrDocument( StoredDocument doc )
   {
     SolrDocument out = new SolrDocument();
-    for( IndexableField f : doc) {
+    for( StorableField f : doc.getFields()) {
       // Make sure multivalued fields are represented as lists
       Object existing = out.get(f.name());
       if (existing == null) {
@@ -267,7 +269,7 @@
     Set<String> fnames = fields.getLuceneFieldNames();
     for (int i=0; i<sz; i++) {
       int id = context.iterator.nextDoc();
-      Document doc = context.searcher.doc(id, fnames);
+      StoredDocument doc = context.searcher.doc(id, fnames);
       SolrDocument sdoc = toSolrDocument( doc );
       if( transformer != null ) {
         transformer.transform( sdoc, id);
diff --git a/solr/core/src/java/org/apache/solr/schema/BCDIntField.java b/solr/core/src/java/org/apache/solr/schema/BCDIntField.java
index ba49a4d..86efdf1 100644
--- a/solr/core/src/java/org/apache/solr/schema/BCDIntField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BCDIntField.java
@@ -20,7 +20,8 @@
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.GeneralField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.util.BCDUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -46,13 +47,13 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
   
   // Note, this can't return type 'Integer' because BCDStrField and BCDLong extend it
   @Override
-  public Object toObject(IndexableField f) {
+  public Object toObject(StorableField f) {
     return Integer.valueOf( toExternal(f) );
   }
 
@@ -62,7 +63,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeInt(name,toExternal(f));
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/BCDLongField.java b/solr/core/src/java/org/apache/solr/schema/BCDLongField.java
index b8f62b4..4945be2 100644
--- a/solr/core/src/java/org/apache/solr/schema/BCDLongField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BCDLongField.java
@@ -17,13 +17,13 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 /**
  *
  */
 public class BCDLongField extends BCDIntField {
   @Override
-  public Long toObject(IndexableField f) {
+  public Long toObject(StorableField f) {
     return Long.valueOf( toExternal(f) );
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/BCDStrField.java b/solr/core/src/java/org/apache/solr/schema/BCDStrField.java
index 460ba14..ab5afd2 100644
--- a/solr/core/src/java/org/apache/solr/schema/BCDStrField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BCDStrField.java
@@ -17,7 +17,7 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 /**
  *
  */
@@ -27,7 +27,7 @@
    * is not an integer, it will not survive the base10k conversion!
    */
   @Override
-  public String toObject(IndexableField f) {
+  public String toObject(StorableField f) {
     return toExternal(f);
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/BinaryField.java b/solr/core/src/java/org/apache/solr/schema/BinaryField.java
index b02ccd1..5285866 100644
--- a/solr/core/src/java/org/apache/solr/schema/BinaryField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BinaryField.java
@@ -21,7 +21,9 @@
 import java.nio.ByteBuffer;
 
 import org.apache.lucene.document.Field;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.util.Base64;
@@ -35,7 +37,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, toBase64String(toObject(f)), false);
   }
 
@@ -46,18 +48,18 @@
 
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return toBase64String(toObject(f));
   }
 
   @Override
-  public ByteBuffer toObject(IndexableField f) {
+  public ByteBuffer toObject(StorableField f) {
     BytesRef bytes = f.binaryValue();
     return  ByteBuffer.wrap(bytes.bytes, bytes.offset, bytes.length);
   }
 
   @Override
-  public IndexableField createField(SchemaField field, Object val, float boost) {
+  public StorableField createField(SchemaField field, Object val, float boost) {
     if (val == null) return null;
     if (!field.stored()) {
       log.trace("Ignoring unstored binary field: " + field);
diff --git a/solr/core/src/java/org/apache/solr/schema/BoolField.java b/solr/core/src/java/org/apache/solr/schema/BoolField.java
index 04353b5..e0ee8ec 100644
--- a/solr/core/src/java/org/apache/solr/schema/BoolField.java
+++ b/solr/core/src/java/org/apache/solr/schema/BoolField.java
@@ -18,7 +18,8 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.GeneralField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.FieldCache;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.util.BytesRef;
@@ -111,12 +112,12 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Boolean toObject(IndexableField f) {
+  public Boolean toObject(StorableField f) {
     return Boolean.valueOf( toExternal(f) );
   }
 
@@ -145,7 +146,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeBool(name, f.stringValue().charAt(0) == 'T');
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/ByteField.java b/solr/core/src/java/org/apache/solr/schema/ByteField.java
index bbcc23b..873ce7d 100644
--- a/solr/core/src/java/org/apache/solr/schema/ByteField.java
+++ b/solr/core/src/java/org/apache/solr/schema/ByteField.java
@@ -18,7 +18,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.ByteFieldSource;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 
 import org.apache.solr.response.TextResponseWriter;
@@ -65,7 +67,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -90,7 +92,7 @@
   }
 
   @Override
-  public Byte toObject(IndexableField f) {
+  public Byte toObject(StorableField f) {
     return Byte.valueOf(toExternal(f));
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/CollationField.java b/solr/core/src/java/org/apache/solr/schema/CollationField.java
index 42d7d09..77c72f0 100644
--- a/solr/core/src/java/org/apache/solr/schema/CollationField.java
+++ b/solr/core/src/java/org/apache/solr/schema/CollationField.java
@@ -31,7 +31,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.collation.CollationKeyAnalyzer;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermRangeQuery;
@@ -185,7 +187,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/CurrencyField.java b/solr/core/src/java/org/apache/solr/schema/CurrencyField.java
index d8d29f3..0a1b94f 100644
--- a/solr/core/src/java/org/apache/solr/schema/CurrencyField.java
+++ b/solr/core/src/java/org/apache/solr/schema/CurrencyField.java
@@ -17,7 +17,9 @@
  */
 
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.Query;
@@ -131,10 +133,10 @@
   }
 
   @Override
-  public IndexableField[] createFields(SchemaField field, Object externalVal, float boost) {
+  public StorableField[] createFields(SchemaField field, Object externalVal, float boost) {
     CurrencyValue value = CurrencyValue.parse(externalVal.toString(), defaultCurrency);
 
-    IndexableField[] f = new IndexableField[field.stored() ? 3 : 2];
+    StorableField[] f = new StorableField[field.stored() ? 3 : 2];
     SchemaField amountField = getAmountField(field);
     f[0] = amountField.createField(String.valueOf(value.getAmount()), amountField.indexed() && !amountField.omitNorms() ? boost : 1F);
     SchemaField currencyField = getCurrencyField(field);
@@ -237,12 +239,8 @@
     }
   }
 
-  public void write(XMLWriter xmlWriter, String name, IndexableField field) throws IOException {
-    xmlWriter.writeStr(name, field.stringValue(), false);
-  }
-
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField field) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField field) throws IOException {
     writer.writeStr(name, field.stringValue(), false);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/DateField.java b/solr/core/src/java/org/apache/solr/schema/DateField.java
index a1fd8fa..c46c46c 100644
--- a/solr/core/src/java/org/apache/solr/schema/DateField.java
+++ b/solr/core/src/java/org/apache/solr/schema/DateField.java
@@ -18,7 +18,9 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.docvalues.DocTermsIndexDocValues;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
@@ -188,7 +190,7 @@
     }
   }
 
-  public IndexableField createField(SchemaField field, Object value, float boost) {
+  public StorableField createField(SchemaField field, Object value, float boost) {
     // Convert to a string before indexing
     if(value instanceof Date) {
       value = toInternal( (Date)value ) + Z;
@@ -213,7 +215,7 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
 
@@ -222,7 +224,7 @@
   }
 
   @Override
-  public Date toObject(IndexableField f) {
+  public Date toObject(StorableField f) {
     try {
       return parseDate( toExternal(f) );
     }
@@ -237,7 +239,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeDate(name, toExternal(f));
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/DoubleField.java b/solr/core/src/java/org/apache/solr/schema/DoubleField.java
index 06ecd3c..5d2968f 100644
--- a/solr/core/src/java/org/apache/solr/schema/DoubleField.java
+++ b/solr/core/src/java/org/apache/solr/schema/DoubleField.java
@@ -19,7 +19,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.search.QParser;
@@ -62,7 +64,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -88,7 +90,7 @@
 
 
   @Override
-  public Double toObject(IndexableField f) {
+  public Double toObject(StorableField f) {
     return Double.valueOf(toExternal(f));
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java b/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
index e7f4c08..f8dac31 100755
--- a/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
+++ b/solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
@@ -18,7 +18,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.search.function.FileFloatSource;
 import org.apache.solr.search.QParser;
 import org.apache.solr.response.TextResponseWriter;
@@ -81,7 +83,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     throw new UnsupportedOperationException();
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/FieldType.java b/solr/core/src/java/org/apache/solr/schema/FieldType.java
index 962bfa0..ced6220 100644
--- a/solr/core/src/java/org/apache/solr/schema/FieldType.java
+++ b/solr/core/src/java/org/apache/solr/schema/FieldType.java
@@ -23,7 +23,9 @@
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.Query;
@@ -235,7 +237,7 @@
    *
    *
    */
-  public IndexableField createField(SchemaField field, Object value, float boost) {
+  public StorableField createField(SchemaField field, Object value, float boost) {
     if (!field.indexed() && !field.stored()) {
       if (log.isTraceEnabled())
         log.trace("Ignoring unindexed/unstored field: " + field);
@@ -272,7 +274,7 @@
    * @param boost The boost value
    * @return the {@link org.apache.lucene.index.IndexableField}.
    */
-  protected IndexableField createField(String name, String val, org.apache.lucene.document.FieldType type, float boost){
+  protected StorableField createField(String name, String val, org.apache.lucene.document.FieldType type, float boost){
     Field f = new Field(name, val, type);
     f.setBoost(boost);
     return f;
@@ -288,9 +290,9 @@
    * @see #createField(SchemaField, Object, float)
    * @see #isPolyField()
    */
-  public IndexableField[] createFields(SchemaField field, Object value, float boost) {
-    IndexableField f = createField( field, value, boost);
-    return f==null ? new IndexableField[]{} : new IndexableField[]{f};
+  public StorableField[] createFields(SchemaField field, Object value, float boost) {
+    StorableField f = createField( field, value, boost);
+    return f==null ? new StorableField[]{} : new StorableField[]{f};
   }
   protected IndexOptions getIndexOptions(SchemaField field,
                                          String internalVal) {
@@ -319,7 +321,7 @@
    * value
    * @see #toInternal
    */
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     // currently used in writing XML of the search result (but perhaps
     // a more efficient toXML(IndexableField f, Writer w) should be used
     // in the future.
@@ -331,14 +333,14 @@
    * @see #toInternal
    * @since solr 1.3
    */
-  public Object toObject(IndexableField f) {
+  public Object toObject(StorableField f) {
     return toExternal(f); // by default use the string
   }
 
   public Object toObject(SchemaField sf, BytesRef term) {
     final CharsRef ref = new CharsRef(term.length);
     indexedToReadable(term, ref);
-    final IndexableField f = createField(sf, ref.toString(), 1.0f);
+    final StorableField f = createField(sf, ref.toString(), 1.0f);
     return toObject(f);
   }
 
@@ -354,12 +356,12 @@
   }
 
   /** Given the stored field, return the human readable representation */
-  public String storedToReadable(IndexableField f) {
+  public String storedToReadable(StorableField f) {
     return toExternal(f);
   }
 
   /** Given the stored field, return the indexed form */
-  public String storedToIndexed(IndexableField f) {
+  public String storedToIndexed(StorableField f) {
     // right now, the transformation of single valued fields like SortableInt
     // is done when the Field is created, not at analysis time... this means
     // that the indexed form is the same as the stored field form.
@@ -528,7 +530,7 @@
   /**
    * calls back to TextResponseWriter to write the field value
    */
-  public abstract void write(TextResponseWriter writer, String name, IndexableField f) throws IOException;
+  public abstract void write(TextResponseWriter writer, String name, StorableField f) throws IOException;
 
 
   /**
diff --git a/solr/core/src/java/org/apache/solr/schema/FloatField.java b/solr/core/src/java/org/apache/solr/schema/FloatField.java
index 4ac8b21..75cf087 100644
--- a/solr/core/src/java/org/apache/solr/schema/FloatField.java
+++ b/solr/core/src/java/org/apache/solr/schema/FloatField.java
@@ -21,7 +21,9 @@
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.search.QParser;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.response.TextResponseWriter;
 
 import java.util.Map;
@@ -60,7 +62,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -85,7 +87,7 @@
   }
 
   @Override
-  public Float toObject(IndexableField f) {
+  public Float toObject(StorableField f) {
     return Float.valueOf( toExternal(f) );
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/GeoHashField.java b/solr/core/src/java/org/apache/solr/schema/GeoHashField.java
index 48540d8..7dd7d53 100644
--- a/solr/core/src/java/org/apache/solr/schema/GeoHashField.java
+++ b/solr/core/src/java/org/apache/solr/schema/GeoHashField.java
@@ -19,7 +19,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LiteralValueSource;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import com.spatial4j.core.context.ParseUtils;
@@ -73,14 +75,14 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f)
+  public void write(TextResponseWriter writer, String name, StorableField f)
           throws IOException {
     writer.writeStr(name, toExternal(f), false);
   }
 
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     Point p = GeohashUtils.decode(f.stringValue(),ctx);
     return p.getY() + "," + p.getX();
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
index 1767213..db6f8a5 100644
--- a/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/IndexSchema.java
@@ -20,6 +20,8 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.AnalyzerWrapper;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.Version;
 import org.apache.lucene.analysis.util.ResourceLoader;
@@ -262,8 +264,8 @@
    * the specified Document
    * @return null if this schema has no unique key field
    */
-  public String printableUniqueKey(org.apache.lucene.document.Document doc) {
-    IndexableField f = doc.getField(uniqueKeyFieldName);
+  public String printableUniqueKey(StoredDocument doc) {
+    StorableField f = doc.getField(uniqueKeyFieldName);
     return f==null ? null : uniqueKeyFieldType.toExternal(f);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/IntField.java b/solr/core/src/java/org/apache/solr/schema/IntField.java
index 20680b2..3c9320c 100644
--- a/solr/core/src/java/org/apache/solr/schema/IntField.java
+++ b/solr/core/src/java/org/apache/solr/schema/IntField.java
@@ -21,7 +21,9 @@
 import org.apache.lucene.queries.function.valuesource.IntFieldSource;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.search.QParser;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.response.TextResponseWriter;
 
 import java.util.Map;
@@ -60,7 +62,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -85,7 +87,7 @@
   }
 
   @Override
-  public Integer toObject(IndexableField f) {
+  public Integer toObject(StorableField f) {
     return Integer.valueOf( toExternal(f) );
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/LatLonType.java b/solr/core/src/java/org/apache/solr/schema/LatLonType.java
index 6a327d5..0bf8032 100644
--- a/solr/core/src/java/org/apache/solr/schema/LatLonType.java
+++ b/solr/core/src/java/org/apache/solr/schema/LatLonType.java
@@ -17,9 +17,11 @@
  */
 
 import org.apache.lucene.document.FieldType;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.VectorValueSource;
@@ -60,10 +62,10 @@
   }
 
   @Override
-  public IndexableField[] createFields(SchemaField field, Object value, float boost) {
+  public StorableField[] createFields(SchemaField field, Object value, float boost) {
     String externalVal = value.toString();
     //we could have tileDiff + 3 fields (two for the lat/lon, one for storage)
-    IndexableField[] f = new IndexableField[(field.indexed() ? 2 : 0) + (field.stored() ? 1 : 0)];
+    StorableField[] f = new StorableField[(field.indexed() ? 2 : 0) + (field.stored() ? 1 : 0)];
     if (field.indexed()) {
       int i = 0;
       double[] latLon;
@@ -244,7 +246,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), false);
   }
 
@@ -258,7 +260,7 @@
   //It never makes sense to create a single field, so make it impossible to happen
 
   @Override
-  public IndexableField createField(SchemaField field, Object value, float boost) {
+  public StorableField createField(SchemaField field, Object value, float boost) {
     throw new UnsupportedOperationException("LatLonType uses multiple fields.  field=" + field.getName());
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/LongField.java b/solr/core/src/java/org/apache/solr/schema/LongField.java
index d9e5dad..9f795a7 100644
--- a/solr/core/src/java/org/apache/solr/schema/LongField.java
+++ b/solr/core/src/java/org/apache/solr/schema/LongField.java
@@ -19,7 +19,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.search.QParser;
@@ -62,7 +64,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -87,7 +89,7 @@
   }
 
   @Override
-  public Long toObject(IndexableField f) {
+  public Long toObject(StorableField f) {
     return Long.valueOf( toExternal(f) );
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/schema/PointType.java b/solr/core/src/java/org/apache/solr/schema/PointType.java
index f59f4b5..7907ee8 100644
--- a/solr/core/src/java/org/apache/solr/schema/PointType.java
+++ b/solr/core/src/java/org/apache/solr/schema/PointType.java
@@ -20,7 +20,9 @@
 import org.apache.lucene.document.FieldType;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.VectorValueSource;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
@@ -69,7 +71,7 @@
   }
 
   @Override
-  public IndexableField[] createFields(SchemaField field, Object value, float boost) {
+  public StorableField[] createFields(SchemaField field, Object value, float boost) {
     String externalVal = value.toString();
     String[] point = new String[0];
     try {
@@ -79,7 +81,7 @@
     }
 
     // TODO: this doesn't currently support polyFields as sub-field types
-    IndexableField[] f = new IndexableField[ (field.indexed() ? dimension : 0) + (field.stored() ? 1 : 0) ];
+    StorableField[] f = new StorableField[ (field.indexed() ? dimension : 0) + (field.stored() ? 1 : 0) ];
 
     if (field.indexed()) {
       for (int i=0; i<dimension; i++) {
@@ -115,12 +117,12 @@
    *
    */
   @Override
-  public IndexableField createField(SchemaField field, Object value, float boost) {
+  public StorableField createField(SchemaField field, Object value, float boost) {
     throw new UnsupportedOperationException("PointType uses multiple fields.  field=" + field.getName());
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), false);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java b/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
index 24cdc4f..41fcd13 100644
--- a/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
+++ b/solr/core/src/java/org/apache/solr/schema/PreAnalyzedField.java
@@ -28,7 +28,9 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.util.AttributeSource;
 import org.apache.lucene.util.AttributeSource.State;
@@ -94,9 +96,9 @@
   }
 
   @Override
-  public IndexableField createField(SchemaField field, Object value,
+  public StorableField createField(SchemaField field, Object value,
           float boost) {
-    IndexableField f = null;
+    StorableField f = null;
     try {
       f = fromString(field, String.valueOf(value), boost);
     } catch (Exception e) {
@@ -112,7 +114,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f)
+  public void write(TextResponseWriter writer, String name, StorableField f)
           throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
@@ -159,7 +161,7 @@
   }
   
   
-  public IndexableField fromString(SchemaField field, String val, float boost) throws Exception {
+  public StorableField fromString(SchemaField field, String val, float boost) throws Exception {
     if (val == null || val.trim().length() == 0) {
       return null;
     }
diff --git a/solr/core/src/java/org/apache/solr/schema/RandomSortField.java b/solr/core/src/java/org/apache/solr/schema/RandomSortField.java
index e766609..0a520e5 100644
--- a/solr/core/src/java/org/apache/solr/schema/RandomSortField.java
+++ b/solr/core/src/java/org/apache/solr/schema/RandomSortField.java
@@ -20,10 +20,12 @@
 import java.io.IOException;
 import java.util.Map;
 
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.index.ReaderUtil;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.IntDocValues;
@@ -97,7 +99,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException { }
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException { }
 
 
   private static FieldComparatorSource randomComparatorSource = new FieldComparatorSource() {
diff --git a/solr/core/src/java/org/apache/solr/schema/SchemaField.java b/solr/core/src/java/org/apache/solr/schema/SchemaField.java
index c7bd130..f676679 100644
--- a/solr/core/src/java/org/apache/solr/schema/SchemaField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SchemaField.java
@@ -19,6 +19,7 @@
 
 import org.apache.solr.common.SolrException;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.search.QParser;
 
@@ -97,11 +98,11 @@
   boolean isTokenized() { return (properties & TOKENIZED)!=0; }
   boolean isBinary() { return (properties & BINARY)!=0; }
 
-  public IndexableField createField(Object val, float boost) {
+  public StorableField createField(Object val, float boost) {
     return type.createField(this,val,boost);
   }
   
-  public IndexableField[] createFields(Object val, float boost) {
+  public StorableField[] createFields(Object val, float boost) {
     return type.createFields(this,val,boost);
   }
 
@@ -123,7 +124,7 @@
       + "}";
   }
 
-  public void write(TextResponseWriter writer, String name, IndexableField val) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField val) throws IOException {
     // name is passed in because it may be null if name should not be used.
     type.write(writer,name,val);
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/ShortField.java b/solr/core/src/java/org/apache/solr/schema/ShortField.java
index 52dd913..7845609 100644
--- a/solr/core/src/java/org/apache/solr/schema/ShortField.java
+++ b/solr/core/src/java/org/apache/solr/schema/ShortField.java
@@ -18,7 +18,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.ShortFieldSource;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 
 import org.apache.solr.response.TextResponseWriter;
@@ -67,7 +69,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -92,7 +94,7 @@
   }
 
   @Override
-  public Short toObject(IndexableField f) {
+  public Short toObject(StorableField f) {
     return Short.valueOf(toExternal(f));
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java b/solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java
index 3d34125..add8e12 100644
--- a/solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java
@@ -29,7 +29,9 @@
 import org.apache.lucene.util.mutable.MutableValueDouble;
 import org.apache.solr.search.QParser;
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -70,12 +72,12 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Double toObject(IndexableField f) {
+  public Double toObject(StorableField f) {
     return NumberUtils.SortableStr2double(f.stringValue());
   }
   
@@ -94,7 +96,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeDouble(name, NumberUtils.SortableStr2double(sval));
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/SortableFloatField.java b/solr/core/src/java/org/apache/solr/schema/SortableFloatField.java
index f99b2b5..6b77ec8 100644
--- a/solr/core/src/java/org/apache/solr/schema/SortableFloatField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SortableFloatField.java
@@ -29,7 +29,9 @@
 import org.apache.lucene.util.mutable.MutableValueFloat;
 import org.apache.solr.search.QParser;
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -71,12 +73,12 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Float toObject(IndexableField f) {
+  public Float toObject(StorableField f) {
     return NumberUtils.SortableStr2float(f.stringValue());
   }
   
@@ -94,7 +96,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeFloat(name, NumberUtils.SortableStr2float(sval));
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/SortableIntField.java b/solr/core/src/java/org/apache/solr/schema/SortableIntField.java
index 7c45394..e921f1a 100644
--- a/solr/core/src/java/org/apache/solr/schema/SortableIntField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SortableIntField.java
@@ -29,7 +29,9 @@
 import org.apache.lucene.util.mutable.MutableValueInt;
 import org.apache.solr.search.QParser;
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -74,7 +76,7 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
 
@@ -92,12 +94,12 @@
   }
 
   @Override
-  public Integer toObject(IndexableField f) {
+  public Integer toObject(StorableField f) {
     return NumberUtils.SortableStr2int(f.stringValue(), 0, 3);    
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeInt(name, NumberUtils.SortableStr2int(sval,0,sval.length()));
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/SortableLongField.java b/solr/core/src/java/org/apache/solr/schema/SortableLongField.java
index 39ce59f..8ebf7de 100644
--- a/solr/core/src/java/org/apache/solr/schema/SortableLongField.java
+++ b/solr/core/src/java/org/apache/solr/schema/SortableLongField.java
@@ -29,7 +29,9 @@
 import org.apache.lucene.util.mutable.MutableValueLong;
 import org.apache.solr.search.QParser;
 import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -83,17 +85,17 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Long toObject(IndexableField f) {
+  public Long toObject(StorableField f) {
     return NumberUtils.SortableStr2long(f.stringValue(),0,5);
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeLong(name, NumberUtils.SortableStr2long(sval,0,sval.length()));
   }
diff --git a/solr/core/src/java/org/apache/solr/schema/StrField.java b/solr/core/src/java/org/apache/solr/schema/StrField.java
index 2590737..a6e8165 100644
--- a/solr/core/src/java/org/apache/solr/schema/StrField.java
+++ b/solr/core/src/java/org/apache/solr/schema/StrField.java
@@ -19,7 +19,9 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.search.QParser;
@@ -35,7 +37,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/TextField.java b/solr/core/src/java/org/apache/solr/schema/TextField.java
index b294988..4529c41 100644
--- a/solr/core/src/java/org/apache/solr/schema/TextField.java
+++ b/solr/core/src/java/org/apache/solr/schema/TextField.java
@@ -19,7 +19,9 @@
 
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.search.*;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
@@ -98,7 +100,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/TrieDateField.java b/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
index fe797e5..fddcdbb 100755
--- a/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
+++ b/solr/core/src/java/org/apache/solr/schema/TrieDateField.java
@@ -20,7 +20,9 @@
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.solr.search.QParser;
 import org.apache.solr.response.TextResponseWriter;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.NumericRangeQuery;
@@ -45,7 +47,7 @@
   }
 
   @Override
-  public Date toObject(IndexableField f) {
+  public Date toObject(StorableField f) {
     return (Date) wrappedField.toObject(f);
   }
 
@@ -73,7 +75,7 @@
 
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     wrappedField.write(writer, name, f);
   }
 
@@ -88,7 +90,7 @@
   }
 
   @Override
-  public String storedToReadable(IndexableField f) {
+  public String storedToReadable(StorableField f) {
     return wrappedField.storedToReadable(f);
   }
 
@@ -103,7 +105,7 @@
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return wrappedField.toExternal(f);
   }
 
@@ -118,12 +120,12 @@
   }
 
   @Override
-  public String storedToIndexed(IndexableField f) {
+  public String storedToIndexed(StorableField f) {
     return wrappedField.storedToIndexed(f);
   }
 
   @Override
-  public IndexableField createField(SchemaField field, Object value, float boost) {
+  public StorableField createField(SchemaField field, Object value, float boost) {
     return wrappedField.createField(field, value, boost);
   }
 
diff --git a/solr/core/src/java/org/apache/solr/schema/TrieField.java b/solr/core/src/java/org/apache/solr/schema/TrieField.java
index e03f2ef..77d29b7 100644
--- a/solr/core/src/java/org/apache/solr/schema/TrieField.java
+++ b/solr/core/src/java/org/apache/solr/schema/TrieField.java
@@ -29,7 +29,9 @@
 import org.apache.lucene.document.FloatField;
 import org.apache.lucene.document.IntField;
 import org.apache.lucene.document.LongField;
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
 import org.apache.lucene.queries.function.valuesource.FloatFieldSource;
@@ -112,7 +114,7 @@
   }
 
   @Override
-  public Object toObject(IndexableField f) {
+  public Object toObject(StorableField f) {
     final Number val = f.numericValue();
     if (val != null) {
       return (type == TrieTypes.DATE) ? new Date(val.longValue()) : val;
@@ -209,7 +211,7 @@
 
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
+  public void write(TextResponseWriter writer, String name, StorableField f) throws IOException {
     writer.writeVal(name, toObject(f));
   }
 
@@ -292,7 +294,7 @@
   }
 
   @Override
-  public String storedToReadable(IndexableField f) {
+  public String storedToReadable(StorableField f) {
     return toExternal(f);
   }
 
@@ -333,13 +335,13 @@
     return readableToIndexed(val);
   }
 
-  static String badFieldString(IndexableField f) {
+  static String badFieldString(StorableField f) {
     String s = f.stringValue();
     return "ERROR:SCHEMA-INDEX-MISMATCH,stringValue="+s;
   }
 
   @Override
-  public String toExternal(IndexableField f) {
+  public String toExternal(StorableField f) {
     return (type == TrieTypes.DATE)
       ? dateField.toExternal((Date) toObject(f)) 
       : toObject(f).toString();
@@ -411,7 +413,7 @@
   }
 
   @Override
-  public String storedToIndexed(IndexableField f) {
+  public String storedToIndexed(StorableField f) {
     final BytesRef bytes = new BytesRef(NumericUtils.BUF_SIZE_LONG);
     final Number val = f.numericValue();
     if (val != null) {
@@ -471,7 +473,7 @@
   }
   
   @Override
-  public IndexableField createField(SchemaField field, Object value, float boost) {
+  public StorableField createField(SchemaField field, Object value, float boost) {
     boolean indexed = field.indexed();
     boolean stored = field.stored();
 
diff --git a/solr/core/src/java/org/apache/solr/schema/UUIDField.java b/solr/core/src/java/org/apache/solr/schema/UUIDField.java
index d6a297e..df45a70 100644
--- a/solr/core/src/java/org/apache/solr/schema/UUIDField.java
+++ b/solr/core/src/java/org/apache/solr/schema/UUIDField.java
@@ -22,7 +22,9 @@
 import java.util.Map;
 import java.util.UUID;
 
+import org.apache.lucene.index.GeneralField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.response.TextResponseWriter;
@@ -53,7 +55,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, IndexableField f)
+  public void write(TextResponseWriter writer, String name, StorableField f)
       throws IOException {
     writer.writeStr(name, f.stringValue(), false);
   }
@@ -88,7 +90,7 @@
   }
 
   @Override
-  public UUID toObject(IndexableField f) {
+  public UUID toObject(StorableField f) {
     return UUID.fromString(f.stringValue());
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/search/Grouping.java b/solr/core/src/java/org/apache/solr/search/Grouping.java
index 0d4c612..c735dad 100755
--- a/solr/core/src/java/org/apache/solr/search/Grouping.java
+++ b/solr/core/src/java/org/apache/solr/search/Grouping.java
@@ -19,6 +19,7 @@
 
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.queries.function.FunctionQuery;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.QueryValueSource;
@@ -787,7 +788,7 @@
           SchemaField schemaField = searcher.getSchema().getField(groupBy);
           FieldType fieldType = schemaField.getType();
           String readableValue = fieldType.indexedToReadable(group.groupValue.utf8ToString());
-          IndexableField field = schemaField.createField(readableValue, 1.0f);
+          StorableField field = schemaField.createField(readableValue, 1.0f);
           nl.add("groupValue", fieldType.toObject(field));
         } else {
           nl.add("groupValue", null);
diff --git a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
index 5aad32f..e51d43b 100644
--- a/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
+++ b/solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
@@ -95,7 +95,7 @@
   private final boolean cachingEnabled;
   private final SolrCache<Query,DocSet> filterCache;
   private final SolrCache<QueryResultKey,DocList> queryResultCache;
-  private final SolrCache<Integer,Document> documentCache;
+  private final SolrCache<Integer,StoredDocument> documentCache;
   private final SolrCache<String,UnInvertedField> fieldValueCache;
 
   private final LuceneQueryOptimizer optimizer;
@@ -433,7 +433,7 @@
   // need to open up access to its Document...
   static class SetNonLazyFieldSelector extends StoredFieldVisitor {
     private Set<String> fieldsToLoad;
-    final Document doc = new Document();
+    final StoredDocument doc = new StoredDocument();
     final LazyDocument lazyDoc;
 
     SetNonLazyFieldSelector(Set<String> toLoad, IndexReader reader, int docID) {
@@ -502,7 +502,7 @@
    * Retrieve the {@link Document} instance corresponding to the document id.
    */
   @Override
-  public Document doc(int i) throws IOException {
+  public StoredDocument doc(int i) throws IOException {
     return doc(i, (Set<String>)null);
   }
 
@@ -522,9 +522,9 @@
    * filter is provided, only the provided fields will be loaded (the 
    * remainder will be available lazily).
    */
-  public Document doc(int i, Set<String> fields) throws IOException {
+  public StoredDocument doc(int i, Set<String> fields) throws IOException {
     
-    Document d;
+    StoredDocument d;
     if (documentCache != null) {
       d = documentCache.get(i);
       if (d!=null) return d;
@@ -549,14 +549,14 @@
    * Takes a list of docs (the doc ids actually), and reads them into an array 
    * of Documents.
    */
-  public void readDocs(Document[] docs, DocList ids) throws IOException {
+  public void readDocs(StoredDocument[] docs, DocList ids) throws IOException {
     readDocs(docs, ids, null);
   }
   /**
    * Takes a list of docs (the doc ids actually) and a set of fields to load,
    * and reads them into an array of Documents.
    */
-  public void readDocs(Document[] docs, DocList ids, Set<String> fields) throws IOException {
+  public void readDocs(StoredDocument[] docs, DocList ids, Set<String> fields) throws IOException {
     DocIterator iter = ids.iterator();
     for (int i=0; i<docs.length; i++) {
       docs[i] = doc(iter.nextDoc(), fields);
@@ -1893,8 +1893,8 @@
    * Takes a list of docs (the doc ids actually), and returns an array 
    * of Documents containing all of the stored fields.
    */
-  public Document[] readDocs(DocList ids) throws IOException {
-     Document[] docs = new Document[ids.size()];
+  public StoredDocument[] readDocs(DocList ids) throws IOException {
+     StoredDocument[] docs = new StoredDocument[ids.size()];
      readDocs(docs,ids);
      return docs;
   }
diff --git a/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java b/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
index 710370a..fd04290 100644
--- a/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
+++ b/solr/core/src/java/org/apache/solr/search/grouping/distributed/shardresultserializer/TopGroupsResultTransformer.java
@@ -19,6 +19,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.DocumentStoredFieldVisitor;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.search.FieldDoc;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.Sort;
@@ -179,7 +180,7 @@
         NamedList<Object> document = new NamedList<Object>();
         documents.add(document);
 
-        Document doc = retrieveDocument(uniqueField, searchGroup.scoreDocs[i].doc);
+        StoredDocument doc = retrieveDocument(uniqueField, searchGroup.scoreDocs[i].doc);
         document.add("id", uniqueField.getType().toExternal(doc.getField(uniqueField.getName())));
         if (!Float.isNaN(searchGroup.scoreDocs[i].score))  {
           document.add("score", searchGroup.scoreDocs[i].score);
@@ -232,7 +233,7 @@
       NamedList<Object> document = new NamedList<Object>();
       documents.add(document);
 
-      Document doc = retrieveDocument(uniqueField, scoreDoc.doc);
+      StoredDocument doc = retrieveDocument(uniqueField, scoreDoc.doc);
       document.add("id", uniqueField.getType().toExternal(doc.getField(uniqueField.getName())));
       if (rb.getGroupingSpec().isNeedScore())  {
         document.add("score", scoreDoc.score);
@@ -265,7 +266,7 @@
     return queryResult;
   }
 
-  private Document retrieveDocument(final SchemaField uniqueField, int doc) throws IOException {
+  private StoredDocument retrieveDocument(final SchemaField uniqueField, int doc) throws IOException {
     DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(uniqueField.getName());
     rb.req.getSearcher().doc(doc, visitor);
     return visitor.getDocument();
diff --git a/solr/core/src/java/org/apache/solr/update/DocumentBuilder.java b/solr/core/src/java/org/apache/solr/update/DocumentBuilder.java
index f17cf9d..236491a 100644
--- a/solr/core/src/java/org/apache/solr/update/DocumentBuilder.java
+++ b/solr/core/src/java/org/apache/solr/update/DocumentBuilder.java
@@ -22,7 +22,10 @@
 import java.util.List;
 
 import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StoredField;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
@@ -56,7 +59,7 @@
     // might actually want to map it to something.  If createField()
     // returns null, then we don't store the field.
     if (sfield.isPolyField()) {
-      IndexableField[] fields = sfield.createFields(val, boost);
+      StorableField[] fields = sfield.createFields(val, boost);
       if (fields.length > 0) {
         if (!sfield.multiValued()) {
           String oldValue = map.put(sfield.getName(), val);
@@ -66,12 +69,12 @@
           }
         }
         // Add each field
-        for (IndexableField field : fields) {
-          doc.add(field);
+        for (StorableField field : fields) {
+          doc.add((Field) field);
         }
       }
     } else {
-      IndexableField field = sfield.createField(val, boost);
+      StorableField field = sfield.createField(val, boost);
       if (field != null) {
         if (!sfield.multiValued()) {
           String oldValue = map.put(sfield.getName(), val);
@@ -81,7 +84,7 @@
           }
         }
       }
-      doc.add(field);
+      doc.add((Field) field);
     }
 
   }
@@ -190,13 +193,13 @@
 
   private static void addField(Document doc, SchemaField field, Object val, float boost) {
     if (field.isPolyField()) {
-      IndexableField[] farr = field.getType().createFields(field, val, boost);
-      for (IndexableField f : farr) {
-        if (f != null) doc.add(f); // null fields are not added
+      StorableField[] farr = field.getType().createFields(field, val, boost);
+      for (StorableField f : farr) {
+        if (f != null) doc.add((Field) f); // null fields are not added
       }
     } else {
-      IndexableField f = field.createField(val, boost);
-      if (f != null) doc.add(f);  // null fields are not added
+      StorableField f = field.createField(val, boost);
+      if (f != null) doc.add((Field) f);  // null fields are not added
     }
   }
   
diff --git a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
index 3b35ba9..5053124 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrPluginUtils.java
@@ -19,6 +19,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.queryparser.classic.ParseException;
 import org.apache.lucene.queryparser.classic.QueryParser;
 import org.apache.lucene.search.*;
@@ -332,7 +334,7 @@
     for (int i=0; i<docs.size(); i++) {
       int id = iterator.nextDoc();
 
-      Document doc = searcher.doc(id);
+      StoredDocument doc = searcher.doc(id);
       String strid = schema.printableUniqueKey(doc);
 
       explainList.add(strid, searcher.explain(query, id) );
@@ -848,10 +850,10 @@
     while (dit.hasNext()) {
       int docid = dit.nextDoc();
 
-      Document luceneDoc = searcher.doc(docid, fields);
+      StoredDocument luceneDoc = searcher.doc(docid, fields);
       SolrDocument doc = new SolrDocument();
       
-      for( IndexableField field : luceneDoc) {
+      for( StorableField field : luceneDoc) {
         if (null == fields || fields.contains(field.name())) {
           SchemaField sf = schema.getField( field.name() );
           doc.addField( field.name(), sf.getType().toObject( field ) );
diff --git a/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java b/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
index 7ed637b..9e4964d 100644
--- a/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
+++ b/solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
@@ -33,6 +33,8 @@
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.LogMergePolicy;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.util.English;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
@@ -419,7 +421,7 @@
     
     IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile(), null);
     SchemaField f; // Solr field type
-    IndexableField luf; // Lucene field
+    StorableField luf; // Lucene field
 
     f = ischema.getField("test_basictv");
     luf = f.createField("test", 0f);
@@ -621,7 +623,7 @@
     core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
 
     DocList dl = ((ResultContext) rsp.getValues().get("response")).docs;
-    Document d = req.getSearcher().doc(dl.iterator().nextDoc());
+    StoredDocument d = req.getSearcher().doc(dl.iterator().nextDoc());
     // ensure field is not lazy, only works for Non-Numeric fields currently (if you change schema behind test, this may fail)
     assertFalse( ((Field) d.getField("test_hlt")).getClass().getSimpleName().equals("LazyField"));
     assertFalse( ((Field) d.getField("title")).getClass().getSimpleName().equals("LazyField"));
@@ -644,7 +646,7 @@
 
     DocList dl = ((ResultContext) rsp.getValues().get("response")).docs;
     DocIterator di = dl.iterator();    
-    Document d = req.getSearcher().doc(di.nextDoc());
+    StoredDocument d = req.getSearcher().doc(di.nextDoc());
     // ensure field is lazy
     assertTrue( (d.getField("test_hlt")).getClass().getSimpleName().equals("LazyField"));
     assertFalse( (d.getField("title")).getClass().getSimpleName().equals("LazyField"));
diff --git a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTest.java b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTest.java
index d698e70..9c34edb 100644
--- a/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/CurrencyFieldTest.java
@@ -17,6 +17,7 @@
  */
 
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.core.SolrCore;
 import org.junit.BeforeClass;
@@ -71,7 +72,7 @@
     FieldType tmp = amount.getType();
     assertTrue(tmp instanceof CurrencyField);
     String currencyValue = "1.50,EUR";
-    IndexableField[] fields = amount.createFields(currencyValue, 2);
+    StorableField[] fields = amount.createFields(currencyValue, 2);
     assertEquals(fields.length, 3);
 
     // First field is currency code, second is value, third is stored.
diff --git a/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java b/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
index 847dae1..4f8a534 100644
--- a/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
@@ -19,6 +19,7 @@
 
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.util.DateMathParser;
 
@@ -207,7 +208,7 @@
   public void testCreateField() {
     int props = FieldProperties.INDEXED ^ FieldProperties.STORED;
     SchemaField sf = new SchemaField( "test", f, props, null );
-    IndexableField out = f.createField(sf, "1995-12-31T23:59:59Z", 1.0f );
+    StorableField out = f.createField(sf, "1995-12-31T23:59:59Z", 1.0f );
     assertEquals(820454399000l, f.toObject( out ).getTime() );
     
     out = f.createField(sf, new Date(820454399000l), 1.0f );
diff --git a/solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java b/solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java
index ee02388..87973e3 100644
--- a/solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java
+++ b/solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java
@@ -18,6 +18,7 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StorableField;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
@@ -83,7 +84,7 @@
     assertEquals(pt.getDimension(), 2);
     double[] xy = new double[]{35.0, -79.34};
     String point = xy[0] + "," + xy[1];
-    IndexableField[] fields = home.createFields(point, 2);
+    StorableField[] fields = home.createFields(point, 2);
     assertEquals(fields.length, 3);//should be 3, we have a stored field
     //first two fields contain the values, third is just stored and contains the original
     for (int i = 0; i < 3; i++) {
diff --git a/solr/core/src/test/org/apache/solr/search/TestStressLucene.java b/solr/core/src/test/org/apache/solr/search/TestStressLucene.java
index 55b8787..38809f5 100644
--- a/solr/core/src/test/org/apache/solr/search/TestStressLucene.java
+++ b/solr/core/src/test/org/apache/solr/search/TestStressLucene.java
@@ -25,6 +25,7 @@
 import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.StoredDocument;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.store.Directory;
@@ -338,7 +339,7 @@
                   verbose("ERROR: Couldn't find a doc for id", id, "using reader",r);
                 }
                 assertTrue(docid >= 0);   // we should have found the document, or it's tombstone
-                Document doc = r.document(docid);
+                StoredDocument doc = r.document(docid);
                 long foundVal = Long.parseLong(doc.get(field));
                 if (foundVal < Math.abs(val)) {
                   verbose("ERROR: id",id,"model_val=",val," foundVal=",foundVal,"reader=",reader);