Index: solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/schema/PolyFieldTest.java	(working copy)
@@ -16,8 +16,8 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.queries.function.ValueSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
@@ -83,12 +83,12 @@
     assertEquals(pt.getDimension(), 2);
     double[] xy = new double[]{35.0, -79.34};
     String point = xy[0] + "," + xy[1];
-    Fieldable[] fields = home.createFields(point, 2);
+    IndexableField[] 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++) {
       boolean hasValue = fields[1].tokenStreamValue() != null
-              || fields[1].getBinaryValue() != null
+              || fields[1].binaryValue() != null
               || fields[1].stringValue() != null;
       assertTrue("Doesn't have a value: " + fields[1], hasValue);
     }
Index: solr/core/src/test/org/apache/solr/schema/DateFieldTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/schema/DateFieldTest.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/schema/DateFieldTest.java	(working copy)
@@ -18,7 +18,7 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.schema.DateField;
 import org.apache.solr.util.DateMathParser;
@@ -119,7 +119,7 @@
   public void testCreateField() {
     int props = FieldProperties.INDEXED ^ FieldProperties.STORED;
     SchemaField sf = new SchemaField( "test", f, props, null );
-    Fieldable out = (Field)f.createField(sf, "1995-12-31T23:59:59Z", 1.0f );
+    IndexableField out = (Field)f.createField(sf, "1995-12-31T23:59:59Z", 1.0f );
     assertEquals(820454399000l, f.toObject( out ).getTime() );
     
     out = (Field)f.createField(sf, new Date(820454399000l), 1.0f );
Index: solr/core/src/test/org/apache/solr/search/TestSort.java
===================================================================
--- solr/core/src/test/org/apache/solr/search/TestSort.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/search/TestSort.java	(working copy)
@@ -17,9 +17,13 @@
 
 package org.apache.solr.search;
 
+import java.io.IOException;
+import java.util.*;
+
 import org.apache.lucene.analysis.core.SimpleAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -29,16 +33,10 @@
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.util.OpenBitSet;
 import org.apache.lucene.util._TestUtil;
-
-import org.apache.solr.request.SolrQueryRequest;
-
 import org.apache.solr.SolrTestCaseJ4;
-
+import org.apache.solr.request.SolrQueryRequest;
 import org.junit.BeforeClass;
 
-import java.io.IOException;
-import java.util.*;
-
 public class TestSort extends SolrTestCaseJ4 {
   @BeforeClass
   public static void beforeClass() throws Exception {
@@ -152,8 +150,8 @@
 
   public void testSort() throws Exception {
     Directory dir = new RAMDirectory();
-    Field f = new Field("f","0", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS);
-    Field f2 = new Field("f2","0", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS);
+    Field f = new Field("f",StringField.TYPE_UNSTORED,"0");
+    Field f2 = new Field("f2",StringField.TYPE_UNSTORED,"0");
 
     for (int iterCnt = 0; iterCnt<iter; iterCnt++) {
       IndexWriter iw = new IndexWriter(
Index: solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java	(working copy)
@@ -26,9 +26,11 @@
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 
+import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.document.FieldSelectorVisitor;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.LogMergePolicy;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.AppendedSolrParams;
@@ -357,32 +359,32 @@
     
     IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile(), null);
     SchemaField f; // Solr field type
-    Fieldable luf; // Lucene field
+    IndexableField luf; // Lucene field
 
     f = ischema.getField("test_basictv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector());
-    assertTrue(luf.isTermVectorStored());
+    assertTrue(luf.storeTermVectors());
 
     f = ischema.getField("test_notv");
     luf = f.createField("test", 0f);
     assertTrue(!f.storeTermVector());
-    assertTrue(!luf.isTermVectorStored());    
+    assertTrue(!luf.storeTermVectors());    
 
     f = ischema.getField("test_postv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector() && f.storeTermPositions());
-    assertTrue(luf.isStorePositionWithTermVector());
+    assertTrue(luf.storeTermVectorPositions());
 
     f = ischema.getField("test_offtv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector() && f.storeTermOffsets());
-    assertTrue(luf.isStoreOffsetWithTermVector());
+    assertTrue(luf.storeTermVectorOffsets());
 
     f = ischema.getField("test_posofftv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector() && f.storeTermPositions() && f.storeTermOffsets());
-    assertTrue(luf.isStoreOffsetWithTermVector() && luf.isStorePositionWithTermVector());
+    assertTrue(luf.storeTermVectorOffsets() && luf.storeTermVectorPositions());
 
   }
 
@@ -554,15 +556,15 @@
     assertU(commit());
     SolrCore core = h.getCore();
    
-    SolrQueryRequest req = req("q", "title:keyword", "fl", "id,title,test_hlt");
+    SolrQueryRequest req = req("q", "title:keyword" , "fl", "id,title,test_hlt");
     SolrQueryResponse rsp = new SolrQueryResponse();
     core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
 
     DocList dl = ((ResultContext) rsp.getValues().get("response")).docs;
-    org.apache.lucene.document.Document d = req.getSearcher().doc(dl.iterator().nextDoc());
+    Document 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)
-    assertTrue( d.getFieldable("test_hlt") instanceof Field );
-    assertTrue( d.getFieldable("title") instanceof Field );
+    assertFalse( ((Field) d.getField("test_hlt")).getClass().getSimpleName().equals("LazyField"));
+    assertFalse( ((Field) d.getField("title")).getClass().getSimpleName().equals("LazyField"));
     req.close();
   }
 
@@ -582,10 +584,11 @@
 
     DocList dl = ((ResultContext) rsp.getValues().get("response")).docs;
     DocIterator di = dl.iterator();    
-    org.apache.lucene.document.Document d = req.getSearcher().doc(di.nextDoc());
+    Document d = req.getSearcher().doc(di.nextDoc());
     // ensure field is lazy
-    assertTrue( !( d.getFieldable("test_hlt") instanceof Field ) );
-    assertTrue( d.getFieldable("title") instanceof Field );
+    System.out.println(d.getField("test_hlt").getClass());
+    assertTrue( ((Field) d.getField("test_hlt")).getClass().getSimpleName().equals("LazyField"));
+    assertFalse( ((Field) d.getField("title")).getClass().getSimpleName().equals("LazyField"));
     req.close();
   } 
             
Index: solr/core/src/test/org/apache/solr/spelling/IndexBasedSpellCheckerTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/spelling/IndexBasedSpellCheckerTest.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/spelling/IndexBasedSpellCheckerTest.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -289,7 +290,7 @@
     );
     for (int i = 0; i < ALT_DOCS.length; i++) {
       Document doc = new Document();
-      doc.add(new Field("title", ALT_DOCS[i], Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(new Field("title", TextField.TYPE_STORED, ALT_DOCS[i]));
       iw.addDocument(doc);
     }
     iw.optimize();
Index: solr/core/src/test/org/apache/solr/update/DocumentBuilderTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/update/DocumentBuilderTest.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/update/DocumentBuilderTest.java	(working copy)
@@ -109,8 +109,8 @@
     doc.addField( "home", "2.2,3.3", 1.0f );
     Document out = DocumentBuilder.toDocument( doc, core.getSchema() );
     assertNotNull( out.get( "home" ) );//contains the stored value and term vector, if there is one
-    assertNotNull( out.getFieldable( "home_0" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
-    assertNotNull( out.getFieldable( "home_1" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
+    assertNotNull( out.getField( "home_0" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
+    assertNotNull( out.getField( "home_1" + FieldType.POLY_FIELD_SEPARATOR + "double" ) );
   }
 
 }
Index: solr/core/src/test/org/apache/solr/update/TestIndexingPerformance.java
===================================================================
--- solr/core/src/test/org/apache/solr/update/TestIndexingPerformance.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/update/TestIndexingPerformance.java	(working copy)
@@ -19,7 +19,6 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.schema.IndexSchema;
Index: solr/core/src/test/org/apache/solr/core/TestArbitraryIndexDir.java
===================================================================
--- solr/core/src/test/org/apache/solr/core/TestArbitraryIndexDir.java	(revision 1158028)
+++ solr/core/src/test/org/apache/solr/core/TestArbitraryIndexDir.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.queryparser.classic.ParseException;
@@ -105,8 +106,8 @@
         new IndexWriterConfig(Version.LUCENE_40, new StandardAnalyzer(Version.LUCENE_40))
     );
     Document doc = new Document();
-    doc.add(new Field("id", "2", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("name", "name2", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("id", TextField.TYPE_STORED, "2"));
+    doc.add(new Field("name", TextField.TYPE_STORED, "name2"));
     iw.addDocument(doc);
     iw.commit();
     iw.close();
Index: solr/core/src/java/org/apache/solr/schema/TrieField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/TrieField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/TrieField.java	(working copy)
@@ -16,9 +16,11 @@
  */
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.*;
+import org.apache.lucene.search.cache.CachedArrayCreator;
+import org.apache.lucene.search.cache.DoubleValuesCreator;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
@@ -108,26 +110,26 @@
   }
 
   @Override
-  public Object toObject(Fieldable f) {
+  public Object toObject(IndexableField f) {
     if (f instanceof NumericField) {
-      final Number val = ((NumericField) f).getNumericValue();
+      final Number val = ((NumericField) f).numericValue();
       if (val==null) return badFieldString(f);
       return (type == TrieTypes.DATE) ? new Date(val.longValue()) : val;
     } else {
       // the following code is "deprecated" and only to support pre-3.2 indexes using the old BinaryField encoding:
-      final byte[] arr = f.getBinaryValue();
-      if (arr==null) return badFieldString(f);
+      final BytesRef bytes = f.binaryValue();
+      if (bytes==null) return badFieldString(f);
       switch (type) {
         case INTEGER:
-          return toInt(arr);
+          return toInt(bytes.bytes, bytes.offset);
         case FLOAT:
-          return Float.intBitsToFloat(toInt(arr));
+          return Float.intBitsToFloat(toInt(bytes.bytes, bytes.offset));
         case LONG:
-          return toLong(arr);
+          return toLong(bytes.bytes, bytes.offset);
         case DOUBLE:
-          return Double.longBitsToDouble(toLong(arr));
+          return Double.longBitsToDouble(toLong(bytes.bytes, bytes.offset));
         case DATE:
-          return new Date(toLong(arr));
+          return new Date(toLong(bytes.bytes, bytes.offset));
         default:
           throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + f.name());
       }
@@ -212,7 +214,7 @@
 
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeVal(name, toObject(f));
   }
 
@@ -283,19 +285,19 @@
   }
 
   @Deprecated
-  static int toInt(byte[] arr) {
-    return (arr[0]<<24) | ((arr[1]&0xff)<<16) | ((arr[2]&0xff)<<8) | (arr[3]&0xff);
+  static int toInt(byte[] arr, int offset) {
+    return (arr[offset]<<24) | ((arr[offset+1]&0xff)<<16) | ((arr[offset+2]&0xff)<<8) | (arr[offset+3]&0xff);
   }
   
   @Deprecated
-  static long toLong(byte[] arr) {
-    int high = (arr[0]<<24) | ((arr[1]&0xff)<<16) | ((arr[2]&0xff)<<8) | (arr[3]&0xff);
-    int low = (arr[4]<<24) | ((arr[5]&0xff)<<16) | ((arr[6]&0xff)<<8) | (arr[7]&0xff);
+  static long toLong(byte[] arr, int offset) {
+    int high = (arr[offset]<<24) | ((arr[offset+1]&0xff)<<16) | ((arr[offset+2]&0xff)<<8) | (arr[offset+3]&0xff);
+    int low = (arr[offset+4]<<24) | ((arr[offset+5]&0xff)<<16) | ((arr[offset+6]&0xff)<<8) | (arr[offset+7]&0xff);
     return (((long)high)<<32) | (low&0x0ffffffffL);
   }
 
   @Override
-  public String storedToReadable(Fieldable f) {
+  public String storedToReadable(IndexableField f) {
     return toExternal(f);
   }
 
@@ -336,14 +338,13 @@
     return readableToIndexed(val);
   }
 
-
-  static String badFieldString(Fieldable f) {
+  static String badFieldString(IndexableField f) {
     String s = f.stringValue();
     return "ERROR:SCHEMA-INDEX-MISMATCH,stringValue="+s;
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return (type == TrieTypes.DATE)
       ? dateField.toExternal((Date) toObject(f)) 
       : toObject(f).toString();
@@ -413,10 +414,10 @@
   }
 
   @Override
-  public String storedToIndexed(Fieldable f) {
+  public String storedToIndexed(IndexableField f) {
     final BytesRef bytes = new BytesRef(NumericUtils.BUF_SIZE_LONG);
-    if (f instanceof NumericField) {
-      final Number val = ((NumericField) f).getNumericValue();
+    if (f instanceof org.apache.lucene.document.NumericField) {
+      final Number val = ((org.apache.lucene.document.NumericField) f).numericValue();
       if (val==null)
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Invalid field contents: "+f.name());
       switch (type) {
@@ -438,31 +439,31 @@
       }
     } else {
       // the following code is "deprecated" and only to support pre-3.2 indexes using the old BinaryField encoding:
-      final byte[] arr = f.getBinaryValue();
-      if (arr==null)
+      final BytesRef bytesRef = f.binaryValue();
+      if (bytesRef==null)
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Invalid field contents: "+f.name());
       switch (type) {
         case INTEGER:
-          NumericUtils.intToPrefixCoded(toInt(arr), 0, bytes);
+          NumericUtils.intToPrefixCoded(toInt(bytesRef.bytes, bytesRef.offset), 0, bytes);
           break;
         case FLOAT: {
           // WARNING: Code Duplication! Keep in sync with o.a.l.util.NumericUtils!
           // copied from NumericUtils to not convert to/from float two times
           // code in next 2 lines is identical to: int v = NumericUtils.floatToSortableInt(Float.intBitsToFloat(toInt(arr)));
-          int v = toInt(arr);
+          int v = toInt(bytesRef.bytes, bytesRef.offset);
           if (v<0) v ^= 0x7fffffff;
           NumericUtils.intToPrefixCoded(v, 0, bytes);
           break;
         }
         case LONG: //fallthrough!
         case DATE:
-          NumericUtils.longToPrefixCoded(toLong(arr), 0, bytes);
+          NumericUtils.longToPrefixCoded(toLong(bytesRef.bytes, bytesRef.offset), 0, bytes);
           break;
         case DOUBLE: {
           // WARNING: Code Duplication! Keep in sync with o.a.l.util.NumericUtils!
           // copied from NumericUtils to not convert to/from double two times
           // code in next 2 lines is identical to: long v = NumericUtils.doubleToSortableLong(Double.longBitsToDouble(toLong(arr)));
-          long v = toLong(arr);
+          long v = toLong(bytesRef.bytes, bytesRef.offset);
           if (v<0) v ^= 0x7fffffffffffffffL;
           NumericUtils.longToPrefixCoded(v, 0, bytes);
           break;
@@ -473,9 +474,9 @@
     }
     return bytes.utf8ToString();
   }
-
+  
   @Override
-  public Fieldable createField(SchemaField field, Object value, float boost) {
+  public IndexableField createField(SchemaField field, Object value, float boost) {
     boolean indexed = field.indexed();
     boolean stored = field.stored();
 
@@ -484,8 +485,15 @@
         log.trace("Ignoring unindexed/unstored field: " + field);
       return null;
     }
-
-    final NumericField f = new NumericField(field.getName(), precisionStep, stored ? Field.Store.YES : Field.Store.NO, indexed);
+    
+    org.apache.lucene.document.FieldType ft = new org.apache.lucene.document.FieldType();
+    ft.setStored(stored);
+    ft.setTokenized(true);
+    ft.setIndexed(indexed);
+    ft.setOmitNorms(field.omitNorms());
+    ft.setIndexOptions(getIndexOptions(field, value.toString()));
+    
+    final org.apache.lucene.document.NumericField f = new org.apache.lucene.document.NumericField(field.getName(), precisionStep, ft);
     switch (type) {
       case INTEGER:
         int i = (value instanceof Number)
@@ -521,8 +529,6 @@
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Unknown type for trie field: " + type);
     }
 
-    f.setOmitNorms(field.omitNorms());
-    f.setIndexOptions(getIndexOptions(field, value.toString()));
     f.setBoost(boost);
     return f;
   }
Index: solr/core/src/java/org/apache/solr/schema/PointType.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/PointType.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/PointType.java	(working copy)
@@ -18,10 +18,10 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.VectorValueSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.Query;
@@ -69,7 +69,7 @@
   }
 
   @Override
-  public Fieldable[] createFields(SchemaField field, Object value, float boost) {
+  public IndexableField[] createFields(SchemaField field, Object value, float boost) {
     String externalVal = value.toString();
     String[] point = new String[0];
     try {
@@ -79,7 +79,7 @@
     }
 
     // TODO: this doesn't currently support polyFields as sub-field types
-    Fieldable[] f = new Fieldable[ (field.indexed() ? dimension : 0) + (field.stored() ? 1 : 0) ];
+    IndexableField[] f = new IndexableField[ (field.indexed() ? dimension : 0) + (field.stored() ? 1 : 0) ];
 
     if (field.indexed()) {
       for (int i=0; i<dimension; i++) {
@@ -89,9 +89,9 @@
 
     if (field.stored()) {
       String storedVal = externalVal;  // normalize or not?
-      f[f.length - 1] = createField(field.getName(), storedVal,
-                getFieldStore(field, storedVal), Field.Index.NO, Field.TermVector.NO,
-                false, IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, boost);
+      org.apache.lucene.document.FieldType customType = new org.apache.lucene.document.FieldType();
+      customType.setStored(true);
+      f[f.length - 1] = createField(field.getName(), storedVal, customType, boost);
     }
     
     return f;
@@ -114,12 +114,12 @@
    *
    */
   @Override
-  public Fieldable createField(SchemaField field, Object value, float boost) {
+  public IndexableField 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, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), false);
   }
 
Index: solr/core/src/java/org/apache/solr/schema/LatLonType.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/LatLonType.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/LatLonType.java	(working copy)
@@ -17,8 +17,9 @@
  */
 
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.queries.function.DocValues;
@@ -55,10 +56,10 @@
   }
 
   @Override
-  public Fieldable[] createFields(SchemaField field, Object value, float boost) {
+  public IndexableField[] 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)
-    Fieldable[] f = new Fieldable[(field.indexed() ? 2 : 0) + (field.stored() ? 1 : 0)];
+    IndexableField[] f = new IndexableField[(field.indexed() ? 2 : 0) + (field.stored() ? 1 : 0)];
     if (field.indexed()) {
       int i = 0;
       double[] latLon = new double[0];
@@ -76,9 +77,9 @@
     }
 
     if (field.stored()) {
-      f[f.length - 1] = createField(field.getName(), externalVal,
-              getFieldStore(field, externalVal), Field.Index.NO, Field.TermVector.NO,
-              false, IndexOptions.DOCS_AND_FREQS_AND_POSITIONS, boost);
+      FieldType customType = new FieldType();
+      customType.setStored(true);
+      f[f.length - 1] = createField(field.getName(), externalVal, customType, boost);
     }
     return f;
   }
@@ -268,7 +269,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), false);
   }
 
@@ -282,7 +283,7 @@
   //It never makes sense to create a single field, so make it impossible to happen
 
   @Override
-  public Fieldable createField(SchemaField field, Object value, float boost) {
+  public IndexableField createField(SchemaField field, Object value, float boost) {
     throw new UnsupportedOperationException("LatLonType uses multiple fields.  field=" + field.getName());
   }
 
Index: solr/core/src/java/org/apache/solr/schema/BinaryField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/BinaryField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/BinaryField.java	(working copy)
@@ -17,24 +17,25 @@
 
 package org.apache.solr.schema;
 
-import org.apache.solr.response.TextResponseWriter;
-import org.apache.solr.common.util.Base64;
-import org.apache.lucene.document.Fieldable;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
 import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.BytesRef;
+import org.apache.solr.common.util.Base64;
+import org.apache.solr.response.TextResponseWriter;
 
-import java.io.IOException;
-import java.nio.ByteBuffer;
 
-
 public class BinaryField extends FieldType  {
 
-  private String  toBase64String(ByteBuffer buf) {
+  private String toBase64String(ByteBuffer buf) {
     return Base64.byteArrayToBase64(buf.array(), buf.position(), buf.limit()-buf.position());
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, toBase64String(toObject(f)), false);
   }
 
@@ -45,17 +46,18 @@
 
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return toBase64String(toObject(f));
   }
-  
+
   @Override
-  public ByteBuffer toObject(Fieldable f) {
-    return  ByteBuffer.wrap(f.getBinaryValue(), f.getBinaryOffset(), f.getBinaryLength() ) ;
+  public ByteBuffer toObject(IndexableField f) {
+    BytesRef bytes = f.binaryValue();
+    return  ByteBuffer.wrap(bytes.bytes, bytes.offset, bytes.length);
   }
 
   @Override
-  public Fieldable createField(SchemaField field, Object val, float boost) {
+  public IndexableField createField(SchemaField field, Object val, float boost) {
     if (val == null) return null;
     if (!field.stored()) {
       log.trace("Ignoring unstored binary field: " + field);
@@ -79,7 +81,7 @@
       len = buf.length;
     }
 
-    Field f = new Field(field.getName(), buf, offset, len);
+    Field f = new org.apache.lucene.document.BinaryField(field.getName(), buf, offset, len);
     f.setBoost(boost);
     return f;
   }
Index: solr/core/src/java/org/apache/solr/schema/BoolField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/BoolField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/BoolField.java	(working copy)
@@ -18,6 +18,10 @@
 package org.apache.solr.schema;
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.FieldCache;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.queries.function.DocValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.BoolDocValues;
@@ -33,7 +37,6 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
-import org.apache.lucene.document.Fieldable;
 import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.analysis.SolrAnalyzer;
 
@@ -117,12 +120,12 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Boolean toObject(Fieldable f) {
+  public Boolean toObject(IndexableField f) {
     return Boolean.valueOf( toExternal(f) );
   }
 
@@ -151,7 +154,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeBool(name, f.stringValue().charAt(0) == 'T');
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/TrieDateField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/TrieDateField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/TrieDateField.java	(working copy)
@@ -20,7 +20,7 @@
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.solr.search.QParser;
 import org.apache.solr.response.TextResponseWriter;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.NumericRangeQuery;
@@ -45,7 +45,7 @@
   }
 
   @Override
-  public Date toObject(Fieldable f) {
+  public Date toObject(IndexableField f) {
     return (Date) wrappedField.toObject(f);
   }
 
@@ -73,7 +73,7 @@
 
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     wrappedField.write(writer, name, f);
   }
 
@@ -88,7 +88,7 @@
   }
 
   @Override
-  public String storedToReadable(Fieldable f) {
+  public String storedToReadable(IndexableField f) {
     return wrappedField.storedToReadable(f);
   }
 
@@ -103,7 +103,7 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return wrappedField.toExternal(f);
   }
 
@@ -118,12 +118,12 @@
   }
 
   @Override
-  public String storedToIndexed(Fieldable f) {
+  public String storedToIndexed(IndexableField f) {
     return wrappedField.storedToIndexed(f);
   }
 
   @Override
-  public Fieldable createField(SchemaField field, Object value, float boost) {
+  public IndexableField createField(SchemaField field, Object value, float boost) {
     return wrappedField.createField(field, value, boost);
   }
 
Index: solr/core/src/java/org/apache/solr/schema/BCDIntField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/BCDIntField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/BCDIntField.java	(working copy)
@@ -20,7 +20,7 @@
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.util.BCDUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -51,13 +51,13 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
   
   // Note, this can't return type 'Integer' because BCDStrField and BCDLong extend it
   @Override
-  public Object toObject(Fieldable f) {
+  public Object toObject(IndexableField f) {
     return Integer.valueOf( toExternal(f) );
   }
 
@@ -67,7 +67,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeInt(name,toExternal(f));
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/SortableDoubleField.java	(working copy)
@@ -27,8 +27,8 @@
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueDouble;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -62,12 +62,12 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Double toObject(Fieldable f) {
+  public Double toObject(IndexableField f) {
     return NumberUtils.SortableStr2double(f.stringValue());
   }
   
@@ -86,7 +86,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeDouble(name, NumberUtils.SortableStr2double(sval));
   }
Index: solr/core/src/java/org/apache/solr/schema/UUIDField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/UUIDField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/UUIDField.java	(working copy)
@@ -22,7 +22,7 @@
 import java.util.Map;
 import java.util.UUID;
 
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.response.TextResponseWriter;
@@ -53,7 +53,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f)
+  public void write(TextResponseWriter writer, String name, IndexableField f)
       throws IOException {
     writer.writeStr(name, f.stringValue(), false);
   }
@@ -88,7 +88,7 @@
   }
 
   @Override
-  public UUID toObject(Fieldable f) {
+  public UUID toObject(IndexableField f) {
     return UUID.fromString(f.stringValue());
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/BCDLongField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/BCDLongField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/BCDLongField.java	(working copy)
@@ -17,13 +17,13 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 /**
  *
  */
 public class BCDLongField extends BCDIntField {
   @Override
-  public Long toObject(Fieldable f) {
+  public Long toObject(IndexableField f) {
     return Long.valueOf( toExternal(f) );
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/StrField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/StrField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/StrField.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.response.TextResponseWriter;
 import org.apache.solr.search.QParser;
@@ -41,7 +41,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
Index: solr/core/src/java/org/apache/solr/schema/DoubleField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/DoubleField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/DoubleField.java	(working copy)
@@ -17,9 +17,9 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.DoubleFieldSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.cache.CachedArrayCreator;
 import org.apache.lucene.search.cache.DoubleValuesCreator;
@@ -52,7 +52,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -78,7 +78,7 @@
 
 
   @Override
-  public Double toObject(Fieldable f) {
+  public Double toObject(IndexableField f) {
     return Double.valueOf(toExternal(f));
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/DateField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/DateField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/DateField.java	(working copy)
@@ -17,8 +17,11 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.TermRangeQuery;
 import org.apache.lucene.queries.function.DocValues;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.docvalues.StringIndexDocValues;
@@ -186,7 +189,7 @@
     }
   }
 
-  public Fieldable createField(SchemaField field, Object value, float boost) {
+  public IndexableField createField(SchemaField field, Object value, float boost) {
     // Convert to a string before indexing
     if(value instanceof Date) {
       value = toInternal( (Date)value ) + Z;
@@ -211,7 +214,7 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
 
@@ -220,7 +223,7 @@
   }
 
   @Override
-  public Date toObject(Fieldable f) {
+  public Date toObject(IndexableField f) {
     try {
       return parseDate( toExternal(f) );
     }
@@ -235,7 +238,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeDate(name, toExternal(f));
   }
 
Index: solr/core/src/java/org/apache/solr/schema/BCDStrField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/BCDStrField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/BCDStrField.java	(working copy)
@@ -17,7 +17,7 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 /**
  *
  */
@@ -27,7 +27,7 @@
    * is not an integer, it will not survive the base10k conversion!
    */
   @Override
-  public String toObject(Fieldable f) {
+  public String toObject(IndexableField f) {
     return toExternal(f);
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/ExternalFileField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/ExternalFileField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/ExternalFileField.java	(working copy)
@@ -18,7 +18,7 @@
 
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.SortField;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.search.function.FileFloatSource;
 import org.apache.solr.search.QParser;
 import org.apache.solr.response.TextResponseWriter;
@@ -76,7 +76,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     throw new UnsupportedOperationException();
   }
 
Index: solr/core/src/java/org/apache/solr/schema/IndexSchema.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/IndexSchema.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/IndexSchema.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Similarity;
@@ -258,8 +258,8 @@
    * @return null if this schema has no unique key field
    * @see #printableUniqueKey
    */
-  public Fieldable getUniqueKeyField(org.apache.lucene.document.Document doc) {
-    return doc.getFieldable(uniqueKeyFieldName);  // this should return null if name is null
+  public IndexableField getUniqueKeyField(org.apache.lucene.document.Document doc) {
+    return doc.getField(uniqueKeyFieldName);  // this should return null if name is null
   }
 
   /**
@@ -268,8 +268,8 @@
    * @return null if this schema has no unique key field
    */
   public String printableUniqueKey(org.apache.lucene.document.Document doc) {
-     Fieldable f = doc.getFieldable(uniqueKeyFieldName);
-     return f==null ? null : uniqueKeyFieldType.toExternal(f);
+    IndexableField f = doc.getField(uniqueKeyFieldName);
+    return f==null ? null : uniqueKeyFieldType.toExternal(f);
   }
 
   private SchemaField getIndexedField(String fname) {
Index: solr/core/src/java/org/apache/solr/schema/RandomSortField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/RandomSortField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/RandomSortField.java	(working copy)
@@ -20,7 +20,7 @@
 import java.io.IOException;
 import java.util.Map;
 
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.queries.function.DocValues;
@@ -97,7 +97,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException { }
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException { }
 
 
   private static FieldComparatorSource randomComparatorSource = new FieldComparatorSource() {
Index: solr/core/src/java/org/apache/solr/schema/SortableLongField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/SortableLongField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/SortableLongField.java	(working copy)
@@ -27,8 +27,8 @@
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueLong;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -72,19 +72,19 @@
     charsRef.copy(indexedToReadable, 0, indexedToReadable.length);
     return charsRef;
   }
-  
+
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Long toObject(Fieldable f) {
+  public Long toObject(IndexableField f) {
     return NumberUtils.SortableStr2long(f.stringValue(),0,5);
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeLong(name, NumberUtils.SortableStr2long(sval,0,sval.length()));
   }
Index: solr/core/src/java/org/apache/solr/schema/LongField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/LongField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/LongField.java	(working copy)
@@ -17,9 +17,9 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LongFieldSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.cache.CachedArrayCreator;
 import org.apache.lucene.search.cache.LongValuesCreator;
@@ -52,7 +52,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -77,7 +77,7 @@
   }
 
   @Override
-  public Long toObject(Fieldable f) {
+  public Long toObject(IndexableField f) {
     return Long.valueOf( toExternal(f) );
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/ShortField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/ShortField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/ShortField.java	(working copy)
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.ShortFieldSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.cache.CachedArrayCreator;
 import org.apache.lucene.search.cache.ShortValuesCreator;
@@ -55,7 +55,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -80,7 +80,7 @@
   }
 
   @Override
-  public Short toObject(Fieldable f) {
+  public Short toObject(IndexableField f) {
     return Short.valueOf(toExternal(f));
   }
 
Index: solr/core/src/java/org/apache/solr/schema/SchemaField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/SchemaField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/SchemaField.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.solr.search.QParser;
 
@@ -99,11 +99,11 @@
   boolean isBinary() { return (properties & BINARY)!=0; }
 
 
-  public Fieldable createField(Object val, float boost) {
+  public IndexableField createField(Object val, float boost) {
     return type.createField(this,val,boost);
   }
   
-  public Fieldable[] createFields(Object val, float boost) {
+  public IndexableField[] createFields(Object val, float boost) {
     return type.createFields(this,val,boost);
   }
 
@@ -125,7 +125,7 @@
       + "}";
   }
 
-  public void write(TextResponseWriter writer, String name, Fieldable val) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField val) throws IOException {
     // name is passed in because it may be null if name should not be used.
     type.write(writer,name,val);
   }
Index: solr/core/src/java/org/apache/solr/schema/SortableFloatField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/SortableFloatField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/SortableFloatField.java	(working copy)
@@ -27,8 +27,8 @@
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueFloat;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -62,12 +62,12 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
 
   @Override
-  public Float toObject(Fieldable f) {
+  public Float toObject(IndexableField f) {
     return NumberUtils.SortableStr2float(f.stringValue());
   }
   
@@ -84,7 +84,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeFloat(name, NumberUtils.SortableStr2float(sval));
   }
Index: solr/core/src/java/org/apache/solr/schema/ByteField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/ByteField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/ByteField.java	(working copy)
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.ByteFieldSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.cache.ByteValuesCreator;
 import org.apache.lucene.search.cache.CachedArrayCreator;
@@ -52,7 +52,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -77,7 +77,7 @@
   }
 
   @Override
-  public Byte toObject(Fieldable f) {
+  public Byte toObject(IndexableField f) {
     return Byte.valueOf(toExternal(f));
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/FloatField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/FloatField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/FloatField.java	(working copy)
@@ -23,7 +23,7 @@
 import org.apache.lucene.search.cache.CachedArrayCreator;
 import org.apache.lucene.search.cache.FloatValuesCreator;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.response.TextResponseWriter;
 
 import java.util.Map;
@@ -50,7 +50,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -75,7 +75,7 @@
   }
 
   @Override
-  public Float toObject(Fieldable f) {
+  public Float toObject(IndexableField f) {
     return Float.valueOf( toExternal(f) );
   }
 }
Index: solr/core/src/java/org/apache/solr/schema/GeoHashField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/GeoHashField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/GeoHashField.java	(working copy)
@@ -17,9 +17,9 @@
 
 package org.apache.solr.schema;
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.LiteralValueSource;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.spatial.geohash.GeoHashUtils;
@@ -68,14 +68,14 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f)
+  public void write(TextResponseWriter writer, String name, IndexableField f)
           throws IOException {
     writer.writeStr(name, toExternal(f), false);
   }
 
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     double[] latLon = GeoHashUtils.decode(f.stringValue());
     return latLon[0] + "," + latLon[1];
   }
Index: solr/core/src/java/org/apache/solr/schema/FieldType.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/FieldType.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/FieldType.java	(working copy)
@@ -22,8 +22,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.search.Query;
@@ -91,7 +91,7 @@
   }
 
   /**
-   * A "polyField" is a FieldType that can produce more than one Fieldable instance for a single value, via the {@link #createFields(org.apache.solr.schema.SchemaField, Object, float)} method.  This is useful
+   * A "polyField" is a FieldType that can produce more than one IndexableField instance for a single value, via the {@link #createFields(org.apache.solr.schema.SchemaField, Object, float)} method.  This is useful
    * when hiding the implementation details of a field from the Solr end user.  For instance, a spatial point may be represented by multiple different fields.
    * @return true if the {@link #createFields(org.apache.solr.schema.SchemaField, Object, float)} method may return more than one field
    */
@@ -235,7 +235,7 @@
    *
    *
    */
-  public Fieldable createField(SchemaField field, Object value, float boost) {
+  public IndexableField createField(SchemaField field, Object value, float boost) {
     if (!field.indexed() && !field.stored()) {
       if (log.isTraceEnabled())
         log.trace("Ignoring unindexed/unstored field: " + field);
@@ -250,79 +250,48 @@
     }
     if (val==null) return null;
 
-    return createField(field.getName(), val, 
-                       getFieldStore(field, val), getFieldIndex(field, val), 
-                       getFieldTermVec(field, val), field.omitNorms(),
-                       getIndexOptions(field, val), boost);
+    org.apache.lucene.document.FieldType newType = new org.apache.lucene.document.FieldType();
+    newType.setIndexed(field.indexed());
+    newType.setTokenized(field.isTokenized());
+    newType.setStored(field.stored());
+    newType.setOmitNorms(field.omitNorms());
+    newType.setIndexOptions(getIndexOptions(field, val));
+    newType.setStoreTermVectors(field.storeTermVector());
+    newType.setStoreTermVectorOffsets(field.storeTermOffsets());
+    newType.setStoreTermVectorPositions(field.storeTermPositions());
+    
+    return createField(field.getName(), val, newType, boost);
   }
 
-
   /**
    * Create the field from native Lucene parts.  Mostly intended for use by FieldTypes outputing multiple
    * Fields per SchemaField
    * @param name The name of the field
    * @param val The _internal_ value to index
-   * @param storage {@link org.apache.lucene.document.Field.Store}
-   * @param index {@link org.apache.lucene.document.Field.Index}
-   * @param vec {@link org.apache.lucene.document.Field.TermVector}
-   * @param omitNorms true if norms should be omitted
-   * @param options options for what should be indexed in the postings
+   * @param type {@link org.apache.lucene.document.FieldType}
    * @param boost The boost value
-   * @return the {@link org.apache.lucene.document.Fieldable}.
+   * @return the {@link org.apache.lucene.index.IndexableField}.
    */
-  protected Fieldable createField(String name, String val, Field.Store storage, Field.Index index,
-                                    Field.TermVector vec, boolean omitNorms, IndexOptions options, float boost){
-    Field f = new Field(name,
-                        val,
-                        storage,
-                        index,
-                        vec);
-    if (index.isIndexed()) {
-      f.setOmitNorms(omitNorms);
-      f.setIndexOptions(options);
-      f.setBoost(boost);
-    }
+  protected IndexableField createField(String name, String val, org.apache.lucene.document.FieldType type, float boost){
+    Field f = new Field(name, type, val);
+    f.setBoost(boost);
     return f;
   }
 
   /**
-   * Given a {@link org.apache.solr.schema.SchemaField}, create one or more {@link org.apache.lucene.document.Fieldable} instances
+   * Given a {@link org.apache.solr.schema.SchemaField}, create one or more {@link org.apache.lucene.index.IndexableField} instances
    * @param field the {@link org.apache.solr.schema.SchemaField}
    * @param value The value to add to the field
    * @param boost The boost to apply
-   * @return An array of {@link org.apache.lucene.document.Fieldable}
+   * @return An array of {@link org.apache.lucene.index.IndexableField}
    *
    * @see #createField(SchemaField, Object, float)
    * @see #isPolyField()
    */
-  public Fieldable[] createFields(SchemaField field, Object value, float boost) {
-    Fieldable f = createField( field, value, boost);
-    return f==null ? new Fieldable[]{} : new Fieldable[]{f};
+  public IndexableField[] createFields(SchemaField field, Object value, float boost) {
+    IndexableField f = createField( field, value, boost);
+    return f==null ? new IndexableField[]{} : new IndexableField[]{f};
   }
-
-  /* Helpers for field construction */
-  protected Field.TermVector getFieldTermVec(SchemaField field,
-                                             String internalVal) {
-    Field.TermVector ftv = Field.TermVector.NO;
-    if (field.storeTermPositions() && field.storeTermOffsets())
-      ftv = Field.TermVector.WITH_POSITIONS_OFFSETS;
-    else if (field.storeTermPositions())
-      ftv = Field.TermVector.WITH_POSITIONS;
-    else if (field.storeTermOffsets())
-      ftv = Field.TermVector.WITH_OFFSETS;
-    else if (field.storeTermVector())
-      ftv = Field.TermVector.YES;
-    return ftv;
-  }
-  protected Field.Store getFieldStore(SchemaField field,
-                                      String internalVal) {
-    return field.stored() ? Field.Store.YES : Field.Store.NO;
-  }
-  protected Field.Index getFieldIndex(SchemaField field,
-                                      String internalVal) {
-    return field.indexed() ? (isTokenized() ? Field.Index.ANALYZED :
-                              Field.Index.NOT_ANALYZED) : Field.Index.NO;
-  }
   protected IndexOptions getIndexOptions(SchemaField field,
                                          String internalVal) {
     IndexOptions options = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
@@ -350,9 +319,9 @@
    * value
    * @see #toInternal
    */
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     // currently used in writing XML of the search result (but perhaps
-    // a more efficient toXML(Fieldable f, Writer w) should be used
+    // a more efficient toXML(IndexableField f, Writer w) should be used
     // in the future.
     return f.stringValue();
   }
@@ -362,14 +331,14 @@
    * @see #toInternal
    * @since solr 1.3
    */
-  public Object toObject(Fieldable f) {
+  public Object toObject(IndexableField 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 Fieldable f = createField(sf, ref.toString(), 1.0f);
+    final IndexableField f = createField(sf, ref.toString(), 1.0f);
     return toObject(f);
   }
 
@@ -385,12 +354,12 @@
   }
 
   /** Given the stored field, return the human readable representation */
-  public String storedToReadable(Fieldable f) {
+  public String storedToReadable(IndexableField f) {
     return toExternal(f);
   }
 
   /** Given the stored field, return the indexed form */
-  public String storedToIndexed(Fieldable f) {
+  public String storedToIndexed(IndexableField 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.
@@ -569,7 +538,7 @@
   /**
    * calls back to TextResponseWriter to write the field value
    */
-  public abstract void write(TextResponseWriter writer, String name, Fieldable f) throws IOException;
+  public abstract void write(TextResponseWriter writer, String name, IndexableField f) throws IOException;
 
 
   /**
Index: solr/core/src/java/org/apache/solr/schema/CollationField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/CollationField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/CollationField.java	(working copy)
@@ -31,7 +31,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.collation.CollationKeyAnalyzer;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermRangeQuery;
@@ -185,7 +185,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
Index: solr/core/src/java/org/apache/solr/schema/TextField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/TextField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/TextField.java	(working copy)
@@ -24,7 +24,7 @@
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.MultiPhraseQuery;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
@@ -74,7 +74,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
Index: solr/core/src/java/org/apache/solr/schema/SortableIntField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/SortableIntField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/SortableIntField.java	(working copy)
@@ -27,8 +27,8 @@
 import org.apache.lucene.util.mutable.MutableValue;
 import org.apache.lucene.util.mutable.MutableValueInt;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.util.NumberUtils;
 import org.apache.solr.response.TextResponseWriter;
 
@@ -65,7 +65,7 @@
   }
 
   @Override
-  public String toExternal(Fieldable f) {
+  public String toExternal(IndexableField f) {
     return indexedToReadable(f.stringValue());
   }
 
@@ -82,12 +82,12 @@
   }
 
   @Override
-  public Integer toObject(Fieldable f) {
+  public Integer toObject(IndexableField f) {
     return NumberUtils.SortableStr2int(f.stringValue(), 0, 3);    
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String sval = f.stringValue();
     writer.writeInt(name, NumberUtils.SortableStr2int(sval,0,sval.length()));
   }
Index: solr/core/src/java/org/apache/solr/schema/IntField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/IntField.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/schema/IntField.java	(working copy)
@@ -23,7 +23,7 @@
 import org.apache.lucene.search.cache.CachedArrayCreator;
 import org.apache.lucene.search.cache.IntValuesCreator;
 import org.apache.solr.search.QParser;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.response.TextResponseWriter;
 
 import java.util.Map;
@@ -50,7 +50,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     String s = f.stringValue();
 
     // these values may be from a legacy lucene index, which may
@@ -75,7 +75,7 @@
   }
 
   @Override
-  public Integer toObject(Fieldable f) {
+  public Integer toObject(IndexableField f) {
     return Integer.valueOf( toExternal(f) );
   }
 }
Index: solr/core/src/java/org/apache/solr/update/DocumentBuilder.java
===================================================================
--- solr/core/src/java/org/apache/solr/update/DocumentBuilder.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/update/DocumentBuilder.java	(working copy)
@@ -22,7 +22,7 @@
 import java.util.List;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
@@ -56,7 +56,7 @@
     // might actually want to map it to something.  If createField()
     // returns null, then we don't store the field.
     if (sfield.isPolyField()) {
-      Fieldable[] fields = sfield.createFields(val, boost);
+      IndexableField[] fields = sfield.createFields(val, boost);
       if (fields.length > 0) {
         if (!sfield.multiValued()) {
           String oldValue = map.put(sfield.getName(), val);
@@ -66,12 +66,12 @@
           }
         }
         // Add each field
-        for (Fieldable field : fields) {
+        for (IndexableField field : fields) {
           doc.add(field);
         }
       }
     } else {
-      Fieldable field = sfield.createField(val, boost);
+      IndexableField field = sfield.createField(val, boost);
       if (field != null) {
         if (!sfield.multiValued()) {
           String oldValue = map.put(sfield.getName(), val);
@@ -145,10 +145,6 @@
     }
   }
 
-  public void setBoost(float boost) {
-    doc.setBoost(boost);
-  }
-
   public void endDoc() {
   }
 
@@ -159,7 +155,7 @@
     // default value are defacto 'required' fields.  
     List<String> missingFields = null;
     for (SchemaField field : schema.getRequiredFields()) {
-      if (doc.getFieldable(field.getName() ) == null) {
+      if (doc.getField(field.getName() ) == null) {
         if (field.getDefaultValue() != null) {
           addField(doc, field, field.getDefaultValue(), 1.0f);
         } else {
@@ -176,7 +172,7 @@
       // add the uniqueKey if possible
       if( schema.getUniqueKeyField() != null ) {
         String n = schema.getUniqueKeyField().getName();
-        String v = doc.get( n );
+        String v = doc.getField( n ).stringValue();
         builder.append( "Document ["+n+"="+v+"] " );
       }
       builder.append("missing required fields: " );
@@ -194,12 +190,12 @@
 
   private static void addField(Document doc, SchemaField field, Object val, float boost) {
     if (field.isPolyField()) {
-      Fieldable[] farr = field.getType().createFields(field, val, boost);
-      for (Fieldable f : farr) {
+      IndexableField[] farr = field.getType().createFields(field, val, boost);
+      for (IndexableField f : farr) {
         if (f != null) doc.add(f); // null fields are not added
       }
     } else {
-      Fieldable f = field.createField(val, boost);
+      IndexableField f = field.createField(val, boost);
       if (f != null) doc.add(f);  // null fields are not added
     }
   }
@@ -231,7 +227,7 @@
   public static Document toDocument( SolrInputDocument doc, IndexSchema schema )
   { 
     Document out = new Document();
-    out.setBoost( doc.getDocumentBoost() );
+    final float docBoost = doc.getDocumentBoost();
     
     // Load fields from SolrDocument to Document
     for( SolrInputField field : doc ) {
@@ -258,7 +254,7 @@
           hasField = true;
           if (sfield != null) {
             used = true;
-            addField(out, sfield, v, boost);
+            addField(out, sfield, v, docBoost*boost);
           }
   
           // Check if we should copy this field to any other fields.
@@ -267,7 +263,7 @@
           for (CopyField cf : copyFields) {
             SchemaField destinationField = cf.getDestination();
             // check if the copy field is a multivalued or not
-            if (!destinationField.multiValued() && out.getFieldable(destinationField.getName()) != null) {
+            if (!destinationField.multiValued() && out.getField(destinationField.getName()) != null) {
               throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                       "ERROR: "+getID(doc, schema)+"multiple values encountered for non multiValued copy field " +
                               destinationField.getName() + ": " + v);
@@ -281,9 +277,9 @@
               val = cf.getLimitedValue((String)val);
             }
             
-            Fieldable [] fields = destinationField.createFields(val, boost);
+            IndexableField [] fields = destinationField.createFields(val, docBoost*boost);
             if (fields != null) { // null fields are not added
-              for (Fieldable f : fields) {
+              for (IndexableField f : fields) {
                 if(f != null) out.add(f);
               }
             }
@@ -293,7 +289,7 @@
           // document boost and *all* boosts on values of that field. 
           // For multi-valued fields, we only want to set the boost on the
           // first field.
-          boost = 1.0f; 
+          boost = docBoost;
         }
       }
       catch( Exception ex ) {
@@ -313,7 +309,7 @@
     // Now validate required fields or add default values
     // fields with default values are defacto 'required'
     for (SchemaField field : schema.getRequiredFields()) {
-      if (out.getFieldable(field.getName() ) == null) {
+      if (out.getField(field.getName() ) == null) {
         if (field.getDefaultValue() != null) {
           addField(out, field, field.getDefaultValue(), 1.0f);
         } 
@@ -339,8 +335,8 @@
    */
   public SolrDocument loadStoredFields( SolrDocument doc, Document luceneDoc  )
   {
-    for( Fieldable field : luceneDoc.getFields() ) {
-      if( field.isStored() ) {
+    for( IndexableField field : luceneDoc) {
+      if( field.stored() ) {
         SchemaField sf = schema.getField( field.name() );
         if( !schema.isCopyFieldTarget( sf ) ) {
           doc.addField( field.name(), sf.getType().toObject( field ) );
Index: solr/core/src/java/org/apache/solr/update/UpdateHandler.java
===================================================================
--- solr/core/src/java/org/apache/solr/update/UpdateHandler.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/update/UpdateHandler.java	(working copy)
@@ -19,9 +19,9 @@
 
 
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.Scorer;
 
@@ -129,7 +129,6 @@
    */
   public abstract void newIndexWriter() throws IOException;
 
-
   public abstract int addDoc(AddUpdateCommand cmd) throws IOException;
   public abstract void delete(DeleteUpdateCommand cmd) throws IOException;
   public abstract void deleteByQuery(DeleteUpdateCommand cmd) throws IOException;
Index: solr/core/src/java/org/apache/solr/update/AddUpdateCommand.java
===================================================================
--- solr/core/src/java/org/apache/solr/update/AddUpdateCommand.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/update/AddUpdateCommand.java	(working copy)
@@ -18,7 +18,7 @@
 package org.apache.solr.update;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrException;
Index: solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java
===================================================================
--- solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/highlight/DefaultSolrHighlighter.java	(working copy)
@@ -33,6 +33,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.highlight.*;
 import org.apache.lucene.search.vectorhighlight.FastVectorHighlighter;
@@ -416,7 +417,14 @@
     // END: Hack
     
     SolrParams params = req.getParams(); 
-    String[] docTexts = doc.getValues(fieldName);
+    IndexableField[] docFields = doc.getFields(fieldName);
+    List<String> listFields = new ArrayList<String>();
+    for (IndexableField field : docFields) {
+      listFields.add(field.stringValue());
+    }
+
+    String[] docTexts = (String[]) listFields.toArray(new String[listFields.size()]);
+   
     // according to Document javadoc, doc.getValues() never returns null. check empty instead of null
     if (docTexts.length == 0) return;
     
@@ -537,7 +545,15 @@
   private void alternateField( NamedList docSummaries, SolrParams params, Document doc, String fieldName ){
     String alternateField = params.getFieldParam(fieldName, HighlightParams.ALTERNATE_FIELD);
     if (alternateField != null && alternateField.length() > 0) {
-      String[] altTexts = doc.getValues(alternateField);
+      IndexableField[] docFields = doc.getFields(alternateField);
+      List<String> listFields = new ArrayList<String>();
+      for (IndexableField field : docFields) {
+        if (field.binaryValue() == null)
+          listFields.add(field.stringValue());
+      }
+
+      String[] altTexts = listFields.toArray(new String[listFields.size()]);
+
       if (altTexts != null && altTexts.length > 0){
         int alternateFieldLen = params.getFieldInt(fieldName, HighlightParams.ALTERNATE_FIELD_LENGTH,0);
         if( alternateFieldLen <= 0 ){
Index: solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java	(working copy)
@@ -34,9 +34,10 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.FieldsEnum;
@@ -163,21 +164,21 @@
   
 
   /**
-   * @return a string representing a Fieldable's flags.  
+   * @return a string representing a IndexableField's flags.  
    */
-  private static String getFieldFlags( Fieldable f )
+  private static String getFieldFlags( IndexableField f )
   {
     StringBuilder flags = new StringBuilder();
-    flags.append( (f != null && f.isIndexed())                     ? FieldFlag.INDEXED.getAbbreviation() : '-' );
-    flags.append( (f != null && f.isTokenized())                   ? FieldFlag.TOKENIZED.getAbbreviation() : '-' );
-    flags.append( (f != null && f.isStored())                      ? FieldFlag.STORED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.indexed())                     ? FieldFlag.INDEXED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.tokenized())                   ? FieldFlag.TOKENIZED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.stored())                      ? FieldFlag.STORED.getAbbreviation() : '-' );
     flags.append( (false)                                          ? FieldFlag.MULTI_VALUED.getAbbreviation() : '-' ); // SchemaField Specific
-    flags.append( (f != null && f.isTermVectorStored())            ? FieldFlag.TERM_VECTOR_STORED.getAbbreviation() : '-' );
-    flags.append( (f != null && f.isStoreOffsetWithTermVector())   ? FieldFlag.TERM_VECTOR_OFFSET.getAbbreviation() : '-' );
-    flags.append( (f != null && f.isStorePositionWithTermVector()) ? FieldFlag.TERM_VECTOR_POSITION.getAbbreviation() : '-' );
-    flags.append( (f != null && f.getOmitNorms())                  ? FieldFlag.OMIT_NORMS.getAbbreviation() : '-' );
-    flags.append( (f != null && f.isLazy())                        ? FieldFlag.LAZY.getAbbreviation() : '-' );
-    flags.append( (f != null && f.isBinary())                      ? FieldFlag.BINARY.getAbbreviation() : '-' );
+    flags.append( (f != null && f.storeTermVectors())            ? FieldFlag.TERM_VECTOR_STORED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.storeTermVectorOffsets())   ? FieldFlag.TERM_VECTOR_OFFSET.getAbbreviation() : '-' );
+    flags.append( (f != null && f.storeTermVectorPositions()) ? FieldFlag.TERM_VECTOR_POSITION.getAbbreviation() : '-' );
+    flags.append( (f != null && f.omitNorms())                  ? FieldFlag.OMIT_NORMS.getAbbreviation() : '-' );
+    flags.append( (f != null && f.getClass().getSimpleName().equals("LazyField")) ? FieldFlag.LAZY.getAbbreviation() : '-' );
+    flags.append( (f != null && f.binaryValue()!=null)                      ? FieldFlag.BINARY.getAbbreviation() : '-' );
     flags.append( (false)                                          ? FieldFlag.SORT_MISSING_FIRST.getAbbreviation() : '-' ); // SchemaField Specific
     flags.append( (false)                                          ? FieldFlag.SORT_MISSING_LAST.getAbbreviation() : '-' ); // SchemaField Specific
     return flags.toString();
@@ -239,34 +240,34 @@
     final CharsRef spare = new CharsRef();
     SimpleOrderedMap<Object> finfo = new SimpleOrderedMap<Object>();
     for( Object o : doc.getFields() ) {
-      Fieldable fieldable = (Fieldable)o;
+      Field field = (Field)o;
       SimpleOrderedMap<Object> f = new SimpleOrderedMap<Object>();
       
-      SchemaField sfield = schema.getFieldOrNull( fieldable.name() );
+      SchemaField sfield = schema.getFieldOrNull( field.name() );
       FieldType ftype = (sfield==null)?null:sfield.getType();
 
       f.add( "type", (ftype==null)?null:ftype.getTypeName() );
       f.add( "schema", getFieldFlags( sfield ) );
-      f.add( "flags", getFieldFlags( fieldable ) );
+      f.add( "flags", getFieldFlags( field ) );
 
-      Term t = new Term(fieldable.name(), ftype!=null ? ftype.storedToIndexed(fieldable) : fieldable.stringValue());
+      Term t = new Term(field.name(), ftype!=null ? ftype.storedToIndexed(field) : field.stringValue());
 
-      f.add( "value", (ftype==null)?null:ftype.toExternal( fieldable ) );
+      f.add( "value", (ftype==null)?null:ftype.toExternal( field ) );
 
       // TODO: this really should be "stored"
-      f.add( "internal", fieldable.stringValue() );  // may be a binary number
+      f.add( "internal", field.stringValue() );  // may be a binary number
 
-      byte[] arr = fieldable.getBinaryValue();
-      if (arr != null) {
-        f.add( "binary", Base64.byteArrayToBase64(arr, 0, arr.length));
+      BytesRef bytes = field.binaryValue();
+      if (bytes != null) {
+        f.add( "binary", Base64.byteArrayToBase64(bytes.bytes, bytes.offset, bytes.length));
       }
-      f.add( "boost", fieldable.getBoost() );
+      f.add( "boost", field.boost() );
       f.add( "docFreq", t.text()==null ? 0 : reader.docFreq( t ) ); // this can be 0 for non-indexed fields
             
       // If we have a term vector, return that
-      if( fieldable.isTermVectorStored() ) {
+      if( field.storeTermVectors() ) {
         try {
-          TermFreqVector v = reader.getTermFreqVector( docId, fieldable.name() );
+          TermFreqVector v = reader.getTermFreqVector( docId, field.name() );
           if( v != null ) {
             SimpleOrderedMap<Integer> tfv = new SimpleOrderedMap<Integer>();
             for( int i=0; i<v.size(); i++ ) {
@@ -280,7 +281,7 @@
         }
       }
       
-      finfo.add( fieldable.name(), f );
+      finfo.add( field.name(), f );
     }
     return finfo;
   }
@@ -324,7 +325,7 @@
           // Find a document with this field
           try {
             Document doc = searcher.doc( top.scoreDocs[0].doc );
-            Fieldable fld = doc.getFieldable( fieldName );
+            IndexableField fld = doc.getField( fieldName );
             if( fld != null ) {
               f.add( "index", getFieldFlags( fld ) );
             }
Index: solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/handler/component/QueryComponent.java	(working copy)
@@ -17,7 +17,12 @@
 
 package org.apache.solr.handler.component;
 
+import java.io.IOException;
+import java.net.URL;
+import java.util.*;
+
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader.ReaderContext;
 import org.apache.lucene.index.Term;
@@ -47,10 +52,6 @@
 import org.apache.solr.search.*;
 import org.apache.solr.util.SolrPluginUtils;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.*;
-
 /**
  * TODO!
  * 
@@ -426,7 +427,7 @@
       Sort sort = searcher.weightSort(rb.getSortSpec().getSort());
       SortField[] sortFields = sort==null ? new SortField[]{SortField.FIELD_SCORE} : sort.getSort();
       NamedList sortVals = new NamedList(); // order is important for the sort fields
-      Field field = new Field("dummy", "", Field.Store.YES, Field.Index.NO); // a dummy Field
+      Field field = new StringField("dummy", ""); // a dummy Field
       ReaderContext topReaderContext = searcher.getTopReaderContext();
       AtomicReaderContext[] leaves = ReaderUtil.leaves(topReaderContext);
       AtomicReaderContext currentLeaf = null;
Index: solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/handler/component/TermVectorComponent.java	(working copy)
@@ -1,14 +1,23 @@
 package org.apache.solr.handler.component;
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.SetBasedFieldSelector;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
+import org.apache.lucene.index.StoredFieldVisitor;
+import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermVectorMapper;
 import org.apache.lucene.index.TermVectorOffsetInfo;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
@@ -26,15 +35,6 @@
 import org.apache.solr.util.SolrPluginUtils;
 import org.apache.solr.util.plugin.SolrCoreAware;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -194,8 +194,42 @@
     if (keyField != null) {
       uniqFieldName = keyField.getName();
     }
-    //Only load the id field to get the uniqueKey of that field
-    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(Collections.singleton(uniqFieldName), Collections.<String>emptySet());
+    //Only load the id field to get the uniqueKey of that
+    //field
+
+    final String finalUniqFieldName = uniqFieldName;
+
+    final List<String> uniqValues = new ArrayList<String>();
+    final StoredFieldVisitor getUniqValue = new StoredFieldVisitor() {
+      @Override 
+      public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+        if (fieldInfo.name.equals(finalUniqFieldName)) {
+          final byte[] b = new byte[numUTF8Bytes];
+          in.readBytes(b, 0, b.length);
+          uniqValues.add(new String(b, "UTF-8"));
+        } else {
+          in.seek(in.getFilePointer() + numUTF8Bytes);
+        }
+        return false;
+      }
+
+      @Override 
+      public boolean intField(FieldInfo fieldInfo, int value) throws IOException {
+        if (fieldInfo.name.equals(finalUniqFieldName)) {
+          uniqValues.add(Integer.toString(value));
+        }
+        return false;
+      }
+
+      @Override 
+      public boolean longField(FieldInfo fieldInfo, long value) throws IOException {
+        if (fieldInfo.name.equals(finalUniqFieldName)) {
+          uniqValues.add(Long.toString(value));
+        }
+        return false;
+      }
+    };
+
     TVMapper mapper = new TVMapper(reader);
     mapper.fieldOptions = allFields; //this will only stay set if fieldOptions.isEmpty() (in other words, only if the user didn't set any fields)
     while (iter.hasNext()) {
@@ -205,13 +239,11 @@
       termVectors.add("doc-" + docId, docNL);
 
       if (keyField != null) {
-        Document document = reader.document(docId, fieldSelector);
-        Fieldable uniqId = document.getFieldable(uniqFieldName);
+        reader.document(docId, getUniqValue);
         String uniqVal = null;
-        if (uniqId != null) {
-          uniqVal = keyField.getType().storedToReadable(uniqId);          
-        }
-        if (uniqVal != null) {
+        if (uniqValues.size() != 0) {
+          uniqVal = uniqValues.get(0);
+          uniqValues.clear();
           docNL.add("uniqueKey", uniqVal);
           termVectors.add("uniqueKeyFieldName", uniqFieldName);
         }
Index: solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/handler/MoreLikeThisHandler.java	(working copy)
@@ -353,7 +353,7 @@
       realMLTQuery = new BooleanQuery();
       realMLTQuery.add(boostedMLTQuery, BooleanClause.Occur.MUST);
       realMLTQuery.add(
-          new TermQuery(new Term(uniqueKeyField.getName(), uniqueKeyField.getType().storedToIndexed(doc.getFieldable(uniqueKeyField.getName())))), 
+          new TermQuery(new Term(uniqueKeyField.getName(), uniqueKeyField.getType().storedToIndexed(doc.getField(uniqueKeyField.getName())))), 
             BooleanClause.Occur.MUST_NOT);
       
       DocListAndSet results = new DocListAndSet();
Index: solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
===================================================================
--- solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java	(working copy)
@@ -16,13 +16,17 @@
  */
 package org.apache.solr.response;
 
+import java.io.*;
+import java.util.*;
+
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.util.BytesRef;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.util.JavaBinCodec;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.JavaBinCodec;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.transform.DocTransformer;
 import org.apache.solr.response.transform.TransformContext;
@@ -33,10 +37,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.*;
-import java.util.*;
 
-
 public class BinaryResponseWriter implements BinaryQueryResponseWriter {
   private static final Logger LOG = LoggerFactory.getLogger(BinaryResponseWriter.class);
   public static final Set<Class> KNOWN_TYPES = new HashSet<Class>();
@@ -159,7 +160,7 @@
 
     public SolrDocument getDoc(Document doc) {
       SolrDocument solrDoc = new SolrDocument();
-      for (Fieldable f : doc.getFields()) {
+      for (IndexableField f : doc) {
         String fieldName = f.name();
         if( !returnFields.wantsField(fieldName) ) 
           continue;
@@ -168,8 +169,16 @@
         if(sf != null) ft =sf.getType();
         Object val;
         if (ft == null) {  // handle fields not in the schema
-          if (f.isBinary()) val = f.getBinaryValue();
-          else val = f.stringValue();
+          BytesRef bytesRef = f.binaryValue();
+          if (bytesRef != null) {
+            if (bytesRef.offset == 0 && bytesRef.length == bytesRef.bytes.length) {
+              val = bytesRef.bytes;
+            } else {
+              final byte[] bytes = new byte[bytesRef.length];
+              val = bytes;
+              System.arraycopy(bytesRef.bytes, bytesRef.offset, bytes, 0, bytesRef.length);
+            }
+          } else val = f.stringValue();
         } else {
           try {
             if (useFieldObjects && KNOWN_TYPES.contains(ft.getClass())) {
Index: solr/core/src/java/org/apache/solr/response/TextResponseWriter.java
===================================================================
--- solr/core/src/java/org/apache/solr/response/TextResponseWriter.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/response/TextResponseWriter.java	(working copy)
@@ -22,7 +22,7 @@
 import java.util.*;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.util.FastWriter;
@@ -120,8 +120,8 @@
     } else if (val instanceof String) {
       writeStr(name, val.toString(), true);
       // micro-optimization... using toString() avoids a cast first
-    } else if (val instanceof Fieldable) {
-      Fieldable f = (Fieldable)val;
+    } else if (val instanceof IndexableField) {
+      IndexableField f = (IndexableField)val;
       SchemaField sf = schema.getFieldOrNull( f.name() );
       if( sf != null ) {
         sf.getType().write(this, name, f);
@@ -202,7 +202,7 @@
   public final SolrDocument toSolrDocument( Document doc )
   {
     SolrDocument out = new SolrDocument();
-    for( Fieldable f : doc.getFields() ) {
+    for( IndexableField f : doc) {
       // Make sure multivalued fields are represented as lists
       Object existing = out.get(f.name());
       if (existing == null) {
Index: solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java
===================================================================
--- solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/response/CSVResponseWriter.java	(working copy)
@@ -20,7 +20,7 @@
 import org.apache.commons.csv.CSVPrinter;
 import org.apache.commons.csv.CSVStrategy;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.SolrDocumentList;
 import org.apache.solr.common.SolrException;
@@ -146,7 +146,7 @@
     CSVSharedBufPrinter mvPrinter;  // printer used to encode multiple values in a single CSV value
 
     // used to collect values
-    List<Fieldable> values = new ArrayList<Fieldable>(1);  // low starting amount in case there are many fields
+    List<IndexableField> values = new ArrayList<IndexableField>(1);  // low starting amount in case there are many fields
     int tmp;
   }
 
Index: solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java
===================================================================
--- solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/response/JSONResponseWriter.java	(working copy)
@@ -26,7 +26,8 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.util.StringHelper;
 import org.apache.solr.common.SolrDocument;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.util.NamedList;
@@ -302,10 +303,10 @@
 
   protected static class MultiValueField {
     final SchemaField sfield;
-    final ArrayList<Fieldable> fields;
-    MultiValueField(SchemaField sfield, Fieldable firstVal) {
+    final ArrayList<IndexableField> fields;
+    MultiValueField(SchemaField sfield, IndexableField firstVal) {
       this.sfield = sfield;
-      this.fields = new ArrayList<Fieldable>(4);
+      this.fields = new ArrayList<IndexableField>(4);
       this.fields.add(firstVal);
     }
   }
Index: solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.document.FieldSelectorVisitor;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.*;
@@ -406,13 +407,13 @@
     return doc(i, (Set<String>)null);
   }
 
-  /** Retrieve a {@link Document} using a {@link org.apache.lucene.document.FieldSelector}
-   * This method does not currently use the Solr document cache.
+  /** Visit a document's fields using a {@link StoredFieldVisitor}
+   *  This method does not currently use the Solr document cache.
    * 
-   * @see IndexReader#document(int, FieldSelector) */
+   * @see IndexReader#document(int, StoredFieldVisitor) */
   @Override
-  public Document doc(int n, FieldSelector fieldSelector) throws IOException {
-    return getIndexReader().document(n, fieldSelector);
+  public void doc(int n, StoredFieldVisitor visitor) throws IOException {
+    getIndexReader().document(n, visitor);
   }
 
   /**
@@ -433,8 +434,9 @@
     if(!enableLazyFieldLoading || fields == null) {
       d = getIndexReader().document(i);
     } else {
-      d = getIndexReader().document(i, 
-             new SetNonLazyFieldSelector(fields));
+      final FieldSelectorVisitor visitor = new FieldSelectorVisitor(new SetNonLazyFieldSelector(fields));
+      getIndexReader().document(i, visitor);
+      d = visitor.getDocument();
     }
 
     if (documentCache != null) {
Index: solr/core/src/java/org/apache/solr/search/Grouping.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/Grouping.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/search/Grouping.java	(working copy)
@@ -18,8 +18,9 @@
 package org.apache.solr.search;
 
 import org.apache.commons.lang.ArrayUtils;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.queries.function.DocValues;
 import org.apache.lucene.queries.function.FunctionQuery;
 import org.apache.lucene.queries.function.ValueSource;
@@ -752,7 +753,7 @@
           SchemaField schemaField = searcher.getSchema().getField(groupBy);
           FieldType fieldType = schemaField.getType();
           String readableValue = fieldType.indexedToReadable(group.groupValue.utf8ToString());
-          Fieldable field = schemaField.createField(readableValue, 0.0f);
+          IndexableField field = schemaField.createField(readableValue, 0.0f);
           nl.add("groupValue", fieldType.toObject(field));
         } else {
           nl.add("groupValue", null);
Index: solr/core/src/java/org/apache/solr/spelling/FileBasedSpellChecker.java
===================================================================
--- solr/core/src/java/org/apache/solr/spelling/FileBasedSpellChecker.java	(revision 1158028)
+++ solr/core/src/java/org/apache/solr/spelling/FileBasedSpellChecker.java	(working copy)
@@ -26,6 +26,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.spell.HighFrequencyDictionary;
 import org.apache.lucene.search.spell.PlainTextDictionary;
 import org.apache.lucene.store.RAMDirectory;
@@ -100,7 +101,7 @@
 
         for (String s : lines) {
           Document d = new Document();
-          d.add(new Field(WORD_FIELD_NAME, s, Field.Store.NO, Field.Index.ANALYZED));
+          d.add(new TextField(WORD_FIELD_NAME, s));
           writer.addDocument(d);
         }
         writer.optimize();
Index: solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java
===================================================================
--- solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java	(revision 1158028)
+++ solr/contrib/analysis-extras/src/java/org/apache/solr/schema/ICUCollationField.java	(working copy)
@@ -27,7 +27,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.collation.ICUCollationKeyAnalyzer;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.SortField;
 import org.apache.lucene.search.TermRangeQuery;
@@ -164,7 +164,7 @@
   }
 
   @Override
-  public void write(TextResponseWriter writer, String name, Fieldable f) throws IOException {
+  public void write(TextResponseWriter writer, String name, IndexableField f) throws IOException {
     writer.writeStr(name, f.stringValue(), true);
   }
 
Index: modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java
===================================================================
--- modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java	(revision 1158028)
+++ modules/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java	(working copy)
@@ -19,7 +19,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermFreqVector;
 import org.apache.lucene.search.*;
@@ -705,10 +707,10 @@
       // field does not store term vector info
       if (vector == null) {
         Document d = ir.document(docNum);
-        String text[] = d.getValues(fieldName);
-        if (text != null) {
-          for (int j = 0; j < text.length; j++) {
-            addTermFrequencies(new StringReader(text[j]), termFreqMap, fieldName);
+        IndexableField fields[] = d.getFields(fieldName);
+        if (fields != null) {
+          for (int j = 0; j < fields.length; j++) {
+            addTermFrequencies(new StringReader(fields[j].stringValue()), termFreqMap, fieldName);
           }
         }
       } else {
Index: modules/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java
===================================================================
--- modules/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java	(revision 1158028)
+++ modules/queries/src/test/org/apache/lucene/queries/function/FunctionTestSetup.java	(working copy)
@@ -4,7 +4,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.queries.function.valuesource.ByteFieldSource;
@@ -128,23 +130,26 @@
 
   private static void addDoc(RandomIndexWriter iw, int i) throws Exception {
     Document d = new Document();
-    Fieldable f;
+    Field f;
     int scoreAndID = i + 1;
 
-    f = newField(ID_FIELD, id2String(scoreAndID), Field.Store.YES, Field.Index.NOT_ANALYZED); // for debug purposes
-    f.setOmitNorms(true);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    customType.setOmitNorms(true);
+    
+    f = newField(ID_FIELD, id2String(scoreAndID), customType); // for debug purposes
     d.add(f);
 
-    f = newField(TEXT_FIELD, "text of doc" + scoreAndID + textLine(i), Field.Store.NO, Field.Index.ANALYZED); // for regular search
-    f.setOmitNorms(true);
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setOmitNorms(true);
+    f = newField(TEXT_FIELD, "text of doc" + scoreAndID + textLine(i), customType2); // for regular search
     d.add(f);
 
-    f = newField(INT_FIELD, "" + scoreAndID, Field.Store.NO, Field.Index.NOT_ANALYZED); // for function scoring
-    f.setOmitNorms(true);
+    f = newField(INT_FIELD, "" + scoreAndID, customType); // for function scoring
     d.add(f);
 
-    f = newField(FLOAT_FIELD, scoreAndID + ".000", Field.Store.NO, Field.Index.NOT_ANALYZED); // for function scoring
-    f.setOmitNorms(true);
+    f = newField(FLOAT_FIELD, scoreAndID + ".000", customType); // for function scoring
     d.add(f);
 
     iw.addDocument(d);
Index: modules/queries/src/test/org/apache/lucene/queries/mlt/TestMoreLikeThis.java
===================================================================
--- modules/queries/src/test/org/apache/lucene/queries/mlt/TestMoreLikeThis.java	(revision 1158028)
+++ modules/queries/src/test/org/apache/lucene/queries/mlt/TestMoreLikeThis.java	(working copy)
@@ -27,6 +27,8 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.BooleanClause;
@@ -66,7 +68,9 @@
   
   private void addDoc(RandomIndexWriter writer, String text) throws IOException {
     Document doc = new Document();
-    doc.add(newField("text", text, Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("text", text, customType));
     writer.addDocument(doc);
   }
   
Index: modules/join/src/test/org/apache/lucene/search/TestBlockJoin.java
===================================================================
--- modules/join/src/test/org/apache/lucene/search/TestBlockJoin.java	(revision 1158028)
+++ modules/join/src/test/org/apache/lucene/search/TestBlockJoin.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -42,16 +43,16 @@
   // One resume...
   private Document makeResume(String name, String country) {
     Document resume = new Document();
-    resume.add(newField("docType", "resume", Field.Index.NOT_ANALYZED));
-    resume.add(newField("name", name, Field.Store.YES, Field.Index.NOT_ANALYZED));
-    resume.add(newField("country", country, Field.Index.NOT_ANALYZED));
+    resume.add(newField("docType", "resume", StringField.TYPE_UNSTORED));
+    resume.add(newField("name", name, StringField.TYPE_STORED));
+    resume.add(newField("country", country, StringField.TYPE_UNSTORED));
     return resume;
   }
 
   // ... has multiple jobs
   private Document makeJob(String skill, int year) {
     Document job = new Document();
-    job.add(newField("skill", skill, Field.Store.YES, Field.Index.NOT_ANALYZED));
+    job.add(newField("skill", skill, StringField.TYPE_STORED));
     job.add(new NumericField("year").setIntValue(year));
     return job;
   }
@@ -188,15 +189,15 @@
     for(int parentDocID=0;parentDocID<numParentDocs;parentDocID++) {
       Document parentDoc = new Document();
       Document parentJoinDoc = new Document();
-      Field id = newField("parentID", ""+parentDocID, Field.Store.YES, Field.Index.NOT_ANALYZED);
+      Field id = newField("parentID", ""+parentDocID, StringField.TYPE_STORED);
       parentDoc.add(id);
       parentJoinDoc.add(id);
-      parentJoinDoc.add(newField("isParent", "x", Field.Index.NOT_ANALYZED));
+      parentJoinDoc.add(newField("isParent", "x", StringField.TYPE_UNSTORED));
       for(int field=0;field<parentFields.length;field++) {
         if (random.nextDouble() < 0.9) {
           Field f = newField("parent" + field,
                              parentFields[field][random.nextInt(parentFields[field].length)],
-                             Field.Index.NOT_ANALYZED);
+                             StringField.TYPE_UNSTORED);
           parentDoc.add(f);
           parentJoinDoc.add(f);
         }
@@ -215,7 +216,7 @@
         Document joinChildDoc = new Document();
         joinDocs.add(joinChildDoc);
 
-        Field childID = newField("childID", ""+childDocID, Field.Store.YES, Field.Index.NOT_ANALYZED);
+        Field childID = newField("childID", ""+childDocID, StringField.TYPE_STORED);
         childDoc.add(childID);
         joinChildDoc.add(childID);
 
@@ -223,7 +224,7 @@
           if (random.nextDouble() < 0.9) {
             Field f = newField("child" + childFieldID,
                                childFields[childFieldID][random.nextInt(childFields[childFieldID].length)],
-                               Field.Index.NOT_ANALYZED);
+                               StringField.TYPE_UNSTORED);
             childDoc.add(f);
             joinChildDoc.add(f);
           }
Index: modules/suggest/src/test/org/apache/lucene/search/spell/TestDirectSpellChecker.java
===================================================================
--- modules/suggest/src/test/org/apache/lucene/search/spell/TestDirectSpellChecker.java	(revision 1158028)
+++ modules/suggest/src/test/org/apache/lucene/search/spell/TestDirectSpellChecker.java	(working copy)
@@ -21,6 +21,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -39,7 +40,7 @@
 
     for (int i = 0; i < 20; i++) {
       Document doc = new Document();
-      doc.add(newField("numbers", English.intToEnglish(i), Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("numbers", English.intToEnglish(i), TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
 
@@ -73,7 +74,7 @@
     // add some more documents
     for (int i = 1000; i < 1100; i++) {
       Document doc = new Document();
-      doc.add(newField("numbers", English.intToEnglish(i), Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("numbers", English.intToEnglish(i), TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
 
@@ -96,13 +97,13 @@
         new MockAnalyzer(random, MockTokenizer.SIMPLE, true));
 
     Document doc = new Document();
-    doc.add(newField("text", "foobar", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("text", "foobar", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
-    doc.add(newField("text", "foobar", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("text", "foobar", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
-    doc.add(newField("text", "foobaz", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("text", "foobaz", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
-    doc.add(newField("text", "fobar", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("text", "fobar", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
    
     IndexReader ir = writer.getReader();
@@ -150,7 +151,7 @@
 
     for (int i = 0; i < 20; i++) {
       Document doc = new Document();
-      doc.add(newField("numbers", English.intToEnglish(i), Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("numbers", English.intToEnglish(i), TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
 
Index: modules/suggest/src/test/org/apache/lucene/search/spell/TestLuceneDictionary.java
===================================================================
--- modules/suggest/src/test/org/apache/lucene/search/spell/TestLuceneDictionary.java	(revision 1158028)
+++ modules/suggest/src/test/org/apache/lucene/search/spell/TestLuceneDictionary.java	(working copy)
@@ -23,7 +23,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.store.Directory;
@@ -51,23 +51,23 @@
     Document doc;
 
     doc = new  Document();
-    doc.add(newField("aaa", "foo", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("aaa", "foo", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     doc = new  Document();
-    doc.add(newField("aaa", "foo", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("aaa", "foo", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     doc = new  Document();
-    doc.add(new  Field("contents", "Tom", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("contents", "Tom", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     doc = new  Document();
-    doc.add(new  Field("contents", "Jerry", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("contents", "Jerry", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("zzz", "bar", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("zzz", "bar", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     writer.optimize();
Index: modules/suggest/src/test/org/apache/lucene/search/spell/TestSpellChecker.java
===================================================================
--- modules/suggest/src/test/org/apache/lucene/search/spell/TestSpellChecker.java	(revision 1158028)
+++ modules/suggest/src/test/org/apache/lucene/search/spell/TestSpellChecker.java	(working copy)
@@ -28,7 +28,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
@@ -58,9 +58,9 @@
 
     for (int i = 0; i < 1000; i++) {
       Document doc = new Document();
-      doc.add(newField("field1", English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(newField("field2", English.intToEnglish(i + 1), Field.Store.YES, Field.Index.ANALYZED)); // + word thousand
-      doc.add(newField("field3", "fvei" + (i % 2 == 0 ? " five" : ""), Field.Store.YES, Field.Index.ANALYZED)); // + word thousand
+      doc.add(newField("field1", English.intToEnglish(i), TextField.TYPE_STORED));
+      doc.add(newField("field2", English.intToEnglish(i + 1), TextField.TYPE_STORED)); // + word thousand
+      doc.add(newField("field3", "fvei" + (i % 2 == 0 ? " five" : ""), TextField.TYPE_STORED)); // + word thousand
       writer.addDocument(doc);
     }
     writer.close();
Index: modules/suggest/src/java/org/apache/lucene/search/spell/SpellChecker.java
===================================================================
--- modules/suggest/src/java/org/apache/lucene/search/spell/SpellChecker.java	(revision 1158028)
+++ modules/suggest/src/java/org/apache/lucene/search/spell/SpellChecker.java	(working copy)
@@ -28,7 +28,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -607,9 +609,7 @@
     Document doc = new Document();
     // the word field is never queried on... its indexed so it can be quickly
     // checked for rebuild (and stored for retrieval). Doesn't need norms or TF/pos
-    Field f = new Field(F_WORD, text, Field.Store.YES, Field.Index.NOT_ANALYZED);
-    f.setIndexOptions(IndexOptions.DOCS_ONLY);
-    f.setOmitNorms(true);
+    Field f = new Field(F_WORD, StringField.TYPE_STORED, text);
     doc.add(f); // orig term
     addGram(text, doc, ng1, ng2);
     return doc;
@@ -622,25 +622,22 @@
       String end = null;
       for (int i = 0; i < len - ng + 1; i++) {
         String gram = text.substring(i, i + ng);
-        Field ngramField = new Field(key, gram, Field.Store.NO, Field.Index.NOT_ANALYZED);
+        FieldType ft = new FieldType(StringField.TYPE_UNSTORED);
+        ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+        Field ngramField = new Field(key, ft, gram);
         // spellchecker does not use positional queries, but we want freqs
         // for scoring these multivalued n-gram fields.
-        ngramField.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
         doc.add(ngramField);
         if (i == 0) {
           // only one term possible in the startXXField, TF/pos and norms aren't needed.
-          Field startField = new Field("start" + ng, gram, Field.Store.NO, Field.Index.NOT_ANALYZED);
-          startField.setIndexOptions(IndexOptions.DOCS_ONLY);
-          startField.setOmitNorms(true);
+          Field startField = new StringField("start" + ng, gram);
           doc.add(startField);
         }
         end = gram;
       }
       if (end != null) { // may not be present if len==ng1
         // only one term possible in the endXXField, TF/pos and norms aren't needed.
-        Field endField = new Field("end" + ng, end, Field.Store.NO, Field.Index.NOT_ANALYZED);
-        endField.setIndexOptions(IndexOptions.DOCS_ONLY);
-        endField.setOmitNorms(true);
+        Field endField = new StringField("end" + ng, end);
         doc.add(endField);
       }
     }
Index: modules/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java
===================================================================
--- modules/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java	(revision 1158028)
+++ modules/facet/src/test/org/apache/lucene/facet/FacetTestUtils.java	(working copy)
@@ -7,9 +7,7 @@
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
@@ -130,8 +128,7 @@
     cps.add(cp);
     Document d = new Document();
     new CategoryDocumentBuilder(tw, iParams).setCategoryPaths(cps).build(d);
-    d.add(new Field("content", "alpha", Store.YES, Index.ANALYZED,
-        TermVector.NO));
+    d.add(new Field("content", TextField.TYPE_STORED, "alpha"));
     iw.addDocument(d);
   }
 
Index: modules/facet/src/test/org/apache/lucene/facet/search/CategoryListIteratorTest.java
===================================================================
--- modules/facet/src/test/org/apache/lucene/facet/search/CategoryListIteratorTest.java	(revision 1158028)
+++ modules/facet/src/test/org/apache/lucene/facet/search/CategoryListIteratorTest.java	(working copy)
@@ -13,6 +13,7 @@
 import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Payload;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -104,7 +105,7 @@
     for (int i = 0; i < data.length; i++) {
       dts.setIdx(i);
       Document doc = new Document();
-      doc.add(new Field("f", dts));
+      doc.add(new TextField("f", dts));
       writer.addDocument(doc);
     }
     IndexReader reader = writer.getReader();
@@ -155,10 +156,10 @@
       dts.setIdx(i);
       Document doc = new Document();
       if (i==0 || i == 2) {
-        doc.add(new Field("f", dts)); // only docs 0 & 2 have payloads!
+        doc.add(new TextField("f", dts)); // only docs 0 & 2 have payloads!
       }
       dts2.setIdx(i);
-      doc.add(new Field("f", dts2));
+      doc.add(new TextField("f", dts2));
       writer.addDocument(doc);
       writer.commit();
     }
@@ -168,7 +169,7 @@
     for (int i = 0; i < 10; ++i) {
       Document d = new Document();
       dts.setIdx(2);
-      d.add(new Field("f", dts2));
+      d.add(new TextField("f", dts2));
       writer.addDocument(d);
       if (i %10 == 0) {
         writer.commit();
Index: modules/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java
===================================================================
--- modules/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java	(revision 1158028)
+++ modules/facet/src/test/org/apache/lucene/facet/search/TestTopKInEachNodeResultHandler.java	(working copy)
@@ -7,9 +7,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -335,7 +333,7 @@
     cps.add(cp);
     Document d = new Document();
     new CategoryDocumentBuilder(tw, iParams).setCategoryPaths(cps).build(d);
-    d.add(new Field("content", "alpha", Store.YES, Index.ANALYZED, TermVector.NO));
+    d.add(new Field("content", TextField.TYPE_STORED, "alpha"));
     iw.addDocument(d);
   }
 
Index: modules/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java
===================================================================
--- modules/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java	(revision 1158028)
+++ modules/facet/src/test/org/apache/lucene/facet/search/DrillDownTest.java	(working copy)
@@ -7,8 +7,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -84,10 +83,10 @@
       ArrayList<CategoryPath> paths = new ArrayList<CategoryPath>();
       Document doc = new Document();
       if (i % 2 == 0) { // 50
-        doc.add(new Field("content", "foo", Store.NO, Index.ANALYZED));
+        doc.add(new TextField("content", "foo"));
       }
       if (i % 3 == 0) { // 33
-        doc.add(new Field("content", "bar", Store.NO, Index.ANALYZED));
+        doc.add(new TextField("content", "bar"));
       }
       if (i % 4 == 0) { // 25
         paths.add(new CategoryPath("a"));
Index: modules/facet/src/test/org/apache/lucene/facet/FacetTestBase.java
===================================================================
--- modules/facet/src/test/org/apache/lucene/facet/FacetTestBase.java	(revision 1158028)
+++ modules/facet/src/test/org/apache/lucene/facet/FacetTestBase.java	(working copy)
@@ -15,9 +15,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.IndexReader;
@@ -247,7 +245,7 @@
     CategoryDocumentBuilder builder = new CategoryDocumentBuilder(tw, iParams);
     builder.setCategoryPaths(categories);
     builder.build(d);
-    d.add(new Field("content", content, Store.YES, Index.ANALYZED, TermVector.NO));
+    d.add(new Field("content", TextField.TYPE_STORED, content));
     iw.addDocument(d);
   }
   
Index: modules/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java
===================================================================
--- modules/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java	(revision 1158028)
+++ modules/facet/src/test/org/apache/lucene/facet/util/TestScoredDocIDsUtils.java	(working copy)
@@ -7,8 +7,8 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -134,7 +134,7 @@
         int docNum = it.getDocID();
         assertNull(
             "Deleted docs must not appear in the allDocsScoredDocIds set: " + docNum, 
-            reader.document(docNum).getFieldable("del"));
+            reader.document(docNum).getField("del"));
       }
 
       assertEquals("Wrong number of (live) documents", allDocs.size(), numIteratedDocs);
@@ -166,7 +166,7 @@
             live != null && !live.get(docNum));
         assertNull(
             "Complement-Set must not contain docs from the original set (doc="+ docNum+")",
-            reader.document(docNum).getFieldable("del"));
+            reader.document(docNum).getField("del"));
         assertFalse(
             "Complement-Set must not contain docs from the original set (doc="+docNum+")",
             resultSet.fastGet(docNum));
@@ -189,8 +189,8 @@
     protected final static String delTxt = "delete";
     protected final static String alphaTxt = "alpha";
     
-    private final static Field deletionMark = new Field(field, delTxt, Store.NO, Index.NOT_ANALYZED_NO_NORMS);
-    private final static Field alphaContent = new Field(field, alphaTxt, Store.NO, Index.NOT_ANALYZED_NO_NORMS);
+    private final static Field deletionMark = new StringField(field, delTxt);
+    private final static Field alphaContent = new StringField(field, alphaTxt);
     
     protected final int numDocs;
     
@@ -208,7 +208,9 @@
         doc.add(deletionMark);
         // Add a special field for docs that are marked for deletion. Later we
         // assert that those docs are not returned by all-scored-doc-IDs.
-        doc.add(new Field("del", Integer.toString(docNum), Store.YES, Index.NO));
+        FieldType ft = new FieldType();
+        ft.setStored(true);
+        doc.add(new Field("del", ft, Integer.toString(docNum)));
       }
 
       if (haveAlpha(docNum)) {
Index: modules/facet/src/java/org/apache/lucene/facet/index/CategoryDocumentBuilder.java
===================================================================
--- modules/facet/src/java/org/apache/lucene/facet/index/CategoryDocumentBuilder.java	(revision 1158028)
+++ modules/facet/src/java/org/apache/lucene/facet/index/CategoryDocumentBuilder.java	(working copy)
@@ -10,6 +10,8 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 
 import org.apache.lucene.DocumentBuilder;
 import org.apache.lucene.facet.index.attributes.CategoryAttribute;
@@ -183,7 +185,9 @@
       // Finally creating a suitable field with stream and adding it to a
       // master field-list, used during the build process (see
       // super.build())
-      fieldList.add(new Field(e.getKey(), stream));
+      FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+      ft.setOmitNorms(true);
+      fieldList.add(new Field(e.getKey(), ft, stream));
     }
 
     return this;
@@ -289,7 +293,6 @@
    */
   public Document build(Document doc) {
     for (Field f : fieldList) {
-      f.setOmitNorms(true);
       doc.add(f);
     }
     return doc;
Index: modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyWriter.java
===================================================================
--- modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyWriter.java	(revision 1158028)
+++ modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyWriter.java	(working copy)
@@ -17,8 +17,9 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
@@ -179,10 +180,12 @@
     openLuceneIndex(directory, openMode);
     reader = null;
 
-    parentStreamField = new Field(Consts.FIELD_PAYLOADS, parentStream);
-    parentStreamField.setOmitNorms(true);
-    fullPathField = new Field(Consts.FULL, "", Store.YES, Index.NOT_ANALYZED_NO_NORMS);
-    fullPathField.setIndexOptions(IndexOptions.DOCS_ONLY);
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setOmitNorms(true);
+    parentStreamField = new Field(Consts.FIELD_PAYLOADS, ft, parentStream);
+    FieldType ft2 = new FieldType(StringField.TYPE_STORED);
+    ft2.setIndexOptions(IndexOptions.DOCS_ONLY);
+    fullPathField = new Field(Consts.FULL, ft2, "");
 
     this.nextID = indexWriter.maxDoc();
 
Index: modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/Consts.java
===================================================================
--- modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/Consts.java	(revision 1158028)
+++ modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/Consts.java	(working copy)
@@ -1,8 +1,11 @@
 package org.apache.lucene.facet.taxonomy.lucene;
 
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.FieldSelectorResult;
+import java.io.IOException;
 
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.StoredFieldVisitor;
+import org.apache.lucene.store.IndexInput;
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -31,18 +34,27 @@
   static final char[] PAYLOAD_PARENT_CHARS = PAYLOAD_PARENT.toCharArray();
 
   /**
-   * The following is a "field selector", an object which tells Lucene to
-   * extract only a single field rather than a whole document.
+   * The following is a "stored field visitor", an object
+   * which tells Lucene to extract only a single field
+   * rather than a whole document.
    */
-  public static final FieldSelector fullPathSelector = new FieldSelector() {
-    public FieldSelectorResult accept(String fieldName) {
-      if (fieldName.equals(FULL)) {
-        return FieldSelectorResult.LOAD_AND_BREAK;
-      }
-      return FieldSelectorResult.NO_LOAD;
-    }  
-  };
+  public static final class LoadFullPathOnly extends StoredFieldVisitor {
+    private String fullPath;
 
+    public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+      final byte[] bytes = new byte[numUTF8Bytes];
+      in.readBytes(bytes, 0, bytes.length);
+      fullPath = new String(bytes, "UTF-8");
+
+      // Stop loading:
+      return true;
+    }
+
+    public String getFullPath() {
+      return fullPath;
+    }
+  }
+
   /**
    * Delimiter used for creating the full path of a category from the list of
    * its labels from root. It is forbidden for labels to contain this
Index: modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyReader.java
===================================================================
--- modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyReader.java	(revision 1158028)
+++ modules/facet/src/java/org/apache/lucene/facet/taxonomy/lucene/LuceneTaxonomyReader.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.lucene.facet.taxonomy.CategoryPath;
 import org.apache.lucene.facet.taxonomy.TaxonomyReader;
+import org.apache.lucene.facet.taxonomy.lucene.Consts.LoadFullPathOnly;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.collections.LRUHashMap;
@@ -295,8 +296,9 @@
       if (catID<0 || catID>=indexReader.maxDoc()) {
         return null;
       }
-      ret = indexReader.document(catID, Consts.fullPathSelector)
-      .get(Consts.FULL);
+      final LoadFullPathOnly loader = new LoadFullPathOnly();
+      indexReader.document(catID, loader);
+      ret = loader.getFullPath();
     } finally {
       indexReaderLock.readLock().unlock();
     }
Index: modules/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java
===================================================================
--- modules/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java	(revision 1158028)
+++ modules/facet/src/examples/org/apache/lucene/facet/example/multiCL/MultiCLIndexer.java	(working copy)
@@ -6,8 +6,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.Term;
@@ -174,8 +173,8 @@
       // create a plain Lucene document and add some regular Lucene fields
       // to it
       Document doc = new Document();
-      doc.add(new Field(SimpleUtils.TITLE, docTitles[docNum], Store.YES, Index.ANALYZED));
-      doc.add(new Field(SimpleUtils.TEXT, docTexts[docNum], Store.NO, Index.ANALYZED));
+      doc.add(new Field(SimpleUtils.TITLE, TextField.TYPE_STORED, docTitles[docNum]));
+      doc.add(new TextField(SimpleUtils.TEXT, docTexts[docNum]));
 
       // finally add the document to the index
       categoryDocBuilder.build(doc);
Index: modules/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleIndexer.java
===================================================================
--- modules/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleIndexer.java	(revision 1158028)
+++ modules/facet/src/examples/org/apache/lucene/facet/example/simple/SimpleIndexer.java	(working copy)
@@ -5,8 +5,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -71,8 +70,8 @@
 
       // create a plain Lucene document and add some regular Lucene fields to it 
       Document doc = new Document();
-      doc.add(new Field(SimpleUtils.TITLE, SimpleUtils.docTitles[docNum], Store.YES, Index.ANALYZED));
-      doc.add(new Field(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum], Store.NO, Index.ANALYZED));
+      doc.add(new Field(SimpleUtils.TITLE, TextField.TYPE_STORED, SimpleUtils.docTitles[docNum]));
+      doc.add(new TextField(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum]));
 
       // invoke the category document builder for adding categories to the document and,
       // as required, to the taxonomy index 
Index: modules/facet/src/examples/org/apache/lucene/facet/example/association/AssociationIndexer.java
===================================================================
--- modules/facet/src/examples/org/apache/lucene/facet/example/association/AssociationIndexer.java	(revision 1158028)
+++ modules/facet/src/examples/org/apache/lucene/facet/example/association/AssociationIndexer.java	(working copy)
@@ -2,8 +2,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -94,10 +93,8 @@
       // create a plain Lucene document and add some regular Lucene fields
       // to it
       Document doc = new Document();
-      doc.add(new Field(SimpleUtils.TITLE, SimpleUtils.docTitles[docNum],
-          Store.YES, Index.ANALYZED));
-      doc.add(new Field(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum],
-          Store.NO, Index.ANALYZED));
+      doc.add(new Field(SimpleUtils.TITLE, TextField.TYPE_STORED, SimpleUtils.docTitles[docNum]));
+      doc.add(new TextField(SimpleUtils.TEXT, SimpleUtils.docTexts[docNum]));
 
       // invoke the category document builder for adding categories to the
       // document and,
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/classic/TestMultiFieldQueryParser.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/classic/TestMultiFieldQueryParser.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/classic/TestMultiFieldQueryParser.java	(working copy)
@@ -26,7 +26,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.BooleanClause;
 import org.apache.lucene.search.IndexSearcher;
@@ -284,7 +284,7 @@
     Directory ramDir = newDirectory();
     IndexWriter iw =  new IndexWriter(ramDir, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer));
     Document doc = new Document();
-    doc.add(newField("body", "blah the footest blah", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("body", "blah the footest blah", TextField.TYPE_UNSTORED));
     iw.addDocument(doc);
     iw.close();
     
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/classic/TestQueryParser.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/classic/TestQueryParser.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/classic/TestQueryParser.java	(working copy)
@@ -37,7 +37,7 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
@@ -1092,7 +1092,7 @@
     Analyzer a = new MockAnalyzer(random, MockTokenizer.SIMPLE, true, MockTokenFilter.ENGLISH_STOPSET, true);
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, a));
     Document doc = new Document();
-    doc.add(newField("f", "the wizard of ozzy", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("f", "the wizard of ozzy", TextField.TYPE_UNSTORED));
     w.addDocument(doc);
     IndexReader r = IndexReader.open(w, true);
     w.close();
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/surround/query/SingleFieldTestDb.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/surround/query/SingleFieldTestDb.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/surround/query/SingleFieldTestDb.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 
@@ -44,7 +45,7 @@
           new MockAnalyzer(random)));
       for (int j = 0; j < docs.length; j++) {
         Document d = new Document();
-        d.add(new Field(fieldName, docs[j], Field.Store.NO, Field.Index.ANALYZED));
+        d.add(new Field(fieldName, TextField.TYPE_UNSTORED, docs[j]));
         writer.addDocument(d);
       }
       writer.close();
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/complexPhrase/TestComplexPhraseQuery.java	(working copy)
@@ -22,7 +22,8 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.queryparser.classic.QueryParser;
 import org.apache.lucene.search.IndexSearcher;
@@ -113,12 +114,12 @@
     super.setUp();
     rd = newDirectory();
     IndexWriter w = new IndexWriter(rd, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < docsContent.length; i++) {
       Document doc = new Document();
-      doc.add(newField("name", docsContent[i].name, Field.Store.YES,
-          Field.Index.ANALYZED));
-      doc.add(newField("id", docsContent[i].id, Field.Store.YES,
-          Field.Index.ANALYZED));
+      doc.add(newField("name", docsContent[i].name, customType));
+      doc.add(newField("id", docsContent[i].id, customType));
       w.addDocument(doc);
     }
     w.close();
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestMultiFieldQPHelper.java	(working copy)
@@ -25,7 +25,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
 import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler;
@@ -321,8 +321,7 @@
     Directory ramDir = newDirectory();
     IndexWriter iw = new IndexWriter(ramDir, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer));
     Document doc = new Document();
-    doc.add(newField("body", "blah the footest blah", Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("body", "blah the footest blah", TextField.TYPE_UNSTORED));
     iw.addDocument(doc);
     iw.close();
 
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestQPHelper.java	(working copy)
@@ -40,7 +40,7 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
@@ -1242,7 +1242,7 @@
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new CannedAnalyzer()));
     Document doc = new Document();
-    doc.add(newField("field", "", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "", TextField.TYPE_UNSTORED));
     w.addDocument(doc);
     IndexReader r = IndexReader.open(w, true);
     IndexSearcher s = newSearcher(r);
Index: modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java
===================================================================
--- modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java	(revision 1158028)
+++ modules/queryparser/src/test/org/apache/lucene/queryparser/flexible/standard/TestNumericQueryParser.java	(working copy)
@@ -194,8 +194,7 @@
       numericConfigMap.put(type.name(), new NumericConfig(PRECISION_STEP,
           NUMBER_FORMAT, type));
       
-      NumericField field = new NumericField(type.name(), PRECISION_STEP,
-          Field.Store.YES, true);
+      NumericField field = new NumericField(type.name(), PRECISION_STEP, NumericField.TYPE_STORED);
       
       numericFieldMap.put(type.name(), field);
       doc.add(field);
@@ -204,8 +203,7 @@
     
     numericConfigMap.put(DATE_FIELD_NAME, new NumericConfig(PRECISION_STEP,
         DATE_FORMAT, NumericField.DataType.LONG));
-    NumericField dateField = new NumericField(DATE_FIELD_NAME, PRECISION_STEP,
-        Field.Store.YES, true);
+    NumericField dateField = new NumericField(DATE_FIELD_NAME, PRECISION_STEP, NumericField.TYPE_STORED);
     numericFieldMap.put(DATE_FIELD_NAME, dateField);
     doc.add(dateField);
     
Index: modules/analysis/common/src/test/org/apache/lucene/analysis/core/TestClassicAnalyzer.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/analysis/core/TestClassicAnalyzer.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/analysis/core/TestClassicAnalyzer.java	(working copy)
@@ -4,7 +4,7 @@
 import org.apache.lucene.analysis.BaseTokenStreamTestCase;
 import org.apache.lucene.analysis.standard.ClassicAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.DocsAndPositionsEnum;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.IndexReader;
@@ -261,12 +261,12 @@
 
     // This produces a too-long term:
     String contents = "abc xyz x" + bigTerm + " another term";
-    doc.add(new Field("content", contents, Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("content", contents));
     writer.addDocument(doc);
 
     // Make sure we can add another normal document
     doc = new Document();
-    doc.add(new Field("content", "abc bbb ccc", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("content", "abc bbb ccc"));
     writer.addDocument(doc);
     writer.close();
 
@@ -297,7 +297,7 @@
     // Make sure we can add a document with exactly the
     // maximum length term, and search on that term:
     doc = new Document();
-    doc.add(new Field("content", bigTerm, Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("content", bigTerm));
     ClassicAnalyzer sa = new ClassicAnalyzer(TEST_VERSION_CURRENT);
     sa.setMaxTokenLength(100000);
     writer  = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, sa));
Index: modules/analysis/common/src/test/org/apache/lucene/analysis/core/TestKeywordAnalyzer.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/analysis/core/TestKeywordAnalyzer.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/analysis/core/TestKeywordAnalyzer.java	(working copy)
@@ -24,6 +24,8 @@
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -46,8 +48,8 @@
         TEST_VERSION_CURRENT, new SimpleAnalyzer(TEST_VERSION_CURRENT)));
 
     Document doc = new Document();
-    doc.add(new Field("partnum", "Q36", Field.Store.YES, Field.Index.NOT_ANALYZED));
-    doc.add(new Field("description", "Illidium Space Modulator", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("partnum", StringField.TYPE_STORED, "Q36"));
+    doc.add(new Field("description", TextField.TYPE_STORED, "Illidium Space Modulator"));
     writer.addDocument(doc);
 
     writer.close();
@@ -74,10 +76,10 @@
     RAMDirectory dir = new RAMDirectory();
     IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new KeywordAnalyzer()));
     Document doc = new Document();
-    doc.add(new Field("partnum", "Q36", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("partnum", TextField.TYPE_STORED, "Q36"));
     writer.addDocument(doc);
     doc = new Document();
-    doc.add(new Field("partnum", "Q37", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("partnum", TextField.TYPE_STORED, "Q37"));
     writer.addDocument(doc);
     writer.close();
 
Index: modules/analysis/common/src/test/org/apache/lucene/analysis/miscellaneous/TestLimitTokenCountAnalyzer.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/analysis/miscellaneous/TestLimitTokenCountAnalyzer.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/analysis/miscellaneous/TestLimitTokenCountAnalyzer.java	(working copy)
@@ -26,7 +26,7 @@
 import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -58,7 +58,7 @@
     for(int i=0;i<10000;i++)
       b.append(" a");
     b.append(" x");
-    doc.add(newField("field", b.toString(), Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", b.toString(), TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.close();
 
Index: modules/analysis/common/src/test/org/apache/lucene/analysis/query/QueryAutoStopWordAnalyzerTest.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/analysis/query/QueryAutoStopWordAnalyzerTest.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/analysis/query/QueryAutoStopWordAnalyzerTest.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -51,8 +52,8 @@
       Document doc = new Document();
       String variedFieldValue = variedFieldValues[i % variedFieldValues.length];
       String repetitiveFieldValue = repetitiveFieldValues[i % repetitiveFieldValues.length];
-      doc.add(new Field("variedField", variedFieldValue, Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(new Field("repetitiveField", repetitiveFieldValue, Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(new Field("variedField", TextField.TYPE_STORED, variedFieldValue));
+      doc.add(new Field("repetitiveField", TextField.TYPE_STORED, repetitiveFieldValue));
       writer.addDocument(doc);
     }
     writer.close();
Index: modules/analysis/common/src/test/org/apache/lucene/analysis/sinks/TestTeeSinkTokenFilter.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/analysis/sinks/TestTeeSinkTokenFilter.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/analysis/sinks/TestTeeSinkTokenFilter.java	(working copy)
@@ -29,6 +29,8 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.TermPositionVector;
@@ -89,8 +91,12 @@
     Document doc = new Document();
     TeeSinkTokenFilter tee = new TeeSinkTokenFilter(analyzer.tokenStream("field", new StringReader("abcd   ")));
     TokenStream sink = tee.newSinkTokenStream();
-    Field f1 = new Field("field", tee, Field.TermVector.WITH_POSITIONS_OFFSETS);
-    Field f2 = new Field("field", sink, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setStoreTermVectors(true);
+    ft.setStoreTermVectorOffsets(true);
+    ft.setStoreTermVectorPositions(true);
+    Field f1 = new Field("field", ft, tee);
+    Field f2 = new Field("field", ft, sink);
     doc.add(f1);
     doc.add(f2);
     w.addDocument(doc);
Index: modules/analysis/common/src/test/org/apache/lucene/analysis/shingle/ShingleAnalyzerWrapperTest.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/analysis/shingle/ShingleAnalyzerWrapperTest.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/analysis/shingle/ShingleAnalyzerWrapperTest.java	(working copy)
@@ -29,6 +29,7 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.Term;
@@ -56,18 +57,15 @@
 
     Document doc;
     doc = new Document();
-    doc.add(new Field("content", "please divide this sentence into shingles",
-            Field.Store.YES,Field.Index.ANALYZED));
+    doc.add(new Field("content", TextField.TYPE_STORED, "please divide this sentence into shingles"));
     writer.addDocument(doc);
 
     doc = new Document();
-    doc.add(new Field("content", "just another test sentence",
-                      Field.Store.YES,Field.Index.ANALYZED));
+    doc.add(new Field("content", TextField.TYPE_STORED, "just another test sentence"));
     writer.addDocument(doc);
 
     doc = new Document();
-    doc.add(new Field("content", "a sentence which contains no test",
-                      Field.Store.YES,Field.Index.ANALYZED));
+    doc.add(new Field("content", TextField.TYPE_STORED, "a sentence which contains no test"));
     writer.addDocument(doc);
 
     writer.close();
Index: modules/analysis/common/src/test/org/apache/lucene/collation/CollationTestBase.java
===================================================================
--- modules/analysis/common/src/test/org/apache/lucene/collation/CollationTestBase.java	(revision 1158028)
+++ modules/analysis/common/src/test/org/apache/lucene/collation/CollationTestBase.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.search.ScoreDoc;
@@ -36,8 +37,11 @@
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Sort;
 import org.apache.lucene.search.SortField;
+import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IndexableBinaryStringTools;
 import org.apache.lucene.util.LuceneTestCase;
@@ -81,10 +85,8 @@
     IndexWriter writer = new IndexWriter(ramDir, new IndexWriterConfig(
         TEST_VERSION_CURRENT, analyzer));
     Document doc = new Document();
-    doc.add(new Field("content", "\u0633\u0627\u0628", 
-                      Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("body", "body",
-                      Field.Store.YES, Field.Index.NOT_ANALYZED));
+    doc.add(new Field("content", TextField.TYPE_STORED, "\u0633\u0627\u0628"));
+    doc.add(new Field("body", StringField.TYPE_STORED, "body"));
     writer.addDocument(doc);
     writer.close();
     IndexSearcher searcher = new IndexSearcher(ramDir, true);
@@ -118,8 +120,7 @@
     // orders the U+0698 character before the U+0633 character, so the single
     // index Term below should NOT be returned by a TermRangeQuery with a Farsi
     // Collator (or an Arabic one for the case when Farsi is not supported).
-    doc.add(new Field("content", "\u0633\u0627\u0628", 
-                      Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("content", TextField.TYPE_STORED, "\u0633\u0627\u0628"));
     writer.addDocument(doc);
     writer.close();
     IndexSearcher searcher = new IndexSearcher(ramDir, true);
@@ -141,10 +142,8 @@
     IndexWriter writer = new IndexWriter(farsiIndex, new IndexWriterConfig(
         TEST_VERSION_CURRENT, analyzer));
     Document doc = new Document();
-    doc.add(new Field("content", "\u0633\u0627\u0628", 
-                      Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("body", "body",
-                      Field.Store.YES, Field.Index.NOT_ANALYZED));
+    doc.add(new Field("content", TextField.TYPE_STORED, "\u0633\u0627\u0628"));
+    doc.add(new Field("body", StringField.TYPE_STORED, "body"));
     writer.addDocument(doc);
     writer.close();
 
@@ -204,20 +203,21 @@
       {  "J",   "y",     "HOT",             "HOT",             "HOT",             "HOT"             },
     };
 
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+    
     for (int i = 0 ; i < sortData.length ; ++i) {
       Document doc = new Document();
-      doc.add(new Field("tracer", sortData[i][0], 
-                        Field.Store.YES, Field.Index.NO));
-      doc.add(new Field("contents", sortData[i][1], 
-                        Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(new Field("tracer", customType, sortData[i][0]));
+      doc.add(new TextField("contents", sortData[i][1]));
       if (sortData[i][2] != null) 
-        doc.add(new Field("US", usAnalyzer.reusableTokenStream("US", new StringReader(sortData[i][2]))));
+        doc.add(new TextField("US", usAnalyzer.reusableTokenStream("US", new StringReader(sortData[i][2]))));
       if (sortData[i][3] != null) 
-        doc.add(new Field("France", franceAnalyzer.reusableTokenStream("France", new StringReader(sortData[i][3]))));
+        doc.add(new TextField("France", franceAnalyzer.reusableTokenStream("France", new StringReader(sortData[i][3]))));
       if (sortData[i][4] != null)
-        doc.add(new Field("Sweden", swedenAnalyzer.reusableTokenStream("Sweden", new StringReader(sortData[i][4]))));
+        doc.add(new TextField("Sweden", swedenAnalyzer.reusableTokenStream("Sweden", new StringReader(sortData[i][4]))));
       if (sortData[i][5] != null) 
-        doc.add(new Field("Denmark", denmarkAnalyzer.reusableTokenStream("Denmark", new StringReader(sortData[i][5]))));
+        doc.add(new TextField("Denmark", denmarkAnalyzer.reusableTokenStream("Denmark", new StringReader(sortData[i][5]))));
       writer.addDocument(doc);
     }
     writer.optimize();
@@ -250,9 +250,9 @@
     int n = result.length;
     for (int i = 0 ; i < n ; ++i) {
       Document doc = searcher.doc(result[i].doc);
-      String[] v = doc.getValues("tracer");
+      IndexableField[] v = doc.getFields("tracer");
       for (int j = 0 ; j < v.length ; ++j) {
-        buff.append(v[j]);
+        buff.append(v[j].stringValue());
       }
     }
     assertEquals(expectedResult, buff.toString());
Index: modules/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/PerFieldAnalyzerWrapper.java
===================================================================
--- modules/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/PerFieldAnalyzerWrapper.java	(revision 1158028)
+++ modules/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/PerFieldAnalyzerWrapper.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.index.IndexableField;
 
 import java.io.Reader;
 import java.io.IOException;
@@ -119,10 +119,11 @@
 
   /** Return the offsetGap from the analyzer assigned to field */
   @Override
-  public int getOffsetGap(Fieldable field) {
+  public int getOffsetGap(IndexableField field) {
     Analyzer analyzer = analyzerMap.get(field.name());
-    if (analyzer == null)
+    if (analyzer == null) {
       analyzer = defaultAnalyzer;
+    }
     return analyzer.getOffsetGap(field);
   }
   
Index: modules/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/LimitTokenCountAnalyzer.java
===================================================================
--- modules/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/LimitTokenCountAnalyzer.java	(revision 1158028)
+++ modules/analysis/common/src/java/org/apache/lucene/analysis/miscellaneous/LimitTokenCountAnalyzer.java	(working copy)
@@ -17,9 +17,9 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.index.IndexableField;
 
 import java.io.Reader;
 import java.io.IOException;
@@ -60,7 +60,7 @@
   }
 
   @Override
-  public int getOffsetGap(Fieldable field) {
+  public int getOffsetGap(IndexableField field) {
     return delegate.getOffsetGap(field);
   }
   
Index: modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTaskTest.java
===================================================================
--- modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTaskTest.java	(revision 1158028)
+++ modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTaskTest.java	(working copy)
@@ -34,8 +34,7 @@
 import org.apache.lucene.benchmark.byTask.utils.StreamUtils.Type;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
 
 /** Tests the functionality of {@link WriteLineDocTask}. */
 public class WriteLineDocTaskTest extends BenchmarkTestCase {
@@ -46,9 +45,9 @@
     @Override
     public Document makeDocument() throws Exception {
       Document doc = new Document();
-      doc.add(new Field(BODY_FIELD, "body", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(TITLE_FIELD, "title", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(DATE_FIELD, "date", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(BODY_FIELD, "body"));
+      doc.add(new StringField(TITLE_FIELD, "title"));
+      doc.add(new StringField(DATE_FIELD, "date"));
       return doc;
     }
     
@@ -60,9 +59,9 @@
     @Override
     public Document makeDocument() throws Exception {
       Document doc = new Document();
-      doc.add(new Field(BODY_FIELD, "body\r\ntext\ttwo", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(TITLE_FIELD, "title\r\ntext", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(DATE_FIELD, "date\r\ntext", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(BODY_FIELD, "body\r\ntext\ttwo"));
+      doc.add(new StringField(TITLE_FIELD, "title\r\ntext"));
+      doc.add(new StringField(DATE_FIELD, "date\r\ntext"));
       return doc;
     }
     
@@ -73,8 +72,8 @@
     @Override
     public Document makeDocument() throws Exception {
       Document doc = new Document();
-      doc.add(new Field(TITLE_FIELD, "title", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(DATE_FIELD, "date", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(TITLE_FIELD, "title"));
+      doc.add(new StringField(DATE_FIELD, "date"));
       return doc;
     }
   }
@@ -84,8 +83,8 @@
     @Override
     public Document makeDocument() throws Exception {
       Document doc = new Document();
-      doc.add(new Field(BODY_FIELD, "body", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(DATE_FIELD, "date", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(BODY_FIELD, "body"));
+      doc.add(new StringField(DATE_FIELD, "date"));
       return doc;
     }
   }
@@ -95,7 +94,7 @@
     @Override
     public Document makeDocument() throws Exception {
       Document doc = new Document();
-      doc.add(new Field(DATE_FIELD, "date", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(DATE_FIELD, "date"));
       return doc;
     }
   }
@@ -106,7 +105,7 @@
     @Override
     public Document makeDocument() throws Exception {
       Document doc = new Document();
-      doc.add(new Field(DATE_FIELD, "date", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(DATE_FIELD, "date"));
       return doc;
     }
   }
@@ -126,9 +125,9 @@
     public Document makeDocument() throws Exception {
       Document doc = new Document();
       String name = Thread.currentThread().getName();
-      doc.add(new Field(BODY_FIELD, "body_" + name, Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(TITLE_FIELD, "title_" + name, Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field(DATE_FIELD, "date_" + name, Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField(BODY_FIELD, "body_" + name));
+      doc.add(new StringField(TITLE_FIELD, "title_" + name));
+      doc.add(new StringField(DATE_FIELD, "date_" + name));
       return doc;
     }
     
Index: modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/feeds/DocMakerTest.java
===================================================================
--- modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/feeds/DocMakerTest.java	(revision 1158028)
+++ modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/feeds/DocMakerTest.java	(working copy)
@@ -137,28 +137,28 @@
     
     // Don't set anything, use the defaults
     doc = createTestNormsDocument(false, false, false, false);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).getOmitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).getOmitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
     
     // Set norms to false
     doc = createTestNormsDocument(true, false, false, false);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).getOmitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).getOmitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
     
     // Set norms to true
     doc = createTestNormsDocument(true, true, false, false);
-    assertFalse(doc.getField(DocMaker.TITLE_FIELD).getOmitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).getOmitNorms());
+    assertFalse(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
     
     // Set body norms to false
     doc = createTestNormsDocument(false, false, true, false);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).getOmitNorms());
-    assertTrue(doc.getField(DocMaker.BODY_FIELD).getOmitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
+    assertTrue(doc.getField(DocMaker.BODY_FIELD).omitNorms());
     
     // Set body norms to true
     doc = createTestNormsDocument(false, false, true, true);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).getOmitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).getOmitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
   }
   
 }
Index: modules/benchmark/src/java/org/apache/lucene/benchmark/quality/utils/DocNameExtractor.java
===================================================================
--- modules/benchmark/src/java/org/apache/lucene/benchmark/quality/utils/DocNameExtractor.java	(revision 1158028)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/quality/utils/DocNameExtractor.java	(working copy)
@@ -17,18 +17,20 @@
 package org.apache.lucene.benchmark.quality.utils;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.store.IndexInput;
 
 /**
  * Utility: extract doc names from an index
  */
 public class DocNameExtractor {
 
-  private FieldSelector fldSel;
-  private String docNameField;
+  private final String docNameField;
   
   /**
    * Constructor for DocNameExtractor.
@@ -36,13 +38,6 @@
    */
   public DocNameExtractor (final String docNameField) {
     this.docNameField = docNameField;
-    fldSel = new FieldSelector() {
-      public FieldSelectorResult accept(String fieldName) {
-        return fieldName.equals(docNameField) ? 
-            FieldSelectorResult.LOAD_AND_BREAK :
-              FieldSelectorResult.NO_LOAD;
-      }
-    };
   }
   
   /**
@@ -53,7 +48,25 @@
    * @throws IOException if cannot extract the doc name from the index.
    */
   public String docName(IndexSearcher searcher, int docid) throws IOException {
-    return searcher.doc(docid,fldSel).get(docNameField);
+    final List<String> name = new ArrayList<String>();
+    searcher.getIndexReader().document(docid, new StoredFieldVisitor() {
+        @Override
+        public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+          if (fieldInfo.name.equals(docNameField) && name.size() == 0) {
+            final byte[] b = new byte[numUTF8Bytes];
+            in.readBytes(b, 0, b.length);
+            name.add(new String(b, "UTF-8"));
+          } else {
+            in.seek(in.getFilePointer() + numUTF8Bytes);
+          }
+          return false;
+        }
+      });
+    if (name.size() != 0) {
+      return name.get(0);
+    } else {
+      return null;
+    }
   }
   
 }
Index: modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java
===================================================================
--- modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java	(revision 1158028)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java	(working copy)
@@ -26,8 +26,8 @@
 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.Fieldable;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.index.IndexableField;
 
 /**
  * Simple task to test performance of tokenizers.  It just
@@ -65,11 +65,11 @@
 
   @Override
   public int doLogic() throws Exception {
-    List<Fieldable> fields = doc.getFields();
+    List<IndexableField> fields = doc.getFields();
     Analyzer analyzer = getRunData().getAnalyzer();
     int tokenCount = 0;
-    for(final Fieldable field : fields) {
-      if (!field.isTokenized() || field instanceof NumericField) continue;
+    for(final IndexableField field : fields) {
+      if (!field.tokenized() || field instanceof NumericField) continue;
       
       final TokenStream stream;
       final TokenStream streamValue = field.tokenStreamValue();
Index: modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java
===================================================================
--- modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java	(revision 1158028)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/SearchTravRetLoadFieldSelectorTask.java	(working copy)
@@ -16,20 +16,20 @@
  */
 
 
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
 import org.apache.lucene.benchmark.byTask.PerfRunData;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.SetBasedFieldSelector;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.index.DocumentStoredFieldVisitor;
+import org.apache.lucene.index.DocumentStoredFieldVisitor;
 import org.apache.lucene.index.IndexReader;
 
-import java.util.StringTokenizer;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Collections;
-import java.io.IOException;
-
 /**
- * Search and Traverse and Retrieve docs task using a SetBasedFieldSelector.
+ * Search and Traverse and Retrieve docs task using a
+ * FieldVisitor loading only the requested fields.
  *
  * <p>Note: This task reuses the reader if it is already open.
  * Otherwise a reader is opened at start and closed at the end.
@@ -41,7 +41,8 @@
  */
 public class SearchTravRetLoadFieldSelectorTask extends SearchTravTask {
 
-  protected FieldSelector fieldSelector;
+  protected Set<String> fieldsToLoad;
+
   public SearchTravRetLoadFieldSelectorTask(PerfRunData runData) {
     super(runData);
     
@@ -55,18 +56,23 @@
 
   @Override
   protected Document retrieveDoc(IndexReader ir, int id) throws IOException {
-    return ir.document(id, fieldSelector);
+    if (fieldsToLoad == null) {
+      return ir.document(id);
+    } else {
+      DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(fieldsToLoad);
+      ir.document(id, visitor);
+      return visitor.getDocument();
+    }
   }
 
   @Override
   public void setParams(String params) {
     this.params = params; // cannot just call super.setParams(), b/c it's params differ.
-    Set<String> fieldsToLoad = new HashSet<String>();
+    fieldsToLoad = new HashSet<String>();
     for (StringTokenizer tokenizer = new StringTokenizer(params, ","); tokenizer.hasMoreTokens();) {
       String s = tokenizer.nextToken();
       fieldsToLoad.add(s);
     }
-    fieldSelector = new SetBasedFieldSelector(fieldsToLoad, Collections.<String> emptySet());
   }
 
 
Index: modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java
===================================================================
--- modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java	(revision 1158028)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.java	(working copy)
@@ -33,6 +33,7 @@
 import org.apache.lucene.benchmark.byTask.utils.StreamUtils;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexableField;
 
 /**
  * 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++) {
-      Field f = doc.getField(fieldsToWrite[i]);
+      IndexableField 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];
Index: modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java
===================================================================
--- modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java	(revision 1158028)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTask.java	(working copy)
@@ -28,8 +28,8 @@
 import org.apache.lucene.benchmark.byTask.PerfRunData;
 import org.apache.lucene.benchmark.byTask.feeds.QueryMaker;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.TopDocs;
@@ -300,10 +300,10 @@
    * @return A Collection of Field names (Strings)
    */
   protected Collection<String> getFieldsToHighlight(Document document) {
-    List<Fieldable> fieldables = document.getFields();
-    Set<String> result = new HashSet<String>(fieldables.size());
-    for (final Fieldable fieldable : fieldables) {
-      result.add(fieldable.name());
+    List<IndexableField> fields = document.getFields();
+    Set<String> result = new HashSet<String>(fields.size());
+    for (final IndexableField f : fields) {
+      result.add(f.name());
     }
     return result;
   }
Index: modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java
===================================================================
--- modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java	(revision 1158028)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/DocMaker.java	(working copy)
@@ -34,10 +34,10 @@
 import org.apache.lucene.benchmark.byTask.utils.Format;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 
 /**
  * Creates {@link Document} objects. Uses a {@link ContentSource} to generate
@@ -94,7 +94,7 @@
     final Document doc;
     DocData docData = new DocData();
     
-    public DocState(boolean reuseFields, Store store, Store bodyStore, Index index, Index bodyIndex, TermVector termVector) {
+    public DocState(boolean reuseFields, FieldType ft, FieldType bodyFt) {
 
       this.reuseFields = reuseFields;
       
@@ -103,11 +103,11 @@
         numericFields = new HashMap<String,NumericField>();
         
         // Initialize the map with the default fields.
-        fields.put(BODY_FIELD, new Field(BODY_FIELD, "", bodyStore, bodyIndex, termVector));
-        fields.put(TITLE_FIELD, new Field(TITLE_FIELD, "", store, index, termVector));
-        fields.put(DATE_FIELD, new Field(DATE_FIELD, "", store, index, termVector));
-        fields.put(ID_FIELD, new Field(ID_FIELD, "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-        fields.put(NAME_FIELD, new Field(NAME_FIELD, "", store, index, termVector));
+        fields.put(BODY_FIELD, new Field(BODY_FIELD, bodyFt, ""));
+        fields.put(TITLE_FIELD, new Field(TITLE_FIELD, ft, ""));
+        fields.put(DATE_FIELD, new Field(DATE_FIELD, ft, ""));
+        fields.put(ID_FIELD, new Field(ID_FIELD, StringField.TYPE_STORED, ""));
+        fields.put(NAME_FIELD, new Field(NAME_FIELD, ft, ""));
 
         numericFields.put(DATE_MSEC_FIELD, new NumericField(DATE_MSEC_FIELD));
         numericFields.put(TIME_SEC_FIELD, new NumericField(TIME_SEC_FIELD));
@@ -125,14 +125,14 @@
      * <code>reuseFields</code> was set to true, then it attempts to reuse a
      * Field instance. If such a field does not exist, it creates a new one.
      */
-    Field getField(String name, Store store, Index index, TermVector termVector) {
+    Field getField(String name, FieldType ft) {
       if (!reuseFields) {
-        return new Field(name, "", store, index, termVector);
+        return new Field(name, ft, "");
       }
       
       Field f = fields.get(name);
       if (f == null) {
-        f = new Field(name, "", store, index, termVector);
+        f = new Field(name, ft, "");
         fields.put(name, f);
       }
       return f;
@@ -179,12 +179,9 @@
 
   protected Config config;
 
-  protected Store storeVal = Store.NO;
-  protected Store bodyStoreVal = Store.NO;
-  protected Index indexVal = Index.ANALYZED_NO_NORMS;
-  protected Index bodyIndexVal = Index.ANALYZED;
-  protected TermVector termVecVal = TermVector.NO;
-  
+  protected FieldType valType;
+  protected FieldType bodyValType;
+    
   protected ContentSource source;
   protected boolean reuseFields;
   protected boolean indexProperties;
@@ -196,6 +193,13 @@
 
   private int printNum = 0;
 
+  public DocMaker() {
+    valType = new FieldType(TextField.TYPE_UNSTORED);
+    valType.setOmitNorms(true);
+    
+    bodyValType = new FieldType(TextField.TYPE_UNSTORED);
+  }
+  
   // create a doc
   // use only part of the body, modify it to keep the rest (or use all if size==0).
   // reset the docdata properties so they are not added more than once.
@@ -206,7 +210,10 @@
     doc.getFields().clear();
     
     // Set ID_FIELD
-    Field idField = ds.getField(ID_FIELD, storeVal, Index.NOT_ANALYZED_NO_NORMS, termVecVal);
+    FieldType ft = new FieldType(valType);
+    ft.setIndexed(true);
+
+    Field idField = ds.getField(ID_FIELD, ft);
     int id;
     if (r != null) {
       id = r.nextInt(updateDocIDLimit);
@@ -223,7 +230,7 @@
     String name = docData.getName();
     if (name == null) name = "";
     name = cnt < 0 ? name : name + "_" + cnt;
-    Field nameField = ds.getField(NAME_FIELD, storeVal, indexVal, termVecVal);
+    Field nameField = ds.getField(NAME_FIELD, valType);
     nameField.setValue(name);
     doc.add(nameField);
     
@@ -242,7 +249,7 @@
     } else {
       dateString = "";
     }
-    Field dateStringField = ds.getField(DATE_FIELD, storeVal, indexVal, termVecVal);
+    Field dateStringField = ds.getField(DATE_FIELD, valType);
     dateStringField.setValue(dateString);
     doc.add(dateStringField);
 
@@ -264,7 +271,7 @@
     
     // Set TITLE_FIELD
     String title = docData.getTitle();
-    Field titleField = ds.getField(TITLE_FIELD, storeVal, indexVal, termVecVal);
+    Field titleField = ds.getField(TITLE_FIELD, valType);
     titleField.setValue(title == null ? "" : title);
     doc.add(titleField);
     
@@ -285,12 +292,12 @@
         bdy = body.substring(0, size); // use part
         docData.setBody(body.substring(size)); // some left
       }
-      Field bodyField = ds.getField(BODY_FIELD, bodyStoreVal, bodyIndexVal, termVecVal);
+      Field bodyField = ds.getField(BODY_FIELD, bodyValType);
       bodyField.setValue(bdy);
       doc.add(bodyField);
       
       if (storeBytes) {
-        Field bytesField = ds.getField(BYTES_FIELD, Store.YES, Index.NOT_ANALYZED_NO_NORMS, TermVector.NO);
+        Field bytesField = ds.getField(BYTES_FIELD, StringField.TYPE_STORED);
         bytesField.setValue(bdy.getBytes("UTF-8"));
         doc.add(bytesField);
       }
@@ -300,7 +307,7 @@
       Properties props = docData.getProps();
       if (props != null) {
         for (final Map.Entry<Object,Object> entry : props.entrySet()) {
-          Field f = ds.getField((String) entry.getKey(), storeVal, indexVal, termVecVal);
+          Field f = ds.getField((String) entry.getKey(), valType);
           f.setValue((String) entry.getValue());
           doc.add(f);
         }
@@ -319,7 +326,7 @@
   protected DocState getDocState() {
     DocState ds = docState.get();
     if (ds == null) {
-      ds = new DocState(reuseFields, storeVal, bodyStoreVal, indexVal, bodyIndexVal, termVecVal);
+      ds = new DocState(reuseFields, valType, bodyValType);
       docState.set(ds);
     }
     return ds;
@@ -455,33 +462,23 @@
     boolean norms = config.get("doc.tokenized.norms", false);
     boolean bodyNorms = config.get("doc.body.tokenized.norms", true);
     boolean termVec = config.get("doc.term.vector", false);
-    storeVal = (stored ? Field.Store.YES : Field.Store.NO);
-    bodyStoreVal = (bodyStored ? Field.Store.YES : Field.Store.NO);
-    if (tokenized) {
-      indexVal = norms ? Index.ANALYZED : Index.ANALYZED_NO_NORMS;
-    } else {
-      indexVal = norms ? Index.NOT_ANALYZED : Index.NOT_ANALYZED_NO_NORMS;
-    }
-
-    if (bodyTokenized) {
-      bodyIndexVal = bodyNorms ? Index.ANALYZED : Index.ANALYZED_NO_NORMS;
-    } else {
-      bodyIndexVal = bodyNorms ? Index.NOT_ANALYZED : Index.NOT_ANALYZED_NO_NORMS;
-    }
-
     boolean termVecPositions = config.get("doc.term.vector.positions", false);
     boolean termVecOffsets = config.get("doc.term.vector.offsets", false);
-    if (termVecPositions && termVecOffsets) {
-      termVecVal = TermVector.WITH_POSITIONS_OFFSETS;
-    } else if (termVecPositions) {
-      termVecVal = TermVector.WITH_POSITIONS;
-    } else if (termVecOffsets) {
-      termVecVal = TermVector.WITH_OFFSETS;
-    } else if (termVec) {
-      termVecVal = TermVector.YES;
-    } else {
-      termVecVal = TermVector.NO;
-    }
+    
+    valType.setStored(stored);
+    bodyValType.setStored(bodyStored);
+    valType.setTokenized(tokenized);
+    valType.setOmitNorms(!norms);
+    bodyValType.setTokenized(bodyTokenized);
+    bodyValType.setOmitNorms(!bodyNorms);
+
+    valType.setStoreTermVectors(termVec);
+    valType.setStoreTermVectorPositions(termVecPositions);
+    valType.setStoreTermVectorOffsets(termVecOffsets);
+    bodyValType.setStoreTermVectors(termVec);
+    bodyValType.setStoreTermVectorPositions(termVecPositions);
+    bodyValType.setStoreTermVectorOffsets(termVecOffsets);
+    
     storeBytes = config.get("doc.store.body.bytes", false);
     
     reuseFields = config.get("doc.reuse.fields", true);
Index: modules/grouping/src/test/org/apache/lucene/search/grouping/TermAllGroupsCollectorTest.java
===================================================================
--- modules/grouping/src/test/org/apache/lucene/search/grouping/TermAllGroupsCollectorTest.java	(revision 1158028)
+++ modules/grouping/src/test/org/apache/lucene/search/grouping/TermAllGroupsCollectorTest.java	(working copy)
@@ -5,7 +5,7 @@
  * 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 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
@@ -20,6 +20,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
@@ -32,6 +34,8 @@
   public void testTotalGroupCount() throws Exception {
 
     final String groupField = "author";
+    FieldType customType = new FieldType();
+    customType.setStored(true);
 
     Directory dir = newDirectory();
     RandomIndexWriter w = new RandomIndexWriter(
@@ -41,51 +45,51 @@
                                                     new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     // 0
     Document doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author1"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "random text"));
+    doc.add(new Field("id", customType, "1"));
     w.addDocument(doc);
 
     // 1
     doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random text blob", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "2", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author1"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some more random text blob"));
+    doc.add(new Field("id", customType, "2"));
     w.addDocument(doc);
 
     // 2
     doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random textual data", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "3", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author1"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some more random textual data"));
+    doc.add(new Field("id", customType, "3"));
     w.addDocument(doc);
     w.commit(); // To ensure a second segment
 
     // 3
     doc = new Document();
-    doc.add(new Field(groupField, "author2", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "4", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author2"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some random text"));
+    doc.add(new Field("id", customType, "4"));
     w.addDocument(doc);
 
     // 4
     doc = new Document();
-    doc.add(new Field(groupField, "author3", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "5", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author3"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some more random text"));
+    doc.add(new Field("id", customType, "5"));
     w.addDocument(doc);
 
     // 5
     doc = new Document();
-    doc.add(new Field(groupField, "author3", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "random blob", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "6", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author3"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "random blob"));
+    doc.add(new Field("id", customType, "6"));
     w.addDocument(doc);
 
     // 6 -- no author field
     doc = new Document();
-    doc.add(new Field("content", "random word stuck in alot of other text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "6", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field("content", TextField.TYPE_STORED, "random word stuck in alot of other text"));
+    doc.add(new Field("id", customType, "6"));
     w.addDocument(doc);
 
     IndexSearcher indexSearcher = new IndexSearcher(w.getReader());
Index: modules/grouping/src/test/org/apache/lucene/search/grouping/TermAllGroupHeadsCollectorTest.java
===================================================================
--- modules/grouping/src/test/org/apache/lucene/search/grouping/TermAllGroupHeadsCollectorTest.java	(revision 1158028)
+++ modules/grouping/src/test/org/apache/lucene/search/grouping/TermAllGroupHeadsCollectorTest.java	(working copy)
@@ -21,6 +21,8 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -47,57 +49,57 @@
 
     // 0
     Document doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField(groupField, "author1", TextField.TYPE_STORED));
+    doc.add(newField("content", "random text", TextField.TYPE_STORED));
+    doc.add(newField("id", "1", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     // 1
     doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random text blob", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "2", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField(groupField, "author1", TextField.TYPE_STORED));
+    doc.add(newField("content", "some more random text blob", TextField.TYPE_STORED));
+    doc.add(newField("id", "2", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     // 2
     doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random textual data", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "3", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField(groupField, "author1", TextField.TYPE_STORED));
+    doc.add(newField("content", "some more random textual data", TextField.TYPE_STORED));
+    doc.add(newField("id", "3", StringField.TYPE_STORED));
     w.addDocument(doc);
     w.commit(); // To ensure a second segment
 
     // 3
     doc = new Document();
-    doc.add(new Field(groupField, "author2", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "4", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField(groupField, "author2", TextField.TYPE_STORED));
+    doc.add(newField("content", "some random text", TextField.TYPE_STORED));
+    doc.add(newField("id", "4", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     // 4
     doc = new Document();
-    doc.add(new Field(groupField, "author3", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "5", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField(groupField, "author3", TextField.TYPE_STORED));
+    doc.add(newField("content", "some more random text", TextField.TYPE_STORED));
+    doc.add(newField("id", "5", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     // 5
     doc = new Document();
-    doc.add(new Field(groupField, "author3", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "random blob", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "6", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField(groupField, "author3", TextField.TYPE_STORED));
+    doc.add(newField("content", "random blob", TextField.TYPE_STORED));
+    doc.add(newField("id", "6", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     // 6 -- no author field
     doc = new Document();
-    doc.add(new Field("content", "random word stuck in alot of other text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "6", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField("content", "random word stuck in alot of other text", TextField.TYPE_STORED));
+    doc.add(newField("id", "6", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     // 7 -- no author field
     doc = new Document();
-    doc.add(new Field("content", "random word stuck in alot of other text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "7", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField("content", "random word stuck in alot of other text", TextField.TYPE_STORED));
+    doc.add(newField("id", "7", StringField.TYPE_STORED));
     w.addDocument(doc);
 
     IndexSearcher indexSearcher = new IndexSearcher(w.getReader());
@@ -182,18 +184,18 @@
 
       Document doc = new Document();
       Document docNoGroup = new Document();
-      Field group = newField("group", "", Field.Index.NOT_ANALYZED);
+      Field group = newField("group", "", StringField.TYPE_UNSTORED);
       doc.add(group);
-      Field sort1 = newField("sort1", "", Field.Index.NOT_ANALYZED);
+      Field sort1 = newField("sort1", "", StringField.TYPE_UNSTORED);
       doc.add(sort1);
       docNoGroup.add(sort1);
-      Field sort2 = newField("sort2", "", Field.Index.NOT_ANALYZED);
+      Field sort2 = newField("sort2", "", StringField.TYPE_UNSTORED);
       doc.add(sort2);
       docNoGroup.add(sort2);
-      Field sort3 = newField("sort3", "", Field.Index.NOT_ANALYZED);
+      Field sort3 = newField("sort3", "", StringField.TYPE_UNSTORED);
       doc.add(sort3);
       docNoGroup.add(sort3);
-      Field content = newField("content", "", Field.Index.ANALYZED);
+      Field content = newField("content", "", TextField.TYPE_UNSTORED);
       doc.add(content);
       docNoGroup.add(content);
       NumericField id = new NumericField("id");
Index: modules/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java
===================================================================
--- modules/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java	(revision 1158028)
+++ modules/grouping/src/test/org/apache/lucene/search/grouping/TestGrouping.java	(working copy)
@@ -23,8 +23,11 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -47,6 +50,9 @@
 
     final String groupField = "author";
 
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+    
     Directory dir = newDirectory();
     RandomIndexWriter w = new RandomIndexWriter(
                                random,
@@ -55,50 +61,50 @@
                                                     new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     // 0
     Document doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "1", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author1"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "random text"));
+    doc.add(new Field("id", customType, "1"));
     w.addDocument(doc);
 
     // 1
     doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "2", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author1"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some more random text"));
+    doc.add(new Field("id", customType, "2"));
     w.addDocument(doc);
 
     // 2
     doc = new Document();
-    doc.add(new Field(groupField, "author1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random textual data", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "3", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author1"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some more random textual data"));
+    doc.add(new Field("id", customType, "3"));
     w.addDocument(doc);
 
     // 3
     doc = new Document();
-    doc.add(new Field(groupField, "author2", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "4", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author2"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some random text"));
+    doc.add(new Field("id", customType, "4"));
     w.addDocument(doc);
 
     // 4
     doc = new Document();
-    doc.add(new Field(groupField, "author3", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "some more random text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "5", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author3"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "some more random text"));
+    doc.add(new Field("id", customType, "5"));
     w.addDocument(doc);
 
     // 5
     doc = new Document();
-    doc.add(new Field(groupField, "author3", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("content", "random", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "6", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field(groupField, TextField.TYPE_STORED, "author3"));
+    doc.add(new Field("content", TextField.TYPE_STORED, "random"));
+    doc.add(new Field("id", customType, "6"));
     w.addDocument(doc);
 
     // 6 -- no author field
     doc = new Document();
-    doc.add(new Field("content", "random word stuck in alot of other text", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("id", "6", Field.Store.YES, Field.Index.NO));
+    doc.add(new Field("content", TextField.TYPE_STORED,  "random word stuck in alot of other text"));
+    doc.add(new Field("id", customType, "6"));
     w.addDocument(doc);
 
     IndexSearcher indexSearcher = new IndexSearcher(w.getReader());
@@ -386,18 +392,19 @@
         Document doc = new Document();
         docs.add(doc);
         if (groupValue.group != null) {
-          doc.add(newField("group", groupValue.group.utf8ToString(), Field.Index.NOT_ANALYZED));
+          doc.add(newField("group", groupValue.group.utf8ToString(), StringField.TYPE_UNSTORED));
         }
-        doc.add(newField("sort1", groupValue.sort1.utf8ToString(), Field.Index.NOT_ANALYZED));
-        doc.add(newField("sort2", groupValue.sort2.utf8ToString(), Field.Index.NOT_ANALYZED));
+        doc.add(newField("sort1", groupValue.sort1.utf8ToString(), StringField.TYPE_UNSTORED));
+        doc.add(newField("sort2", groupValue.sort2.utf8ToString(), StringField.TYPE_UNSTORED));
         doc.add(new NumericField("id").setIntValue(groupValue.id));
-        doc.add(newField("content", groupValue.content, Field.Index.ANALYZED));
+        doc.add(newField("content", groupValue.content, TextField.TYPE_UNSTORED));
         //System.out.println("TEST:     doc content=" + groupValue.content + " group=" + (groupValue.group == null ? "null" : groupValue.group.utf8ToString()) + " sort1=" + groupValue.sort1.utf8ToString() + " id=" + groupValue.id);
       }
       // So we can pull filter marking last doc in block:
-      final Field groupEnd = newField("groupend", "x", Field.Index.NOT_ANALYZED);
-      groupEnd.setIndexOptions(IndexOptions.DOCS_ONLY);
-      groupEnd.setOmitNorms(true);
+      FieldType ft = new FieldType(StringField.TYPE_UNSTORED);
+      ft.setIndexOptions(IndexOptions.DOCS_ONLY);
+      ft.setOmitNorms(true);
+      final Field groupEnd = newField("groupend", "x", ft);
       docs.get(docs.size()-1).add(groupEnd);
       // Add as a doc block:
       w.addDocuments(docs);
@@ -497,15 +504,15 @@
 
       Document doc = new Document();
       Document docNoGroup = new Document();
-      Field group = newField("group", "", Field.Index.NOT_ANALYZED);
+      Field group = newField("group", "", StringField.TYPE_UNSTORED);
       doc.add(group);
-      Field sort1 = newField("sort1", "", Field.Index.NOT_ANALYZED);
+      Field sort1 = newField("sort1", "", StringField.TYPE_UNSTORED);
       doc.add(sort1);
       docNoGroup.add(sort1);
-      Field sort2 = newField("sort2", "", Field.Index.NOT_ANALYZED);
+      Field sort2 = newField("sort2", "", StringField.TYPE_UNSTORED);
       doc.add(sort2);
       docNoGroup.add(sort2);
-      Field content = newField("content", "", Field.Index.ANALYZED);
+      Field content = newField("content", "", TextField.TYPE_UNSTORED);
       doc.add(content);
       docNoGroup.add(content);
       NumericField id = new NumericField("id");
Index: modules/grouping/src/java/org/apache/lucene/search/grouping/package.html
===================================================================
--- modules/grouping/src/java/org/apache/lucene/search/grouping/package.html	(revision 1158028)
+++ modules/grouping/src/java/org/apache/lucene/search/grouping/package.html	(working copy)
@@ -130,7 +130,7 @@
   List&lt;Document&gt; oneGroup = ...;
   
   Field groupEndField = new Field("groupEnd", "x", Field.Store.NO, Field.Index.NOT_ANALYZED);
-  groupEndField.setOmitTermFreqAndPositions(true);
+  groupEndField.setIndexOptions(IndexOptions.DOCS_ONLY);
   groupEndField.setOmitNorms(true);
   oneGroup.get(oneGroup.size()-1).add(groupEndField);
 
Index: lucene/contrib/CHANGES.txt
===================================================================
--- lucene/contrib/CHANGES.txt	(revision 1158028)
+++ lucene/contrib/CHANGES.txt	(working copy)
@@ -4,7 +4,15 @@
 http://s.apache.org/luceneversions
 
 ======================= Trunk (not yet released) =======================
+  
+Changes in Runtime Behavior
 
+ * LUCENE-3309: Fast vector highlighter now inserts the
+   MultiValuedSeparator for NOT_ANALYZED fields (in addition to
+   ANALYZED fields).  To ensure your offsets are correct you should
+   provide an analyzer that returns 1 from the offsetGap method.
+   (Mike McCandless)
+
 Build
 
  * LUCENE-2845: Moved contrib/benchmark to modules.
Index: lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java
===================================================================
--- lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java	(working copy)
@@ -37,9 +37,9 @@
 import org.apache.lucene.analysis.Token;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermVectorOffsetInfo;
 import org.apache.lucene.search.IndexSearcher;
@@ -238,7 +238,7 @@
         if (eFieldTermDocInfoFactoriesByTermText.getKey().indexed && !eFieldTermDocInfoFactoriesByTermText.getKey().omitNorms) {
           final String fieldName = eFieldTermDocInfoFactoriesByTermText.getKey().fieldName;
           final FieldInvertState invertState = new FieldInvertState();
-          invertState.setBoost(eFieldTermDocInfoFactoriesByTermText.getKey().boost * document.getDocument().getBoost());
+          invertState.setBoost(eFieldTermDocInfoFactoriesByTermText.getKey().boost);
           invertState.setLength(eFieldTermDocInfoFactoriesByTermText.getKey().fieldLength);
           normsByFieldNameAndDocumentNumber.get(fieldName)[document.getDocumentNumber()] = similarityProvider.get(fieldName).computeNorm(invertState);
         } else {
@@ -469,7 +469,7 @@
     // normalize settings per field name in document
 
     Map<String /* field name */, FieldSetting> fieldSettingsByFieldName = new HashMap<String, FieldSetting>();
-    for (Fieldable field : document.getDocument().getFields()) {
+    for (IndexableField field : document.getDocument()) {
       FieldSetting fieldSetting = fieldSettingsByFieldName.get(field.name());
       if (fieldSetting == null) {
         fieldSetting = new FieldSetting();
@@ -479,52 +479,52 @@
       }
 
       // todo: fixme: multiple fields with the same name does not mean field boost += more boost.
-      fieldSetting.boost *= field.getBoost();
+      fieldSetting.boost *= field.boost();
       //fieldSettings.dimensions++;
 
 
       // once fieldSettings, always fieldSettings.
-      if (field.getOmitNorms()) {
+      if (field.omitNorms()) {
         fieldSetting.omitNorms = true;
       }
-      if (field.isIndexed() ) {
+      if (field.indexed() ) {
         fieldSetting.indexed = true;
       }
-      if (field.isTokenized()) {
+      if (field.tokenized()) {
         fieldSetting.tokenized = true;
       }
-      if (field.isStored()) {
+      if (field.stored()) {
         fieldSetting.stored = true;
       }
-      if (field.isBinary()) {
+      if (field.binaryValue() != null) {
         fieldSetting.isBinary = true;
       }
-      if (field.isTermVectorStored()) {
+      if (field.storeTermVectors()) {
         fieldSetting.storeTermVector = true;
       }
-      if (field.isStorePositionWithTermVector()) {
+      if (field.storeTermVectorPositions()) {
         fieldSetting.storePositionWithTermVector = true;
       }
-      if (field.isStoreOffsetWithTermVector()) {
+      if (field.storeTermVectorOffsets()) {
         fieldSetting.storeOffsetWithTermVector = true;
       }
     }
 
-    Map<Fieldable, LinkedList<Token>> tokensByField = new LinkedHashMap<Fieldable, LinkedList<Token>>(20);
+    Map<IndexableField, LinkedList<Token>> tokensByField = new LinkedHashMap<IndexableField, LinkedList<Token>>(20);
 
     // tokenize indexed fields.
-    for (Iterator<Fieldable> it = document.getDocument().getFields().iterator(); it.hasNext();) {
+    for (Iterator<IndexableField> it = document.getDocument().iterator(); it.hasNext();) {
 
-      Fieldable field = it.next();
+      IndexableField field = it.next();
 
       FieldSetting fieldSetting = fieldSettingsByFieldName.get(field.name());
 
-      if (field.isIndexed()) {
+      if (field.indexed()) {
 
         LinkedList<Token> tokens = new LinkedList<Token>();
         tokensByField.put(field, tokens);
 
-        if (field.isTokenized()) {
+        if (field.tokenized()) {
           final TokenStream tokenStream;
           // todo readerValue(), binaryValue()
           if (field.tokenStreamValue() != null) {
@@ -564,8 +564,8 @@
         }
       }
 
-      if (!field.isStored()) {
-        it.remove();
+      if (!field.stored()) {
+        //it.remove();
       }
     }
 
@@ -574,7 +574,7 @@
     termDocumentInformationFactoryByDocument.put(document, termDocumentInformationFactoryByTermTextAndFieldSetting);
 
     // build term vector, term positions and term offsets
-    for (Map.Entry<Fieldable, LinkedList<Token>> eField_Tokens : tokensByField.entrySet()) {
+    for (Map.Entry<IndexableField, LinkedList<Token>> eField_Tokens : tokensByField.entrySet()) {
       FieldSetting fieldSetting = fieldSettingsByFieldName.get(eField_Tokens.getKey().name());
 
       Map<String, TermDocumentInformationFactory> termDocumentInformationFactoryByTermText = termDocumentInformationFactoryByTermTextAndFieldSetting.get(fieldSettingsByFieldName.get(eField_Tokens.getKey().name()));
@@ -610,7 +610,7 @@
           termDocumentInformationFactory.payloads.add(null);
         }
 
-        if (eField_Tokens.getKey().isStoreOffsetWithTermVector()) {
+        if (eField_Tokens.getKey().storeTermVectorOffsets()) {
 
           termDocumentInformationFactory.termOffsets.add(new TermVectorOffsetInfo(fieldSetting.offset + token.startOffset(), fieldSetting.offset + token.endOffset()));
           lastOffset = fieldSetting.offset + token.endOffset();
@@ -619,7 +619,7 @@
 
       }
 
-      if (eField_Tokens.getKey().isStoreOffsetWithTermVector()) {
+      if (eField_Tokens.getKey().storeTermVectorOffsets()) {
         fieldSetting.offset = lastOffset + 1;
       }
 
Index: lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndex.java
===================================================================
--- lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndex.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndex.java	(working copy)
@@ -27,8 +27,8 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MultiNorms;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermsEnum;
@@ -190,16 +190,16 @@
         InstantiatedDocument document = new InstantiatedDocument();
         // copy stored fields from source reader
         Document sourceDocument = sourceIndexReader.document(i);
-        for (Fieldable field : sourceDocument.getFields()) {
+        for (IndexableField field : sourceDocument) {
           if (fields == null || fields.contains(field.name())) {
             document.getDocument().add(field);
           }
         }
         document.setDocumentNumber(i);
         documentsByNumber[i] = document;
-        for (Fieldable field : document.getDocument().getFields()) {
+        for (IndexableField field : document.getDocument()) {
           if (fields == null || fields.contains(field.name())) {
-            if (field.isTermVectorStored()) {
+            if (field.storeTermVectors()) {
               if (document.getVectorSpace() == null) {
                 document.setVectorSpace(new HashMap<String, List<InstantiatedTermDocumentInformation>>());
               }
@@ -290,8 +290,8 @@
       if (document == null) {
         continue; // deleted
       }
-      for (Fieldable field : document.getDocument().getFields()) {
-        if (field.isTermVectorStored() && field.isStoreOffsetWithTermVector()) {
+      for (IndexableField field : document.getDocument()) {
+        if (field.storeTermVectors() && field.storeTermVectorOffsets()) {
           TermPositionVector termPositionVector = (TermPositionVector) sourceIndexReader.getTermFreqVector(document.getDocumentNumber(), field.name());
           if (termPositionVector != null) {
             for (int i = 0; i < termPositionVector.getTerms().length; i++) {
Index: lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java
===================================================================
--- lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java	(working copy)
@@ -30,7 +30,6 @@
 import java.util.Comparator;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.codecs.PerDocValues;
 import org.apache.lucene.store.Directory;
@@ -252,42 +251,6 @@
   }
 
   /**
-   * Return the {@link org.apache.lucene.document.Document} at the <code>n</code><sup>th</sup>
-   * position.
-     <p>
-   * <b>Warning!</b>
-   * The resulting document is the actual stored document instance
-   * and not a deserialized clone as retuned by an IndexReader
-   * over a {@link org.apache.lucene.store.Directory}.
-   * I.e., if you need to touch the document, clone it first!
-   * <p>
-   * This can also be seen as a feature for live changes of stored values,
-   * but be careful! Adding a field with an name unknown to the index
-   * or to a field with previously no stored values will make
-   * {@link org.apache.lucene.store.instantiated.InstantiatedIndexReader#getFieldNames(org.apache.lucene.index.IndexReader.FieldOption)}
-   * out of sync, causing problems for instance when merging the
-   * instantiated index to another index.
-     <p>
-   * This implementation ignores the field selector! All stored fields are always returned!
-   * <p>
-   *
-   * @param n document number
-   * @param fieldSelector ignored
-   * @return The stored fields of the {@link org.apache.lucene.document.Document} at the nth position
-   * @throws CorruptIndexException if the index is corrupt
-   * @throws IOException if there is a low-level IO error
-   * 
-   * @see org.apache.lucene.document.Fieldable
-   * @see org.apache.lucene.document.FieldSelector
-   * @see org.apache.lucene.document.SetBasedFieldSelector
-   * @see org.apache.lucene.document.LoadFirstFieldSelector
-   */
-  @Override
-  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
-    return document(n);
-  }
-
-  /**
    * Returns the stored fields of the <code>n</code><sup>th</sup>
    * <code>Document</code> in this index.
    * <p>
@@ -313,6 +276,11 @@
     return getIndex().getDocumentsByNumber()[n].getDocument();
   }
 
+  @Override
+  public void document(int docID, StoredFieldVisitor visitor) throws IOException {
+    throw new UnsupportedOperationException();
+  }
+  
   /**
    * never ever touch these values. it is the true values, unless norms have
    * been touched.
Index: lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedDocument.java
===================================================================
--- lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedDocument.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedDocument.java	(working copy)
@@ -68,7 +68,6 @@
     return document;
   }
 
-
   @Override
   public String toString() {
     return document.toString();
Index: lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestRealTime.java
===================================================================
--- lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestRealTime.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestRealTime.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.util.LuceneTestCase;
@@ -43,7 +44,7 @@
     Collector collector;
 
     doc = new Document();
-    doc.add(new Field("f", "a", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(new StringField("f", "a"));
     writer.addDocument(doc);
     writer.commit();
 
@@ -52,7 +53,7 @@
     assertEquals(1, collector.hits);
 
     doc = new Document();
-    doc.add(new Field("f", "a", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(new StringField("f", "a"));
     writer.addDocument(doc);
     writer.commit();
 
Index: lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestIndicesEquals.java
===================================================================
--- lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestIndicesEquals.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestIndicesEquals.java	(working copy)
@@ -29,6 +29,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.MultiNorms;
@@ -204,19 +206,47 @@
 
 
   private void assembleDocument(Document document, int i) {
-    document.add(new Field("a", i + " Do you really want to go and live in that house all winter?", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorOffsets(true);
+    customType.setStoreTermVectorPositions(true);
+    //document.add(new Field("a", i + " Do you really want to go and live in that house all winter?", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    document.add(new Field("a", customType, i + " Do you really want to go and live in that house all winter?"));
     if (i > 0) {
-      document.add(new Field("b0", i + " All work and no play makes Jack a dull boy", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-      document.add(new Field("b1", i + " All work and no play makes Jack a dull boy", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO));
-      document.add(new Field("b2", i + " All work and no play makes Jack a dull boy", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
-      document.add(new Field("b3", i + " All work and no play makes Jack a dull boy", Field.Store.YES, Field.Index.NO, Field.TermVector.NO));
+      //document.add(new Field("b0", i + " All work and no play makes Jack a dull boy", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      document.add(new Field("b0", customType, i + " All work and no play makes Jack a dull boy"));
+
+      //document.add(new Field("b1", i + " All work and no play makes Jack a dull boy", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, Field.TermVector.NO));
+      FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+      customType2.setStored(true);
+      customType2.setTokenized(false);
+      customType2.setOmitNorms(true);
+      document.add(new Field("b1", customType2, i + " All work and no play makes Jack a dull boy"));
+      
+      //document.add(new Field("b2", i + " All work and no play makes Jack a dull boy", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.NO));
+      FieldType customType3 = new FieldType(TextField.TYPE_UNSTORED);
+      customType3.setTokenized(false);
+      document.add(new Field("b1", customType3, i + " All work and no play makes Jack a dull boy"));
+      
+      //document.add(new Field("b3", i + " All work and no play makes Jack a dull boy", Field.Store.YES, Field.Index.NO, Field.TermVector.NO));
+      FieldType customType4 = new FieldType(TextField.TYPE_UNSTORED);
+      customType4.setStored(true);
+      customType4.setIndexed(false);
+      customType4.setTokenized(false);
+      document.add(new Field("b1", customType4, i + " All work and no play makes Jack a dull boy"));
       if (i > 1) {
-        document.add(new Field("c", i + " Redrum redrum", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+        //document.add(new Field("c", i + " Redrum redrum", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+        document.add(new Field("c", customType, i + " Redrum redrum"));
         if (i > 2) {
-          document.add(new Field("d", i + " Hello Danny, come and play with us... forever and ever. and ever.", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+          //document.add(new Field("d", i + " Hello Danny, come and play with us... forever and ever. and ever.", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+          document.add(new Field("d", customType, i + " Hello Danny, come and play with us... forever and ever. and ever."));
           if (i > 3) {
-            Field f = new Field("e", i + " Heres Johnny!", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
-            f.setOmitNorms(true);
+            //Field f = new Field("e", i + " Heres Johnny!", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+            //f.setOmitNorms(true);
+            FieldType customType5 = new FieldType(TextField.TYPE_UNSTORED);
+            customType5.setOmitNorms(true);
+            Field f = new Field("e", customType5, i + " Heres Johnny!");
             document.add(f);
             if (i > 4) {
               final List<Token> tokens = new ArrayList<Token>(2);
@@ -247,7 +277,8 @@
                 }
               };
               
-              document.add(new Field("f", ts));
+              //document.add(new Field("f", ts));
+              document.add(new TextField("f", ts));
             }
           }
         }
Index: lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestUnoptimizedReaderOnConstructor.java
===================================================================
--- lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestUnoptimizedReaderOnConstructor.java	(revision 1158028)
+++ lucene/contrib/instantiated/src/test/org/apache/lucene/store/instantiated/TestUnoptimizedReaderOnConstructor.java	(working copy)
@@ -25,7 +25,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 
 /**
  * @since 2009-mar-30 13:15:49
@@ -66,7 +66,7 @@
 
   private void addDocument(IndexWriter iw, String text) throws IOException {
     Document doc = new Document();
-    doc.add(new Field("field", text, Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("field", text));
     iw.addDocument(doc);
   }
 }
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribFieldsReader.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribFieldsReader.java	(revision 0)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribFieldsReader.java	(revision 1160484)
@@ -0,0 +1,319 @@
+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.File;
+import java.io.IOException;
+import java.util.*;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.document.FieldSelectorVisitor;
+import org.apache.lucene.document.LoadFirstFieldSelector;
+import org.apache.lucene.document.SetBasedFieldSelector;
+import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.store.AlreadyClosedException;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util._TestUtil;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+
+public class TestContribFieldsReader extends LuceneTestCase {
+  private static Directory dir;
+  private static org.apache.lucene.document.Document testDoc = new org.apache.lucene.document.Document();
+  private static FieldInfos fieldInfos = null;
+
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    fieldInfos = new FieldInfos();
+    DocHelper.setupDoc(testDoc);
+    _TestUtil.add(testDoc, fieldInfos);
+    dir = newDirectory();
+    IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy());
+    ((LogMergePolicy) conf.getMergePolicy()).setUseCompoundFile(false);
+    IndexWriter writer = new IndexWriter(dir, conf);
+    writer.addDocument(testDoc);
+    writer.close();
+  }
+
+  @AfterClass
+  public static void afterClass() throws Exception {
+    dir.close();
+    dir = null;
+    fieldInfos = null;
+    testDoc = null;
+  }
+
+  private Document getDocument(IndexReader ir, int docID, FieldSelector selector) throws IOException {
+    final FieldSelectorVisitor visitor = new FieldSelectorVisitor(selector);
+    ir.document(docID, visitor);
+    return visitor.getDocument();
+  }
+
+  public void testLazyFields() throws Exception {
+    assertTrue(dir != null);
+    assertTrue(fieldInfos != null);
+    IndexReader reader = IndexReader.open(dir);
+    Set<String> loadFieldNames = new HashSet<String>();
+    loadFieldNames.add(DocHelper.TEXT_FIELD_1_KEY);
+    loadFieldNames.add(DocHelper.TEXT_FIELD_UTF1_KEY);
+    Set<String> lazyFieldNames = new HashSet<String>();
+    //new String[]{DocHelper.LARGE_LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_BINARY_KEY};
+    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
+    lazyFieldNames.add(DocHelper.LAZY_FIELD_KEY);
+    lazyFieldNames.add(DocHelper.LAZY_FIELD_BINARY_KEY);
+    lazyFieldNames.add(DocHelper.TEXT_FIELD_UTF2_KEY);
+    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames);
+    Document doc = getDocument(reader, 0, fieldSelector);
+    assertTrue("doc is null and it shouldn't be", doc != null);
+    IndexableField field = doc.getField(DocHelper.LAZY_FIELD_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertTrue("field is not lazy and it should be", field.getClass().getSimpleName().equals("LazyField"));
+    String value = field.stringValue();
+    assertTrue("value is null and it shouldn't be", value != null);
+    assertTrue(value + " is not equal to " + DocHelper.LAZY_FIELD_TEXT, value.equals(DocHelper.LAZY_FIELD_TEXT) == true);
+    assertTrue("calling stringValue() twice should give same reference", field.stringValue() == field.stringValue());
+
+    field = doc.getField(DocHelper.TEXT_FIELD_1_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertFalse("Field is lazy and it should not be", field.getClass().getSimpleName().equals("LazyField"));
+    field = doc.getField(DocHelper.TEXT_FIELD_UTF1_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertFalse("Field is lazy and it should not be", field.getClass().getSimpleName().equals("LazyField"));
+    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF1_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF1_TEXT) == true);
+
+    field = doc.getField(DocHelper.TEXT_FIELD_UTF2_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertTrue("Field is lazy and it should not be", field.getClass().getSimpleName().equals("LazyField"));
+    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF2_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF2_TEXT) == true);
+
+    field = doc.getField(DocHelper.LAZY_FIELD_BINARY_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertTrue("stringValue isn't null for lazy binary field", field.stringValue() == null);
+
+    byte [] bytes = field.binaryValue().bytes;
+    assertTrue("bytes is null and it shouldn't be", bytes != null);
+    assertTrue("", DocHelper.LAZY_FIELD_BINARY_BYTES.length == bytes.length);
+    assertTrue("calling binaryValue() twice should give same reference", field.binaryValue().bytes == field.binaryValue().bytes);
+    for (int i = 0; i < bytes.length; i++) {
+      assertTrue("byte[" + i + "] is mismatched", bytes[i] == DocHelper.LAZY_FIELD_BINARY_BYTES[i]);
+
+    }
+    reader.close();
+  }
+
+  public void testLatentFields() throws Exception {
+    assertTrue(dir != null);
+    assertTrue(fieldInfos != null);
+    IndexReader reader = IndexReader.open(dir);
+    Set<String> loadFieldNames = new HashSet<String>();
+    loadFieldNames.add(DocHelper.TEXT_FIELD_1_KEY);
+    loadFieldNames.add(DocHelper.TEXT_FIELD_UTF1_KEY);
+    Set<String> lazyFieldNames = new HashSet<String>();
+    //new String[]{DocHelper.LARGE_LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_BINARY_KEY};
+    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
+    lazyFieldNames.add(DocHelper.LAZY_FIELD_KEY);
+    lazyFieldNames.add(DocHelper.LAZY_FIELD_BINARY_KEY);
+    lazyFieldNames.add(DocHelper.TEXT_FIELD_UTF2_KEY);
+
+    // Use LATENT instead of LAZY
+    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames) {
+        @Override
+        public FieldSelectorResult accept(String fieldName) {
+          final FieldSelectorResult result = super.accept(fieldName);
+          if (result == FieldSelectorResult.LAZY_LOAD) {
+            return FieldSelectorResult.LATENT;
+          } else {
+            return result;
+          }
+        }
+      };
+
+    Document doc = getDocument(reader, 0, fieldSelector);
+    assertTrue("doc is null and it shouldn't be", doc != null);
+    IndexableField field = doc.getField(DocHelper.LAZY_FIELD_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertTrue("field is not lazy and it should be", field.getClass().getSimpleName().equals("LazyField"));
+    String value = field.stringValue();
+    assertTrue("value is null and it shouldn't be", value != null);
+    assertTrue(value + " is not equal to " + DocHelper.LAZY_FIELD_TEXT, value.equals(DocHelper.LAZY_FIELD_TEXT) == true);
+    assertTrue("calling stringValue() twice should give different references", field.stringValue() != field.stringValue());
+
+    field = doc.getField(DocHelper.TEXT_FIELD_1_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertFalse("Field is lazy and it should not be", field.getClass().getSimpleName().equals("LazyField"));
+    assertTrue("calling stringValue() twice should give same reference", field.stringValue() == field.stringValue());
+
+    field = doc.getField(DocHelper.TEXT_FIELD_UTF1_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertFalse("Field is lazy and it should not be", field.getClass().getSimpleName().equals("LazyField"));
+    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF1_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF1_TEXT) == true);
+    assertTrue("calling stringValue() twice should give same reference", field.stringValue() == field.stringValue());
+
+    field = doc.getField(DocHelper.TEXT_FIELD_UTF2_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertTrue("Field is lazy and it should not be", field.getClass().getSimpleName().equals("LazyField"));
+    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF2_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF2_TEXT) == true);
+    assertTrue("calling stringValue() twice should give different references", field.stringValue() != field.stringValue());
+
+    field = doc.getField(DocHelper.LAZY_FIELD_BINARY_KEY);
+    assertTrue("field is null and it shouldn't be", field != null);
+    assertTrue("stringValue isn't null for lazy binary field", field.stringValue() == null);
+    assertTrue("calling binaryValue() twice should give different references", field.binaryValue().bytes != field.binaryValue().bytes);
+
+    byte [] bytes = field.binaryValue().bytes;
+    assertTrue("bytes is null and it shouldn't be", bytes != null);
+    assertTrue("", DocHelper.LAZY_FIELD_BINARY_BYTES.length == bytes.length);
+    for (int i = 0; i < bytes.length; i++) {
+      assertTrue("byte[" + i + "] is mismatched", bytes[i] == DocHelper.LAZY_FIELD_BINARY_BYTES[i]);
+
+    }
+    reader.close();
+  }
+
+  public void testLoadFirst() throws Exception {
+    assertTrue(dir != null);
+    assertTrue(fieldInfos != null);
+    IndexReader reader = IndexReader.open(dir);
+    LoadFirstFieldSelector fieldSelector = new LoadFirstFieldSelector();
+    Document doc = getDocument(reader, 0, fieldSelector);
+    assertTrue("doc is null and it shouldn't be", doc != null);
+    int count = 0;
+    List<IndexableField> l = doc.getFields();
+    for (final IndexableField IndexableField : l ) {
+      Field field = (Field) IndexableField;
+
+      assertTrue("field is null and it shouldn't be", field != null);
+      String sv = field.stringValue();
+      assertTrue("sv is null and it shouldn't be", sv != null);
+      count++;
+    }
+    assertTrue(count + " does not equal: " + 1, count == 1);
+    reader.close();
+  }
+
+  /**
+   * Not really a test per se, but we should have some way of assessing whether this is worthwhile.
+   * <p/>
+   * Must test using a File based directory
+   *
+   * @throws Exception
+   */
+  public void testLazyPerformance() throws Exception {
+    String userName = System.getProperty("user.name");
+    File file = _TestUtil.getTempDir("lazyDir" + userName);
+    Directory tmpDir = newFSDirectory(file);
+    assertTrue(tmpDir != null);
+
+    IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE).setMergePolicy(newLogMergePolicy());
+    ((LogMergePolicy) conf.getMergePolicy()).setUseCompoundFile(false);
+    IndexWriter writer = new IndexWriter(tmpDir, conf);
+    writer.addDocument(testDoc);
+    writer.close();
+
+    assertTrue(fieldInfos != null);
+    long lazyTime = 0;
+    long regularTime = 0;
+    int length = 10;
+    Set<String> lazyFieldNames = new HashSet<String>();
+    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
+    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(Collections. <String> emptySet(), lazyFieldNames);
+
+    for (int i = 0; i < length; i++) {
+      IndexReader reader = IndexReader.open(tmpDir);
+
+      Document doc;
+      doc = reader.document(0);//Load all of them
+      assertTrue("doc is null and it shouldn't be", doc != null);
+      IndexableField field = doc.getField(DocHelper.LARGE_LAZY_FIELD_KEY);
+      assertTrue("field is null and it shouldn't be", field != null);
+      assertFalse("field is lazy", field.getClass().getSimpleName().equals("LazyField"));
+      String value;
+      long start;
+      long finish;
+      start = System.currentTimeMillis();
+      //On my machine this was always 0ms.
+      value = field.stringValue();
+      finish = System.currentTimeMillis();
+      assertTrue("value is null and it shouldn't be", value != null);
+      regularTime += (finish - start);
+      reader.close();
+      reader = null;
+      doc = null;
+      //Hmmm, are we still in cache???
+      System.gc();
+      reader = IndexReader.open(tmpDir);
+      doc = getDocument(reader, 0, fieldSelector);
+      field = doc.getField(DocHelper.LARGE_LAZY_FIELD_KEY);
+      assertTrue("field is not lazy", field.getClass().getSimpleName().equals("LazyField"));
+      start = System.currentTimeMillis();
+      //On my machine this took around 50 - 70ms
+      value = field.stringValue();
+      finish = System.currentTimeMillis();
+      assertTrue("value is null and it shouldn't be", value != null);
+      lazyTime += (finish - start);
+      reader.close();
+
+    }
+    tmpDir.close();
+    if (VERBOSE) {
+      System.out.println("Average Non-lazy time (should be very close to zero): " + regularTime / length + " ms for " + length + " reads");
+      System.out.println("Average Lazy Time (should be greater than zero): " + lazyTime / length + " ms for " + length + " reads");
+    }
+  }
+  
+  public void testLoadSize() throws IOException {
+    IndexReader reader = IndexReader.open(dir);
+    Document doc;
+    
+    doc = getDocument(reader, 0, new FieldSelector(){
+      public FieldSelectorResult accept(String fieldName) {
+        if (fieldName.equals(DocHelper.TEXT_FIELD_1_KEY) ||
+            fieldName.equals(DocHelper.LAZY_FIELD_BINARY_KEY))
+          return FieldSelectorResult.SIZE;
+        else if (fieldName.equals(DocHelper.TEXT_FIELD_3_KEY))
+          return FieldSelectorResult.LOAD;
+        else
+          return FieldSelectorResult.NO_LOAD;
+      }
+    });
+    IndexableField f1 = doc.getField(DocHelper.TEXT_FIELD_1_KEY);
+    IndexableField f3 = doc.getField(DocHelper.TEXT_FIELD_3_KEY);
+    IndexableField fb = doc.getField(DocHelper.LAZY_FIELD_BINARY_KEY);
+    assertTrue(f1.binaryValue()!=null);
+    assertTrue(f3.binaryValue()==null);
+    assertTrue(fb.binaryValue()!=null);
+    assertSizeEquals(2*DocHelper.FIELD_1_TEXT.length(), f1.binaryValue().bytes);
+    assertEquals(DocHelper.FIELD_3_TEXT, f3.stringValue());
+    assertSizeEquals(DocHelper.LAZY_FIELD_BINARY_BYTES.length, fb.binaryValue().bytes);
+    
+    reader.close();
+  }
+  
+  private void assertSizeEquals(int size, byte[] sizebytes) {
+    assertEquals((byte) (size>>>24), sizebytes[0]);
+    assertEquals((byte) (size>>>16), sizebytes[1]);
+    assertEquals((byte) (size>>> 8), sizebytes[2]);
+    assertEquals((byte)  size      , sizebytes[3]);
+  }
+}
\ No newline at end of file

Property changes on: lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribFieldsReader.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribIndexReader.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribIndexReader.java	(revision 0)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribIndexReader.java	(revision 1160484)
@@ -0,0 +1,188 @@
+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.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.BinaryField;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.document.FieldSelectorVisitor;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.SetBasedFieldSelector;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.LuceneTestCase;
+
+public class TestContribIndexReader extends LuceneTestCase {
+  private Document getDocument(IndexReader ir, int docID, FieldSelector selector)  throws IOException {
+    final FieldSelectorVisitor visitor = new FieldSelectorVisitor(selector);
+    ir.document(docID, visitor);
+    return visitor.getDocument();
+  }
+
+  static void addDoc(IndexWriter writer, String value) throws IOException {
+    Document doc = new Document();
+    doc.add(newField("content", value, TextField.TYPE_UNSTORED));
+    writer.addDocument(doc);
+  }
+
+  static void addDocumentWithFields(IndexWriter writer) throws IOException {
+    Document doc = new Document();
+        
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+
+    FieldType customType3 = new FieldType();
+    customType3.setStored(true);
+    doc.add(newField("keyword", "test1", customType));
+    doc.add(newField("text", "test1", customType2));
+    doc.add(newField("unindexed", "test1", customType3));
+    doc.add(new TextField("unstored","test1"));
+    writer.addDocument(doc);
+  }
+
+
+  static void addDocumentWithDifferentFields(IndexWriter writer) throws IOException {
+    Document doc = new Document();
+      
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+
+    FieldType customType3 = new FieldType();
+    customType3.setStored(true);
+    doc.add(newField("keyword2", "test1", customType));
+    doc.add(newField("text2", "test1", customType2));
+    doc.add(newField("unindexed2", "test1", customType3));
+    doc.add(new TextField("unstored2","test1"));
+    writer.addDocument(doc);
+  }
+
+  static void addDocumentWithTermVectorFields(IndexWriter writer) throws IOException {
+    Document doc = new Document();
+    FieldType customType4 = new FieldType(TextField.TYPE_UNSTORED);
+    customType4.setStored(true);
+    FieldType customType5 = new FieldType(TextField.TYPE_UNSTORED);
+    customType5.setStored(true);
+    customType5.setStoreTermVectors(true);
+    FieldType customType6 = new FieldType(TextField.TYPE_UNSTORED);
+    customType6.setStored(true);
+    customType6.setStoreTermVectors(true);
+    customType6.setStoreTermVectorOffsets(true);
+    FieldType customType7 = new FieldType(TextField.TYPE_UNSTORED);
+    customType7.setStored(true);
+    customType7.setStoreTermVectors(true);
+    customType7.setStoreTermVectorPositions(true);
+    FieldType customType8 = new FieldType(TextField.TYPE_UNSTORED);
+    customType8.setStored(true);
+    customType8.setStoreTermVectors(true);
+    customType8.setStoreTermVectorOffsets(true);
+    customType8.setStoreTermVectorPositions(true);
+    doc.add(newField("tvnot","tvnot",customType4));
+    doc.add(newField("termvector","termvector",customType5));
+    doc.add(newField("tvoffset","tvoffset", customType6));
+    doc.add(newField("tvposition","tvposition", customType7));
+    doc.add(newField("tvpositionoffset","tvpositionoffset", customType8));
+        
+    writer.addDocument(doc);
+  }
+
+  public void testBinaryFields() throws IOException {
+    Directory dir = newDirectory();
+    byte[] bin = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+        
+    IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
+        
+    for (int i = 0; i < 10; i++) {
+      addDoc(writer, "document number " + (i + 1));
+      addDocumentWithFields(writer);
+      addDocumentWithDifferentFields(writer);
+      addDocumentWithTermVectorFields(writer);
+    }
+    writer.close();
+    writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND).setMergePolicy(newLogMergePolicy()));
+    Document doc = new Document();
+    doc.add(new BinaryField("bin1", bin));
+    doc.add(new TextField("junk", "junk text"));
+    writer.addDocument(doc);
+    writer.close();
+    IndexReader reader = IndexReader.open(dir, false);
+    Document doc2 = reader.document(reader.maxDoc() - 1);
+    IndexableField[] fields = doc2.getFields("bin1");
+    assertNotNull(fields);
+    assertEquals(1, fields.length);
+    Field b1 = (Field) fields[0];
+    assertTrue(b1.isBinary());
+    BytesRef bytesRef = b1.binaryValue();
+    assertEquals(bin.length, bytesRef.length);
+    for (int i = 0; i < bin.length; i++) {
+      assertEquals(bin[i], bytesRef.bytes[i + bytesRef.offset]);
+    }
+    Set<String> lazyFields = new HashSet<String>();
+    lazyFields.add("bin1");
+    FieldSelector sel = new SetBasedFieldSelector(new HashSet<String>(), lazyFields);
+    doc2 = getDocument(reader, reader.maxDoc() - 1, sel);
+    fields = doc2.getFields("bin1");
+    assertNotNull(fields);
+    assertEquals(1, fields.length);
+    IndexableField fb1 = fields[0];
+    assertTrue(fb1.binaryValue()!=null);
+    bytesRef = fb1.binaryValue();
+    assertEquals(bin.length, bytesRef.bytes.length);
+    assertEquals(bin.length, bytesRef.length);
+    for (int i = 0; i < bin.length; i++) {
+      assertEquals(bin[i], bytesRef.bytes[i + bytesRef.offset]);
+    }
+    reader.close();
+    // force optimize
+
+
+    writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND).setMergePolicy(newLogMergePolicy()));
+    writer.optimize();
+    writer.close();
+    reader = IndexReader.open(dir, false);
+    doc2 = reader.document(reader.maxDoc() - 1);
+    fields = doc2.getFields("bin1");
+    assertNotNull(fields);
+    assertEquals(1, fields.length);
+    b1 = (Field) fields[0];
+    assertTrue(b1.isBinary());
+    bytesRef = b1.binaryValue();
+    assertEquals(bin.length, bytesRef.length);
+    for (int i = 0; i < bin.length; i++) {
+      assertEquals(bin[i], bytesRef.bytes[i + bytesRef.offset]);
+    }
+    reader.close();
+    dir.close();
+  }
+}

Property changes on: lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribIndexReader.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribParallelReader.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribParallelReader.java	(revision 0)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribParallelReader.java	(revision 1159961)
@@ -0,0 +1,156 @@
+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.IOException;
+import java.util.Arrays;
+import java.util.Random;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.document.FieldSelectorVisitor;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.MapFieldSelector;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.search.*;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+
+public class TestContribParallelReader extends LuceneTestCase {
+
+  private IndexSearcher parallel;
+  private IndexSearcher single;
+  private Directory dir, dir1, dir2;
+  
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    single = single(random);
+    parallel = parallel(random);
+  }
+  
+  @Override
+  public void tearDown() throws Exception {
+    single.getIndexReader().close();
+    single.close();
+    parallel.getIndexReader().close();
+    parallel.close();
+    dir.close();
+    dir1.close();
+    dir2.close();
+    super.tearDown();
+  }
+
+  // Fields 1-4 indexed together:
+  private IndexSearcher single(Random random) throws IOException {
+    dir = newDirectory();
+    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    Document d1 = new Document();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d1.add(newField("f1", "v1", customType));
+    d1.add(newField("f2", "v1", customType));
+    d1.add(newField("f3", "v1", customType));
+    d1.add(newField("f4", "v1", customType));
+    w.addDocument(d1);
+    Document d2 = new Document();
+    d2.add(newField("f1", "v2", customType));
+    d2.add(newField("f2", "v2", customType));
+    d2.add(newField("f3", "v2", customType));
+    d2.add(newField("f4", "v2", customType));
+    w.addDocument(d2);
+    w.close();
+
+    return new IndexSearcher(dir, false);
+  }
+
+  // Fields 1 & 2 in one index, 3 & 4 in other, with ParallelReader:
+  private IndexSearcher parallel(Random random) throws IOException {
+    dir1 = getDir1(random);
+    dir2 = getDir2(random);
+    ParallelReader pr = new ParallelReader();
+    pr.add(IndexReader.open(dir1, false));
+    pr.add(IndexReader.open(dir2, false));
+    return newSearcher(pr);
+  }
+
+  private Document getDocument(IndexReader ir, int docID, FieldSelector selector) throws IOException {
+    final FieldSelectorVisitor visitor = new FieldSelectorVisitor(selector);
+    ir.document(docID, visitor);
+    return visitor.getDocument();
+  }
+
+  public void testDocument() throws IOException {
+    Directory dir1 = getDir1(random);
+    Directory dir2 = getDir2(random);
+    ParallelReader pr = new ParallelReader();
+    pr.add(IndexReader.open(dir1, false));
+    pr.add(IndexReader.open(dir2, false));
+
+    Document doc11 = getDocument(pr, 0, new MapFieldSelector("f1"));
+    Document doc24 = getDocument(pr, 1, new MapFieldSelector(Arrays.asList("f4")));
+    Document doc223 = getDocument(pr, 1, new MapFieldSelector("f2", "f3"));
+    
+    assertEquals(1, doc11.getFields().size());
+    assertEquals(1, doc24.getFields().size());
+    assertEquals(2, doc223.getFields().size());
+    
+    assertEquals("v1", doc11.get("f1"));
+    assertEquals("v2", doc24.get("f4"));
+    assertEquals("v2", doc223.get("f2"));
+    assertEquals("v2", doc223.get("f3"));
+    pr.close();
+    dir1.close();
+    dir2.close();
+  }
+
+  private Directory getDir1(Random random) throws IOException {
+    Directory dir1 = newDirectory();
+    IndexWriter w1 = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    Document d1 = new Document();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d1.add(newField("f1", "v1", customType));
+    d1.add(newField("f2", "v1", customType));
+    w1.addDocument(d1);
+    Document d2 = new Document();
+    d2.add(newField("f1", "v2", customType));
+    d2.add(newField("f2", "v2", customType));
+    w1.addDocument(d2);
+    w1.close();
+    return dir1;
+  }
+
+  private Directory getDir2(Random random) throws IOException {
+    Directory dir2 = newDirectory();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    IndexWriter w2 = new IndexWriter(dir2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    Document d3 = new Document();
+    d3.add(newField("f3", "v1", customType));
+    d3.add(newField("f4", "v1", customType));
+    w2.addDocument(d3);
+    Document d4 = new Document();
+    d4.add(newField("f3", "v2", customType));
+    d4.add(newField("f4", "v2", customType));
+    w2.addDocument(d4);
+    w2.close();
+    return dir2;
+  }
+}

Property changes on: lucene/contrib/misc/src/test/org/apache/lucene/index/TestContribParallelReader.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestLazyBug.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestLazyBug.java	(revision 0)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestLazyBug.java	(revision 1159961)
@@ -0,0 +1,145 @@
+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.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.document.FieldSelectorResult;
+import org.apache.lucene.document.FieldSelectorVisitor;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+
+/**
+ * Test demonstrating EOF bug on the last field of the last doc
+ * if other docs have allready been accessed.
+ */
+public class TestLazyBug extends LuceneTestCase {
+
+  public static int NUM_DOCS = TEST_NIGHTLY ? 500 : 50;
+  public static int NUM_FIELDS = TEST_NIGHTLY ? 100 : 10;
+
+  private static String[] data = new String[] {
+    "now",
+    "is the time",
+    "for all good men",
+    "to come to the aid",
+    "of their country!",
+    "this string contains big chars:{\u0111 \u0222 \u0333 \u1111 \u2222 \u3333}",
+    "this string is a bigger string, mary had a little lamb, little lamb, little lamb!"
+  };
+
+  private static Set<String> dataset = asSet(data);
+
+  private static String MAGIC_FIELD = "f"+(NUM_FIELDS/3);
+  
+  private static Directory directory;
+  
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    directory = makeIndex();
+  }
+  
+  @AfterClass
+  public static void afterClass() throws Exception {
+    directory.close();
+    directory = null;
+  }
+
+  private static FieldSelector SELECTOR = new FieldSelector() {
+      public FieldSelectorResult accept(String f) {
+        if (f.equals(MAGIC_FIELD)) {
+          return FieldSelectorResult.LOAD;
+        }
+        return FieldSelectorResult.LAZY_LOAD;
+      }
+    };
+
+  private static Directory makeIndex() throws Exception {
+    Directory dir = newDirectory();
+    try {
+      IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
+                                                                     TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
+      LogMergePolicy lmp = (LogMergePolicy) writer.getConfig().getMergePolicy();
+      lmp.setUseCompoundFile(false);
+      for (int d = 1; d <= NUM_DOCS; d++) {
+        Document doc = new Document();
+        for (int f = 1; f <= NUM_FIELDS; f++ ) {
+          doc.add(newField("f"+f,
+                            data[f % data.length]
+                            + '#' + data[random.nextInt(data.length)],
+                            TextField.TYPE_UNSTORED));
+        }
+        writer.addDocument(doc);
+      }
+      writer.close();
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+    return dir;
+  }
+
+  public void doTest(int[] docs) throws Exception {
+    IndexReader reader = IndexReader.open(directory, true);
+    for (int i = 0; i < docs.length; i++) {
+      final FieldSelectorVisitor visitor = new FieldSelectorVisitor(SELECTOR);
+      reader.document(docs[i], visitor);
+      Document d = visitor.getDocument();
+      d.get(MAGIC_FIELD);
+
+      List<IndexableField> fields = d.getFields();
+      for (Iterator<IndexableField> fi = fields.iterator(); fi.hasNext(); ) {
+        IndexableField f=null;
+        try {
+          f =  fi.next();
+          String fname = f.name();
+          String fval = f.stringValue();
+          assertNotNull(docs[i]+" FIELD: "+fname, fval);
+          String[] vals = fval.split("#");
+          if (!dataset.contains(vals[0]) || !dataset.contains(vals[1])) {
+            fail("FIELD:"+fname+",VAL:"+fval);
+          }
+        } catch (Exception e) {
+          throw new Exception(docs[i]+" WTF: "+f.name(), e);
+        }
+      }
+    }
+    reader.close();
+  }
+
+  public void testLazyWorks() throws Exception {
+    doTest(new int[] { NUM_DOCS-1 });
+  }
+
+  public void testLazyAlsoWorks() throws Exception {
+    doTest(new int[] { NUM_DOCS-1, NUM_DOCS/2 });
+  }
+
+  public void testLazyBroken() throws Exception {
+    doTest(new int[] { NUM_DOCS/2, NUM_DOCS-1 });
+  }
+
+}

Property changes on: lucene/contrib/misc/src/test/org/apache/lucene/index/TestLazyBug.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestMultiPassIndexSplitter.java	(working copy)
@@ -19,6 +19,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.BytesRef;
@@ -36,8 +38,13 @@
     Document doc;
     for (int i = 0; i < NUM_DOCS; i++) {
       doc = new Document();
-      doc.add(newField("id", i + "", Field.Store.YES, Field.Index.NOT_ANALYZED));
-      doc.add(newField("f", i + " " + i, Field.Store.YES, Field.Index.ANALYZED));
+      FieldType storedTextType = new FieldType(TextField.TYPE_UNSTORED);
+      storedTextType.setStored(true);
+      storedTextType.setTokenized(false);
+      FieldType storedTextType2 = new FieldType(TextField.TYPE_UNSTORED);
+      storedTextType.setStored(true);
+      doc.add(newField("id", i + "", storedTextType));
+      doc.add(newField("f", i + " " + i, storedTextType2));
       w.addDocument(doc);
     }
     w.close();
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/codecs/appending/TestAppendingCodec.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/codecs/appending/TestAppendingCodec.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/codecs/appending/TestAppendingCodec.java	(working copy)
@@ -22,9 +22,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.IndexReader;
@@ -141,7 +140,12 @@
     ((TieredMergePolicy)cfg.getMergePolicy()).setUseCompoundFile(false);
     IndexWriter writer = new IndexWriter(dir, cfg);
     Document doc = new Document();
-    doc.add(newField("f", text, Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType storedTextType = new FieldType(TextField.TYPE_UNSTORED);
+    storedTextType.setStored(true);
+    storedTextType.setStoreTermVectors(true);
+    storedTextType.setStoreTermVectorPositions(true);
+    storedTextType.setStoreTermVectorOffsets(true);
+    doc.add(newField("f", text, storedTextType));
     writer.addDocument(doc);
     writer.commit();
     writer.addDocument(doc);
@@ -149,8 +153,8 @@
     writer.close();
     IndexReader reader = IndexReader.open(dir, null, true, 1, new AppendingCodecProvider());
     assertEquals(2, reader.numDocs());
-    doc = reader.document(0);
-    assertEquals(text, doc.get("f"));
+    Document doc2 = reader.document(0);
+    assertEquals(text, doc2.get("f"));
     Fields fields = MultiFields.getFields(reader);
     Terms terms = fields.terms("f");
     assertNotNull(terms);
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestPKIndexSplitter.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestPKIndexSplitter.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestPKIndexSplitter.java	(working copy)
@@ -23,8 +23,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.Bits;
@@ -102,15 +102,15 @@
     StringBuilder sb = new StringBuilder();
     Document doc = new Document();
     String id = format.format(n);
-    doc.add(newField("id", id, Store.YES, Index.NOT_ANALYZED));
-    doc.add(newField("indexname", indexName, Store.YES, Index.NOT_ANALYZED));
+    doc.add(newField("id", id, StringField.TYPE_STORED));
+    doc.add(newField("indexname", indexName, StringField.TYPE_STORED));
     sb.append("a");
     sb.append(n);
-    doc.add(newField("field1", sb.toString(), Store.YES, Index.ANALYZED));
+    doc.add(newField("field1", sb.toString(), TextField.TYPE_STORED));
     sb.append(" b");
     sb.append(n);
     for (int i = 1; i < numFields; i++) {
-      doc.add(newField("field" + (i + 1), sb.toString(), Store.YES, Index.ANALYZED));
+      doc.add(newField("field" + (i + 1), sb.toString(), TextField.TYPE_STORED));
     }
     return doc;
   }
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestTermVectorAccessor.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestTermVectorAccessor.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestTermVectorAccessor.java	(working copy)
@@ -3,6 +3,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -30,33 +32,42 @@
     Document doc;
 
     doc = new Document();
-    doc.add(newField("a", "a b a c a d a e a f a g a h a", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(newField("b", "a b c b d b e b f b g b h b", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(newField("c", "a c b c d c e c f c g c h c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("a", "a b a c a d a e a f a g a h a", customType));
+    doc.add(newField("b", "a b c b d b e b f b g b h b", customType));
+    doc.add(newField("c", "a c b c d c e c f c g c h c", customType));
     iw.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("a", "a b a c a d a e a f a g a h a", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
-    doc.add(newField("b", "a b c b d b e b f b g b h b", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
-    doc.add(newField("c", "a c b c d c e c f c g c h c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStoreTermVectors(true);
+    customType2.setStoreTermVectorPositions(true);
+    doc.add(newField("a", "a b a c a d a e a f a g a h a", customType2));
+    doc.add(newField("b", "a b c b d b e b f b g b h b", customType2));
+    doc.add(newField("c", "a c b c d c e c f c g c h c", customType2));
     iw.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("a", "a b a c a d a e a f a g a h a", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES));
-    doc.add(newField("b", "a b c b d b e b f b g b h b", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES));
-    doc.add(newField("c", "a c b c d c e c f c g c h c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES));
+    FieldType customType3 = new FieldType(TextField.TYPE_UNSTORED);
+    customType3.setStoreTermVectors(true);
+    doc.add(newField("a", "a b a c a d a e a f a g a h a", customType3));
+    doc.add(newField("b", "a b c b d b e b f b g b h b", customType3));
+    doc.add(newField("c", "a c b c d c e c f c g c h c", customType3));
     iw.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("a", "a b a c a d a e a f a g a h a", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO));
-    doc.add(newField("b", "a b c b d b e b f b g b h b", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO));
-    doc.add(newField("c", "a c b c d c e c f c g c h c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO));
+    doc.add(newField("a", "a b a c a d a e a f a g a h a", TextField.TYPE_UNSTORED));
+    doc.add(newField("b", "a b c b d b e b f b g b h b", TextField.TYPE_UNSTORED));
+    doc.add(newField("c", "a c b c d c e c f c g c h c", TextField.TYPE_UNSTORED));
     iw.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("a", "a b a c a d a e a f a g a h a", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(newField("b", "a b c b d b e b f b g b h b", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO));
-    doc.add(newField("c", "a c b c d c e c f c g c h c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES));
+    doc.add(newField("a", "a b a c a d a e a f a g a h a", customType));
+    doc.add(newField("b", "a b c b d b e b f b g b h b", TextField.TYPE_UNSTORED));
+    doc.add(newField("c", "a c b c d c e c f c g c h c", customType3));
     iw.addDocument(doc);
 
     iw.close();
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestFieldNormModifier.java	(working copy)
@@ -23,6 +23,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.DefaultSimilarity;
@@ -65,13 +67,21 @@
     
     for (int i = 0; i < NUM_DOCS; i++) {
       Document d = new Document();
-      d.add(newField("field", "word", Field.Store.YES, Field.Index.ANALYZED));
-      d.add(newField("nonorm", "word", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-      d.add(newField("untokfield", "20061212 20071212", Field.Store.YES, Field.Index.ANALYZED));
       
+      FieldType storedTextType = new FieldType(TextField.TYPE_UNSTORED);
+      storedTextType.setStored(true);
+      d.add(newField("field", "word", storedTextType));
+
+      FieldType storedTextType2 = new FieldType(TextField.TYPE_UNSTORED);
+      storedTextType2.setStored(true);
+      storedTextType2.setTokenized(false);
+      storedTextType2.setOmitNorms(true);
+      d.add(newField("nonorm", "word", storedTextType2));
+      d.add(newField("untokfield", "20061212 20071212", storedTextType));
+      
       for (int j = 1; j <= i; j++) {
-        d.add(newField("field", "crap", Field.Store.YES, Field.Index.ANALYZED));
-        d.add(newField("nonorm", "more words", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+        d.add(newField("field", "crap", storedTextType));
+        d.add(newField("nonorm", "more words", storedTextType2));
       }
       writer.addDocument(d);
     }
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestIndexSplitter.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestIndexSplitter.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestIndexSplitter.java	(working copy)
@@ -21,6 +21,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
@@ -112,10 +113,10 @@
     Directory fsDir = newFSDirectory(indexPath);
     IndexWriter indexWriter = new IndexWriter(fsDir, iwConfig);
     Document doc = new Document();
-    doc.add(new Field("content", "doc 1", Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));
+    doc.add(new Field("content", StringField.TYPE_STORED, "doc 1"));
     indexWriter.addDocument(doc);
     doc = new Document();
-    doc.add(new Field("content", "doc 2", Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));
+    doc.add(new Field("content", StringField.TYPE_STORED, "doc 2"));
     indexWriter.addDocument(doc);
     indexWriter.close();
     fsDir.close();
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestNRTManager.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestNRTManager.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestNRTManager.java	(working copy)
@@ -33,7 +33,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.PhraseQuery;
@@ -77,17 +78,12 @@
   // TODO: is there a pre-existing way to do this!!!
   private Document cloneDoc(Document doc1) {
     final Document doc2 = new Document();
-    for(Fieldable f : doc1.getFields()) {
+    for(IndexableField f : doc1) {
       Field field1 = (Field) f;
       
       Field field2 = new Field(field1.name(),
-                               field1.stringValue(),
-                               field1.isStored() ? Field.Store.YES : Field.Store.NO,
-                               field1.isIndexed() ? (field1.isTokenized() ? Field.Index.ANALYZED : Field.Index.NOT_ANALYZED) : Field.Index.NO);
-      if (field1.getOmitNorms()) {
-        field2.setOmitNorms(true);
-      }
-      field2.setIndexOptions(field1.getIndexOptions());
+                              ((Field) f).getFieldType(),
+                               field1.stringValue());
       doc2.add(field2);
     }
 
@@ -240,7 +236,7 @@
                 final String addedField;
                 if (random.nextBoolean()) {
                   addedField = "extra" + random.nextInt(10);
-                  doc.add(new Field(addedField, "a random field", Field.Store.NO, Field.Index.ANALYZED));
+                  doc.add(new TextField(addedField, "a random field"));
                 } else {
                   addedField = null;
                 }
@@ -262,7 +258,7 @@
                       packID = packCount.getAndIncrement() + "";
                     }
 
-                    final Field packIDField = newField("packID", packID, Field.Store.YES, Field.Index.NOT_ANALYZED);
+                    final Field packIDField = newField("packID", packID, StringField.TYPE_STORED);
                     final List<String> docIDs = new ArrayList<String>();
                     final SubDocs subDocs = new SubDocs(packID, docIDs);
                     final List<Document> docsList = new ArrayList<Document>();
Index: lucene/contrib/misc/src/test/org/apache/lucene/search/TestThreadSafe.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/search/TestThreadSafe.java	(revision 0)
+++ lucene/contrib/misc/src/test/org/apache/lucene/search/TestThreadSafe.java	(revision 1159961)
@@ -0,0 +1,158 @@
+package org.apache.lucene.search;
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.*;
+
+import java.util.Random;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.io.IOException;
+
+public class TestThreadSafe extends LuceneTestCase {
+  Directory dir1;
+
+  IndexReader ir1;
+
+  class Thr extends Thread {
+    final int iter;
+    final Random rand;
+    final AtomicBoolean failed;
+
+    // pass in random in case we want to make things reproducable
+    public Thr(int iter, Random rand, AtomicBoolean failed) {
+      this.iter = iter;
+      this.rand = rand;
+      this.failed = failed;
+    }
+
+    @Override
+      public void run() {
+      try {
+        for (int i=0; i<iter; i++) {
+          /*** future
+           // pick a random index reader... a shared one, or create your own
+           IndexReader ir;
+          ***/
+
+          switch(rand.nextInt(1)) {
+          case 0: loadDoc(ir1); break;
+          }
+
+        }
+      } catch (Throwable th) {
+        failed.set(true);
+        throw new RuntimeException(th);
+      }
+    }
+
+
+    private Document getDocument(IndexReader ir, int docID, FieldSelector selector) throws IOException {
+      final FieldSelectorVisitor visitor = new FieldSelectorVisitor(selector);
+      ir.document(docID, visitor);
+      return visitor.getDocument();
+    }
+
+    void loadDoc(IndexReader ir) throws IOException {
+      // beware of deleted docs in the future
+      Document doc = getDocument(ir, rand.nextInt(ir.maxDoc()),
+                                                            new FieldSelector() {
+                                                              public FieldSelectorResult accept(String fieldName) {
+                                                                switch(rand.nextInt(2)) {
+                                                                case 0: return FieldSelectorResult.LAZY_LOAD;
+                                                                case 1: return FieldSelectorResult.LOAD;
+                                                                  // TODO: add other options
+                                                                default: return FieldSelectorResult.LOAD;
+                                                                }
+                                                              }
+                                                            }
+                                                            );
+
+      for (final IndexableField f : doc ) {
+        validateField(f);
+      }
+
+    }
+
+  }
+
+
+  void validateField(IndexableField f) {
+    String val = f.stringValue();
+    if (!val.startsWith("^") || !val.endsWith("$")) {
+      throw new RuntimeException("Invalid field:" + f.toString() + " val=" +val);
+    }
+  }
+
+  String[] words = "now is the time for all good men to come to the aid of their country".split(" ");
+
+  void buildDir(Directory dir, int nDocs, int maxFields, int maxFieldLen) throws IOException {
+    IndexWriter iw = new IndexWriter(dir, new IndexWriterConfig(
+                                                                TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(10));
+    for (int j=0; j<nDocs; j++) {
+      Document d = new Document();
+      int nFields = random.nextInt(maxFields);
+      for (int i=0; i<nFields; i++) {
+        int flen = random.nextInt(maxFieldLen);
+        StringBuilder sb = new StringBuilder("^ ");
+        while (sb.length() < flen) sb.append(' ').append(words[random.nextInt(words.length)]);
+        sb.append(" $");
+        d.add(newField("f"+i, sb.toString(), TextField.TYPE_STORED));
+      }
+      iw.addDocument(d);
+    }
+    iw.close();
+  }
+
+
+  void doTest(int iter, int nThreads) throws Exception {
+    Thr[] tarr = new Thr[nThreads];
+    AtomicBoolean failed = new AtomicBoolean();
+    for (int i=0; i<nThreads; i++) {
+      tarr[i] = new Thr(iter, new Random(random.nextLong()), failed);
+      tarr[i].start();
+    }
+    for (int i=0; i<nThreads; i++) {
+      tarr[i].join();
+    }
+    assertFalse(failed.get());
+  }
+
+  public void testLazyLoadThreadSafety() throws Exception{
+    dir1 = newDirectory();
+    // test w/ field sizes bigger than the buffer of an index input
+    buildDir(dir1, 15, 5, 2000);
+
+    // do many small tests so the thread locals go away inbetween
+    int num = atLeast(10);
+    for (int i = 0; i < num; i++) {
+      ir1 = IndexReader.open(dir1, false);
+      doTest(10,10);
+      ir1.close();
+    }
+    dir1.close();
+  }
+
+}

Property changes on: lucene/contrib/misc/src/test/org/apache/lucene/search/TestThreadSafe.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/test/org/apache/lucene/misc/TestHighFreqTerms.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/misc/TestHighFreqTerms.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/misc/TestHighFreqTerms.java	(working copy)
@@ -21,6 +21,8 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.store.Directory;
@@ -199,13 +201,15 @@
     /**
      * Generate 10 documents where term n  has a docFreq of n and a totalTermFreq of n*2 (squared). 
      */
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 1; i <= 10; i++) {
       Document doc = new Document();
       String content = getContent(i);
     
-      doc.add(newField(random, "FIELD_1", content, Field.Store.YES,Field.Index.ANALYZED, Field.TermVector.NO));
+      doc.add(newField(random, "FIELD_1", content, customType));
       //add a different field
-      doc.add(newField(random, "different_field", "diff", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
+      doc.add(newField(random, "different_field", "diff", customType));
       writer.addDocument(doc);
     }
     
@@ -213,7 +217,7 @@
     //highest freq terms for a specific field.
     for (int i = 1; i <= 10; i++) {
       Document doc = new Document();
-      doc.add(newField(random, "different_field", "diff", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
+      doc.add(newField(random, "different_field", "diff", customType));
       writer.addDocument(doc);
     }
     // add some docs where tf < df so we can see if sorting works
@@ -224,7 +228,7 @@
     for (int i = 0; i < highTF; i++) {
       content += "highTF ";
     }
-    doc.add(newField(random, "FIELD_1", content, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
+    doc.add(newField(random, "FIELD_1", content, customType));
     writer.addDocument(doc);
     // highTF medium df =5
     int medium_df = 5;
@@ -235,7 +239,7 @@
       for (int j = 0; j < tf; j++) {
         newcontent += "highTFmedDF ";
       }
-      newdoc.add(newField(random, "FIELD_1", newcontent, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
+      newdoc.add(newField(random, "FIELD_1", newcontent, customType));
       writer.addDocument(newdoc);
     }
     // add a doc with high tf in field different_field
@@ -245,7 +249,7 @@
     for (int i = 0; i < targetTF; i++) {
       content += "TF150 ";
     }
-    doc.add(newField(random, "different_field", content, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
+    doc.add(newField(random, "different_field", content, customType));
     writer.addDocument(doc);
     writer.close();
     
Index: lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java	(revision 1158028)
+++ lucene/contrib/misc/src/test/org/apache/lucene/misc/TestLengthNormModifier.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.FieldNormModifier;
 import org.apache.lucene.index.IndexReader;
@@ -70,16 +72,17 @@
 	
 	for (int i = 0; i < NUM_DOCS; i++) {
 	    Document d = new Document();
-	    d.add(newField("field", "word",
-			    Field.Store.YES, Field.Index.ANALYZED));
-	    d.add(newField("nonorm", "word",
-			    Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+	    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+	    customType.setStored(true);
+	    d.add(newField("field", "word", customType));
+      FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+      customType2.setStored(true);
+      customType2.setOmitNorms(true);
+	    d.add(newField("nonorm", "word", customType2));
 		
 	    for (int j = 1; j <= i; j++) {
-		d.add(newField("field", "crap",
-				Field.Store.YES, Field.Index.ANALYZED));
-		d.add(newField("nonorm", "more words",
-				Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+		d.add(newField("field", "crap", customType));
+		d.add(newField("nonorm", "more words", customType2));
 	    }
 	    writer.addDocument(d);
 	}
Index: lucene/contrib/misc/src/java/org/apache/lucene/document/SetBasedFieldSelector.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/document/SetBasedFieldSelector.java	(revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/document/SetBasedFieldSelector.java	(revision 1160484)
@@ -0,0 +1,62 @@
+package org.apache.lucene.document;
+
+/**
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.Set;
+
+import org.apache.lucene.document.Field;
+
+/**
+ * Declare what fields to load normally and what fields to load lazily
+ *
+ **/
+
+public class SetBasedFieldSelector implements FieldSelector {
+  
+  private Set<String> fieldsToLoad;
+  private Set<String> lazyFieldsToLoad;
+  
+  /**
+   * Pass in the Set of {@link Field} names to load and the Set of {@link Field} names to load lazily.  If both are null, the
+   * Document will not have any {@link Field} on it.  
+   * @param fieldsToLoad A Set of {@link String} field names to load.  May be empty, but not null
+   * @param lazyFieldsToLoad A Set of {@link String} field names to load lazily.  May be empty, but not null  
+   */
+  public SetBasedFieldSelector(Set<String> fieldsToLoad, Set<String> lazyFieldsToLoad) {
+    this.fieldsToLoad = fieldsToLoad;
+    this.lazyFieldsToLoad = lazyFieldsToLoad;
+  }
+
+  /**
+   * Indicate whether to load the field with the given name or not. If the {@link Field#name()} is not in either of the 
+   * initializing Sets, then {@link org.apache.lucene.document.FieldSelectorResult#NO_LOAD} is returned.  If a Field name
+   * is in both <code>fieldsToLoad</code> and <code>lazyFieldsToLoad</code>, lazy has precedence.
+   * 
+   * @param fieldName The {@link Field} name to check
+   * @return The {@link FieldSelectorResult}
+   */
+  public FieldSelectorResult accept(String fieldName) {
+    FieldSelectorResult result = FieldSelectorResult.NO_LOAD;
+    if (fieldsToLoad.contains(fieldName) == true){
+      result = FieldSelectorResult.LOAD;
+    }
+    if (lazyFieldsToLoad.contains(fieldName) == true){
+      result = FieldSelectorResult.LAZY_LOAD;
+    }                                           
+    return result;
+  }
+}

Property changes on: lucene/contrib/misc/src/java/org/apache/lucene/document/SetBasedFieldSelector.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/java/org/apache/lucene/document/MapFieldSelector.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/document/MapFieldSelector.java	(revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/document/MapFieldSelector.java	(revision 1159961)
@@ -0,0 +1,67 @@
+package org.apache.lucene.document;
+
+/**
+ * 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.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A {@link FieldSelector} based on a Map of field names to {@link FieldSelectorResult}s
+ *
+ */
+public class MapFieldSelector implements FieldSelector {
+    
+    Map<String,FieldSelectorResult> fieldSelections;
+    
+    /** Create a a MapFieldSelector
+     * @param fieldSelections maps from field names (String) to {@link FieldSelectorResult}s
+     */
+    public MapFieldSelector(Map<String,FieldSelectorResult> fieldSelections) {
+        this.fieldSelections = fieldSelections;
+    }
+    
+    /** Create a a MapFieldSelector
+     * @param fields fields to LOAD.  List of Strings.  All other fields are NO_LOAD.
+     */
+    public MapFieldSelector(List<String> fields) {
+        fieldSelections = new HashMap<String,FieldSelectorResult>(fields.size()*5/3);
+        for (final String field : fields)
+            fieldSelections.put(field, FieldSelectorResult.LOAD);
+    }
+    
+    /** Create a a MapFieldSelector
+     * @param fields fields to LOAD.  All other fields are NO_LOAD.
+     */
+    public MapFieldSelector(String... fields) {
+      this(Arrays.asList(fields));
+    }
+
+
+    
+    /** Load field according to its associated value in fieldSelections
+     * @param field a field name
+     * @return the fieldSelections value that field maps to or NO_LOAD if none.
+     */
+    public FieldSelectorResult accept(String field) {
+        FieldSelectorResult selection = fieldSelections.get(field);
+        return selection!=null ? selection : FieldSelectorResult.NO_LOAD;
+    }
+    
+}

Property changes on: lucene/contrib/misc/src/java/org/apache/lucene/document/MapFieldSelector.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorResult.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorResult.java	(revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorResult.java	(revision 1159961)
@@ -0,0 +1,78 @@
+package org.apache.lucene.document;
+
+/**
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+/**
+ *  Provides information about what should be done with this Field 
+ *
+ **/
+import org.apache.lucene.index.IndexableField; // for javadocs
+
+public enum FieldSelectorResult {
+
+    /**
+     * Load this {@link Field} every time the {@link Document} is loaded, reading in the data as it is encountered.
+     *  {@link Document#getField(String)} should not return null.
+     *<p/>
+     * {@link Document#add(IndexableField)} should be called by the Reader.
+     */
+  LOAD,
+
+    /**
+     * Lazily load this {@link Field}.  This means the {@link Field} is valid, but it may not actually contain its data until
+     * invoked.  {@link Document#getField(String)} is safe to use and should
+     * return a valid instance of a {@link IndexableField}.
+     *<p/>
+     * {@link Document#add(IndexableField)} should be called by the Reader.
+     */
+  LAZY_LOAD,
+
+    /**
+     * Do not load the {@link Field}.  {@link Document#getField(String)} should return null.
+     * {@link Document#add(IndexableField)} is not called.
+     * <p/>
+     * {@link Document#add(IndexableField)} should not be called by the Reader.
+     */
+  NO_LOAD,
+
+    /**
+     * Load this field as in the {@link #LOAD} case, but immediately return from {@link Field} loading for the {@link Document}.  Thus, the
+     * Document may not have its complete set of Fields.  {@link Document#getField(String)} should
+     * both be valid for this {@link Field}
+     * <p/>
+     * {@link Document#add(IndexableField)} should be called by the Reader.
+     */
+  LOAD_AND_BREAK,
+
+    /** Expert:  Load the size of this {@link Field} rather than its value.
+     * Size is measured as number of bytes required to store the field == bytes for a binary or any compressed value, and 2*chars for a String value.
+     * The size is stored as a binary value, represented as an int in a byte[], with the higher order byte first in [0]
+     */
+  SIZE,
+
+    /** Expert: Like {@link #SIZE} but immediately break from the field loading loop, i.e., stop loading further fields, after the size is loaded */         
+  SIZE_AND_BREAK,
+
+  /**
+     * Lazily load this {@link Field}, but do not cache the result.  This means the {@link Field} is valid, but it may not actually contain its data until
+     * invoked.  {@link Document#getField(String)} is safe to use and should
+     * return a valid instance of a {@link IndexableField}.
+     *<p/>
+     * {@link Document#add(IndexableField)} should be called by the Reader.
+     */
+  LATENT
+}

Property changes on: lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorResult.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelector.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelector.java	(revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelector.java	(revision 1159961)
@@ -0,0 +1,36 @@
+package org.apache.lucene.document;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+
+/**
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+/**
+ * Similar to a {@link java.io.FileFilter}, the FieldSelector allows one to make decisions about
+ * what Fields get loaded on a {@link Document} by {@link FieldSelectorVisitor}
+ *
+ **/
+public interface FieldSelector {
+
+  /**
+   * 
+   * @param fieldName the field to accept or reject
+   * @return an instance of {@link FieldSelectorResult}
+   * if the {@link Field} named <code>fieldName</code> should be loaded.
+   */
+  FieldSelectorResult accept(String fieldName);
+}

Property changes on: lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelector.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorVisitor.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorVisitor.java	(revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorVisitor.java	(revision 1160484)
@@ -0,0 +1,325 @@
+package org.apache.lucene.document;
+
+/**
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.IOException;
+import java.io.Reader;
+
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.BinaryField;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.document.NumericField.DataType;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.FieldReaderException;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.StoredFieldVisitor;
+import org.apache.lucene.store.IndexInput;
+import org.apache.lucene.util.BytesRef;
+
+/** Create this, passing a legacy {@link FieldSelector} to it, then
+ *  pass this class to {@link IndexReader#document(int,
+ *  StoredFieldVisitor)}, then call {@link #getDocument} to
+ *  retrieve the loaded document.
+
+ *  <p><b>NOTE</b>:  If you use Lazy fields, you should not
+ *  access the returned document after the reader has been
+ *  closed!
+ */
+
+public class FieldSelectorVisitor extends StoredFieldVisitor {
+
+  private final FieldSelector selector;
+  private final Document doc;
+
+  public FieldSelectorVisitor(FieldSelector selector) {
+    this.selector = selector;
+    doc = new Document();
+  }
+
+  public Document getDocument() {
+    return doc;
+  }
+
+  @Override
+  public boolean binaryField(FieldInfo fieldInfo, IndexInput in, int numBytes) throws IOException {
+    final FieldSelectorResult accept = selector.accept(fieldInfo.name);
+    switch (accept) {
+    case LOAD:
+    case LOAD_AND_BREAK:
+      final byte[] b = new byte[numBytes];
+      in.readBytes(b, 0, b.length);
+      doc.add(new BinaryField(fieldInfo.name, b));
+      return accept != FieldSelectorResult.LOAD;
+    case LAZY_LOAD:
+    case LATENT:
+      addFieldLazy(in, fieldInfo, true, accept == FieldSelectorResult.LAZY_LOAD, numBytes);
+      return false;
+    case SIZE:
+    case SIZE_AND_BREAK:
+      in.seek(in.getFilePointer() + numBytes);
+      addFieldSize(fieldInfo, numBytes);
+      return accept != FieldSelectorResult.SIZE;
+    default:
+      // skip
+      in.seek(in.getFilePointer() + numBytes);
+      return false;
+    }
+  }
+
+  @Override
+  public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+    final FieldSelectorResult accept = selector.accept(fieldInfo.name);
+    switch (accept) {
+    case LOAD:
+    case LOAD_AND_BREAK:
+      final byte[] b = new byte[numUTF8Bytes];
+      in.readBytes(b, 0, b.length);
+      FieldType ft = new FieldType(TextField.TYPE_STORED);
+      ft.setStoreTermVectors(fieldInfo.storeTermVector);
+      ft.setStoreTermVectorOffsets(fieldInfo.storeOffsetWithTermVector);
+      ft.setStoreTermVectorPositions(fieldInfo.storePositionWithTermVector);
+      doc.add(new Field(fieldInfo.name, ft, new String(b, "UTF-8"))); 
+      return accept != FieldSelectorResult.LOAD;
+    case LAZY_LOAD:
+    case LATENT:
+      addFieldLazy(in, fieldInfo, false, accept == FieldSelectorResult.LAZY_LOAD, numUTF8Bytes);
+      return false;
+    case SIZE:
+    case SIZE_AND_BREAK:
+      in.seek(in.getFilePointer() + numUTF8Bytes);
+      addFieldSize(fieldInfo, 2*numUTF8Bytes);
+      return accept != FieldSelectorResult.SIZE;
+    default:
+      // skip
+      in.seek(in.getFilePointer() + numUTF8Bytes);
+      return false;
+    }
+  }
+
+  @Override
+  public boolean intField(FieldInfo fieldInfo, int value) throws IOException {
+		FieldType ft = new FieldType(NumericField.TYPE_STORED);
+		ft.setIndexed(fieldInfo.isIndexed);
+		ft.setOmitNorms(fieldInfo.omitNorms);
+		ft.setIndexOptions(fieldInfo.indexOptions);
+    return addNumericField(fieldInfo, new NumericField(fieldInfo.name, ft).setIntValue(value));
+  }
+
+  @Override
+  public boolean longField(FieldInfo fieldInfo, long value) throws IOException { 
+		FieldType ft = new FieldType(NumericField.TYPE_STORED);
+		ft.setIndexed(fieldInfo.isIndexed);
+		ft.setOmitNorms(fieldInfo.omitNorms);
+		ft.setIndexOptions(fieldInfo.indexOptions);
+    return addNumericField(fieldInfo, new NumericField(fieldInfo.name, ft).setLongValue(value));
+  }
+
+  @Override
+  public boolean floatField(FieldInfo fieldInfo, float value) throws IOException {
+		FieldType ft = new FieldType(NumericField.TYPE_STORED);
+		ft.setIndexed(fieldInfo.isIndexed);
+		ft.setOmitNorms(fieldInfo.omitNorms);
+		ft.setIndexOptions(fieldInfo.indexOptions);
+    return addNumericField(fieldInfo, new NumericField(fieldInfo.name, ft).setFloatValue(value));
+  }
+
+  @Override
+  public boolean doubleField(FieldInfo fieldInfo, double value) throws IOException {
+		FieldType ft = new FieldType(NumericField.TYPE_STORED);
+		ft.setIndexed(fieldInfo.isIndexed);
+		ft.setOmitNorms(fieldInfo.omitNorms);
+		ft.setIndexOptions(fieldInfo.indexOptions);
+    return addNumericField(fieldInfo, new NumericField(fieldInfo.name, ft).setDoubleValue(value));
+  }
+
+  private boolean addNumericField(FieldInfo fieldInfo, NumericField f) {
+    doc.add(f);
+    final FieldSelectorResult accept = selector.accept(fieldInfo.name);
+    switch (accept) {
+    case LOAD:
+      return false;
+    case LOAD_AND_BREAK:
+      return true;
+    case LAZY_LOAD:
+    case LATENT:
+      return false;
+    case SIZE:
+      return false;
+    case SIZE_AND_BREAK:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  private void addFieldLazy(IndexInput in, FieldInfo fi, boolean binary, boolean cacheResult, int numBytes) throws IOException {
+    final IndexableField f;
+    final long pointer = in.getFilePointer();
+    // Need to move the pointer ahead by toRead positions
+    in.seek(pointer+numBytes);
+    FieldType ft = new FieldType();
+    ft.setStored(true);
+    ft.setOmitNorms(fi.omitNorms);
+    ft.setIndexOptions(fi.indexOptions);
+    ft.setLazy(true);
+    
+    if (binary) {
+      f = new LazyField(in, fi.name, ft, numBytes, pointer, binary, cacheResult);
+    } else {
+      ft.setStoreTermVectors(fi.storeTermVector);
+      ft.setStoreTermVectorOffsets(fi.storeOffsetWithTermVector);
+      ft.setStoreTermVectorPositions(fi.storePositionWithTermVector);
+      f = new LazyField(in, fi.name, ft, numBytes, pointer, binary, cacheResult);
+    }
+    
+    doc.add(f);
+  }
+
+  // Add the size of field as a byte[] containing the 4 bytes of the integer byte size (high order byte first; char = 2 bytes)
+  // Read just the size -- caller must skip the field content to continue reading fields
+  // Return the size in bytes or chars, depending on field type
+  private void addFieldSize(FieldInfo fi, int numBytes) throws IOException {
+    byte[] sizebytes = new byte[4];
+    sizebytes[0] = (byte) (numBytes>>>24);
+    sizebytes[1] = (byte) (numBytes>>>16);
+    sizebytes[2] = (byte) (numBytes>>> 8);
+    sizebytes[3] = (byte)  numBytes      ;
+    doc.add(new BinaryField(fi.name, sizebytes));
+  }
+
+  /**
+   * A Lazy field implementation that defers loading of fields until asked for, instead of when the Document is
+   * loaded.
+   */
+  private static class LazyField extends Field {
+    private int toRead;
+    private long pointer;
+    private final boolean cacheResult;
+    private final IndexInput in;
+    private boolean isBinary;
+
+    public LazyField(IndexInput in, String name, FieldType ft, int toRead, long pointer, boolean isBinary, boolean cacheResult) {
+      super(name, ft);
+      this.in = in;
+      this.toRead = toRead;
+      this.pointer = pointer;
+      this.isBinary = isBinary;
+      this.cacheResult = cacheResult;
+    }
+
+    @Override
+    public Number numericValue() {
+      return null;
+    }
+
+    @Override
+    public DataType numericDataType() {
+      return null;
+    }
+
+    private IndexInput localFieldsStream;
+
+    private IndexInput getFieldStream() {
+      if (localFieldsStream == null) {
+        localFieldsStream = (IndexInput) in.clone();
+      }
+      return localFieldsStream;
+    }
+
+    /** The value of the field as a Reader, or null.  If null, the String value,
+     * binary value, or TokenStream value is used.  Exactly one of stringValue(), 
+     * readerValue(), getBinaryValue(), and tokenStreamValue() must be set. */
+    @Override
+    public Reader readerValue() {
+      return null;
+    }
+
+    /** The value of the field as a TokenStream, or null.  If null, the Reader value,
+     * String value, or binary value is used. Exactly one of stringValue(), 
+     * readerValue(), getBinaryValue(), and tokenStreamValue() must be set. */
+    @Override
+    public TokenStream tokenStreamValue() {
+      return null;
+    }
+
+    /** The value of the field as a String, or null.  If null, the Reader value,
+     * binary value, or TokenStream value is used.  Exactly one of stringValue(), 
+     * readerValue(), getBinaryValue(), and tokenStreamValue() must be set. */
+    @Override
+    synchronized public String stringValue() {
+      if (isBinary) {
+        return null;
+      } else {
+        if (fieldsData == null) {
+          String result = null;
+          IndexInput localFieldsStream = getFieldStream();
+          try {
+            localFieldsStream.seek(pointer);
+            byte[] bytes = new byte[toRead];
+            localFieldsStream.readBytes(bytes, 0, toRead);
+            result = new String(bytes, "UTF-8");
+          } catch (IOException e) {
+            throw new FieldReaderException(e);
+          }
+          if (cacheResult == true){
+            fieldsData = result;
+          }
+          return result;
+        } else {
+          return (String) fieldsData;
+        }
+      }
+    }
+
+    @Override
+    synchronized public BytesRef binaryValue() {
+      if (isBinary) {
+        if (fieldsData == null) {
+          // Allocate new buffer if result is null or too small
+          final byte[] b = new byte[toRead];
+   
+          IndexInput localFieldsStream = getFieldStream();
+
+          // Throw this IOException since IndexReader.document does so anyway, so probably not that big of a change for people
+          // since they are already handling this exception when getting the document
+          try {
+            localFieldsStream.seek(pointer);
+            localFieldsStream.readBytes(b, 0, toRead);
+          } catch (IOException e) {
+            throw new FieldReaderException(e);
+          }
+
+          final BytesRef result = new BytesRef(b);
+          result.length = toRead;
+          if (cacheResult == true){
+            fieldsData = result;
+          }
+          return result;
+        } else {
+          return (BytesRef) fieldsData;
+        }
+      } else {
+        return null;
+      }
+    }
+  }
+}
\ No newline at end of file

Property changes on: lucene/contrib/misc/src/java/org/apache/lucene/document/FieldSelectorVisitor.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java	(revision 0)
+++ lucene/contrib/misc/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java	(revision 1160484)
@@ -0,0 +1,29 @@
+package org.apache.lucene.document;
+/**
+ * Copyright 2004 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+
+/**
+ * Load the First field and break.
+ * <p/>
+ * See {@link FieldSelectorResult#LOAD_AND_BREAK}
+ */
+public class LoadFirstFieldSelector implements FieldSelector {
+
+  public FieldSelectorResult accept(String fieldName) {
+    return FieldSelectorResult.LOAD_AND_BREAK;
+  }
+}

Property changes on: lucene/contrib/misc/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java
===================================================================
--- lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java	(revision 1158028)
+++ lucene/contrib/misc/src/java/org/apache/lucene/index/FieldNormModifier.java	(working copy)
@@ -35,7 +35,7 @@
  * 
  * If Similarity class is specified, uses its computeNorm method to set norms.
  * If -n command line argument is used, removed field norms, as if 
- * {@link org.apache.lucene.document.Field.Index}.NO_NORMS was used.
+ * {@link org.apache.lucene.document.FieldType#setOmitNorms(boolean)} was used.
  *
  * <p>
  * NOTE: This will overwrite any length normalization or field/document boosts.
Index: lucene/contrib/demo/src/java/org/apache/lucene/demo/IndexFiles.java
===================================================================
--- lucene/contrib/demo/src/java/org/apache/lucene/demo/IndexFiles.java	(revision 1158028)
+++ lucene/contrib/demo/src/java/org/apache/lucene/demo/IndexFiles.java	(working copy)
@@ -21,8 +21,11 @@
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -173,8 +176,9 @@
           // field that is indexed (i.e. searchable), but don't tokenize 
           // the field into separate words and don't index term frequency
           // or positional information:
-          Field pathField = new Field("path", file.getPath(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
-          pathField.setIndexOptions(IndexOptions.DOCS_ONLY);
+          FieldType ft = new FieldType(TextField.TYPE_STORED);
+          ft.setIndexOptions(IndexOptions.DOCS_ONLY);
+          Field pathField = new Field("path", StringField.TYPE_STORED, file.getPath());
           doc.add(pathField);
 
           // Add the last modified date of the file a field named "modified".
@@ -192,7 +196,7 @@
           // so that the text of the file is tokenized and indexed, but not stored.
           // Note that FileReader expects the file to be in UTF-8 encoding.
           // If that's not the case searching for special characters will fail.
-          doc.add(new Field("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));
+          doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));
 
           if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
             // New index, so we just add the document (no old document can be there):
Index: lucene/contrib/memory/src/test/org/apache/lucene/index/memory/MemoryIndexTest.java
===================================================================
--- lucene/contrib/memory/src/test/org/apache/lucene/index/memory/MemoryIndexTest.java	(revision 1158028)
+++ lucene/contrib/memory/src/test/org/apache/lucene/index/memory/MemoryIndexTest.java	(working copy)
@@ -31,6 +31,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.queryparser.classic.QueryParser;
@@ -108,8 +109,8 @@
     IndexWriter writer = new IndexWriter(ramdir,
                                          new IndexWriterConfig(TEST_VERSION_CURRENT, analyzer).setCodecProvider(_TestUtil.alwaysCodec("Standard")));
     Document doc = new Document();
-    Field field1 = newField("foo", fooField.toString(), Field.Store.NO, Field.Index.ANALYZED);
-    Field field2 = newField("term", termField.toString(), Field.Store.NO, Field.Index.ANALYZED);
+    Field field1 = newField("foo", fooField.toString(), TextField.TYPE_UNSTORED);
+    Field field2 = newField("term", termField.toString(), TextField.TYPE_UNSTORED);
     doc.add(field1);
     doc.add(field2);
     writer.addDocument(doc);
Index: lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java
===================================================================
--- lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java	(revision 1158028)
+++ lucene/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java	(working copy)
@@ -35,23 +35,25 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
+import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.Fields;
+import org.apache.lucene.index.FieldsEnum;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
+import org.apache.lucene.index.IndexReader.ReaderContext;
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.OrdTermState;
-import org.apache.lucene.index.TermState;
-import org.apache.lucene.index.Terms;
-import org.apache.lucene.index.TermsEnum;
-import org.apache.lucene.index.FieldsEnum;
-import org.apache.lucene.index.DocsEnum;
-import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermFreqVector;
 import org.apache.lucene.index.TermPositionVector;
+import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.TermVectorMapper;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.codecs.PerDocValues;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.search.Collector;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -60,8 +62,8 @@
 import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.store.RAMDirectory; // for javadocs
 import org.apache.lucene.util.ArrayUtil;
-import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Constants; // for javadocs
 
 /**
@@ -240,11 +242,8 @@
   /**
    * Convenience method; Tokenizes the given field text and adds the resulting
    * terms to the index; Equivalent to adding an indexed non-keyword Lucene
-   * {@link org.apache.lucene.document.Field} that is
-   * {@link org.apache.lucene.document.Field.Index#ANALYZED tokenized},
-   * {@link org.apache.lucene.document.Field.Store#NO not stored},
-   * {@link org.apache.lucene.document.Field.TermVector#WITH_POSITIONS termVectorStored with positions} (or
-   * {@link org.apache.lucene.document.Field.TermVector#WITH_POSITIONS termVectorStored with positions and offsets}),
+   * {@link org.apache.lucene.document.Field} that is tokenized, not stored,
+   * termVectorStored with positions (or termVectorStored with positions and offsets),
    * 
    * @param fieldName
    *            a name to be associated with the text
@@ -1237,19 +1236,12 @@
     }
   
     @Override
-    public Document document(int n) {
+    public void document(int docID, StoredFieldVisitor visitor) {
       if (DEBUG) System.err.println("MemoryIndexReader.document");
-      return new Document(); // there are no stored fields
+      // no-op: there are no stored fields
     }
-
-    //When we convert to JDK 1.5 make this Set<String>
+    
     @Override
-    public Document document(int n, FieldSelector fieldSelector) throws IOException {
-      if (DEBUG) System.err.println("MemoryIndexReader.document");
-      return new Document(); // there are no stored fields
-    }
-
-    @Override
     public boolean hasDeletions() {
       if (DEBUG) System.err.println("MemoryIndexReader.hasDeletions");
       return false;
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/DuplicateFilterTest.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/DuplicateFilterTest.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/DuplicateFilterTest.java	(working copy)
@@ -19,7 +19,11 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.DocsEnum;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.*;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
@@ -71,9 +75,9 @@
 
   private void addDoc(RandomIndexWriter writer, String url, String text, String date) throws IOException {
     Document doc = new Document();
-    doc.add(newField(KEY_FIELD, url, Field.Store.YES, Field.Index.NOT_ANALYZED));
-    doc.add(newField("text", text, Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("date", date, Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField(KEY_FIELD, url, StringField.TYPE_STORED));
+    doc.add(newField("text", text, TextField.TYPE_STORED));
+    doc.add(newField("date", date, TextField.TYPE_STORED));
     writer.addDocument(doc);
   }
 
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/TermsFilterTest.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/TermsFilterTest.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/TermsFilterTest.java	(working copy)
@@ -17,8 +17,12 @@
  * limitations under the License.
  */
 
+import java.util.HashSet;
+
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -56,7 +60,7 @@
     for (int i = 0; i < 100; i++) {
       Document doc = new Document();
       int term = i * 10; //terms are units of 10;
-      doc.add(newField(fieldName, "" + term, Field.Store.YES, Field.Index.NOT_ANALYZED));
+      doc.add(newField(fieldName, "" + term, StringField.TYPE_STORED));
       w.addDocument(doc);
     }
     IndexReader reader = new SlowMultiReaderWrapper(w.getReader());
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/ChainedFilterTest.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/ChainedFilterTest.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/ChainedFilterTest.java	(working copy)
@@ -21,7 +21,8 @@
 import java.util.GregorianCalendar;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -62,9 +63,12 @@
 
     for (int i = 0; i < MAX; i++) {
       Document doc = new Document();
-      doc.add(newField("key", "" + (i + 1), Field.Store.YES, Field.Index.NOT_ANALYZED));
-      doc.add(newField("owner", (i < MAX / 2) ? "bob" : "sue", Field.Store.YES, Field.Index.NOT_ANALYZED));
-      doc.add(newField("date", cal.getTime().toString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setTokenized(false);
+      doc.add(newField("key", "" + (i + 1), customType));
+      doc.add(newField("owner", (i < MAX / 2) ? "bob" : "sue", customType));
+      doc.add(newField("date", cal.getTime().toString(), customType));
       writer.addDocument(doc);
 
       cal.add(Calendar.DATE, 1);
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/BooleanFilterTest.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/BooleanFilterTest.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/BooleanFilterTest.java	(working copy)
@@ -20,7 +20,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -60,10 +61,10 @@
 
   private void addDoc(RandomIndexWriter writer, String accessRights, String price, String date, String inStock) throws IOException {
     Document doc = new Document();
-    doc.add(newField("accessRights", accessRights, Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("price", price, Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("date", date, Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("inStock", inStock, Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("accessRights", accessRights, TextField.TYPE_STORED));
+    doc.add(newField("price", price, TextField.TYPE_STORED));
+    doc.add(newField("date", date, TextField.TYPE_STORED));
+    doc.add(newField("inStock", inStock, TextField.TYPE_STORED));
     writer.addDocument(doc);
   }
 
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/FuzzyLikeThisQueryTest.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/FuzzyLikeThisQueryTest.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/FuzzyLikeThisQueryTest.java	(working copy)
@@ -20,7 +20,8 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -64,8 +65,8 @@
 
   private void addDoc(RandomIndexWriter writer, String name, String id) throws IOException {
     Document doc = new Document();
-    doc.add(newField("name", name, Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("id", id, Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("name", name, TextField.TYPE_STORED));
+    doc.add(newField("id", id, TextField.TYPE_STORED));
     writer.addDocument(doc);
   }
 
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/regex/TestRegexQuery.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/regex/TestRegexQuery.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/regex/TestRegexQuery.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.index.TermsEnum;
 
@@ -47,7 +48,7 @@
     directory = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
     Document doc = new Document();
-    doc.add(newField(FN, "the quick brown fox jumps over the lazy dog", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField(FN, "the quick brown fox jumps over the lazy dog", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     reader = writer.getReader();
     writer.close();
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/regex/TestSpanRegexQuery.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/regex/TestSpanRegexQuery.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/regex/TestSpanRegexQuery.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
@@ -62,12 +64,10 @@
     // Field.Store.NO, Field.Index.ANALYZED));
     // writer.addDocument(doc);
     // doc = new Document();
-    doc.add(newField("field", "auto update", Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("field", "auto update", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     doc = new Document();
-    doc.add(newField("field", "first auto update", Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("field", "first auto update", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.optimize();
     writer.close();
@@ -87,13 +87,13 @@
       LockObtainFailedException, IOException {
     // creating a document to store
     Document lDoc = new Document();
-    lDoc.add(newField("field", "a1 b1", Field.Store.NO,
-        Field.Index.ANALYZED_NO_NORMS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    lDoc.add(newField("field", "a1 b1", customType));
 
     // creating a document to store
     Document lDoc2 = new Document();
-    lDoc2.add(newField("field", "a2 b2", Field.Store.NO,
-        Field.Index.ANALYZED_NO_NORMS));
+    lDoc2.add(newField("field", "a2 b2", customType));
 
     // creating first index writer
     IndexWriter writerA = new IndexWriter(indexStoreA, newIndexWriterConfig(
Index: lucene/contrib/queries/src/test/org/apache/lucene/search/TestSlowCollationMethods.java
===================================================================
--- lucene/contrib/queries/src/test/org/apache/lucene/search/TestSlowCollationMethods.java	(revision 1158028)
+++ lucene/contrib/queries/src/test/org/apache/lucene/search/TestSlowCollationMethods.java	(working copy)
@@ -6,6 +6,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.BooleanClause.Occur;
@@ -56,7 +58,11 @@
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
       String value = _TestUtil.randomUnicodeString(random);
-      Field field = newField("field", value, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setOmitNorms(true);
+      customType.setTokenized(false);
+      Field field = newField("field", value, customType);
       doc.add(field);
       iw.addDocument(doc);
     }
Index: lucene/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java
===================================================================
--- lucene/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java	(revision 1158028)
+++ lucene/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestCartesian.java	(working copy)
@@ -24,7 +24,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.Term;
@@ -93,26 +95,30 @@
   private void addPoint(IndexWriter writer, String name, double lat, double lng) throws IOException{
     
     Document doc = new Document();
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("name", name, customType));
     
-    doc.add(newField("name", name,Field.Store.YES, Field.Index.ANALYZED));
-    
     // convert the lat / long to lucene fields
-    doc.add(new NumericField(latField, Integer.MAX_VALUE, Field.Store.YES, true).setDoubleValue(lat));
-    doc.add(new NumericField(lngField, Integer.MAX_VALUE, Field.Store.YES, true).setDoubleValue(lng));
+    FieldType customType2 = new FieldType(NumericField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    doc.add(new NumericField(latField, Integer.MAX_VALUE, customType2).setDoubleValue(lat));
+    doc.add(new NumericField(lngField, Integer.MAX_VALUE, customType2).setDoubleValue(lng));
     
     // add a default meta field to make searching all documents easy 
-    doc.add(newField("metafile", "doc",Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("metafile", "doc", customType));
     
     int ctpsize = ctps.size();
+    FieldType customType3 = new FieldType(TextField.TYPE_UNSTORED);
+    customType3.setStored(true);
+    customType3.setTokenized(false);
+    customType3.setOmitNorms(true);
     for (int i =0; i < ctpsize; i++){
       CartesianTierPlotter ctp = ctps.get(i);
-      doc.add(new NumericField(ctp.getTierFieldName(), Integer.MAX_VALUE, 
-          Field.Store.YES, 
-          true).setDoubleValue(ctp.getTierBoxId(lat,lng)));
+      doc.add(new NumericField(ctp.getTierFieldName(), Integer.MAX_VALUE, customType).setDoubleValue(ctp.getTierBoxId(lat,lng)));
       
-      doc.add(newField(geoHashPrefix, GeoHashUtils.encode(lat,lng), 
-    		  Field.Store.YES, 
-    		  Field.Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(newField(geoHashPrefix, GeoHashUtils.encode(lat,lng), customType3));
     }
     writer.addDocument(doc);
     
Index: lucene/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestDistance.java
===================================================================
--- lucene/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestDistance.java	(revision 1158028)
+++ lucene/contrib/spatial/src/test/org/apache/lucene/spatial/tier/TestDistance.java	(working copy)
@@ -21,7 +21,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
@@ -62,15 +64,19 @@
   private void addPoint(IndexWriter writer, String name, double lat, double lng) throws IOException{
     
     Document doc = new Document();
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("name", name, customType));
     
-    doc.add(newField("name", name,Field.Store.YES, Field.Index.ANALYZED));
-    
     // convert the lat / long to lucene fields
-    doc.add(new NumericField(latField, Integer.MAX_VALUE, Field.Store.YES, true).setDoubleValue(lat));
-    doc.add(new NumericField(lngField, Integer.MAX_VALUE,Field.Store.YES, true).setDoubleValue(lng));
+    FieldType customType2 = new FieldType(NumericField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(new NumericField(latField, Integer.MAX_VALUE, customType2).setDoubleValue(lat));
+    doc.add(new NumericField(lngField, Integer.MAX_VALUE, customType2).setDoubleValue(lng));
     
     // add a default meta field to make searching all documents easy 
-    doc.add(newField("metafile", "doc",Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("metafile", "doc", customType));
     writer.addDocument(doc);
     
   }
Index: lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java
===================================================================
--- lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java	(revision 1158028)
+++ lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestParser.java	(working copy)
@@ -9,8 +9,10 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenFilter;
 import org.apache.lucene.analysis.MockTokenizer;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.IndexSearcher;
@@ -41,201 +43,202 @@
  */
 
 public class TestParser extends LuceneTestCase {
-	private static CoreParser builder;
-	private static Directory dir;
-	private static IndexReader reader;
-	private static IndexSearcher searcher;
+  private static CoreParser builder;
+  private static Directory dir;
+  private static IndexReader reader;
+  private static IndexSearcher searcher;
 
-	@BeforeClass
-	public static void beforeClass() throws Exception {
-	  // TODO: rewrite test (this needs to set QueryParser.enablePositionIncrements, too, for work with CURRENT):
-	  Analyzer analyzer=new MockAnalyzer(random, MockTokenizer.WHITESPACE, true, MockTokenFilter.ENGLISH_STOPSET, false); 
+  @BeforeClass
+  public static void beforeClass() throws Exception {
+    // TODO: rewrite test (this needs to set QueryParser.enablePositionIncrements, too, for work with CURRENT):
+    Analyzer analyzer=new MockAnalyzer(random, MockTokenizer.WHITESPACE, true, MockTokenFilter.ENGLISH_STOPSET, false); 
     //initialize the parser
-	  builder=new CorePlusExtensionsParser("contents",analyzer);
-		
-			BufferedReader d = new BufferedReader(new InputStreamReader(TestParser.class.getResourceAsStream("reuters21578.txt"))); 
-			dir=newDirectory();
-			IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(Version.LUCENE_40, analyzer));
-			String line = d.readLine();		
-			while(line!=null)
-			{
-				int endOfDate=line.indexOf('\t');
-				String date=line.substring(0,endOfDate).trim();
-				String content=line.substring(endOfDate).trim();
-				org.apache.lucene.document.Document doc =new org.apache.lucene.document.Document();
-				doc.add(newField("date",date,Field.Store.YES,Field.Index.ANALYZED));
-				doc.add(newField("contents",content,Field.Store.YES,Field.Index.ANALYZED));
-				NumericField numericField = new NumericField("date2");
-				numericField.setIntValue(Integer.valueOf(date));
-				doc.add(numericField);
-				writer.addDocument(doc);
-				line=d.readLine();
-			}			
-			d.close();
+    builder=new CorePlusExtensionsParser("contents",analyzer);
+    
+      BufferedReader d = new BufferedReader(new InputStreamReader(TestParser.class.getResourceAsStream("reuters21578.txt"))); 
+      dir=newDirectory();
+      IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(Version.LUCENE_40, analyzer));
+      String line = d.readLine();   
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      while(line!=null)
+      {
+        int endOfDate=line.indexOf('\t');
+        String date=line.substring(0,endOfDate).trim();
+        String content=line.substring(endOfDate).trim();
+        Document doc = new Document();
+        doc.add(newField("date",date,customType));
+        doc.add(newField("contents",content,customType));
+        NumericField numericField = new NumericField("date2");
+        numericField.setIntValue(Integer.valueOf(date));
+        doc.add(numericField);
+        writer.addDocument(doc);
+        line=d.readLine();
+      }     
+      d.close();
       writer.close();
-		reader=IndexReader.open(dir, true);
-		searcher=newSearcher(reader);
-		
-	}
-	
-	
-	
-	
-	@AfterClass
-	public static void afterClass() throws Exception {
-		reader.close();
-		searcher.close();
-		dir.close();
-		reader = null;
-		searcher = null;
-		dir = null;
-		builder = null;
-	}
-	
-	public void testSimpleXML() throws ParserException, IOException
-	{
-			Query q=parse("TermQuery.xml");
-			dumpResults("TermQuery", q, 5);
-	}
-	public void testSimpleTermsQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("TermsQuery.xml");
-			dumpResults("TermsQuery", q, 5);
-	}
-	public void testBooleanQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("BooleanQuery.xml");
-			dumpResults("BooleanQuery", q, 5);
-	}
-	public void testRangeFilterQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("RangeFilterQuery.xml");
-			dumpResults("RangeFilter", q, 5);
-	}
-	public void testUserQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("UserInputQuery.xml");
-			dumpResults("UserInput with Filter", q, 5);
-	}
-	
-	public void testCustomFieldUserQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("UserInputQueryCustomField.xml");
-			assertEquals(20.0f, q.getBoost());
-			int h = searcher.search(q, null, 1000).totalHits;
-			assertEquals("UserInputQueryCustomField should produce 0 result ", 0,h);
-	}
-	
-	public void testLikeThisQueryXML() throws Exception
-	{
-			Query q=parse("LikeThisQuery.xml");
-			dumpResults("like this", q, 5);
-	}
-	public void testBoostingQueryXML() throws Exception
-	{
-			Query q=parse("BoostingQuery.xml");
-			dumpResults("boosting ",q, 5);
-	}
-	public void testFuzzyLikeThisQueryXML() throws Exception
-	{
-			Query q=parse("FuzzyLikeThisQuery.xml");
-			//show rewritten fuzzyLikeThisQuery - see what is being matched on
-			if(VERBOSE)
-			{
-				System.out.println(q.rewrite(reader));
-			}
-			dumpResults("FuzzyLikeThis", q, 5);
-	}
-	public void testTermsFilterXML() throws Exception
-	{
-			Query q=parse("TermsFilterQuery.xml");
-			dumpResults("Terms Filter",q, 5);
-	}
+    reader=IndexReader.open(dir, true);
+    searcher=newSearcher(reader);
+    
+  }
+  
+  
+  
+  
+  @AfterClass
+  public static void afterClass() throws Exception {
+    reader.close();
+    searcher.close();
+    dir.close();
+    reader = null;
+    searcher = null;
+    dir = null;
+    builder = null;
+  }
+  
+  public void testSimpleXML() throws ParserException, IOException
+  {
+      Query q=parse("TermQuery.xml");
+      dumpResults("TermQuery", q, 5);
+  }
+  public void testSimpleTermsQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("TermsQuery.xml");
+      dumpResults("TermsQuery", q, 5);
+  }
+  public void testBooleanQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("BooleanQuery.xml");
+      dumpResults("BooleanQuery", q, 5);
+  }
+  public void testRangeFilterQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("RangeFilterQuery.xml");
+      dumpResults("RangeFilter", q, 5);
+  }
+  public void testUserQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("UserInputQuery.xml");
+      dumpResults("UserInput with Filter", q, 5);
+  }
+  
+  public void testCustomFieldUserQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("UserInputQueryCustomField.xml");
+      int h = searcher.search(q, null, 1000).totalHits;
+      assertEquals("UserInputQueryCustomField should produce 0 result ", 0,h);
+  }
+  
+  public void testLikeThisQueryXML() throws Exception
+  {
+      Query q=parse("LikeThisQuery.xml");
+      dumpResults("like this", q, 5);
+  }
+  public void testBoostingQueryXML() throws Exception
+  {
+      Query q=parse("BoostingQuery.xml");
+      dumpResults("boosting ",q, 5);
+  }
+  public void testFuzzyLikeThisQueryXML() throws Exception
+  {
+      Query q=parse("FuzzyLikeThisQuery.xml");
+      //show rewritten fuzzyLikeThisQuery - see what is being matched on
+      if(VERBOSE)
+      {
+        System.out.println(q.rewrite(reader));
+      }
+      dumpResults("FuzzyLikeThis", q, 5);
+  }
+  public void testTermsFilterXML() throws Exception
+  {
+      Query q=parse("TermsFilterQuery.xml");
+      dumpResults("Terms Filter",q, 5);
+  }
   public void testBoostingTermQueryXML() throws Exception
-	{
-			Query q=parse("BoostingTermQuery.xml");
-			dumpResults("BoostingTermQuery",q, 5);
-	}
+  {
+      Query q=parse("BoostingTermQuery.xml");
+      dumpResults("BoostingTermQuery",q, 5);
+  }
   public void testSpanTermXML() throws Exception
-	{
-			Query q=parse("SpanQuery.xml");
-			dumpResults("Span Query",q, 5);
-	}
-	public void testConstantScoreQueryXML() throws Exception
-	{
-			Query q=parse("ConstantScoreQuery.xml");
-			dumpResults("ConstantScoreQuery",q, 5);
-	}
-	public void testMatchAllDocsPlusFilterXML() throws ParserException, IOException
-	{
-			Query q=parse("MatchAllDocsQuery.xml");
-			dumpResults("MatchAllDocsQuery with range filter", q, 5);
-	}
-	public void testBooleanFilterXML() throws ParserException, IOException
-	{
-			Query q=parse("BooleanFilter.xml");
-			dumpResults("Boolean filter", q, 5);
-	}
-	public void testNestedBooleanQuery() throws ParserException, IOException
-	{
-			Query q=parse("NestedBooleanQuery.xml");
-			dumpResults("Nested Boolean query", q, 5);
-	}
-	public void testCachedFilterXML() throws ParserException, IOException
-	{
-			Query q=parse("CachedFilter.xml");
-			dumpResults("Cached filter", q, 5);
-	}
-	public void testDuplicateFilterQueryXML() throws ParserException, IOException
-	{
+  {
+      Query q=parse("SpanQuery.xml");
+      dumpResults("Span Query",q, 5);
+  }
+  public void testConstantScoreQueryXML() throws Exception
+  {
+      Query q=parse("ConstantScoreQuery.xml");
+      dumpResults("ConstantScoreQuery",q, 5);
+  }
+  public void testMatchAllDocsPlusFilterXML() throws ParserException, IOException
+  {
+      Query q=parse("MatchAllDocsQuery.xml");
+      dumpResults("MatchAllDocsQuery with range filter", q, 5);
+  }
+  public void testBooleanFilterXML() throws ParserException, IOException
+  {
+      Query q=parse("BooleanFilter.xml");
+      dumpResults("Boolean filter", q, 5);
+  }
+  public void testNestedBooleanQuery() throws ParserException, IOException
+  {
+      Query q=parse("NestedBooleanQuery.xml");
+      dumpResults("Nested Boolean query", q, 5);
+  }
+  public void testCachedFilterXML() throws ParserException, IOException
+  {
+      Query q=parse("CachedFilter.xml");
+      dumpResults("Cached filter", q, 5);
+  }
+  public void testDuplicateFilterQueryXML() throws ParserException, IOException
+  {
       Assume.assumeTrue(searcher.getIndexReader().getSequentialSubReaders() == null || 
                         searcher.getIndexReader().getSequentialSubReaders().length == 1);
-			Query q=parse("DuplicateFilterQuery.xml");
-			int h = searcher.search(q, null, 1000).totalHits;
-			assertEquals("DuplicateFilterQuery should produce 1 result ", 1,h);
-	}
-	
-	public void testNumericRangeFilterQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("NumericRangeFilterQuery.xml");
-			dumpResults("NumericRangeFilter", q, 5);
-	}
-	
-	public void testNumericRangeQueryQueryXML() throws ParserException, IOException
-	{
-			Query q=parse("NumericRangeQueryQuery.xml");
-			dumpResults("NumericRangeQuery", q, 5);
-	}
-	
+      Query q=parse("DuplicateFilterQuery.xml");
+      int h = searcher.search(q, null, 1000).totalHits;
+      assertEquals("DuplicateFilterQuery should produce 1 result ", 1,h);
+  }
+  
+  public void testNumericRangeFilterQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("NumericRangeFilterQuery.xml");
+      dumpResults("NumericRangeFilter", q, 5);
+  }
+  
+  public void testNumericRangeQueryQueryXML() throws ParserException, IOException
+  {
+      Query q=parse("NumericRangeQueryQuery.xml");
+      dumpResults("NumericRangeQuery", q, 5);
+  }
+  
 
 
-	//================= Helper methods ===================================
-	private Query parse(String xmlFileName) throws ParserException, IOException
-	{
-		InputStream xmlStream=TestParser.class.getResourceAsStream(xmlFileName);
-		Query result=builder.parse(xmlStream);
-		xmlStream.close();
-		return result;
-	}
-	private void dumpResults(String qType,Query q, int numDocs) throws IOException
-	{
+  //================= Helper methods ===================================
+  private Query parse(String xmlFileName) throws ParserException, IOException
+  {
+    InputStream xmlStream=TestParser.class.getResourceAsStream(xmlFileName);
+    Query result=builder.parse(xmlStream);
+    xmlStream.close();
+    return result;
+  }
+  private void dumpResults(String qType,Query q, int numDocs) throws IOException
+  {
                 if (VERBOSE) {
                   System.out.println("TEST: query=" + q);
                 }
                 TopDocs hits = searcher.search(q, null, numDocs);
-		assertTrue(qType +" should produce results ", hits.totalHits>0);
-		if(VERBOSE)
-		{
-			System.out.println("========="+qType+"============");
-			ScoreDoc[] scoreDocs = hits.scoreDocs;
-			for(int i=0;i<Math.min(numDocs,hits.totalHits);i++)
-			{
-				org.apache.lucene.document.Document ldoc=searcher.doc(scoreDocs[i].doc);
-				System.out.println("["+ldoc.get("date")+"]"+ldoc.get("contents"));
-			}
-			System.out.println();
-		}
-	}
-	
+    assertTrue(qType +" should produce results ", hits.totalHits>0);
+    if(VERBOSE)
+    {
+      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);
+        System.out.println("["+ldoc.get("date")+"]"+ldoc.get("contents"));
+      }
+      System.out.println();
+    }
+  }
+  
 
 }
Index: lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java
===================================================================
--- lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java	(revision 1158028)
+++ lucene/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java	(working copy)
@@ -11,6 +11,8 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -128,13 +130,15 @@
 	{
 		org.apache.lucene.document.Document result=new org.apache.lucene.document.Document();
 		StringTokenizer st=new StringTokenizer(nameValuePairs,"\t=");
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
 		while(st.hasMoreTokens())
 		{
 			String name=st.nextToken().trim();
 			if(st.hasMoreTokens())
 			{
 				String value=st.nextToken().trim();
-				result.add(newField(name,value,Field.Store.YES,Field.Index.ANALYZED));
+				result.add(newField(name,value,customType));
 			}
 		}
 		return result;
Index: lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java
===================================================================
--- lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java	(working copy)
@@ -28,9 +28,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
@@ -61,8 +60,11 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamConcurrent(),
-          TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectorOffsets(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectors(true);
+      document.add(new Field(FIELD, customType, new TokenStreamConcurrent()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -105,8 +107,12 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamConcurrent(),
-          TermVector.WITH_POSITIONS_OFFSETS));
+
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectorOffsets(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectors(true);
+      document.add(new Field(FIELD, customType, new TokenStreamConcurrent()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -176,8 +182,12 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamSparse(),
-          TermVector.WITH_POSITIONS_OFFSETS));
+
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectorOffsets(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectors(true);
+      document.add(new Field(FIELD, customType, new TokenStreamSparse()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -219,8 +229,12 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, TEXT, Store.YES, Index.ANALYZED,
-          TermVector.WITH_OFFSETS));
+
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setStoreTermVectorOffsets(true);
+      customType.setStoreTermVectors(true);
+      document.add(new Field(FIELD, customType, TEXT));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -260,8 +274,11 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamSparse(),
-          TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectorOffsets(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectors(true);
+      document.add(new Field(FIELD, customType, new TokenStreamSparse()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
Index: lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java
===================================================================
--- lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/TokenSourcesTest.java	(working copy)
@@ -28,7 +28,8 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
@@ -107,8 +108,10 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new OverlapAnalyzer()));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamOverlap(),
-          TermVector.WITH_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorOffsets(true);
+      document.add(new Field(FIELD, customType, new TokenStreamOverlap()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -153,8 +156,11 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new OverlapAnalyzer()));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamOverlap(),
-          TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorOffsets(true);
+      customType.setStoreTermVectorPositions(true);
+      document.add(new Field(FIELD, customType, new TokenStreamOverlap()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -199,8 +205,10 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new OverlapAnalyzer()));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamOverlap(),
-          TermVector.WITH_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorOffsets(true);
+      document.add(new Field(FIELD, customType, new TokenStreamOverlap()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
@@ -246,8 +254,10 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new OverlapAnalyzer()));
     try {
       final Document document = new Document();
-      document.add(new Field(FIELD, new TokenStreamOverlap(),
-          TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorOffsets(true);
+      document.add(new Field(FIELD, customType, new TokenStreamOverlap()));
       indexWriter.addDocument(document);
     } finally {
       indexWriter.close();
Index: lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java
===================================================================
--- lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterTest.java	(working copy)
@@ -44,9 +44,9 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -1637,7 +1637,9 @@
   
   private Document doc( String f, String v ){
     Document doc = new Document();
-    doc.add( new Field( f, v, Store.YES, Index.ANALYZED ) );
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add( new Field( f, customType, v));
     return doc;
   }
   
@@ -1698,7 +1700,7 @@
    * QueryFragmentScorer(query));
    * 
    * for (int i = 0; i < hits.totalHits; i++) { String text =
-   * searcher.doc(hits.scoreDocs[i].doc).get(FIELD_NAME); TokenStream
+   * searcher.doc2(hits.scoreDocs[i].doc).get(FIELD_NAME); TokenStream
    * tokenStream=bigramAnalyzer.tokenStream(FIELD_NAME,new StringReader(text));
    * String highlightedText = highlighter.getBestFragment(tokenStream,text);
    * System.out.println(highlightedText); } }
@@ -1752,21 +1754,23 @@
       addDoc(writer, text);
     }
     Document doc = new Document();
-    NumericField nfield = new NumericField(NUMERIC_FIELD_NAME, Store.YES, true);
+    FieldType storedNumericType = new FieldType(NumericField.TYPE_UNSTORED);
+    storedNumericType.setStored(true);
+    NumericField nfield = new NumericField(NUMERIC_FIELD_NAME, storedNumericType);
     nfield.setIntValue(1);
     doc.add(nfield);
     writer.addDocument(doc, analyzer);
-    nfield = new NumericField(NUMERIC_FIELD_NAME, Store.YES, true);
+    nfield = new NumericField(NUMERIC_FIELD_NAME, storedNumericType);
     nfield.setIntValue(3);
     doc = new Document();
     doc.add(nfield);
     writer.addDocument(doc, analyzer);
-    nfield = new NumericField(NUMERIC_FIELD_NAME, Store.YES, true);
+    nfield = new NumericField(NUMERIC_FIELD_NAME, storedNumericType);
     nfield.setIntValue(5);
     doc = new Document();
     doc.add(nfield);
     writer.addDocument(doc, analyzer);
-    nfield = new NumericField(NUMERIC_FIELD_NAME, Store.YES, true);
+    nfield = new NumericField(NUMERIC_FIELD_NAME, storedNumericType);
     nfield.setIntValue(7);
     doc = new Document();
     doc.add(nfield);
@@ -1787,7 +1791,10 @@
   }
   private void addDoc(IndexWriter writer, String text) throws IOException {
     Document d = new Document();
-    Field f = new Field(FIELD_NAME, text, Field.Store.YES, Field.Index.ANALYZED);
+
+    FieldType storedType = new FieldType(TextField.TYPE_UNSTORED);
+    storedType.setStored(true);
+    Field f = new Field(FIELD_NAME, storedType, text);
     d.add(f);
     writer.addDocument(d);
 
Index: lucene/contrib/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java
===================================================================
--- lucene/contrib/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/test/org/apache/lucene/search/vectorhighlight/AbstractTestCase.java	(working copy)
@@ -34,14 +34,14 @@
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DisjunctionMaxQuery;
 import org.apache.lucene.search.PhraseQuery;
 import org.apache.lucene.search.Query;
@@ -359,8 +359,14 @@
     IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(
         TEST_VERSION_CURRENT, analyzer).setOpenMode(OpenMode.CREATE));
     Document doc = new Document();
-    for( String value: values )
-      doc.add( new Field( F, value, Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorOffsets(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStored(true);
+    for( String value: values ) {
+      doc.add( new Field( F, customType, value ) );
+    }
     writer.addDocument( doc );
     writer.close();
     if (reader != null) reader.close();
@@ -372,8 +378,14 @@
     IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(
         TEST_VERSION_CURRENT, analyzerK).setOpenMode(OpenMode.CREATE));
     Document doc = new Document();
-    for( String value: values )
-      doc.add( new Field( F, value, Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
+    FieldType customType = new FieldType(TextField.TYPE_STORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorOffsets(true);
+    customType.setStoreTermVectorPositions(true);
+    for( String value: values ) {
+      doc.add( new Field( F, customType, value ));
+      //doc.add( new Field( F, value, Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
+    }
     writer.addDocument( doc );
     writer.close();
     if (reader != null) reader.close();
Index: lucene/contrib/highlighter/src/test/org/apache/lucene/search/vectorhighlight/SimpleFragmentsBuilderTest.java
===================================================================
--- lucene/contrib/highlighter/src/test/org/apache/lucene/search/vectorhighlight/SimpleFragmentsBuilderTest.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/test/org/apache/lucene/search/vectorhighlight/SimpleFragmentsBuilderTest.java	(working copy)
@@ -19,9 +19,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -139,7 +138,12 @@
     IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(
         TEST_VERSION_CURRENT, analyzerW).setOpenMode(OpenMode.CREATE));
     Document doc = new Document();
-    doc.add( new Field( F, "aaa", Store.NO, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorOffsets(true);
+    customType.setStoreTermVectorPositions(true);
+    doc.add( new Field( F, customType, "aaa" ) );
+    //doc.add( new Field( F, "aaa", Store.NO, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
     writer.addDocument( doc );
     writer.close();
     if (reader != null) reader.close();
@@ -155,9 +159,8 @@
     SimpleFragListBuilder sflb = new SimpleFragListBuilder();
     FieldFragList ffl = sflb.createFieldFragList( fpl, 100 );
     SimpleFragmentsBuilder sfb = new SimpleFragmentsBuilder();
-    // '/' separator doesn't effect the snippet because of NOT_ANALYZED field
     sfb.setMultiValuedSeparator( '/' );
-    assertEquals( "abc<b>defg</b>hijkl", sfb.createFragment( reader, 0, F, ffl ) );
+    assertEquals( "abc/<b>defg</b>/hijkl/", sfb.createFragment( reader, 0, F, ffl ) );
   }
   
   public void testMVSeparator() throws Exception {
Index: lucene/contrib/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java
===================================================================
--- lucene/contrib/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/java/org/apache/lucene/search/highlight/TokenSources.java	(working copy)
@@ -60,10 +60,11 @@
    * @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
-   *         {@link org.apache.lucene.document.Fieldable} on the
+   *         {@link org.apache.lucene.index.IndexableField} on the
    *         {@link org.apache.lucene.document.Document}
    * @throws IOException if there was an error loading
    */
+
   public static TokenStream getAnyTokenStream(IndexReader reader, int docId,
       String field, Document doc, Analyzer analyzer) throws IOException {
     TokenStream ts = null;
Index: lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldTermStack.java
===================================================================
--- lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldTermStack.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/FieldTermStack.java	(working copy)
@@ -21,6 +21,7 @@
 import java.util.LinkedList;
 import java.util.Set;
 
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.TermFreqVector;
 import org.apache.lucene.index.TermPositionVector;
@@ -46,8 +47,12 @@
   //  Directory dir = new RAMDirectory();
   //  IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig(Version.LUCENE_CURRENT, analyzer));
   //  Document doc = new Document();
-  //  doc.add( new Field( "f", "a a a b b c a b b c d e f", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
-  //  doc.add( new Field( "f", "b a b a f", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS ) );
+  //  FieldType ft = new FieldType(TextField.TYPE_STORED);
+  //  ft.setStoreTermVectors(true);
+  //  ft.setStoreTermVectorOffsets(true);
+  //  ft.setStoreTermVectorPositions(true);
+  //  doc.add( new Field( "f", ft, "a a a b b c a b b c d e f" ) );
+  //  doc.add( new Field( "f", ft, "b a b a f" ) );
   //  writer.addDocument( doc );
   //  writer.close();
     
@@ -67,7 +72,7 @@
    */
   public FieldTermStack( IndexReader reader, int docId, String fieldName, final FieldQuery fieldQuery ) throws IOException {
     this.fieldName = fieldName;
-
+    
     TermFreqVector tfv = reader.getTermFreqVector( docId, fieldName );
     if( tfv == null ) return; // just return to make null snippets
     TermPositionVector tpv = null;
Index: lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/BaseFragmentsBuilder.java
===================================================================
--- lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/BaseFragmentsBuilder.java	(revision 1158028)
+++ lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/BaseFragmentsBuilder.java	(working copy)
@@ -21,15 +21,18 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.MapFieldSelector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.search.highlight.DefaultEncoder;
 import org.apache.lucene.search.highlight.Encoder;
+import org.apache.lucene.search.vectorhighlight.FieldFragList.WeightedFragInfo.SubInfo;
 import org.apache.lucene.search.vectorhighlight.FieldFragList.WeightedFragInfo;
-import org.apache.lucene.search.vectorhighlight.FieldFragList.WeightedFragInfo.SubInfo;
 import org.apache.lucene.search.vectorhighlight.FieldPhraseList.WeightedPhraseInfo.Toffs;
+import org.apache.lucene.store.IndexInput;
 
 public abstract class BaseFragmentsBuilder implements FragmentsBuilder {
 
@@ -107,10 +110,27 @@
     return fragments.toArray( new String[fragments.size()] );
   }
   
-  protected Field[] getFields( IndexReader reader, int docId, String fieldName) throws IOException {
+  protected Field[] getFields( IndexReader reader, int docId, final String fieldName) throws IOException {
     // according to javadoc, doc.getFields(fieldName) cannot be used with lazy loaded field???
-    Document doc = reader.document( docId, new MapFieldSelector(fieldName) );
-    return doc.getFields( fieldName ); // according to Document class javadoc, this never returns null
+    final List<Field> fields = new ArrayList<Field>();
+    reader.document(docId, new StoredFieldVisitor() {
+        @Override
+        public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+          if (fieldInfo.name.equals(fieldName)) {
+            final byte[] b = new byte[numUTF8Bytes];
+            in.readBytes(b, 0, b.length);
+            FieldType ft = new FieldType(TextField.TYPE_STORED);
+            ft.setStoreTermVectors(fieldInfo.storeTermVector);
+            ft.setStoreTermVectorOffsets(fieldInfo.storeOffsetWithTermVector);
+            ft.setStoreTermVectorPositions(fieldInfo.storePositionWithTermVector);
+            fields.add(new Field(fieldInfo.name, ft, new String(b, "UTF-8")));
+          } else {
+            in.seek(in.getFilePointer() + numUTF8Bytes);
+          }
+          return false;
+        }
+      });
+    return fields.toArray(new Field[fields.size()]);
   }
 
   protected String makeFragment( StringBuilder buffer, int[] index, Field[] values, WeightedFragInfo fragInfo,
@@ -142,8 +162,7 @@
       int startOffset, int endOffset ){
     while( buffer.length() < endOffset && index[0] < values.length ){
       buffer.append( values[index[0]].stringValue() );
-      if( values[index[0]].isTokenized() )
-        buffer.append( multiValuedSeparator );
+      buffer.append( multiValuedSeparator );
       index[0]++;
     }
     int eo = buffer.length() < endOffset ? buffer.length() : endOffset;
Index: lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/package.html
===================================================================
--- lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/package.html	(revision 1158028)
+++ lucene/contrib/highlighter/src/java/org/apache/lucene/search/vectorhighlight/package.html	(working copy)
@@ -25,7 +25,7 @@
 <li>support N-gram fields</li>
 <li>support phrase-unit highlighting with slops</li>
 <li>need Java 1.5</li>
-<li>highlight fields need to be TermVector.WITH_POSITIONS_OFFSETS</li>
+<li>highlight fields need to be stored with Positions and Offsets</li>
 <li>take into account query boost to score fragments</li>
 <li>support colored highlight tags</li>
 <li>pluggable FragListBuilder</li>
@@ -95,7 +95,7 @@
 
 <h3>Step 2.</h3>
 <p>In Step 2, Fast Vector Highlighter generates {@link org.apache.lucene.search.vectorhighlight.FieldTermStack}. Fast Vector Highlighter uses {@link org.apache.lucene.index.TermFreqVector} data
-(must be stored {@link org.apache.lucene.document.Field.TermVector#WITH_POSITIONS_OFFSETS})
+(must be stored {@link org.apache.lucene.document.FieldType#setStoreTermVectorOffsets(boolean)} and {@link org.apache.lucene.document.FieldType#setStoreTermVectorPositions(boolean)})
 to generate it. <code>FieldTermStack</code> keeps the terms in the user query.
 Therefore, in this sample case, Fast Vector Highlighter generates the following <code>FieldTermStack</code>:</p>
 <pre>
Index: lucene/src/test/org/apache/lucene/search/TestSort.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSort.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSort.java	(working copy)
@@ -28,11 +28,15 @@
 import org.apache.lucene.document.IndexDocValuesField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -121,37 +125,48 @@
     dirs.add(indexStore);
     RandomIndexWriter writer = new RandomIndexWriter(random, indexStore, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
 
+    FieldType ft1 = new FieldType();
+    ft1.setStored(true);
+    FieldType ft2 = new FieldType();
+    ft2.setIndexed(true);
     for (int i=0; i<data.length; ++i) {
       if (((i%2)==0 && even) || ((i%2)==1 && odd)) {
         Document doc = new Document();
-        doc.add (new Field ("tracer",   data[i][0], Field.Store.YES, Field.Index.NO));
-        doc.add (new Field ("contents", data[i][1], Field.Store.NO, Field.Index.ANALYZED));
+        doc.add (new Field ("tracer", ft1, data[i][0]));
+        doc.add (new TextField ("contents", data[i][1]));
         if (data[i][2] != null) {
-          Field f = supportsDocValues ? 
-              IndexDocValuesField.set(new Field ("int",      data[i][2], Field.Store.NO, Field.Index.NOT_ANALYZED), ValueType.VAR_INTS)
-                               : new Field ("int",      data[i][2], Field.Store.NO, Field.Index.NOT_ANALYZED);
+          Field f = new StringField ("int", data[i][2]);
+          if (supportsDocValues) {
+            f = IndexDocValuesField.build(f, ValueType.VAR_INTS);
+          };
           doc.add(f);
         }
         if (data[i][3] != null) {
-          Field f = supportsDocValues ?
-              IndexDocValuesField.set(new Field ("float",    data[i][3], Field.Store.NO, Field.Index.NOT_ANALYZED), ValueType.FLOAT_32)
-                              :  new Field ("float",    data[i][3], Field.Store.NO, Field.Index.NOT_ANALYZED);
+          Field f = new StringField ("float", data[i][3]);
+          if (supportsDocValues) {
+            f = IndexDocValuesField.build(f, ValueType.FLOAT_32);
+          }
           doc.add(f);
         }
-        if (data[i][4] != null) doc.add (new Field ("string",   data[i][4], Field.Store.NO, Field.Index.NOT_ANALYZED));
-        if (data[i][5] != null) doc.add (new Field ("custom",   data[i][5], Field.Store.NO, Field.Index.NOT_ANALYZED));
-        if (data[i][6] != null) doc.add (new Field ("i18n",     data[i][6], Field.Store.NO, Field.Index.NOT_ANALYZED));
-        if (data[i][7] != null) doc.add (new Field ("long",     data[i][7], Field.Store.NO, Field.Index.NOT_ANALYZED));
+        if (data[i][4] != null) doc.add (new StringField ("string",   data[i][4]));
+        if (data[i][5] != null) doc.add (new StringField ("custom",   data[i][5]));
+        if (data[i][6] != null) doc.add (new StringField ("i18n",     data[i][6]));
+        if (data[i][7] != null) doc.add (new StringField ("long",     data[i][7]));
         if (data[i][8] != null) {
-          Field f = supportsDocValues ?
-              IndexDocValuesField.set(new Field ("double",     data[i][8], Field.Store.NO, Field.Index.NOT_ANALYZED), ValueType.FLOAT_64)
-                              :  new Field ("double",     data[i][8], Field.Store.NO, Field.Index.NOT_ANALYZED);
+          Field f = new StringField ("double", data[i][8]);
+          if (supportsDocValues) {
+            f = IndexDocValuesField.build(f, ValueType.FLOAT_64);
+          }
           doc.add(f);
         }
-        if (data[i][9] != null) doc.add (new Field ("short",     data[i][9], Field.Store.NO, Field.Index.NOT_ANALYZED));
-        if (data[i][10] != null) doc.add (new Field ("byte",     data[i][10], Field.Store.NO, Field.Index.NOT_ANALYZED));
-        if (data[i][11] != null) doc.add (new Field ("parser",     data[i][11], Field.Store.NO, Field.Index.NOT_ANALYZED));
-        doc.setBoost(2);  // produce some scores above 1.0
+        if (data[i][9] != null) doc.add (new StringField ("short",     data[i][9]));
+        if (data[i][10] != null) doc.add (new StringField ("byte",     data[i][10]));
+        if (data[i][11] != null) doc.add (new StringField ("parser",     data[i][11]));
+
+        for(IndexableField f : doc.getFields()) {
+          ((Field) f).setBoost(2.0f);
+        }
+
         writer.addDocument (doc);
       }
     }
@@ -176,18 +191,21 @@
             setMaxBufferedDocs(4).
             setMergePolicy(newLogMergePolicy(97))
     );
+    FieldType customType = new FieldType();
+    customType.setStored(true);
     for (int i=0; i<NUM_STRINGS; i++) {
         Document doc = new Document();
         String num = getRandomCharString(getRandomNumber(2, 8), 48, 52);
-        doc.add (new Field ("tracer", num, Field.Store.YES, Field.Index.NO));
+        doc.add (new Field ("tracer", customType, num));
         //doc.add (new Field ("contents", Integer.toString(i), Field.Store.NO, Field.Index.ANALYZED));
-        doc.add (new Field ("string", num, Field.Store.NO, Field.Index.NOT_ANALYZED));
+        doc.add (new StringField ("string", num));
         String num2 = getRandomCharString(getRandomNumber(1, 4), 48, 50);
-        doc.add (new Field ("string2", num2, Field.Store.NO, Field.Index.NOT_ANALYZED));
-        doc.add (new Field ("tracer2", num2, Field.Store.YES, Field.Index.NO));
-        doc.setBoost(2);  // produce some scores above 1.0
+        doc.add (new StringField ("string2", num2));
+        doc.add (new Field ("tracer2", customType, num2));
+        for(IndexableField f : doc.getFields()) {
+          ((Field) f).setBoost(2.0f);
+        }
         writer.addDocument (doc);
-      
     }
     //writer.optimize ();
     //System.out.println(writer.getSegmentCount());
@@ -387,17 +405,17 @@
     boolean fail = false;
     for (int x = 0; x < n; ++x) {
       Document doc2 = searcher.doc(result[x].doc);
-      String[] v = doc2.getValues("tracer");
-      String[] v2 = doc2.getValues("tracer2");
+      IndexableField[] v = doc2.getFields("tracer");
+      IndexableField[] v2 = doc2.getFields("tracer2");
       for (int j = 0; j < v.length; ++j) {
         if (last != null) {
-          int cmp = v[j].compareTo(last);
+          int cmp = v[j].stringValue().compareTo(last);
           if (!(cmp >= 0)) { // ensure first field is in order
             fail = true;
             System.out.println("fail:" + v[j] + " < " + last);
           }
           if (cmp == 0) { // ensure second field is in reverse order
-            cmp = v2[j].compareTo(lastSub);
+            cmp = v2[j].stringValue().compareTo(lastSub);
             if (cmp > 0) {
               fail = true;
               System.out.println("rev field fail:" + v2[j] + " > " + lastSub);
@@ -409,8 +427,8 @@
             }
           }
         }
-        last = v[j];
-        lastSub = v2[j];
+        last = v[j].stringValue();
+        lastSub = v2[j].stringValue();
         lastDocId = result[x].doc;
         buff.append(v[j] + "(" + v2[j] + ")(" + result[x].doc+") ");
       }
@@ -1051,9 +1069,9 @@
     int n = result.length;
     for (int i=0; i<n; ++i) {
       Document doc = searcher.doc(result[i].doc);
-      String[] v = doc.getValues("tracer");
+      IndexableField[] v = doc.getFields("tracer");
       for (int j=0; j<v.length; ++j) {
-        buff.append (v[j]);
+        buff.append (v[j].stringValue());
       }
     }
     assertEquals (msg, expectedResult, buff.toString());
@@ -1064,12 +1082,12 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(
                         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("f", "", Field.Store.NO, Field.Index.NOT_ANALYZED));
-    doc.add(newField("t", "1", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("f", "", StringField.TYPE_UNSTORED));
+    doc.add(newField("t", "1", StringField.TYPE_UNSTORED));
     w.addDocument(doc);
     w.commit();
     doc = new Document();
-    doc.add(newField("t", "1", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("t", "1", StringField.TYPE_UNSTORED));
     w.addDocument(doc);
 
     IndexReader r = IndexReader.open(w, true);
@@ -1091,8 +1109,8 @@
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     for (int i=0; i<5; i++) {
         Document doc = new Document();
-        doc.add (new Field ("string", "a"+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
-        doc.add (new Field ("string", "b"+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
+        doc.add (new StringField ("string", "a"+i));
+        doc.add (new StringField ("string", "b"+i));
         writer.addDocument (doc);
     }
     writer.optimize(); // enforce one segment to have a higher unique term count in all cases
@@ -1112,8 +1130,8 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, indexStore);
     for (int i=0; i<5; i++) {
       Document doc = new Document();
-      doc.add (new Field ("string", "a"+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add (new Field ("string", "b"+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add (new StringField ("string", "a"+i));
+      doc.add (new StringField ("string", "b"+i));
       writer.addDocument (doc);
     }
     IndexReader reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestDocBoost.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestDocBoost.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestDocBoost.java	(working copy)
@@ -38,26 +38,18 @@
     Directory store = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, store, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
 
-    Fieldable f1 = newField("field", "word", Field.Store.YES, Field.Index.ANALYZED);
-    Fieldable f2 = newField("field", "word", Field.Store.YES, Field.Index.ANALYZED);
+    Field f1 = newField("field", "word", TextField.TYPE_STORED);
+    Field f2 = newField("field", "word", TextField.TYPE_STORED);
     f2.setBoost(2.0f);
 
     Document d1 = new Document();
     Document d2 = new Document();
-    Document d3 = new Document();
-    Document d4 = new Document();
-    d3.setBoost(3.0f);
-    d4.setBoost(2.0f);
 
     d1.add(f1);                                 // boost = 1
     d2.add(f2);                                 // boost = 2
-    d3.add(f1);                                 // boost = 3
-    d4.add(f2);                                 // boost = 4
 
     writer.addDocument(d1);
     writer.addDocument(d2);
-    writer.addDocument(d3);
-    writer.addDocument(d4);
 
     IndexReader reader = writer.getReader();
     writer.close();
@@ -89,7 +81,7 @@
 
     float lastScore = 0.0f;
 
-    for (int i = 0; i < 4; i++) {
+    for (int i = 0; i < 2; i++) {
       assertTrue(scores[i] > lastScore);
       lastScore = scores[i];
     }
Index: lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFuzzyQuery2.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -85,7 +86,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.KEYWORD, false)).setMergePolicy(newLogMergePolicy()));
     
     Document doc = new Document();
-    Field field = newField("field", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field field = newField("field", "", TextField.TYPE_UNSTORED);
     doc.add(field);
     
     for (int i = 0; i < terms; i++) {
Index: lucene/src/test/org/apache/lucene/search/TestNot.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestNot.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestNot.java	(working copy)
@@ -25,7 +25,7 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 
 /** Similarity unit test.
  *
@@ -38,7 +38,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, store);
 
     Document d1 = new Document();
-    d1.add(newField("field", "a b", Field.Store.YES, Field.Index.ANALYZED));
+    d1.add(newField("field", "a b", TextField.TYPE_STORED));
 
     writer.addDocument(d1);
     IndexReader reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestTimeLimitingCollector.java	(working copy)
@@ -22,7 +22,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -111,7 +111,7 @@
 
   private void add(String value, RandomIndexWriter iw) throws IOException {
     Document d = new Document();
-    d.add(newField(FIELD_NAME, value, Field.Store.NO, Field.Index.ANALYZED));
+    d.add(newField(FIELD_NAME, value, TextField.TYPE_UNSTORED));
     iw.addDocument(d);
   }
 
Index: lucene/src/test/org/apache/lucene/search/TestCachingWrapperFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestCachingWrapperFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestCachingWrapperFilter.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -175,7 +177,10 @@
 
     // add a doc, refresh the reader, and check that its there
     Document doc = new Document();
-    doc.add(newField("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    doc.add(newField("id", "1", customType));
     writer.addDocument(doc);
 
     reader = refreshReader(reader);
Index: lucene/src/test/org/apache/lucene/search/TestPrefixFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPrefixFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPrefixFilter.java	(working copy)
@@ -23,7 +23,7 @@
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 
 /**
  * Tests {@link PrefixFilter} class.
@@ -40,7 +40,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
     for (int i = 0; i < categories.length; i++) {
       Document doc = new Document();
-      doc.add(newField("category", categories[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
+      doc.add(newField("category", categories[i], StringField.TYPE_STORED));
       writer.addDocument(doc);
     }
     IndexReader reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestAutomatonQueryUnicode.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestAutomatonQueryUnicode.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestAutomatonQueryUnicode.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -47,12 +48,9 @@
     directory = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
     Document doc = new Document();
-    Field titleField = newField("title", "some title", Field.Store.NO,
-        Field.Index.ANALYZED);
-    Field field = newField(FN, "", Field.Store.NO,
-        Field.Index.ANALYZED);
-    Field footerField = newField("footer", "a footer", Field.Store.NO,
-        Field.Index.ANALYZED);
+    Field titleField = newField("title", "some title", TextField.TYPE_UNSTORED);
+    Field field = newField(FN, "", TextField.TYPE_UNSTORED);
+    Field footerField = newField("footer", "a footer", TextField.TYPE_UNSTORED);
     doc.add(titleField);
     doc.add(field);
     doc.add(footerField);
Index: lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestBooleanQuery.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -68,7 +69,7 @@
     Directory dir = newDirectory();
     RandomIndexWriter w = new RandomIndexWriter(random, dir);
     Document doc = new Document();
-    doc.add(newField("field", "a b c d", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a b c d", TextField.TYPE_UNSTORED));
     w.addDocument(doc);
 
     IndexReader r = w.getReader();
@@ -129,7 +130,7 @@
     Directory dir1 = newDirectory();
     RandomIndexWriter iw1 = new RandomIndexWriter(random, dir1);
     Document doc1 = new Document();
-    doc1.add(newField("field", "foo bar", Field.Index.ANALYZED));
+    doc1.add(newField("field", "foo bar", TextField.TYPE_UNSTORED));
     iw1.addDocument(doc1);
     IndexReader reader1 = iw1.getReader();
     iw1.close();
@@ -137,7 +138,7 @@
     Directory dir2 = newDirectory();
     RandomIndexWriter iw2 = new RandomIndexWriter(random, dir2);
     Document doc2 = new Document();
-    doc2.add(newField("field", "foo baz", Field.Index.ANALYZED));
+    doc2.add(newField("field", "foo baz", TextField.TYPE_UNSTORED));
     iw2.addDocument(doc2);
     IndexReader reader2 = iw2.getReader();
     iw2.close();
Index: lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPhraseQuery.java	(working copy)
@@ -68,19 +68,19 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory, analyzer);
     
     Document doc = new Document();
-    doc.add(newField("field", "one two three four five", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("repeated", "this is a repeated field - first part", Field.Store.YES, Field.Index.ANALYZED));
-    Fieldable repeatedField = newField("repeated", "second part of a repeated field", Field.Store.YES, Field.Index.ANALYZED);
+    doc.add(newField("field", "one two three four five", TextField.TYPE_STORED));
+    doc.add(newField("repeated", "this is a repeated field - first part", TextField.TYPE_STORED));
+    IndexableField repeatedField = newField("repeated", "second part of a repeated field", TextField.TYPE_STORED);
     doc.add(repeatedField);
-    doc.add(newField("palindrome", "one two three two one", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("palindrome", "one two three two one", TextField.TYPE_STORED));
     writer.addDocument(doc);
     
     doc = new Document();
-    doc.add(newField("nonexist", "phrase exist notexist exist found", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("nonexist", "phrase exist notexist exist found", TextField.TYPE_STORED));
     writer.addDocument(doc);
     
     doc = new Document();
-    doc.add(newField("nonexist", "phrase exist notexist exist found", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("nonexist", "phrase exist notexist exist found", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     reader = writer.getReader();
@@ -223,7 +223,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory, 
         newIndexWriterConfig( Version.LUCENE_40, stopAnalyzer));
     Document doc = new Document();
-    doc.add(newField("field", "the stop words are here", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("field", "the stop words are here", TextField.TYPE_STORED));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     writer.close();
@@ -258,12 +258,12 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
     
     Document doc = new Document();
-    doc.add(newField("source", "marketing info", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("source", "marketing info", TextField.TYPE_STORED));
     writer.addDocument(doc);
     
     doc = new Document();
-    doc.add(newField("contents", "foobar", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("source", "marketing info", Field.Store.YES, Field.Index.ANALYZED)); 
+    doc.add(newField("contents", "foobar", TextField.TYPE_STORED));
+    doc.add(newField("source", "marketing info", TextField.TYPE_STORED)); 
     writer.addDocument(doc);
     
     IndexReader reader = writer.getReader();
@@ -294,15 +294,15 @@
     writer = new RandomIndexWriter(random, directory, 
         newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE));
     doc = new Document();
-    doc.add(newField("contents", "map entry woo", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("contents", "map entry woo", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("contents", "woo map entry", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("contents", "woo map entry", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     doc = new Document();
-    doc.add(newField("contents", "map foobarword entry woo", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("contents", "map foobarword entry woo", TextField.TYPE_STORED));
     writer.addDocument(doc);
 
     reader = writer.getReader();
@@ -345,15 +345,15 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
 
     Document doc = new Document();
-    doc.add(newField("field", "foo firstname lastname foo", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("field", "foo firstname lastname foo", TextField.TYPE_STORED));
     writer.addDocument(doc);
     
     Document doc2 = new Document();
-    doc2.add(newField("field", "foo firstname zzz lastname foo", Field.Store.YES, Field.Index.ANALYZED));
+    doc2.add(newField("field", "foo firstname zzz lastname foo", TextField.TYPE_STORED));
     writer.addDocument(doc2);
     
     Document doc3 = new Document();
-    doc3.add(newField("field", "foo firstname zzz yyy lastname foo", Field.Store.YES, Field.Index.ANALYZED));
+    doc3.add(newField("field", "foo firstname zzz yyy lastname foo", TextField.TYPE_STORED));
     writer.addDocument(doc3);
     
     IndexReader reader = writer.getReader();
@@ -608,7 +608,7 @@
     RandomIndexWriter w  = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer).setMergePolicy(newLogMergePolicy()));
     List<List<String>> docs = new ArrayList<List<String>>();
     Document d = new Document();
-    Field f = newField("f", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field f = newField("f", "", TextField.TYPE_UNSTORED);
     d.add(f);
 
     Random r = random;
Index: lucene/src/test/org/apache/lucene/search/TestPositionIncrement.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPositionIncrement.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPositionIncrement.java	(working copy)
@@ -30,7 +30,7 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.DocsAndPositionsEnum;
 import org.apache.lucene.index.IndexReader;
@@ -88,7 +88,7 @@
     Directory store = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, store, analyzer);
     Document d = new Document();
-    d.add(newField("field", "bogus", Field.Store.YES, Field.Index.ANALYZED));
+    d.add(newField("field", "bogus", TextField.TYPE_STORED));
     writer.addDocument(d);
     IndexReader reader = writer.getReader();
     writer.close();
@@ -206,7 +206,7 @@
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, new MockPayloadAnalyzer());
     Document doc = new Document();
-    doc.add(new Field("content", new StringReader(
+    doc.add(new TextField("content", new StringReader(
         "a a b c d e a f g h i j a b k k")));
     writer.addDocument(doc);
 
Index: lucene/src/test/org/apache/lucene/search/TestTermRangeQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestTermRangeQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestTermRangeQuery.java	(working copy)
@@ -27,6 +27,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.Terms;
@@ -265,8 +267,8 @@
   private void insertDoc(IndexWriter writer, String content) throws IOException {
     Document doc = new Document();
 
-    doc.add(newField("id", "id" + docCount, Field.Store.YES, Field.Index.NOT_ANALYZED));
-    doc.add(newField("content", content, Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("id", "id" + docCount, StringField.TYPE_STORED));
+    doc.add(newField("content", content, TextField.TYPE_UNSTORED));
 
     writer.addDocument(doc);
     docCount++;
Index: lucene/src/test/org/apache/lucene/search/TestSearchWithThreads.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSearchWithThreads.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSearchWithThreads.java	(working copy)
@@ -22,6 +22,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -44,7 +45,7 @@
     // TODO: replace w/ the @nightly test data; make this
     // into an optional @nightly stress test
     final Document doc = new Document();
-    final Field body = newField("body", "", Field.Index.ANALYZED);
+    final Field body = newField("body", "", TextField.TYPE_UNSTORED);
     doc.add(body);
     final StringBuilder sb = new StringBuilder();
     for(int docCount=0;docCount<NUM_DOCS;docCount++) {
Index: lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSloppyPhraseQuery.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -137,8 +139,9 @@
 
   private static Document makeDocument(String docText) {
     Document doc = new Document();
-    Field f = new Field("f", docText, Field.Store.NO, Field.Index.ANALYZED);
-    f.setOmitNorms(true);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    Field f = new Field("f", customType, docText);
     doc.add(f);
     return doc;
   }
Index: lucene/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestBooleanMinShouldMatch.java	(working copy)
@@ -20,6 +20,9 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -54,12 +57,17 @@
         index = newDirectory();
         RandomIndexWriter w = new RandomIndexWriter(random, index);
 
+        FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+        customType.setStored(true);
+        FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+        customType2.setStored(true);
+        
         for (int i = 0; i < data.length; i++) {
             Document doc = new Document();
-            doc.add(newField("id", String.valueOf(i), Field.Store.YES, Field.Index.NOT_ANALYZED));//Field.Keyword("id",String.valueOf(i)));
-            doc.add(newField("all", "all", Field.Store.YES, Field.Index.NOT_ANALYZED));//Field.Keyword("all","all"));
+            doc.add(newField("id", String.valueOf(i), customType));//Field.Keyword("id",String.valueOf(i)));
+            doc.add(newField("all", "all", customType));//Field.Keyword("all","all"));
             if (null != data[i]) {
-                doc.add(newField("data", data[i], Field.Store.YES, Field.Index.ANALYZED));//Field.Text("data",data[i]));
+                doc.add(newField("data", data[i], customType2));//Field.Text("data",data[i]));
             }
             w.addDocument(doc);
         }
Index: lucene/src/test/org/apache/lucene/search/TestBooleanOr.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestBooleanOr.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestBooleanOr.java	(working copy)
@@ -21,6 +21,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -138,16 +140,16 @@
 
     //
     Document d = new Document();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     d.add(newField(
         FIELD_T,
         "Optimize not deleting all files",
-        Field.Store.YES,
-        Field.Index.ANALYZED));
+        customType));
     d.add(newField(
         FIELD_C,
         "Deleted When I run an optimize in our production environment.",
-        Field.Store.YES,
-        Field.Index.ANALYZED));
+        customType));
 
     //
     writer.addDocument(d);
Index: lucene/src/test/org/apache/lucene/search/cache/TestEntryCreators.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/cache/TestEntryCreators.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/cache/TestEntryCreators.java	(working copy)
@@ -24,7 +24,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.FieldCache.*;
@@ -91,8 +92,9 @@
       for( NumberTypeTester tester : typeTests ) {
         if (random.nextInt(20) != 17 && i > 1) {
           tester.values[i] = 10 + random.nextInt( 20 ); // get some field overlap
-          doc.add(newField(tester.field, String.valueOf(tester.values[i]), 
-              Field.Store.NO, Field.Index.NOT_ANALYZED ));
+          FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+          customType.setTokenized(false);
+          doc.add(newField(tester.field, String.valueOf(tester.values[i]), customType));
         }
       }
       writer.addDocument(doc);
Index: lucene/src/test/org/apache/lucene/search/TestDateSort.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestDateSort.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestDateSort.java	(working copy)
@@ -26,6 +26,8 @@
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.Query;
@@ -107,13 +109,12 @@
     Document document = new Document();
 
     // Add the text field.
-    Field textField = newField(TEXT_FIELD, text, Field.Store.YES, Field.Index.ANALYZED);
+    Field textField = newField(TEXT_FIELD, text, TextField.TYPE_STORED);
     document.add(textField);
 
     // Add the date/time field.
     String dateTimeString = DateTools.timeToString(time, DateTools.Resolution.SECOND);
-    Field dateTimeField = newField(DATE_TIME_FIELD, dateTimeString, Field.Store.YES,
-        Field.Index.NOT_ANALYZED);
+    Field dateTimeField = newField(DATE_TIME_FIELD, dateTimeString, StringField.TYPE_STORED);
     document.add(dateTimeField);
 
     return document;
Index: lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java	(working copy)
@@ -20,7 +20,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -64,16 +66,14 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, 
             new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)).setMergePolicy(newLogMergePolicy()));
 
+    FieldType customType = new FieldType(TextField.TYPE_STORED);
+    customType.setTokenized(false);
     for (int i = 0; i < data.length; i++) {
       Document doc = new Document();
-      doc.add(newField("id", String.valueOf(i), Field.Store.YES,
-          Field.Index.NOT_ANALYZED));// Field.Keyword("id",String.valueOf(i)));
-      doc
-          .add(newField("all", "all", Field.Store.YES,
-              Field.Index.NOT_ANALYZED));// Field.Keyword("all","all"));
+      doc.add(newField("id", String.valueOf(i), customType));// Field.Keyword("id",String.valueOf(i)));
+      doc.add(newField("all", "all", customType));// Field.Keyword("all","all"));
       if (null != data[i]) {
-        doc.add(newField("data", data[i], Field.Store.YES,
-            Field.Index.ANALYZED));// Field.Text("data",data[i]));
+        doc.add(newField("data", data[i], TextField.TYPE_STORED));// Field.Text("data",data[i]));
       }
       writer.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/search/TestWildcardRandom.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestWildcardRandom.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestWildcardRandom.java	(working copy)
@@ -25,6 +25,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -51,7 +52,7 @@
         .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)));
     
     Document doc = new Document();
-    Field field = newField("field", "", Field.Store.NO, Field.Index.ANALYZED_NO_NORMS);
+    Field field = newField("field", "", StringField.TYPE_UNSTORED);
     doc.add(field);
     
     NumberFormat df = new DecimalFormat("000", new DecimalFormatSymbols(Locale.ENGLISH));
Index: lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/payloads/TestPayloadNearQuery.java	(working copy)
@@ -24,7 +24,8 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Payload;
@@ -112,9 +113,11 @@
     //writer.infoStream = System.out;
     for (int i = 0; i < 1000; i++) {
       Document doc = new Document();
-      doc.add(newField("field", English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      doc.add(newField("field", English.intToEnglish(i), customType));
       String txt = English.intToEnglish(i) +' '+English.intToEnglish(i+1);
-      doc.add(newField("field2",  txt, Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField("field2",  txt, customType));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/payloads/TestPayloadTermQuery.java	(working copy)
@@ -48,6 +48,8 @@
 import org.apache.lucene.document.Field;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 
 import java.io.Reader;
 import java.io.IOException;
@@ -117,13 +119,15 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer())
                                                      .setSimilarityProvider(similarityProvider).setMergePolicy(newLogMergePolicy()));
     //writer.infoStream = System.out;
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < 1000; i++) {
       Document doc = new Document();
-      Field noPayloadField = newField(PayloadHelper.NO_PAYLOAD_FIELD, English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED);
+      Field noPayloadField = newField(PayloadHelper.NO_PAYLOAD_FIELD, English.intToEnglish(i), customType);
       //noPayloadField.setBoost(0);
       doc.add(noPayloadField);
-      doc.add(newField("field", English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(newField("multiField", English.intToEnglish(i) + "  " + English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField("field", English.intToEnglish(i), customType));
+      doc.add(newField("multiField", English.intToEnglish(i) + "  " + English.intToEnglish(i), customType));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/payloads/PayloadHelper.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.English;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.index.IndexReader;
@@ -122,9 +123,9 @@
     // writer.infoStream = System.out;
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(new Field(FIELD, English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(new Field(MULTI_FIELD, English.intToEnglish(i) + "  " + English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(new Field(NO_PAYLOAD_FIELD, English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(new Field(FIELD, TextField.TYPE_STORED, English.intToEnglish(i)));
+      doc.add(new Field(MULTI_FIELD, TextField.TYPE_STORED, English.intToEnglish(i) + "  " + English.intToEnglish(i)));
+      doc.add(new Field(NO_PAYLOAD_FIELD, TextField.TYPE_STORED, English.intToEnglish(i)));
       writer.addDocument(doc);
     }
     reader = IndexReader.open(writer, true);
Index: lucene/src/test/org/apache/lucene/search/TestMultiTermQueryRewrites.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestMultiTermQueryRewrites.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestMultiTermQueryRewrites.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiReader;
@@ -53,7 +54,7 @@
 
     for (int i = 0; i < 10; i++) {
       Document doc = new Document();
-      doc.add(newField("data", Integer.toString(i), Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("data", Integer.toString(i), StringField.TYPE_UNSTORED));
       writer.addDocument(doc);
       ((i % 2 == 0) ? swriter1 : swriter2).addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/search/TestBooleanScorer.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestBooleanScorer.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestBooleanScorer.java	(working copy)
@@ -22,6 +22,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -40,9 +42,11 @@
     String[] values = new String[] { "1", "2", "3", "4" };
 
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < values.length; i++) {
       Document doc = new Document();
-      doc.add(newField(FIELD, values[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
+      doc.add(newField(FIELD, values[i], customType));
       writer.addDocument(doc);
     }
     IndexReader ir = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestDocIdSet.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestDocIdSet.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestDocIdSet.java	(working copy)
@@ -25,8 +25,8 @@
 import junit.framework.Assert;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -103,7 +103,7 @@
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, dir);
     Document doc = new Document();
-    doc.add(newField("c", "val", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField("c", "val", StringField.TYPE_UNSTORED));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     writer.close();
Index: lucene/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader.ReaderContext;
@@ -57,7 +57,7 @@
     RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     for (int i = 0; i < docFields.length; i++) {
       Document doc = new Document();
-      doc.add(newField(FIELD, docFields[i], Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField(FIELD, docFields[i], TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/spans/TestSpanFirstQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestSpanFirstQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestSpanFirstQuery.java	(working copy)
@@ -21,7 +21,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -41,10 +41,10 @@
     
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, analyzer);
     Document doc = new Document();
-    doc.add(newField("field", "the quick brown fox", Field.Index.ANALYZED));
+    doc.add(newField("field", "the quick brown fox", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     Document doc2 = new Document();
-    doc2.add(newField("field", "quick brown fox", Field.Index.ANALYZED));
+    doc2.add(newField("field", "quick brown fox", TextField.TYPE_UNSTORED));
     writer.addDocument(doc2);
     
     IndexReader reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/spans/TestBasics.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestBasics.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestBasics.java	(working copy)
@@ -32,7 +32,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Payload;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -120,7 +121,9 @@
     //writer.infoStream = System.out;
     for (int i = 0; i < 2000; i++) {
       Document doc = new Document();
-      doc.add(newField("field", English.intToEnglish(i), Field.Store.YES, Field.Index.ANALYZED));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      doc.add(newField("field", English.intToEnglish(i), customType));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/spans/TestSpans.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestSpans.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestSpans.java	(working copy)
@@ -38,7 +38,9 @@
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.ReaderUtil;
 
@@ -56,9 +58,11 @@
     super.setUp();
     directory = newDirectory();
     RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < docFields.length; i++) {
       Document doc = new Document();
-      doc.add(newField(field, docFields[i], Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField(field, docFields[i], customType));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
@@ -452,8 +456,12 @@
   // LUCENE-1404
   private void addDoc(IndexWriter writer, String id, String text) throws IOException {
     final Document doc = new Document();
-    doc.add( newField("id", id, Field.Store.YES, Field.Index.NOT_ANALYZED) );
-    doc.add( newField("text", text, Field.Store.YES, Field.Index.ANALYZED) );
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    doc.add( newField("id", id, customType2) );
+    doc.add( newField("text", text, customType) );
     writer.addDocument(doc);
   }
 
Index: lucene/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java	(working copy)
@@ -23,6 +23,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -46,7 +47,7 @@
   }
   
   protected static Field field(String name, String value) {
-    return newField(name, value, Field.Store.NO, Field.Index.ANALYZED);
+    return newField(name, value, TextField.TYPE_UNSTORED);
   }
 
   protected static IndexSearcher searcher;
Index: lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestSpansAdvanced.java	(working copy)
@@ -25,7 +25,9 @@
 import org.apache.lucene.analysis.MockTokenFilter;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -90,10 +92,12 @@
       final String text) throws IOException {
     
     final Document document = new Document();
-    document.add(newField(FIELD_ID, id, Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
-    document.add(newField(FIELD_TEXT, text, Field.Store.YES,
-        Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    document.add(newField(FIELD_ID, id, customType2));
+    document.add(newField(FIELD_TEXT, text, customType));
     writer.addDocument(document);
   }
   
Index: lucene/src/test/org/apache/lucene/search/spans/TestSpanMultiTermQueryWrapper.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestSpanMultiTermQueryWrapper.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestSpanMultiTermQueryWrapper.java	(working copy)
@@ -19,6 +19,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -42,7 +43,7 @@
     directory = newDirectory();
     RandomIndexWriter iw = new RandomIndexWriter(random, directory);
     Document doc = new Document();
-    Field field = newField("field", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field field = newField("field", "", TextField.TYPE_UNSTORED);
     doc.add(field);
     
     field.setValue("quick brown fox");
Index: lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java	(working copy)
@@ -31,7 +31,8 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.IndexReader;
@@ -113,8 +114,9 @@
                                                      newIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer()).setSimilarityProvider(similarity));
 
     Document doc = new Document();
-    doc.add(newField(PayloadHelper.FIELD, "one two three one four three",
-        Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField(PayloadHelper.FIELD, "one two three one four three", customType));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     writer.close();
@@ -261,7 +263,7 @@
                                                      newIndexWriterConfig(TEST_VERSION_CURRENT, new TestPayloadAnalyzer()));
 
     Document doc = new Document();
-    doc.add(new Field("content", new StringReader("a b c d e f g h i j a k")));
+    doc.add(new TextField("content", new StringReader("a b c d e f g h i j a k")));
     writer.addDocument(doc);
 
     IndexReader reader = writer.getReader();
@@ -300,7 +302,7 @@
                                                      newIndexWriterConfig(TEST_VERSION_CURRENT, new TestPayloadAnalyzer()));
 
     Document doc = new Document();
-    doc.add(new Field("content", new StringReader("a b a d k f a h i k a k")));
+    doc.add(new TextField("content", new StringReader("a b a d k f a h i k a k")));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     IndexSearcher is = newSearcher(reader);
@@ -337,7 +339,7 @@
                                                      newIndexWriterConfig(TEST_VERSION_CURRENT, new TestPayloadAnalyzer()));
 
     Document doc = new Document();
-    doc.add(new Field("content", new StringReader("j k a l f k k p a t a k l k t a")));
+    doc.add(new TextField("content", new StringReader("j k a l f k k p a t a k l k t a")));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     IndexSearcher is = newSearcher(reader);
@@ -379,7 +381,9 @@
                                                      newIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer()).setSimilarityProvider(similarity));
 
     Document doc = new Document();
-    doc.add(newField(PayloadHelper.FIELD,"xx rr yy mm  pp", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField(PayloadHelper.FIELD,"xx rr yy mm  pp", customType));
     writer.addDocument(doc);
   
     IndexReader reader = writer.getReader();
@@ -440,10 +444,12 @@
                                                      newIndexWriterConfig(TEST_VERSION_CURRENT, new PayloadAnalyzer()).setSimilarityProvider(similarity));
 
     Document doc = null;
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for(int i = 0; i < docs.length; i++) {
       doc = new Document();
       String docText = docs[i];
-      doc.add(newField(PayloadHelper.FIELD,docText, Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField(PayloadHelper.FIELD,docText, customType));
       writer.addDocument(doc);
     }
 
Index: lucene/src/test/org/apache/lucene/search/TestSubScorerFreqs.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSubScorerFreqs.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSubScorerFreqs.java	(working copy)
@@ -46,12 +46,11 @@
     int num = atLeast(31);
     for (int i = 0; i < num; i++) {
       Document doc = new Document();
-      doc.add(newField("f", "a b c d b c d c d d", Field.Store.NO,
-          Field.Index.ANALYZED));
+      doc.add(newField("f", "a b c d b c d c d d", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
 
       doc = new Document();
-      doc.add(newField("f", "a b c d", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("f", "a b c d", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
 
Index: lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestDocValuesScoring.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.IndexDocValuesField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -50,11 +51,11 @@
     Directory dir = newDirectory();
     RandomIndexWriter iw = new RandomIndexWriter(random, dir);
     Document doc = new Document();
-    Field field = newField("foo", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field field = newField("foo", "", TextField.TYPE_UNSTORED);
     doc.add(field);
     IndexDocValuesField dvField = new IndexDocValuesField("foo_boost");
     doc.add(dvField);
-    Field field2 = newField("bar", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field field2 = newField("bar", "", TextField.TYPE_UNSTORED);
     doc.add(field2);
     
     field.setValue("quick brown fox");
Index: lucene/src/test/org/apache/lucene/search/TestQueryWrapperFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestQueryWrapperFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestQueryWrapperFilter.java	(working copy)
@@ -18,8 +18,7 @@
  */
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -33,7 +32,7 @@
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, dir);
     Document doc = new Document();
-    doc.add(newField("field", "value", Store.NO, Index.ANALYZED));
+    doc.add(newField("field", "value", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     writer.close();
Index: lucene/src/test/org/apache/lucene/search/TestTermVectors.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestTermVectors.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestTermVectors.java	(working copy)
@@ -23,6 +23,8 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
@@ -47,26 +49,25 @@
     //writer.infoStream = System.out;
     for (int i = 0; i < 1000; i++) {
       Document doc = new Document();
-      Field.TermVector termVector;
+      FieldType ft = new FieldType(TextField.TYPE_STORED);
       int mod3 = i % 3;
       int mod2 = i % 2;
-      if (mod2 == 0 && mod3 == 0){
-        termVector = Field.TermVector.WITH_POSITIONS_OFFSETS;
+      if (mod2 == 0 && mod3 == 0) {
+        ft.setStoreTermVectors(true);
+        ft.setStoreTermVectorOffsets(true);
+        ft.setStoreTermVectorPositions(true);
+      } else if (mod2 == 0) {
+        ft.setStoreTermVectors(true);
+        ft.setStoreTermVectorPositions(true);
+      } else if (mod3 == 0) {
+        ft.setStoreTermVectors(true);
+        ft.setStoreTermVectorOffsets(true);
+      } else {
+        ft.setStoreTermVectors(true);
       }
-      else if (mod2 == 0){
-        termVector = Field.TermVector.WITH_POSITIONS;
-      }
-      else if (mod3 == 0){
-        termVector = Field.TermVector.WITH_OFFSETS;
-      }
-      else {
-        termVector = Field.TermVector.YES;
-      }
-      doc.add(new Field("field", English.intToEnglish(i),
-          Field.Store.YES, Field.Index.ANALYZED, termVector));
+      doc.add(new Field("field", ft, English.intToEnglish(i)));
       //test no term vectors too
-      doc.add(new Field("noTV", English.intToEnglish(i),
-          Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(new Field("noTV", TextField.TYPE_STORED, English.intToEnglish(i)));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
@@ -91,11 +92,10 @@
     ScoreDoc[] hits = searcher.search(query, null, 1000).scoreDocs;
     assertEquals(100, hits.length);
       
-    for (int i = 0; i < hits.length; i++)
-    {
+    for (int i = 0; i < hits.length; i++) {
       TermFreqVector [] vector = searcher.reader.getTermFreqVectors(hits[i].doc);
       assertTrue(vector != null);
-      assertTrue(vector.length == 1);
+      assertEquals("doc=" + hits[i].doc + " tv=" + vector, 1, vector.length);
     }
     TermFreqVector vector;
     vector = searcher.reader.getTermFreqVector(hits[0].doc, "noTV");
@@ -109,11 +109,15 @@
   public void testTermVectorsFieldOrder() throws IOException {
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, new MockAnalyzer(random, MockTokenizer.SIMPLE, true));
-    Document doc = new Document();
-    doc.add(new Field("c", "some content here", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("a", "some content here", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("b", "some content here", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("x", "some content here", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    Document doc = new Document();;
+    FieldType ft = new FieldType(TextField.TYPE_STORED);
+    ft.setStoreTermVectors(true);
+    ft.setStoreTermVectorOffsets(true);
+    ft.setStoreTermVectorPositions(true);
+    doc.add(newField("c", "some content here", ft));
+    doc.add(newField("a", "some content here", ft));
+    doc.add(newField("b", "some content here", ft));
+    doc.add(newField("x", "some content here", ft));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     writer.close();
@@ -341,10 +345,14 @@
   
   private void setupDoc(Document doc, String text)
   {
-    doc.add(new Field("field2", text, Field.Store.YES,
-        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("field", text, Field.Store.YES,
-        Field.Index.ANALYZED, Field.TermVector.YES));
+    FieldType ft = new FieldType(TextField.TYPE_STORED);
+    ft.setStoreTermVectors(true);
+    ft.setStoreTermVectorOffsets(true);
+    ft.setStoreTermVectorPositions(true);
+    FieldType ft2 = new FieldType(TextField.TYPE_STORED);
+    ft2.setStoreTermVectors(true);
+    doc.add(newField("field2", text, ft));
+    doc.add(newField("field", text, ft2));
     //System.out.println("Document: " + doc);
   }
 
@@ -359,17 +367,19 @@
     }
     for (int i = 0; i < 100; i++) {
       Document doc = new Document();
-      doc.add(new Field("field", English.intToEnglish(i),
-                        Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
+      doc.add(newField("field", English.intToEnglish(i), TextField.TYPE_STORED));
       writer.addDocument(doc);
     }
     if (VERBOSE) {
       System.out.println("TEST: now add vectors");
     }
+    FieldType ft = new FieldType(TextField.TYPE_STORED);
+    ft.setStoreTermVectors(true);
+    ft.setStoreTermVectorOffsets(true);
+    ft.setStoreTermVectorPositions(true);
     for(int i=0;i<10;i++) {
       Document doc = new Document();
-      doc.add(new Field("field", English.intToEnglish(100+i),
-                        Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(newField("field", English.intToEnglish(100+i), ft));
       writer.addDocument(doc);
     }
 
@@ -400,16 +410,28 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, 
         new MockAnalyzer(random, MockTokenizer.SIMPLE, true)).setOpenMode(OpenMode.CREATE));
     Document doc = new Document();
-    doc.add(new Field("field", "one",
-                      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
-    doc.add(new Field("field", "one",
-                      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
-    doc.add(new Field("field", "one",
-                      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
-    doc.add(new Field("field", "one",
-                      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_OFFSETS));
-    doc.add(new Field("field", "one",
-                      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    
+    FieldType ft2 = new FieldType(TextField.TYPE_STORED);
+    ft2.setStoreTermVectors(true);
+    
+    FieldType ft3 = new FieldType(TextField.TYPE_STORED);
+    ft3.setStoreTermVectors(true);
+    ft3.setStoreTermVectorPositions(true);
+    
+    FieldType ft4 = new FieldType(TextField.TYPE_STORED);
+    ft4.setStoreTermVectors(true);
+    ft4.setStoreTermVectorOffsets(true);
+    
+    FieldType ft5 = new FieldType(TextField.TYPE_STORED);
+    ft5.setStoreTermVectors(true);
+    ft5.setStoreTermVectorOffsets(true);
+    ft5.setStoreTermVectorPositions(true);
+    
+    doc.add(newField("field", "one", TextField.TYPE_STORED));
+    doc.add(newField("field", "one", ft2));
+    doc.add(newField("field", "one", ft3));
+    doc.add(newField("field", "one", ft4));
+    doc.add(newField("field", "one", ft5));
     writer.addDocument(doc);
     IndexReader reader = writer.getReader();
     writer.close();
Index: lucene/src/test/org/apache/lucene/search/TestMultiValuedNumericRangeQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestMultiValuedNumericRangeQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestMultiValuedNumericRangeQuery.java	(working copy)
@@ -23,8 +23,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.store.Directory;
@@ -51,8 +51,8 @@
       Document doc = new Document();
       for (int m=0, c=random.nextInt(10); m<=c; m++) {
         int value = random.nextInt(Integer.MAX_VALUE);
-        doc.add(newField("asc", format.format(value), Field.Store.NO, Field.Index.NOT_ANALYZED));
-        doc.add(new NumericField("trie", Field.Store.NO, true).setIntValue(value));
+        doc.add(newField("asc", format.format(value), StringField.TYPE_UNSTORED));
+        doc.add(new NumericField("trie").setIntValue(value));
       }
       writer.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/search/TestTermScorer.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestTermScorer.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestTermScorer.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -51,8 +52,7 @@
     for (int i = 0; i < values.length; i++) {
       Document doc = new Document();
       doc
-          .add(newField(FIELD, values[i], Field.Store.YES,
-              Field.Index.ANALYZED));
+          .add(newField(FIELD, values[i], TextField.TYPE_STORED));
       writer.addDocument(doc);
     }
     indexReader = new SlowMultiReaderWrapper(writer.getReader());
Index: lucene/src/test/org/apache/lucene/search/TestPhrasePrefixQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPhrasePrefixQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPhrasePrefixQuery.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.TermsEnum;
 import org.apache.lucene.index.IndexReader;
@@ -47,16 +47,11 @@
     Document doc3 = new Document();
     Document doc4 = new Document();
     Document doc5 = new Document();
-    doc1.add(newField("body", "blueberry pie", Field.Store.YES,
-        Field.Index.ANALYZED));
-    doc2.add(newField("body", "blueberry strudel", Field.Store.YES,
-        Field.Index.ANALYZED));
-    doc3.add(newField("body", "blueberry pizza", Field.Store.YES,
-        Field.Index.ANALYZED));
-    doc4.add(newField("body", "blueberry chewing gum", Field.Store.YES,
-        Field.Index.ANALYZED));
-    doc5.add(newField("body", "piccadilly circus", Field.Store.YES,
-        Field.Index.ANALYZED));
+    doc1.add(newField("body", "blueberry pie", TextField.TYPE_STORED));
+    doc2.add(newField("body", "blueberry strudel", TextField.TYPE_STORED));
+    doc3.add(newField("body", "blueberry pizza", TextField.TYPE_STORED));
+    doc4.add(newField("body", "blueberry chewing gum", TextField.TYPE_STORED));
+    doc5.add(newField("body", "piccadilly circus", TextField.TYPE_STORED));
     writer.addDocument(doc1);
     writer.addDocument(doc2);
     writer.addDocument(doc3);
Index: lucene/src/test/org/apache/lucene/search/TestSetNorm.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSetNorm.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSetNorm.java	(working copy)
@@ -39,7 +39,7 @@
     IndexWriter writer = new IndexWriter(store, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
 
     // add the same document four times
-    Fieldable f1 = newField("field", "word", Field.Store.YES, Field.Index.ANALYZED);
+    Field f1 = newField("field", "word", TextField.TYPE_STORED);
     Document d1 = new Document();
     d1.add(f1);
     writer.addDocument(d1);
Index: lucene/src/test/org/apache/lucene/search/TestWildcard.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestWildcard.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestWildcard.java	(working copy)
@@ -21,9 +21,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.Index;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -244,7 +242,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, indexStore);
     for (int i = 0; i < contents.length; ++i) {
       Document doc = new Document();
-      doc.add(newField(field, contents[i], Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField(field, contents[i], TextField.TYPE_STORED));
       writer.addDocument(doc);
     }
     writer.close();
@@ -344,7 +342,7 @@
         .setMergePolicy(newLogMergePolicy()));
     for (int i = 0; i < docs.length; i++) {
       Document doc = new Document();
-      doc.add(newField(field,docs[i],Store.NO,Index.ANALYZED));
+      doc.add(newField(field,docs[i],TextField.TYPE_UNSTORED));
       iw.addDocument(doc);
     }
     iw.close();
Index: lucene/src/test/org/apache/lucene/search/TestTopDocsMerge.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestTopDocsMerge.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestTopDocsMerge.java	(working copy)
@@ -24,6 +24,8 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -90,8 +92,8 @@
 
       for(int docIDX=0;docIDX<numDocs;docIDX++) {
         final Document doc = new Document();
-        doc.add(newField("string", _TestUtil.randomRealisticUnicodeString(random), Field.Index.NOT_ANALYZED));
-        doc.add(newField("text", content[random.nextInt(content.length)], Field.Index.ANALYZED));
+        doc.add(newField("string", _TestUtil.randomRealisticUnicodeString(random), StringField.TYPE_STORED));
+        doc.add(newField("text", content[random.nextInt(content.length)], TextField.TYPE_UNSTORED));
         doc.add(new NumericField("float").setFloatValue(random.nextFloat()));
         final int intValue;
         if (random.nextInt(100) == 17) {
Index: lucene/src/test/org/apache/lucene/search/BaseTestRangeFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/BaseTestRangeFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/BaseTestRangeFilter.java	(working copy)
@@ -23,6 +23,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -116,9 +118,11 @@
     /* build an index */
     
     Document doc = new Document();
-    Field idField = newField(random, "id", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
-    Field randField = newField(random, "rand", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
-    Field bodyField = newField(random, "body", "", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS);
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStored(true);
+    Field idField = newField(random, "id", "", customType);
+    Field randField = newField(random, "rand", "", customType);
+    Field bodyField = newField(random, "body", "", StringField.TYPE_UNSTORED);
     doc.add(idField);
     doc.add(randField);
     doc.add(bodyField);
Index: lucene/src/test/org/apache/lucene/search/TestAutomatonQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestAutomatonQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestAutomatonQuery.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -46,12 +47,9 @@
     directory = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
     Document doc = new Document();
-    Field titleField = newField("title", "some title", Field.Store.NO,
-        Field.Index.ANALYZED);
-    Field field = newField(FN, "this is document one 2345", Field.Store.NO,
-        Field.Index.ANALYZED);
-    Field footerField = newField("footer", "a footer", Field.Store.NO,
-        Field.Index.ANALYZED);
+    Field titleField = newField("title", "some title", TextField.TYPE_UNSTORED);
+    Field field = newField(FN, "this is document one 2345", TextField.TYPE_UNSTORED);
+    Field footerField = newField("footer", "a footer", TextField.TYPE_UNSTORED);
     doc.add(titleField);
     doc.add(field);
     doc.add(footerField);
Index: lucene/src/test/org/apache/lucene/search/TestBoolean2.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestBoolean2.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestBoolean2.java	(working copy)
@@ -23,6 +23,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
@@ -56,7 +57,7 @@
     RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     for (int i = 0; i < docFields.length; i++) {
       Document doc = new Document();
-      doc.add(newField(field, docFields[i], Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField(field, docFields[i], TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
     writer.close();
@@ -81,12 +82,12 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random))
         .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)));
     Document doc = new Document();
-    doc.add(newField("field2", "xxx", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field2", "xxx", TextField.TYPE_UNSTORED));
     for(int i=0;i<NUM_EXTRA_DOCS/2;i++) {
       w.addDocument(doc);
     }
     doc = new Document();
-    doc.add(newField("field2", "big bad bug", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field2", "big bad bug", TextField.TYPE_UNSTORED));
     for(int i=0;i<NUM_EXTRA_DOCS/2;i++) {
       w.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/search/TestExplanations.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestExplanations.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestExplanations.java	(working copy)
@@ -20,6 +20,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -73,11 +75,11 @@
     RandomIndexWriter writer= new RandomIndexWriter(random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     for (int i = 0; i < docFields.length; i++) {
       Document doc = new Document();
-      doc.add(newField(KEY, ""+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
-      Field f = newField(FIELD, docFields[i], Field.Store.NO, Field.Index.ANALYZED);
+      doc.add(newField(KEY, ""+i, StringField.TYPE_UNSTORED));
+      Field f = newField(FIELD, docFields[i], TextField.TYPE_UNSTORED);
       f.setBoost(i);
       doc.add(f);
-      doc.add(newField(ALTFIELD, docFields[i], Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField(ALTFIELD, docFields[i], TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestThreadSafe.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestThreadSafe.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestThreadSafe.java	(working copy)
@@ -1,154 +0,0 @@
-package org.apache.lucene.search;
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.index.IndexWriterConfig;
-import org.apache.lucene.index.IndexWriterConfig.OpenMode;
-import org.apache.lucene.analysis.MockAnalyzer;
-import org.apache.lucene.document.*;
-
-import java.util.Random;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.io.IOException;
-
-public class TestThreadSafe extends LuceneTestCase {
-  Directory dir1;
-
-  IndexReader ir1;
-
-  class Thr extends Thread {
-    final int iter;
-    final Random rand;
-    final AtomicBoolean failed;
-
-    // pass in random in case we want to make things reproducable
-    public Thr(int iter, Random rand, AtomicBoolean failed) {
-      this.iter = iter;
-      this.rand = rand;
-      this.failed = failed;
-    }
-
-    @Override
-    public void run() {
-      try {
-        for (int i=0; i<iter; i++) {
-          /*** future
-           // pick a random index reader... a shared one, or create your own
-           IndexReader ir;
-           ***/
-
-          switch(rand.nextInt(1)) {
-            case 0: loadDoc(ir1); break;
-          }
-
-        }
-      } catch (Throwable th) {
-        failed.set(true);
-        throw new RuntimeException(th);
-      }
-    }
-
-
-    void loadDoc(IndexReader ir) throws IOException {
-      // beware of deleted docs in the future
-      Document doc = ir.document(rand.nextInt(ir.maxDoc()),
-                new FieldSelector() {
-                  public FieldSelectorResult accept(String fieldName) {
-                    switch(rand.nextInt(2)) {
-                      case 0: return FieldSelectorResult.LAZY_LOAD;
-                      case 1: return FieldSelectorResult.LOAD;
-                      // TODO: add other options
-                      default: return FieldSelectorResult.LOAD;
-                    }
-                  }
-                }
-              );
-
-      List<Fieldable> fields = doc.getFields();
-      for (final Fieldable f : fields ) {
-        validateField(f);
-      }
-
-    }
-
-  }
-
-
-  void validateField(Fieldable f) {
-    String val = f.stringValue();
-    if (!val.startsWith("^") || !val.endsWith("$")) {
-      throw new RuntimeException("Invalid field:" + f.toString() + " val=" +val);
-    }
-  }
-
-  String[] words = "now is the time for all good men to come to the aid of their country".split(" ");
-
-  void buildDir(Directory dir, int nDocs, int maxFields, int maxFieldLen) throws IOException {
-    IndexWriter iw = new IndexWriter(dir, new IndexWriterConfig(
-        TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(10));
-    for (int j=0; j<nDocs; j++) {
-      Document d = new Document();
-      int nFields = random.nextInt(maxFields);
-      for (int i=0; i<nFields; i++) {
-        int flen = random.nextInt(maxFieldLen);
-        StringBuilder sb = new StringBuilder("^ ");
-        while (sb.length() < flen) sb.append(' ').append(words[random.nextInt(words.length)]);
-        sb.append(" $");
-        Field.Store store = Field.Store.YES;  // make random later
-        Field.Index index = Field.Index.ANALYZED;  // make random later
-        d.add(newField("f"+i, sb.toString(), store, index));
-      }
-      iw.addDocument(d);
-    }
-    iw.close();
-  }
-
-
-  void doTest(int iter, int nThreads) throws Exception {
-    Thr[] tarr = new Thr[nThreads];
-    AtomicBoolean failed = new AtomicBoolean();
-    for (int i=0; i<nThreads; i++) {
-      tarr[i] = new Thr(iter, new Random(random.nextLong()), failed);
-      tarr[i].start();
-    }
-    for (int i=0; i<nThreads; i++) {
-      tarr[i].join();
-    }
-    assertFalse(failed.get());
-  }
-
-  public void testLazyLoadThreadSafety() throws Exception{
-    dir1 = newDirectory();
-    // test w/ field sizes bigger than the buffer of an index input
-    buildDir(dir1, 15, 5, 2000);
-
-    // do many small tests so the thread locals go away inbetween
-    int num = atLeast(10);
-    for (int i = 0; i < num; i++) {
-      ir1 = IndexReader.open(dir1, false);
-      doTest(10,10);
-      ir1.close();
-    }
-    dir1.close();
-  }
-
-}
Index: lucene/src/test/org/apache/lucene/search/TestFieldCache.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFieldCache.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFieldCache.java	(working copy)
@@ -19,6 +19,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -56,12 +57,12 @@
     writer.w.setInfoStream(VERBOSE ? System.out : null);
     for (int i = 0; i < NUM_DOCS; i++){
       Document doc = new Document();
-      doc.add(newField("theLong", String.valueOf(theLong--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theDouble", String.valueOf(theDouble--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theByte", String.valueOf(theByte--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theShort", String.valueOf(theShort--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theInt", String.valueOf(theInt--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theFloat", String.valueOf(theFloat--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("theLong", String.valueOf(theLong--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theDouble", String.valueOf(theDouble--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theByte", String.valueOf(theByte--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theShort", String.valueOf(theShort--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theInt", String.valueOf(theInt--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theFloat", String.valueOf(theFloat--), StringField.TYPE_UNSTORED));
 
       // sometimes skip the field:
       if (random.nextInt(40) != 17) {
@@ -78,7 +79,7 @@
           s = _TestUtil.randomUnicodeString(random, 250);
         }
         unicodeStrings[i] = s;
-        doc.add(newField("theRandomUnicodeString", unicodeStrings[i], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+        doc.add(newField("theRandomUnicodeString", unicodeStrings[i], StringField.TYPE_UNSTORED));
       }
       writer.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/search/TestScorerPerf.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestScorerPerf.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestScorerPerf.java	(working copy)
@@ -13,7 +13,7 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -64,7 +64,7 @@
       Document d = new Document();
       for (int j=0; j<nTerms; j++) {
         if (random.nextInt(freq[j]) == 0) {
-          d.add(newField("f", terms[j].text(), Field.Store.NO, Field.Index.NOT_ANALYZED));
+          d.add(newField("f", terms[j].text(), StringField.TYPE_UNSTORED));
           //System.out.println(d);
         }
       }
Index: lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestConstantScoreQuery.java	(working copy)
@@ -19,6 +19,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -89,7 +90,7 @@
       RandomIndexWriter writer = new RandomIndexWriter (random, directory);
 
       Document doc = new Document();
-      doc.add(newField("field", "term", Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("field", "term", StringField.TYPE_UNSTORED));
       writer.addDocument(doc);
 
       reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestFuzzyQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFuzzyQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFuzzyQuery.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -464,7 +465,7 @@
 
   private void addDoc(String text, RandomIndexWriter writer) throws IOException {
     Document doc = new Document();
-    doc.add(newField("field", text, Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("field", text, TextField.TYPE_STORED));
     writer.addDocument(doc);
   }
 }
Index: lucene/src/test/org/apache/lucene/search/TestRegexpRandom2.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestRegexpRandom2.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestRegexpRandom2.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.Term;
@@ -63,7 +64,7 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.KEYWORD, false))
         .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)));
     Document doc = new Document();
-    Field field = newField("field", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    Field field = newField("field", "", StringField.TYPE_UNSTORED);
     doc.add(field);
     List<String> terms = new ArrayList<String>();
     int num = atLeast(200);
Index: lucene/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestMultiThreadTermVectors.java	(working copy)
@@ -41,9 +41,13 @@
     IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     //writer.setUseCompoundFile(false);
     //writer.infoStream = System.out;
+    FieldType customType = new FieldType(TextField.TYPE_STORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    customType.setStoreTermVectors(true);
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      Fieldable fld = newField("field", English.intToEnglish(i), Field.Store.YES, Field.Index.NOT_ANALYZED, Field.TermVector.YES);
+      Field fld = newField("field", English.intToEnglish(i), customType);
       doc.add(fld);
       writer.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/search/TestRegexpQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestRegexpQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestRegexpQuery.java	(working copy)
@@ -21,7 +21,7 @@
 import java.util.Arrays;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -50,7 +50,7 @@
     Document doc = new Document();
     doc.add(newField(FN,
         "the quick brown fox jumps over the lazy ??? dog 493432 49344",
-        Field.Store.NO, Field.Index.ANALYZED));
+        TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     reader = writer.getReader();
     writer.close();
Index: lucene/src/test/org/apache/lucene/search/TestDateFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestDateFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestDateFilter.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -47,11 +49,13 @@
     
     Document doc = new Document();
     // add time that is in the past
+    FieldType customType = new FieldType(TextField.TYPE_STORED);
+    customType.setTokenized(false);
+    FieldType customType2 = new FieldType(TextField.TYPE_STORED);
     doc.add(newField("datefield", DateTools.timeToString(now - 1000,
-        DateTools.Resolution.MILLISECOND), Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
+        DateTools.Resolution.MILLISECOND), customType));
     doc.add(newField("body", "Today is a very sunny day in New York City",
-        Field.Store.YES, Field.Index.ANALYZED));
+        customType2));
     writer.addDocument(doc);
     
     IndexReader reader = writer.getReader();
@@ -114,11 +118,13 @@
     
     Document doc = new Document();
     // add time that is in the future
+    FieldType customType = new FieldType(TextField.TYPE_STORED);
+    customType.setTokenized(false);
+    FieldType customType2 = new FieldType(TextField.TYPE_STORED);
     doc.add(newField("datefield", DateTools.timeToString(now + 888888,
-        DateTools.Resolution.MILLISECOND), Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
+        DateTools.Resolution.MILLISECOND), customType));
     doc.add(newField("body", "Today is a very sunny day in New York City",
-        Field.Store.YES, Field.Index.ANALYZED));
+        customType2));
     writer.addDocument(doc);
     
     IndexReader reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestCachingSpanFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestCachingSpanFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestCachingSpanFilter.java	(working copy)
@@ -22,6 +22,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.SerialMergeScheduler;
@@ -54,7 +57,10 @@
 
     // add a doc, refresh the reader, and check that its there
     Document doc = new Document();
-    doc.add(newField("id", "1", Field.Store.YES, Field.Index.NOT_ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    doc.add(newField("id", "1", customType));
     writer.addDocument(doc);
 
     reader = refreshReader(reader);
Index: lucene/src/test/org/apache/lucene/search/TestFilteredSearch.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFilteredSearch.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFilteredSearch.java	(working copy)
@@ -22,7 +22,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexWriter;
@@ -64,7 +64,7 @@
     try {
       for (int i = 0; i < 60; i++) {//Simple docs
         Document doc = new Document();
-        doc.add(newField(FIELD, Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
+        doc.add(newField(FIELD, Integer.toString(i), StringField.TYPE_STORED));
         writer.addDocument(doc);
       }
       if(optimize)
Index: lucene/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestMatchAllDocsQuery.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
@@ -89,7 +90,7 @@
   
   private void addDoc(String text, IndexWriter iw, float boost) throws IOException {
     Document doc = new Document();
-    Field f = newField("key", text, Field.Store.YES, Field.Index.ANALYZED);
+    Field f = newField("key", text, TextField.TYPE_STORED);
     f.setBoost(boost);
     doc.add(f);
     iw.addDocument(doc);
Index: lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestDisjunctionMaxQuery.java	(working copy)
@@ -21,6 +21,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.SlowMultiReaderWrapper;
@@ -83,6 +86,11 @@
   public IndexReader r;
   public IndexSearcher s;
   
+  private static final FieldType nonAnalyzedType = new FieldType(TextField.TYPE_STORED);
+  static {
+    nonAnalyzedType.setTokenized(false);
+  }
+  
   @Override
   public void setUp() throws Exception {
     super.setUp();
@@ -97,57 +105,51 @@
     // d1 is an "ok" match for: albino elephant
     {
       Document d1 = new Document();
-      d1.add(newField("id", "d1", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
+      d1.add(newField("id", "d1", nonAnalyzedType));// Field.Keyword("id",
                                                                                // "d1"));
       d1
-          .add(newField("hed", "elephant", Field.Store.YES,
-              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
+          .add(newField("hed", "elephant", TextField.TYPE_STORED));// Field.Text("hed", "elephant"));
       d1
-          .add(newField("dek", "elephant", Field.Store.YES,
-              Field.Index.ANALYZED));// Field.Text("dek", "elephant"));
+          .add(newField("dek", "elephant", TextField.TYPE_STORED));// Field.Text("dek", "elephant"));
       writer.addDocument(d1);
     }
     
     // d2 is a "good" match for: albino elephant
     {
       Document d2 = new Document();
-      d2.add(newField("id", "d2", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
+      d2.add(newField("id", "d2", nonAnalyzedType));// Field.Keyword("id",
                                                                                // "d2"));
       d2
-          .add(newField("hed", "elephant", Field.Store.YES,
-              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
-      d2.add(newField("dek", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("dek",
+          .add(newField("hed", "elephant", TextField.TYPE_STORED));// Field.Text("hed", "elephant"));
+      d2.add(newField("dek", "albino", TextField.TYPE_STORED));// Field.Text("dek",
                                                                                 // "albino"));
       d2
-          .add(newField("dek", "elephant", Field.Store.YES,
-              Field.Index.ANALYZED));// Field.Text("dek", "elephant"));
+          .add(newField("dek", "elephant", TextField.TYPE_STORED));// Field.Text("dek", "elephant"));
       writer.addDocument(d2);
     }
     
     // d3 is a "better" match for: albino elephant
     {
       Document d3 = new Document();
-      d3.add(newField("id", "d3", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
+      d3.add(newField("id", "d3", nonAnalyzedType));// Field.Keyword("id",
                                                                                // "d3"));
-      d3.add(newField("hed", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("hed",
+      d3.add(newField("hed", "albino", TextField.TYPE_STORED));// Field.Text("hed",
                                                                                 // "albino"));
       d3
-          .add(newField("hed", "elephant", Field.Store.YES,
-              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
+          .add(newField("hed", "elephant", TextField.TYPE_STORED));// Field.Text("hed", "elephant"));
       writer.addDocument(d3);
     }
     
     // d4 is the "best" match for: albino elephant
     {
       Document d4 = new Document();
-      d4.add(newField("id", "d4", Field.Store.YES, Field.Index.NOT_ANALYZED));// Field.Keyword("id",
+      d4.add(newField("id", "d4", nonAnalyzedType));// Field.Keyword("id",
                                                                                // "d4"));
-      d4.add(newField("hed", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("hed",
+      d4.add(newField("hed", "albino", TextField.TYPE_STORED));// Field.Text("hed",
                                                                                 // "albino"));
       d4
-          .add(newField("hed", "elephant", Field.Store.YES,
-              Field.Index.ANALYZED));// Field.Text("hed", "elephant"));
-      d4.add(newField("dek", "albino", Field.Store.YES, Field.Index.ANALYZED));// Field.Text("dek",
+          .add(newField("hed", "elephant", nonAnalyzedType));// Field.Text("hed", "elephant"));
+      d4.add(newField("dek", "albino", TextField.TYPE_STORED));// Field.Text("dek",
                                                                                 // "albino"));
       writer.addDocument(d4);
     }
Index: lucene/src/test/org/apache/lucene/search/TestSimilarity.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSimilarity.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSimilarity.java	(working copy)
@@ -31,6 +31,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 
 /** Similarity unit test.
  *
@@ -61,10 +62,10 @@
         .setSimilarityProvider(new SimpleSimilarityProvider()));
     
     Document d1 = new Document();
-    d1.add(newField("field", "a c", Field.Store.YES, Field.Index.ANALYZED));
+    d1.add(newField("field", "a c", TextField.TYPE_STORED));
 
     Document d2 = new Document();
-    d2.add(newField("field", "a b c", Field.Store.YES, Field.Index.ANALYZED));
+    d2.add(newField("field", "a b c", TextField.TYPE_STORED));
     
     writer.addDocument(d1);
     writer.addDocument(d2);
Index: lucene/src/test/org/apache/lucene/search/TestFieldCacheRangeFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFieldCacheRangeFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFieldCacheRangeFilter.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.store.Directory;
 import org.junit.Test;
 
@@ -535,8 +536,8 @@
 
     for (int d = -20; d <= 20; d++) {
       Document doc = new Document();
-      doc.add(newField("id",Integer.toString(d), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("body","body", Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("id",Integer.toString(d), StringField.TYPE_UNSTORED));
+      doc.add(newField("body","body", StringField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
     
Index: lucene/src/test/org/apache/lucene/search/TestRegexpRandom.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestRegexpRandom.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestRegexpRandom.java	(working copy)
@@ -25,6 +25,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -51,7 +53,10 @@
         .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)));
     
     Document doc = new Document();
-    Field field = newField("field", "", Field.Store.NO, Field.Index.ANALYZED_NO_NORMS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setOmitNorms(true);
+    Field field = newField("field", "", customType);
     doc.add(field);
     
     NumberFormat df = new DecimalFormat("000", new DecimalFormatSymbols(Locale.ENGLISH));
Index: lucene/src/test/org/apache/lucene/search/TestSpanQueryFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSpanQueryFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSpanQueryFilter.java	(working copy)
@@ -20,7 +20,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -39,7 +39,7 @@
     for (int i = 0; i < 500; i++) {
       Document document = new Document();
       document.add(newField("field", English.intToEnglish(i) + " equals " + English.intToEnglish(i),
-              Field.Store.NO, Field.Index.ANALYZED));
+              TextField.TYPE_UNSTORED));
       writer.addDocument(document);
     }
     final int number = 10;
Index: lucene/src/test/org/apache/lucene/search/TestPrefixRandom.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPrefixRandom.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPrefixRandom.java	(working copy)
@@ -23,6 +23,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
@@ -53,7 +54,7 @@
         .setMaxBufferedDocs(_TestUtil.nextInt(random, 50, 1000)));
     
     Document doc = new Document();
-    Field field = newField("field", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    Field field = newField("field", "", StringField.TYPE_UNSTORED);
     doc.add(field);
 
     // we generate aweful prefixes: good for testing.
Index: lucene/src/test/org/apache/lucene/search/TestCustomSearcherSort.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestCustomSearcherSort.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestCustomSearcherSort.java	(working copy)
@@ -25,7 +25,8 @@
 
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -51,21 +52,23 @@
     index = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, index);
     RandomGen random = new RandomGen(this.random);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
     for (int i = 0; i < INDEX_SIZE; ++i) { // don't decrease; if to low the
                                            // problem doesn't show up
       Document doc = new Document();
       if ((i % 5) != 0) { // some documents must not have an entry in the first
                           // sort field
-        doc.add(newField("publicationDate_", random.getLuceneDate(),
-            Field.Store.YES, Field.Index.NOT_ANALYZED));
+        doc.add(newField("publicationDate_", random.getLuceneDate(), customType));
       }
       if ((i % 7) == 0) { // some documents to match the query (see below)
-        doc.add(newField("content", "test", Field.Store.YES,
-            Field.Index.ANALYZED));
+        doc.add(newField("content", "test", customType2));
       }
       // every document has a defined 'mandant' field
-      doc.add(newField("mandant", Integer.toString(i % 3), Field.Store.YES,
-          Field.Index.NOT_ANALYZED));
+      doc.add(newField("mandant", Integer.toString(i % 3), customType));
       writer.addDocument(doc);
     }
     reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestSimilarityProvider.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInvertState;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -44,9 +45,9 @@
         new MockAnalyzer(random)).setSimilarityProvider(sim);
     RandomIndexWriter iw = new RandomIndexWriter(random, directory, iwc);
     Document doc = new Document();
-    Field field = newField("foo", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field field = newField("foo", "", TextField.TYPE_UNSTORED);
     doc.add(field);
-    Field field2 = newField("bar", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field field2 = newField("bar", "", TextField.TYPE_UNSTORED);
     doc.add(field2);
     
     field.setValue("quick brown fox");
Index: lucene/src/test/org/apache/lucene/search/TestPrefixInBooleanQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPrefixInBooleanQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPrefixInBooleanQuery.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
@@ -50,8 +51,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
 
     Document doc = new Document();
-    Field field = newField(FIELD, "meaninglessnames", Field.Store.NO,
-        Field.Index.NOT_ANALYZED_NO_NORMS);
+    Field field = newField(FIELD, "meaninglessnames", StringField.TYPE_UNSTORED);
     doc.add(field);
     
     for (int i = 0; i < 5137; ++i) {
Index: lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery32.java	(working copy)
@@ -58,15 +58,15 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random))
         .setMaxBufferedDocs(_TestUtil.nextInt(random, 100, 1000))
         .setMergePolicy(newLogMergePolicy()));
-    
+  
     NumericField
-      field8 = new NumericField("field8", 8, Field.Store.YES, true),
-      field4 = new NumericField("field4", 4, Field.Store.YES, true),
-      field2 = new NumericField("field2", 2, Field.Store.YES, true),
-      fieldNoTrie = new NumericField("field"+Integer.MAX_VALUE, Integer.MAX_VALUE, rarely() ? Field.Store.YES : Field.Store.NO, true),
-      ascfield8 = new NumericField("ascfield8", 8, Field.Store.NO, true),
-      ascfield4 = new NumericField("ascfield4", 4, Field.Store.NO, true),
-      ascfield2 = new NumericField("ascfield2", 2, Field.Store.NO, true);
+	    field8 = new NumericField("field8", 8, NumericField.TYPE_STORED),
+	    field4 = new NumericField("field4", 4, NumericField.TYPE_STORED),
+	    field2 = new NumericField("field2", 2, NumericField.TYPE_STORED),
+	    fieldNoTrie = new NumericField("field"+Integer.MAX_VALUE, Integer.MAX_VALUE, rarely() ? NumericField.TYPE_STORED : NumericField.TYPE_UNSTORED),
+	    ascfield8 = new NumericField("ascfield8", 8, NumericField.TYPE_UNSTORED),
+	    ascfield4 = new NumericField("ascfield4", 4, NumericField.TYPE_UNSTORED),
+	    ascfield2 = new NumericField("ascfield2", 2, NumericField.TYPE_UNSTORED);
     
     Document doc = new Document();
     // add fields, that have a distance to test general functionality
Index: lucene/src/test/org/apache/lucene/search/TestElevationComparator.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestElevationComparator.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestElevationComparator.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.FieldValueHitQueue.Entry;
@@ -124,7 +125,7 @@
  private Document adoc(String[] vals) {
    Document doc = new Document();
    for (int i = 0; i < vals.length - 2; i += 2) {
-     doc.add(newField(vals[i], vals[i + 1], Field.Store.YES, Field.Index.ANALYZED));
+     doc.add(newField(vals[i], vals[i + 1], TextField.TYPE_STORED));
    }
    return doc;
  }
Index: lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestNumericRangeQuery64.java	(working copy)
@@ -57,15 +57,15 @@
         .setMergePolicy(newLogMergePolicy()));
     
     NumericField
-      field8 = new NumericField("field8", 8, Field.Store.YES, true),
-      field6 = new NumericField("field6", 6, Field.Store.YES, true),
-      field4 = new NumericField("field4", 4, Field.Store.YES, true),
-      field2 = new NumericField("field2", 2, Field.Store.YES, true),
-      fieldNoTrie = new NumericField("field"+Integer.MAX_VALUE, Integer.MAX_VALUE, rarely() ? Field.Store.YES : Field.Store.NO, true),
-      ascfield8 = new NumericField("ascfield8", 8, Field.Store.NO, true),
-      ascfield6 = new NumericField("ascfield6", 6, Field.Store.NO, true),
-      ascfield4 = new NumericField("ascfield4", 4, Field.Store.NO, true),
-      ascfield2 = new NumericField("ascfield2", 2, Field.Store.NO, true);
+      field8 = new NumericField("field8", 8, NumericField.TYPE_STORED),
+      field6 = new NumericField("field6", 6, NumericField.TYPE_STORED),
+      field4 = new NumericField("field4", 4, NumericField.TYPE_STORED),
+      field2 = new NumericField("field2", 2, NumericField.TYPE_STORED),
+      fieldNoTrie = new NumericField("field"+Integer.MAX_VALUE, Integer.MAX_VALUE, rarely() ? NumericField.TYPE_STORED : NumericField.TYPE_UNSTORED),
+      ascfield8 = new NumericField("ascfield8", 8, NumericField.TYPE_UNSTORED),
+      ascfield6 = new NumericField("ascfield6", 6, NumericField.TYPE_UNSTORED),
+      ascfield4 = new NumericField("ascfield4", 4, NumericField.TYPE_UNSTORED),
+      ascfield2 = new NumericField("ascfield2", 2, NumericField.TYPE_UNSTORED);
     
     Document doc = new Document();
     // add fields, that have a distance to test general functionality
Index: lucene/src/test/org/apache/lucene/search/TestPrefixQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestPrefixQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestPrefixQuery.java	(working copy)
@@ -25,7 +25,7 @@
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 
 /**
  * Tests {@link PrefixQuery} class.
@@ -41,7 +41,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, directory);
     for (int i = 0; i < categories.length; i++) {
       Document doc = new Document();
-      doc.add(newField("category", categories[i], Field.Store.YES, Field.Index.NOT_ANALYZED));
+      doc.add(newField("category", categories[i], StringField.TYPE_STORED));
       writer.addDocument(doc);
     }
     IndexReader reader = writer.getReader();
Index: lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestMultiPhraseQuery.java	(working copy)
@@ -33,6 +33,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.store.RAMDirectory;
@@ -164,7 +166,7 @@
   
   private void add(String s, RandomIndexWriter writer) throws IOException {
     Document doc = new Document();
-    doc.add(newField("body", s, Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(newField("body", s, TextField.TYPE_STORED));
     writer.addDocument(doc);
   }
   
@@ -287,8 +289,8 @@
   private void add(String s, String type, RandomIndexWriter writer)
       throws IOException {
     Document doc = new Document();
-    doc.add(newField("body", s, Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("type", type, Field.Store.YES, Field.Index.NOT_ANALYZED));
+    doc.add(newField("body", s, TextField.TYPE_STORED));
+    doc.add(newField("type", type, StringField.TYPE_UNSTORED));
     writer.addDocument(doc);
   }
   
@@ -389,7 +391,7 @@
 
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, new CannedAnalyzer(tokens));
     Document doc = new Document();
-    doc.add(new Field("field", "", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("field", ""));
     writer.addDocument(doc);
     writer.addDocument(doc);
     IndexReader r = writer.getReader();
@@ -481,7 +483,7 @@
     IndexWriterConfig cfg = newIndexWriterConfig(TEST_VERSION_CURRENT, new CannedAnalyzer(INCR_0_DOC_TOKENS));
     IndexWriter writer = new IndexWriter(dir, cfg);
     Document doc = new Document();
-    doc.add(new Field("field", "", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("field", ""));
     writer.addDocument(doc);
     IndexReader r = IndexReader.open(writer,false);
     writer.close();
Index: lucene/src/test/org/apache/lucene/search/TestFilteredQuery.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFilteredQuery.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFilteredQuery.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
@@ -54,23 +55,23 @@
     RandomIndexWriter writer = new RandomIndexWriter (random, directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
 
     Document doc = new Document();
-    doc.add (newField("field", "one two three four five", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add (newField("sorter", "b", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add (newField("field", "one two three four five", TextField.TYPE_STORED));
+    doc.add (newField("sorter", "b", TextField.TYPE_STORED));
     writer.addDocument (doc);
 
     doc = new Document();
-    doc.add (newField("field", "one two three four", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add (newField("sorter", "d", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add (newField("field", "one two three four", TextField.TYPE_STORED));
+    doc.add (newField("sorter", "d", TextField.TYPE_STORED));
     writer.addDocument (doc);
 
     doc = new Document();
-    doc.add (newField("field", "one two three y", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add (newField("sorter", "a", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add (newField("field", "one two three y", TextField.TYPE_STORED));
+    doc.add (newField("sorter", "a", TextField.TYPE_STORED));
     writer.addDocument (doc);
 
     doc = new Document();
-    doc.add (newField("field", "one two x", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add (newField("sorter", "c", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add (newField("field", "one two x", TextField.TYPE_STORED));
+    doc.add (newField("sorter", "c", TextField.TYPE_STORED));
     writer.addDocument (doc);
 
     // tests here require single segment (eg try seed
Index: lucene/src/test/org/apache/lucene/search/TestFieldCacheTermsFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestFieldCacheTermsFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/search/TestFieldCacheTermsFilter.java	(working copy)
@@ -21,6 +21,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.store.Directory;
@@ -41,7 +42,7 @@
     for (int i = 0; i < 100; i++) {
       Document doc = new Document();
       int term = i * 10; //terms are units of 10;
-      doc.add(newField(fieldName, "" + term, Field.Store.YES, Field.Index.NOT_ANALYZED));
+      doc.add(newField(fieldName, "" + term, StringField.TYPE_STORED));
       w.addDocument(doc);
     }
     IndexReader reader = w.getReader();
Index: lucene/src/test/org/apache/lucene/index/TestIndexableField.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexableField.java	(revision 0)
+++ lucene/src/test/org/apache/lucene/index/TestIndexableField.java	(revision 1160484)
@@ -0,0 +1,342 @@
+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 java.io.StringReader;
+import java.util.Iterator;
+
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.NumericField.DataType;
+import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.index.values.PerDocFieldValues;
+import org.apache.lucene.index.values.ValueType;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.NumericRangeQuery;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util._TestUtil;
+
+public class TestIndexableField extends LuceneTestCase {
+
+  private class MyField implements IndexableField {
+
+    private final int counter;
+
+    public MyField(int counter) {
+      this.counter = counter;
+    }
+
+    @Override
+    public String name() {
+      return "f" + counter;
+    }
+
+    @Override
+    public float boost() {
+      return 1.0f + random.nextFloat();
+    }
+  
+    @Override
+    public boolean stored() {
+      return (counter & 1) == 0 || (counter % 10) == 3;
+    }
+
+    @Override
+    public BytesRef binaryValue() {
+      if ((counter%10) == 3) {
+        final byte[] bytes = new byte[10];
+        for(int idx=0;idx<bytes.length;idx++) {
+          bytes[idx] = (byte) (counter+idx);
+        }
+        return new BytesRef(bytes, 0, bytes.length);
+      } else {
+        return null;
+      }
+    }
+
+    @Override
+    public String stringValue() {
+      final int fieldID = counter%10;
+      if (fieldID != 3 && fieldID != 7 && fieldID != 9) {
+        return "text " + counter;
+      } else {
+        return null;
+      }
+    }
+
+    @Override
+    public Reader readerValue() {
+      if (counter%10 == 7) {
+        return new StringReader("text " + counter);
+      } else {
+        return null;
+      }
+    }
+
+    @Override
+    public TokenStream tokenStreamValue() {
+      if (numeric()) {
+        return new NumericField(name()).setIntValue(counter).tokenStreamValue();
+      } else {
+        return null;
+      }
+    }
+
+    // Numeric field:
+    @Override
+    public boolean numeric() {
+      return counter%10 == 9;
+    }
+
+    @Override
+    public DataType numericDataType() {
+      return DataType.INT;
+    }
+
+    @Override
+    public Number numericValue() {
+      return counter;
+    }
+
+    // If this returns true then we index this field:
+    @Override
+    public boolean indexed() {
+      return (counter % 10) != 3;
+    }
+
+    @Override
+    public boolean tokenized() {
+      return true;
+    }
+
+    @Override
+    public boolean omitNorms() {
+      return false;
+    }
+
+    @Override
+    public FieldInfo.IndexOptions indexOptions() {
+      return FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
+    }
+
+    @Override
+    public boolean storeTermVectors() {
+      return counter % 2 == 1 && counter%10 != 9;
+    }
+
+    @Override
+    public boolean storeTermVectorOffsets() {
+      return counter % 2 == 1 && counter%10 != 9;
+    }
+
+    @Override
+    public boolean storeTermVectorPositions() {
+      return counter % 2 == 1 && counter%10 != 9;
+    }
+  
+    // TODO: randomly enable doc values
+    @Override
+    public PerDocFieldValues docValues() {
+      return null;
+    }
+
+    @Override
+    public ValueType docValuesType() {
+      return null;
+    }
+  }
+
+  // Silly test showing how to index documents w/o using Lucene's core
+  // Document nor Field class
+  public void testArbitraryFields() throws Exception {
+
+    final Directory dir = newDirectory();
+    final RandomIndexWriter w = new RandomIndexWriter(random, dir);
+
+    final int NUM_DOCS = atLeast(27);
+    if (VERBOSE) {
+      System.out.println("TEST: " + NUM_DOCS + " docs");
+    }
+    final int[] fieldsPerDoc = new int[NUM_DOCS];
+    int baseCount = 0;
+
+    for(int docCount=0;docCount<NUM_DOCS;docCount++) {
+      final int fieldCount = _TestUtil.nextInt(random, 1, 17);
+      fieldsPerDoc[docCount] = fieldCount-1;
+
+      final int finalDocCount = docCount;
+      if (VERBOSE) {
+        System.out.println("TEST: " + fieldCount + " fields in doc " + docCount);
+      }
+
+      final int finalBaseCount = baseCount;
+      baseCount += fieldCount-1;
+
+      w.addDocument(new Iterable<IndexableField>() {
+        @Override
+        public Iterator<IndexableField> iterator() {
+          return new Iterator<IndexableField>() {
+            int fieldUpto;
+
+            @Override
+            public boolean hasNext() {
+              return fieldUpto < fieldCount;
+            }
+
+            @Override
+            public IndexableField next() {
+              assert fieldUpto < fieldCount;
+              if (fieldUpto == 0) {
+                fieldUpto = 1;
+                return newField("id", ""+finalDocCount, StringField.TYPE_STORED);
+              } else {
+                return new MyField(finalBaseCount + (fieldUpto++-1));
+              }
+            }
+
+            @Override
+            public void remove() {
+              throw new UnsupportedOperationException();
+            }
+          };
+        }
+        });
+    }
+
+    final IndexReader r = w.getReader();
+    w.close();
+
+    final IndexSearcher s = new IndexSearcher(r);
+    int counter = 0;
+    for(int id=0;id<NUM_DOCS;id++) {
+      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 int endCounter = counter + fieldsPerDoc[id];
+      while(counter < endCounter) {
+        final String name = "f" + counter;
+        final int fieldID = counter % 10;
+
+        final boolean stored = (counter&1) == 0 || fieldID == 3;
+        final boolean binary = fieldID == 3;
+        final boolean indexed = fieldID != 3;
+        final boolean numeric = fieldID == 9;
+
+        final String stringValue;
+        if (fieldID != 3 && fieldID != 9) {
+          stringValue = "text " + counter;
+        } else {
+          stringValue = null;
+        }
+
+        // stored:
+        if (stored) {
+          IndexableField 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);
+            final BytesRef b = f.binaryValue();
+            assertNotNull(b);
+            assertEquals(10, b.length);
+            for(int idx=0;idx<10;idx++) {
+              assertEquals((byte) (idx+counter), b.bytes[b.offset+idx]);
+            }
+          } else if (numeric) {
+            assertTrue(f instanceof NumericField);
+            final NumericField nf = (NumericField) f;
+            assertEquals(NumericField.DataType.INT, nf.numericDataType());
+            assertEquals(counter, nf.numericValue().intValue());
+          } else {
+            assert stringValue != null;
+            assertEquals(stringValue, f.stringValue());
+          }
+        }
+        
+        if (indexed) {
+          final boolean tv = counter % 2 == 1 && fieldID != 9;
+          final TermFreqVector tfv = r.getTermFreqVector(docID, name);
+          if (tv) {
+            assertNotNull(tfv);
+            assertTrue(tfv instanceof TermPositionVector);
+            final TermPositionVector tpv = (TermPositionVector) tfv;
+            final BytesRef[] terms = tpv.getTerms();
+            assertEquals(2, terms.length);
+            assertEquals(new BytesRef(""+counter), terms[0]);
+            assertEquals(new BytesRef("text"), terms[1]);
+
+            final int[] freqs = tpv.getTermFrequencies();
+            assertEquals(2, freqs.length);
+            assertEquals(1, freqs[0]);
+            assertEquals(1, freqs[1]);
+
+            int[] positions = tpv.getTermPositions(0);
+            assertEquals(1, positions.length);
+            assertEquals(1, positions[0]);
+
+            positions = tpv.getTermPositions(1);
+            assertEquals(1, positions.length);
+            assertEquals(0, positions[0]);
+
+            // TODO: offsets
+            
+          } else {
+            assertNull(tfv);
+          }
+
+          if (numeric) {
+            NumericRangeQuery nrq = NumericRangeQuery.newIntRange(name, counter, counter, true, true);
+            final TopDocs hits2 = s.search(nrq, 1);
+            assertEquals(1, hits2.totalHits);
+            assertEquals(docID, hits2.scoreDocs[0].doc);
+          } else {
+            BooleanQuery bq = new BooleanQuery();
+            bq.add(new TermQuery(new Term("id", ""+id)), BooleanClause.Occur.MUST);
+            bq.add(new TermQuery(new Term(name, "text")), BooleanClause.Occur.MUST);
+            final TopDocs hits2 = s.search(bq, 1);
+            assertEquals(1, hits2.totalHits);
+            assertEquals(docID, hits2.scoreDocs[0].doc);
+
+            bq = new BooleanQuery();
+            bq.add(new TermQuery(new Term("id", ""+id)), BooleanClause.Occur.MUST);
+            bq.add(new TermQuery(new Term(name, ""+counter)), BooleanClause.Occur.MUST);
+            final TopDocs hits3 = s.search(bq, 1);
+            assertEquals(1, hits3.totalHits);
+            assertEquals(docID, hits3.scoreDocs[0].doc);
+          }
+        }
+
+        counter++;
+      }
+    }
+
+    r.close();
+    dir.close();
+  }
+}
\ No newline at end of file

Property changes on: lucene/src/test/org/apache/lucene/index/TestIndexableField.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/values/TestDocValuesIndexing.java	(working copy)
@@ -25,12 +25,12 @@
 import java.util.List;
 
 import org.apache.lucene.analysis.MockAnalyzer;
-import org.apache.lucene.document.AbstractField;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.IndexDocValuesField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CorruptIndexException;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
@@ -81,7 +81,7 @@
       IndexDocValuesField valuesField = new IndexDocValuesField("docId");
       valuesField.setInt(i);
       doc.add(valuesField);
-      doc.add(new Field("docId", "" + i, Store.NO, Index.ANALYZED));
+      doc.add(new TextField("docId", "" + i));
       writer.addDocument(doc);
     }
     writer.commit();
@@ -480,22 +480,24 @@
       ValueType.FLOAT_32,
       ValueType.FLOAT_64);
 
-  private static Index[] IDX_VALUES = new Index[] { Index.ANALYZED,
-      Index.ANALYZED_NO_NORMS, Index.NOT_ANALYZED, Index.NOT_ANALYZED_NO_NORMS,
-      Index.NO };
-
   private FixedBitSet indexValues(IndexWriter w, int numValues, ValueType value,
       List<ValueType> valueVarList, boolean withDeletions, int bytesSize)
       throws CorruptIndexException, IOException {
     final boolean isNumeric = NUMERICS.contains(value);
     FixedBitSet deleted = new FixedBitSet(numValues);
     Document doc = new Document();
-    Index idx = IDX_VALUES[random.nextInt(IDX_VALUES.length)];
-    AbstractField field = random.nextBoolean() ? new IndexDocValuesField(value.name())
-        : newField(value.name(), _TestUtil.randomRealisticUnicodeString(random,
-            10), idx == Index.NO ? Store.YES : Store.NO, idx);
-    doc.add(field);
-    IndexDocValuesField valField = new IndexDocValuesField("prototype");
+    FieldType ft = new FieldType();
+    ft.setIndexed(random.nextBoolean());
+    if (ft.indexed()) {
+      ft.setTokenized(random.nextBoolean());
+      ft.setOmitNorms(random.nextBoolean());
+    }
+    else {
+      ft.setStored(true);
+    }
+    
+    IndexDocValuesField valField = new IndexDocValuesField(value.name());
+    doc.add(valField);
     final BytesRef bytesRef = new BytesRef();
 
     final String idBase = value.name() + "_";
@@ -543,9 +545,7 @@
         }
       }
       doc.removeFields("id");
-      doc.add(new Field("id", idBase + i, Store.YES,
-          Index.NOT_ANALYZED_NO_NORMS));
-      valField.set(field);
+      doc.add(new Field("id", StringField.TYPE_STORED, idBase + i));
       w.addDocument(doc);
 
       if (i % 7 == 0) {
@@ -567,8 +567,9 @@
     w.commit();
 
     // TODO test unoptimized with deletions
-    if (withDeletions || random.nextBoolean())
+    if (withDeletions || random.nextBoolean()) {
       w.optimize(true);
+    }
     return deleted;
   }
 }
Index: lucene/src/test/org/apache/lucene/index/TestStressNRT.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestStressNRT.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestStressNRT.java	(working copy)
@@ -28,7 +28,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoreDoc;
@@ -81,6 +82,9 @@
     final int nReadThreads = _TestUtil.nextInt(random, 1, TEST_NIGHTLY ? 10 : 5);
     initModel(ndocs);
 
+    final FieldType storedOnlyType = new FieldType();
+    storedOnlyType.setStored(true);
+
     if (VERBOSE) {
       System.out.println("\n");
       System.out.println("TEST: commitPercent=" + commitPercent);
@@ -228,8 +232,8 @@
                     // add tombstone first
                     if (tombstones) {
                       Document d = new Document();
-                      d.add(new Field("id","-"+Integer.toString(id), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-                      d.add(new Field(field, Long.toString(nextVal), Field.Store.YES, Field.Index.NO));
+                      d.add(newField("id", "-"+Integer.toString(id), StringField.TYPE_STORED));
+                      d.add(newField(field, Long.toString(nextVal), storedOnlyType));
                       writer.updateDocument(new Term("id", "-"+Integer.toString(id)), d);
                     }
 
@@ -244,8 +248,8 @@
                     // add tombstone first
                     if (tombstones) {
                       Document d = new Document();
-                      d.add(new Field("id","-"+Integer.toString(id), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-                      d.add(new Field(field, Long.toString(nextVal), Field.Store.YES, Field.Index.NO));
+                      d.add(newField("id", "-"+Integer.toString(id), StringField.TYPE_STORED));
+                      d.add(newField(field, Long.toString(nextVal), storedOnlyType));
                       writer.updateDocument(new Term("id", "-"+Integer.toString(id)), d);
                     }
 
@@ -257,8 +261,8 @@
                   } else {
                     // assertU(adoc("id",Integer.toString(id), field, Long.toString(nextVal)));
                     Document d = new Document();
-                    d.add(newField("id",Integer.toString(id), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-                    d.add(newField(field, Long.toString(nextVal), Field.Store.YES, Field.Index.NO));
+                    d.add(newField("id", Integer.toString(id), StringField.TYPE_STORED));
+                    d.add(newField(field, Long.toString(nextVal), storedOnlyType));
                     if (VERBOSE) {
                       System.out.println("TEST: " + Thread.currentThread().getName() + ": u id:" + id + " val=" + nextVal);
                     }
Index: lucene/src/test/org/apache/lucene/index/TestIndexReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReader.java	(working copy)
@@ -31,27 +31,22 @@
 import java.util.SortedSet;
 import org.junit.Assume;
 import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.BinaryField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.SetBasedFieldSelector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.FieldOption;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.FieldCache;
-import org.apache.lucene.search.Similarity;
-import org.apache.lucene.search.IndexSearcher;
-import org.apache.lucene.search.ScoreDoc;
-import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.LockObtainFailedException;
-import org.apache.lucene.store.MockDirectoryWrapper;
 import org.apache.lucene.store.NoSuchDirectoryException;
-import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.store.LockReleaseFailedException;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;
@@ -154,10 +149,20 @@
         );
 
         Document doc = new Document();
-        doc.add(new Field("keyword","test1", Field.Store.YES, Field.Index.NOT_ANALYZED));
-        doc.add(new Field("text","test1", Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(new Field("unindexed","test1", Field.Store.YES, Field.Index.NO));
-        doc.add(new Field("unstored","test1", Field.Store.NO, Field.Index.ANALYZED));
+        FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+        customType.setStored(true);
+        customType.setTokenized(false);
+
+        FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+        customType2.setStored(true);
+
+        FieldType customType3 = new FieldType();
+        customType3.setStored(true);
+        
+        doc.add(new Field("keyword",customType,"test1"));
+        doc.add(new Field("text",customType2,"test1"));
+        doc.add(new Field("unindexed",customType3,"test1"));
+        doc.add(new TextField("unstored","test1"));
         writer.addDocument(doc);
 
         writer.close();
@@ -180,29 +185,49 @@
         int mergeFactor = ((LogMergePolicy) writer.getConfig().getMergePolicy()).getMergeFactor();
         for (int i = 0; i < 5*mergeFactor; i++) {
           doc = new Document();
-          doc.add(new Field("keyword","test1", Field.Store.YES, Field.Index.NOT_ANALYZED));
-          doc.add(new Field("text","test1", Field.Store.YES, Field.Index.ANALYZED));
-          doc.add(new Field("unindexed","test1", Field.Store.YES, Field.Index.NO));
-          doc.add(new Field("unstored","test1", Field.Store.NO, Field.Index.ANALYZED));
+          doc.add(new Field("keyword",customType,"test1"));
+          doc.add(new Field("text",customType2, "test1"));
+          doc.add(new Field("unindexed",customType3,"test1"));
+          doc.add(new TextField("unstored","test1"));
           writer.addDocument(doc);
         }
         // new fields are in some different segments (we hope)
         for (int i = 0; i < 5*mergeFactor; i++) {
           doc = new Document();
-          doc.add(new Field("keyword2","test1", Field.Store.YES, Field.Index.NOT_ANALYZED));
-          doc.add(new Field("text2","test1", Field.Store.YES, Field.Index.ANALYZED));
-          doc.add(new Field("unindexed2","test1", Field.Store.YES, Field.Index.NO));
-          doc.add(new Field("unstored2","test1", Field.Store.NO, Field.Index.ANALYZED));
+          doc.add(new Field("keyword2",customType,"test1"));
+          doc.add(new Field("text2",customType2, "test1"));
+          doc.add(new Field("unindexed2",customType3,"test1"));
+          doc.add(new TextField("unstored2","test1"));
           writer.addDocument(doc);
         }
         // new termvector fields
+
+        FieldType customType4 = new FieldType(TextField.TYPE_UNSTORED);
+        customType4.setStored(true);
+        FieldType customType5 = new FieldType(TextField.TYPE_UNSTORED);
+        customType5.setStored(true);
+        customType5.setStoreTermVectors(true);
+        FieldType customType6 = new FieldType(TextField.TYPE_UNSTORED);
+        customType6.setStored(true);
+        customType6.setStoreTermVectors(true);
+        customType6.setStoreTermVectorOffsets(true);
+        FieldType customType7 = new FieldType(TextField.TYPE_UNSTORED);
+        customType7.setStored(true);
+        customType7.setStoreTermVectors(true);
+        customType7.setStoreTermVectorPositions(true);
+        FieldType customType8 = new FieldType(TextField.TYPE_UNSTORED);
+        customType8.setStored(true);
+        customType8.setStoreTermVectors(true);
+        customType8.setStoreTermVectorOffsets(true);
+        customType8.setStoreTermVectorPositions(true);
+        
         for (int i = 0; i < 5*mergeFactor; i++) {
           doc = new Document();
-          doc.add(new Field("tvnot","tvnot", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
-          doc.add(new Field("termvector","termvector", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
-          doc.add(new Field("tvoffset","tvoffset", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_OFFSETS));
-          doc.add(new Field("tvposition","tvposition", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
-          doc.add(newField("tvpositionoffset","tvpositionoffset", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+          doc.add(new Field("tvnot",customType4,"tvnot"));
+          doc.add(new Field("termvector",customType5,"termvector"));
+          doc.add(new Field("tvoffset",customType6,"tvoffset"));
+          doc.add(new Field("tvposition",customType7,"tvposition"));
+          doc.add(new Field("tvpositionoffset",customType8, "tvpositionoffset"));
           writer.addDocument(doc);
         }
         
@@ -277,14 +302,32 @@
     // want to get some more segments here
     // new termvector fields
     int mergeFactor = ((LogMergePolicy) writer.getConfig().getMergePolicy()).getMergeFactor();
+    FieldType customType4 = new FieldType(TextField.TYPE_UNSTORED);
+    customType4.setStored(true);
+    FieldType customType5 = new FieldType(TextField.TYPE_UNSTORED);
+    customType5.setStored(true);
+    customType5.setStoreTermVectors(true);
+    FieldType customType6 = new FieldType(TextField.TYPE_UNSTORED);
+    customType6.setStored(true);
+    customType6.setStoreTermVectors(true);
+    customType6.setStoreTermVectorOffsets(true);
+    FieldType customType7 = new FieldType(TextField.TYPE_UNSTORED);
+    customType7.setStored(true);
+    customType7.setStoreTermVectors(true);
+    customType7.setStoreTermVectorPositions(true);
+    FieldType customType8 = new FieldType(TextField.TYPE_UNSTORED);
+    customType8.setStored(true);
+    customType8.setStoreTermVectors(true);
+    customType8.setStoreTermVectorOffsets(true);
+    customType8.setStoreTermVectorPositions(true);
     for (int i = 0; i < 5 * mergeFactor; i++) {
       Document doc = new Document();
-        doc.add(new Field("tvnot","one two two three three three", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
-        doc.add(new Field("termvector","one two two three three three", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
-        doc.add(new Field("tvoffset","one two two three three three", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_OFFSETS));
-        doc.add(new Field("tvposition","one two two three three three", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
-        doc.add(new Field("tvpositionoffset","one two two three three three", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-
+        doc.add(new Field("tvnot",customType4,"one two two three three three"));
+        doc.add(new Field("termvector",customType5,"one two two three three three"));
+        doc.add(new Field("tvoffset",customType6,"one two two three three three"));
+        doc.add(new Field("tvposition",customType7,"one two two three three three"));
+        doc.add(new Field("tvpositionoffset",customType8, "one two two three three three"));
+        
         writer.addDocument(doc);
     }
     writer.close();
@@ -338,37 +381,22 @@
         writer.close();
         writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.APPEND).setMergePolicy(newLogMergePolicy()));
         Document doc = new Document();
-        doc.add(new Field("bin1", bin));
-        doc.add(new Field("junk", "junk text", Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(new BinaryField("bin1", bin));
+        doc.add(new TextField("junk", "junk text"));
         writer.addDocument(doc);
         writer.close();
         IndexReader reader = IndexReader.open(dir, false);
-        doc = reader.document(reader.maxDoc() - 1);
-        Field[] fields = doc.getFields("bin1");
+        Document doc2 = reader.document(reader.maxDoc() - 1);
+        IndexableField[] fields = doc2.getFields("bin1");
         assertNotNull(fields);
         assertEquals(1, fields.length);
-        Field b1 = fields[0];
-        assertTrue(b1.isBinary());
-        byte[] data1 = b1.getBinaryValue();
-        assertEquals(bin.length, b1.getBinaryLength());
+        IndexableField b1 = fields[0];
+        assertTrue(b1.binaryValue() != null);
+        BytesRef bytesRef = b1.binaryValue();
+        assertEquals(bin.length, bytesRef.length);
         for (int i = 0; i < bin.length; i++) {
-          assertEquals(bin[i], data1[i + b1.getBinaryOffset()]);
+          assertEquals(bin[i], bytesRef.bytes[i + bytesRef.offset]);
         }
-        Set<String> lazyFields = new HashSet<String>();
-        lazyFields.add("bin1");
-        FieldSelector sel = new SetBasedFieldSelector(new HashSet<String>(), lazyFields);
-        doc = reader.document(reader.maxDoc() - 1, sel);
-        Fieldable[] fieldables = doc.getFieldables("bin1");
-        assertNotNull(fieldables);
-        assertEquals(1, fieldables.length);
-        Fieldable fb1 = fieldables[0];
-        assertTrue(fb1.isBinary());
-        assertEquals(bin.length, fb1.getBinaryLength());
-        data1 = fb1.getBinaryValue();
-        assertEquals(bin.length, fb1.getBinaryLength());
-        for (int i = 0; i < bin.length; i++) {
-          assertEquals(bin[i], data1[i + fb1.getBinaryOffset()]);
-        }
         reader.close();
         // force optimize
 
@@ -377,16 +405,16 @@
         writer.optimize();
         writer.close();
         reader = IndexReader.open(dir, false);
-        doc = reader.document(reader.maxDoc() - 1);
-        fields = doc.getFields("bin1");
+        doc2 = reader.document(reader.maxDoc() - 1);
+        fields = doc2.getFields("bin1");
         assertNotNull(fields);
         assertEquals(1, fields.length);
         b1 = fields[0];
-        assertTrue(b1.isBinary());
-        data1 = b1.getBinaryValue();
-        assertEquals(bin.length, b1.getBinaryLength());
+        assertTrue(b1.binaryValue() != null);
+        bytesRef = b1.binaryValue();
+        assertEquals(bin.length, bytesRef.length);
         for (int i = 0; i < bin.length; i++) {
-          assertEquals(bin[i], data1[i + b1.getBinaryOffset()]);
+          assertEquals(bin[i], bytesRef.bytes[i + bytesRef.offset]);
         }
         reader.close();
         dir.close();
@@ -778,38 +806,76 @@
     static void addDocumentWithFields(IndexWriter writer) throws IOException
     {
         Document doc = new Document();
-        doc.add(newField("keyword","test1", Field.Store.YES, Field.Index.NOT_ANALYZED));
-        doc.add(newField("text","test1", Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("unindexed","test1", Field.Store.YES, Field.Index.NO));
-        doc.add(newField("unstored","test1", Field.Store.NO, Field.Index.ANALYZED));
+        
+        FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+        customType.setStored(true);
+        customType.setTokenized(false);
+
+        FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+        customType2.setStored(true);
+
+        FieldType customType3 = new FieldType();
+        customType3.setStored(true);
+        doc.add(newField("keyword", "test1", customType));
+        doc.add(newField("text", "test1", customType2));
+        doc.add(newField("unindexed", "test1", customType3));
+        doc.add(new TextField("unstored","test1"));
         writer.addDocument(doc);
     }
 
     static void addDocumentWithDifferentFields(IndexWriter writer) throws IOException
     {
-        Document doc = new Document();
-        doc.add(newField("keyword2","test1", Field.Store.YES, Field.Index.NOT_ANALYZED));
-        doc.add(newField("text2","test1", Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("unindexed2","test1", Field.Store.YES, Field.Index.NO));
-        doc.add(newField("unstored2","test1", Field.Store.NO, Field.Index.ANALYZED));
-        writer.addDocument(doc);
+      Document doc = new Document();
+      
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setTokenized(false);
+
+      FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+      customType2.setStored(true);
+
+      FieldType customType3 = new FieldType();
+      customType3.setStored(true);
+      doc.add(newField("keyword2", "test1", customType));
+      doc.add(newField("text2", "test1", customType2));
+      doc.add(newField("unindexed2", "test1", customType3));
+      doc.add(new TextField("unstored2","test1"));
+      writer.addDocument(doc);
     }
 
     static void addDocumentWithTermVectorFields(IndexWriter writer) throws IOException
     {
         Document doc = new Document();
-        doc.add(newField("tvnot","tvnot", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
-        doc.add(newField("termvector","termvector", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.YES));
-        doc.add(newField("tvoffset","tvoffset", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_OFFSETS));
-        doc.add(newField("tvposition","tvposition", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS));
-        doc.add(newField("tvpositionoffset","tvpositionoffset", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+        FieldType customType4 = new FieldType(TextField.TYPE_UNSTORED);
+        customType4.setStored(true);
+        FieldType customType5 = new FieldType(TextField.TYPE_UNSTORED);
+        customType5.setStored(true);
+        customType5.setStoreTermVectors(true);
+        FieldType customType6 = new FieldType(TextField.TYPE_UNSTORED);
+        customType6.setStored(true);
+        customType6.setStoreTermVectors(true);
+        customType6.setStoreTermVectorOffsets(true);
+        FieldType customType7 = new FieldType(TextField.TYPE_UNSTORED);
+        customType7.setStored(true);
+        customType7.setStoreTermVectors(true);
+        customType7.setStoreTermVectorPositions(true);
+        FieldType customType8 = new FieldType(TextField.TYPE_UNSTORED);
+        customType8.setStored(true);
+        customType8.setStoreTermVectors(true);
+        customType8.setStoreTermVectorOffsets(true);
+        customType8.setStoreTermVectorPositions(true);
+        doc.add(newField("tvnot","tvnot",customType4));
+        doc.add(newField("termvector","termvector",customType5));
+        doc.add(newField("tvoffset","tvoffset", customType6));
+        doc.add(newField("tvposition","tvposition", customType7));
+        doc.add(newField("tvpositionoffset","tvpositionoffset", customType8));
         
         writer.addDocument(doc);
     }
     
     static void addDoc(IndexWriter writer, String value) throws IOException {
         Document doc = new Document();
-        doc.add(newField("content", value, Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(newField("content", value, TextField.TYPE_UNSTORED));
         writer.addDocument(doc);
     }
 
@@ -862,11 +928,11 @@
         if (liveDocs1 == null || liveDocs1.get(i)) {
           Document doc1 = index1.document(i);
           Document doc2 = index2.document(i);
-          List<Fieldable> fieldable1 = doc1.getFields();
-          List<Fieldable> fieldable2 = doc2.getFields();
-          assertEquals("Different numbers of fields for doc " + i + ".", fieldable1.size(), fieldable2.size());
-          Iterator<Fieldable> itField1 = fieldable1.iterator();
-          Iterator<Fieldable> itField2 = fieldable2.iterator();
+          List<IndexableField> field1 = doc1.getFields();
+          List<IndexableField> 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();
           while (itField1.hasNext()) {
             Field curField1 = (Field) itField1.next();
             Field curField2 = (Field) itField2.next();
@@ -1047,7 +1113,12 @@
 
   static Document createDocument(String id) {
     Document doc = new Document();
-    doc.add(newField("id", id, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    customType.setOmitNorms(true);
+    
+    doc.add(newField("id", id, customType));
     return doc;
   }
 
@@ -1097,7 +1168,7 @@
     Directory dir = newDirectory();
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("number", "17", StringField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.close();
 
@@ -1132,7 +1203,7 @@
             setMergePolicy(newLogMergePolicy(10))
     );
     Document doc = new Document();
-    doc.add(newField("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("number", "17", StringField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.commit();
 
@@ -1164,8 +1235,8 @@
     Directory dir = newDirectory();
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setCodecProvider(_TestUtil.alwaysCodec("Standard")));
     Document doc = new Document();
-    doc.add(newField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", Field.Store.NO, Field.Index.ANALYZED));
-    doc.add(newField("number", "0 1 2 3 4 5 6 7 8 9", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", TextField.TYPE_UNSTORED));
+    doc.add(newField("number", "0 1 2 3 4 5 6 7 8 9", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.addDocument(doc);
     writer.commit();
@@ -1197,8 +1268,8 @@
     Directory dir = newDirectory();
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setCodecProvider(_TestUtil.alwaysCodec("Standard")));
     Document doc = new Document();
-    doc.add(newField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", Field.Store.NO, Field.Index.ANALYZED));
-    doc.add(newField("number", "0 1 2 3 4 5 6 7 8 9", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", TextField.TYPE_UNSTORED));
+    doc.add(newField("number", "0 1 2 3 4 5 6 7 8 9", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.addDocument(doc);
     writer.close();
@@ -1302,7 +1373,7 @@
     Directory dir = newDirectory();
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document d = new Document();
-    d.add(newField("f", "a a b", Field.Index.ANALYZED));
+    d.add(newField("f", "a a b", TextField.TYPE_UNSTORED));
     writer.addDocument(d);
     IndexReader r = writer.getReader();
     writer.close();
Index: lucene/src/test/org/apache/lucene/index/TestStressIndexing2.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestStressIndexing2.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestStressIndexing2.java	(working copy)
@@ -31,7 +31,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.store.Directory;
@@ -130,11 +131,16 @@
 
   static Term idTerm = new Term("id","");
   IndexingThread[] threads;
-  static Comparator<Fieldable> fieldNameComparator = new Comparator<Fieldable>() {
-        public int compare(Fieldable o1, Fieldable o2) {
-          return o1.name().compareTo(o2.name());
-        }
+  static Comparator<IndexableField> fieldNameComparator = new Comparator<IndexableField>() {
+    public int compare(IndexableField o1, IndexableField o2) {
+      return o1.name().compareTo(o2.name());
+    }
   };
+  static Comparator<IndexableField> fieldNameComparator2 = new Comparator<IndexableField>() {
+    public int compare(IndexableField o1, IndexableField o2) {
+      return o1.name().compareTo(o2.name());
+    }
+  };
 
   // This test avoids using any extra synchronization in the multiple
   // indexing threads to test that IndexWriter does correctly synchronize
@@ -249,13 +255,12 @@
     Iterator<Document> iter = docs.values().iterator();
     while (iter.hasNext()) {
       Document d = iter.next();
-      ArrayList<Fieldable> fields = new ArrayList<Fieldable>();
+      ArrayList<IndexableField> fields = new ArrayList<IndexableField>();
       fields.addAll(d.getFields());
       // put fields in same order each time
-      Collections.sort(fields, fieldNameComparator);
+      Collections.sort(fields, fieldNameComparator2);
       
       Document d1 = new Document();
-      d1.setBoost(d.getBoost());
       for (int i=0; i<fields.size(); i++) {
         d1.add(fields.get(i));
       }
@@ -508,8 +513,8 @@
   }
 
   public static void verifyEquals(Document d1, Document d2) {
-    List<Fieldable> ff1 = d1.getFields();
-    List<Fieldable> ff2 = d2.getFields();
+    List<IndexableField> ff1 = d1.getFields();
+    List<IndexableField> ff2 = d2.getFields();
 
     Collections.sort(ff1, fieldNameComparator);
     Collections.sort(ff2, fieldNameComparator);
@@ -517,10 +522,10 @@
     assertEquals(ff1 + " : " + ff2, ff1.size(), ff2.size());
 
     for (int i=0; i<ff1.size(); i++) {
-      Fieldable f1 = ff1.get(i);
-      Fieldable f2 = ff2.get(i);
-      if (f1.isBinary()) {
-        assert(f2.isBinary());
+      IndexableField f1 = ff1.get(i);
+      IndexableField f2 = ff2.get(i);
+      if (f1.binaryValue() != null) {
+        assert(f2.binaryValue() != null);
       } else {
         String s1 = f1.stringValue();
         String s2 = f2.stringValue();
@@ -666,48 +671,65 @@
     public void indexDoc() throws IOException {
       Document d = new Document();
 
+      FieldType customType1 = new FieldType(TextField.TYPE_STORED);
+      customType1.setTokenized(false);
+      customType1.setOmitNorms(true);
+      
       ArrayList<Field> fields = new ArrayList<Field>();      
       String idString = getIdString();
-      Field idField =  newField("id", idString, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
+      Field idField =  newField("id", idString, customType1);
       fields.add(idField);
 
       int nFields = nextInt(maxFields);
       for (int i=0; i<nFields; i++) {
 
-        Field.TermVector tvVal = Field.TermVector.NO;
+        FieldType customType = new FieldType();
         switch (nextInt(4)) {
         case 0:
-          tvVal = Field.TermVector.NO;
           break;
         case 1:
-          tvVal = Field.TermVector.YES;
+          customType.setStoreTermVectors(true);
           break;
         case 2:
-          tvVal = Field.TermVector.WITH_POSITIONS;
+          customType.setStoreTermVectors(true);
+          customType.setStoreTermVectorPositions(true);
           break;
         case 3:
-          tvVal = Field.TermVector.WITH_POSITIONS_OFFSETS;
+          customType.setStoreTermVectors(true);
+          customType.setStoreTermVectorOffsets(true);
           break;
         }
         
         switch (nextInt(4)) {
           case 0:
-            fields.add(newField("f" + nextInt(100), getString(1), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS, tvVal));
+            customType.setStored(true);
+            customType.setOmitNorms(true);
+            customType.setIndexed(true);
+            fields.add(newField("f" + nextInt(100), getString(1), customType));
             break;
           case 1:
-            fields.add(newField("f" + nextInt(100), getString(0), Field.Store.NO, Field.Index.ANALYZED, tvVal));
+            customType.setIndexed(true);
+            customType.setTokenized(true);
+            fields.add(newField("f" + nextInt(100), getString(0), customType));
             break;
           case 2:
-            fields.add(newField("f" + nextInt(100), getString(0), Field.Store.YES, Field.Index.NO, Field.TermVector.NO));
+            customType.setStored(true);
+            customType.setStoreTermVectors(false);
+            customType.setStoreTermVectorOffsets(false);
+            customType.setStoreTermVectorPositions(false);
+            fields.add(newField("f" + nextInt(100), getString(0), customType));
             break;
           case 3:
-            fields.add(newField("f" + nextInt(100), getString(bigFieldSize), Field.Store.YES, Field.Index.ANALYZED, tvVal));
+            customType.setStored(true);
+            customType.setIndexed(true);
+            customType.setTokenized(true);
+            fields.add(newField("f" + nextInt(100), getString(bigFieldSize), customType));
             break;          
         }
       }
 
       if (sameFieldOrder) {
-        Collections.sort(fields, fieldNameComparator);
+        Collections.sort(fields, fieldNameComparator2);
       } else {
         // random placement of id field also
         Collections.swap(fields,nextInt(fields.size()), 0);
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriter.java	(working copy)
@@ -26,28 +26,23 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
-import org.apache.lucene.analysis.MockFixedLengthPayloadFilter;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.Tokenizer;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
+import org.apache.lucene.document.BinaryField;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.FieldCache;
@@ -60,7 +55,6 @@
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.store.Lock;
 import org.apache.lucene.store.LockFactory;
@@ -69,15 +63,13 @@
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.store.SingleInstanceLockFactory;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.CharsRef;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util.ThreadInterruptedException;
-import org.apache.lucene.util.UnicodeUtil;
 import org.apache.lucene.util._TestUtil;
-import org.apache.lucene.index.codecs.preflexrw.PreFlexRWCodec;
 
 public class TestIndexWriter extends LuceneTestCase {
 
+    private static final FieldType storedTextType = new FieldType(TextField.TYPE_UNSTORED);
     public void testDocCount() throws IOException {
         Directory dir = newDirectory();
 
@@ -138,15 +130,15 @@
     static void addDoc(IndexWriter writer) throws IOException
     {
         Document doc = new Document();
-        doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
         writer.addDocument(doc);
     }
 
     static void addDocWithIndex(IndexWriter writer, int index) throws IOException
     {
         Document doc = new Document();
-        doc.add(newField("content", "aaa " + index, Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("id", "" + index, Field.Store.YES, Field.Index.ANALYZED));
+        doc.add(newField("content", "aaa " + index, storedTextType));
+        doc.add(newField("id", "" + index, storedTextType));
         writer.addDocument(doc);
     }
 
@@ -256,12 +248,12 @@
       IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(10));
       for(int j=0;j<100;j++) {
         Document doc = new Document();
-        doc.add(newField("a"+j, "aaa" + j, Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("b"+j, "aaa" + j, Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("c"+j, "aaa" + j, Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("d"+j, "aaa", Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("e"+j, "aaa", Field.Store.YES, Field.Index.ANALYZED));
-        doc.add(newField("f"+j, "aaa", Field.Store.YES, Field.Index.ANALYZED));
+        doc.add(newField("a"+j, "aaa" + j, storedTextType));
+        doc.add(newField("b"+j, "aaa" + j, storedTextType));
+        doc.add(newField("c"+j, "aaa" + j, storedTextType));
+        doc.add(newField("d"+j, "aaa", storedTextType));
+        doc.add(newField("e"+j, "aaa", storedTextType));
+        doc.add(newField("f"+j, "aaa", storedTextType));
         writer.addDocument(doc);
       }
       writer.close();
@@ -292,7 +284,7 @@
       int lastNumFile = dir.listAll().length;
       for(int j=0;j<9;j++) {
         Document doc = new Document();
-        doc.add(newField("field", "aaa" + j, Field.Store.YES, Field.Index.ANALYZED));
+        doc.add(newField("field", "aaa" + j, storedTextType));
         writer.addDocument(doc);
         int numFile = dir.listAll().length;
         // Verify that with a tiny RAM buffer we see new
@@ -315,7 +307,7 @@
       int lastFlushCount = -1;
       for(int j=1;j<52;j++) {
         Document doc = new Document();
-        doc.add(new Field("field", "aaa" + j, Field.Store.YES, Field.Index.ANALYZED));
+        doc.add(new Field("field", storedTextType, "aaa" + j));
         writer.addDocument(doc);
         _TestUtil.syncConcurrentMerges(writer);
         int flushCount = writer.getFlushCount();
@@ -369,7 +361,7 @@
 
       for(int j=1;j<52;j++) {
         Document doc = new Document();
-        doc.add(new Field("field", "aaa" + j, Field.Store.YES, Field.Index.ANALYZED));
+        doc.add(new Field("field", storedTextType, "aaa" + j));
         writer.addDocument(doc);
       }
       
@@ -430,7 +422,7 @@
         for(int j=0;j<100;j++) {
           Document doc = new Document();
           for(int k=0;k<100;k++) {
-            doc.add(newField("field", Integer.toString(random.nextInt()), Field.Store.YES, Field.Index.ANALYZED));
+            doc.add(newField("field", Integer.toString(random.nextInt()), storedTextType));
           }
           writer.addDocument(doc);
         }
@@ -439,7 +431,7 @@
         // occurs (heavy on byte blocks)
         for(int j=0;j<100;j++) {
           Document doc = new Document();
-          doc.add(newField("field", "aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa", Field.Store.YES, Field.Index.ANALYZED));
+          doc.add(newField("field", "aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa", storedTextType));
           writer.addDocument(doc);
         }
 
@@ -454,7 +446,7 @@
           String longTerm = b.toString();
 
           Document doc = new Document();
-          doc.add(newField("field", longTerm, Field.Store.YES, Field.Index.ANALYZED));
+          doc.add(newField("field", longTerm, storedTextType));
           writer.addDocument(doc);
         }
       }
@@ -472,12 +464,18 @@
       MockDirectoryWrapper dir = newDirectory();
       IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(10));
       // Enable norms for only 1 doc, pre flush
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setOmitNorms(true);
       for(int j=0;j<10;j++) {
         Document doc = new Document();
-        Field f = newField("field", "aaa", Field.Store.YES, Field.Index.ANALYZED);
+        Field f = null;
         if (j != 8) {
-          f.setOmitNorms(true);
+          f = newField("field", "aaa", customType);
         }
+        else {
+          f = newField("field", "aaa", storedTextType);
+        }
         doc.add(f);
         writer.addDocument(doc);
       }
@@ -495,10 +493,13 @@
       // Enable norms for only 1 doc, post flush
       for(int j=0;j<27;j++) {
         Document doc = new Document();
-        Field f = newField("field", "aaa", Field.Store.YES, Field.Index.ANALYZED);
+        Field f = null;
         if (j != 26) {
-          f.setOmitNorms(true);
+          f = newField("field", "aaa", customType);
         }
+        else {
+          f = newField("field", "aaa", storedTextType);
+        }
         doc.add(f);
         writer.addDocument(doc);
       }
@@ -527,7 +528,12 @@
         b.append(" a a a a a a a a");
       }
       Document doc = new Document();
-      doc.add(newField("field", b.toString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectorOffsets(true);
+      doc.add(newField("field", b.toString(), customType));
       writer.addDocument(doc);
       writer.close();
 
@@ -595,7 +601,12 @@
               setMergePolicy(newLogMergePolicy(10))
       );
       Document doc = new Document();
-      doc.add(newField("field", "aaa", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectorOffsets(true);
+      doc.add(newField("field", "aaa", customType));
       for(int i=0;i<19;i++)
         writer.addDocument(doc);
       writer.flush(false, true);
@@ -615,7 +626,12 @@
       IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
       writer.setInfoStream(VERBOSE ? System.out : null);
       Document doc = new Document();
-      doc.add(newField("field", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectorOffsets(true);
+      doc.add(newField("field", "aaa", customType));
       writer.addDocument(doc);
       writer.commit();
       if (VERBOSE) {
@@ -644,7 +660,9 @@
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
 
     Document document = new Document();
-    document.add(newField("tvtest", "", Store.NO, Index.ANALYZED, TermVector.YES));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    document.add(newField("tvtest", "", customType));
     iw.addDocument(document);
     iw.close();
     dir.close();
@@ -661,8 +679,9 @@
       ((LogMergePolicy) conf.getMergePolicy()).setMergeFactor(2);
       IndexWriter iw = new IndexWriter(dir, conf);
       Document document = new Document();
-      document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
-                             Field.TermVector.YES));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
+      document.add(newField("tvtest", "a b c", customType));
       Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
       for(int i=0;i<4;i++)
         iw.addDocument(document);
@@ -688,24 +707,21 @@
       Document doc = new Document();
       String contents = "aa bb cc dd ee ff gg hh ii jj kk";
 
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      FieldType type = null;
       if (i == 7) {
         // Add empty docs here
-        doc.add(newField("content3", "", Field.Store.NO,
-                          Field.Index.ANALYZED));
+        doc.add(newField("content3", "", TextField.TYPE_UNSTORED));
       } else {
-        Field.Store storeVal;
         if (i%2 == 0) {
-          doc.add(newField("content4", contents, Field.Store.YES,
-                            Field.Index.ANALYZED));
-          storeVal = Field.Store.YES;
+          doc.add(newField("content4", contents, customType));
+          type = customType;
         } else
-          storeVal = Field.Store.NO;
-        doc.add(newField("content1", contents, storeVal,
-                          Field.Index.ANALYZED));
-        doc.add(newField("content3", "", Field.Store.YES,
-                          Field.Index.ANALYZED));
-        doc.add(newField("content5", "", storeVal,
-                          Field.Index.ANALYZED));
+          type = TextField.TYPE_UNSTORED; 
+        doc.add(newField("content1", contents, TextField.TYPE_UNSTORED));
+        doc.add(newField("content3", "", customType));
+        doc.add(newField("content5", "", type));
       }
 
       for(int j=0;j<4;j++)
@@ -731,7 +747,11 @@
     Directory directory = newDirectory();
 
     final Document doc = new Document();
-    Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+
+    Field idField = newField("id", "", customType);
     doc.add(idField);
 
     for(int pass=0;pass<2;pass++) {
@@ -835,7 +855,7 @@
     for(int i=0;i<10000;i++)
       b.append(" a");
     b.append(" x");
-    doc.add(newField("field", b.toString(), Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", b.toString(), TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.close();
 
@@ -853,7 +873,7 @@
     Directory dir = newDirectory();
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("", "a b c", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.close();
     dir.close();
@@ -887,8 +907,9 @@
     Directory dir = newDirectory();
     MockIndexWriter w = new MockIndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("field", "a field", Field.Store.YES,
-                      Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("field", "a field", customType));
     w.addDocument(doc);
     w.commit();
     assertTrue(w.beforeWasCalled);
@@ -931,7 +952,7 @@
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(new Field("field", tokens));
+    doc.add(new TextField("field", tokens));
     w.addDocument(doc);
     w.commit();
 
@@ -972,20 +993,20 @@
       b[i] = (byte) (i+77);
 
     Document doc = new Document();
-    Field f = new Field("binary", b, 10, 17);
-    byte[] bx = f.getBinaryValue();
+    Field f = new BinaryField("binary", b, 10, 17);
+    byte[] bx = f.binaryValue().bytes;
     assertTrue(bx != null);
     assertEquals(50, bx.length);
-    assertEquals(10, f.getBinaryOffset());
-    assertEquals(17, f.getBinaryLength());
+    assertEquals(10, f.binaryValue().offset);
+    assertEquals(17, f.binaryValue().length);
     doc.add(f);
     w.addDocument(doc);
     w.close();
 
     IndexReader ir = IndexReader.open(dir, true);
-    doc = ir.document(0);
-    f = doc.getField("binary");
-    b = f.getBinaryValue();
+    Document doc2 = ir.document(0);
+    IndexableField f2 = doc2.getField("binary");
+    b = f2.binaryValue().bytes;
     assertTrue(b != null);
     assertEquals(17, b.length, 17);
     assertEquals(87, b[0]);
@@ -1001,10 +1022,11 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, analyzer));
     Document doc = new Document();
-    Field f = newField("field", "", Field.Store.NO,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS);
-    Field f2 = newField("field", "crunch man", Field.Store.NO,
-        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    Field f = newField("field", "", customType);
+    Field f2 = newField("field", "crunch man", customType);
     doc.add(f);
     doc.add(f2);
     w.addDocument(doc);
@@ -1046,8 +1068,14 @@
     Directory dir = newDirectory();
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
     Document doc = new Document();
-    doc.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES,
-                      Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    
+    doc.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", customType));
     writer.addDocument(doc);
     writer.addDocument(doc);
     writer.addDocument(doc);
@@ -1099,7 +1127,7 @@
             w = new IndexWriter(dir, conf);
 
             Document doc = new Document();
-            doc.add(newField("field", "some text contents", Field.Store.YES, Field.Index.ANALYZED));
+            doc.add(newField("field", "some text contents", storedTextType));
             for(int i=0;i<100;i++) {
               w.addDocument(doc);
               if (i%10 == 0) {
@@ -1213,9 +1241,18 @@
       b[i] = (byte) (i+77);
 
     Document doc = new Document();
-    Field f = new Field("binary", b, 10, 17);
+
+    FieldType customType = new FieldType(BinaryField.TYPE_STORED);
+    customType.setTokenized(true);
+    customType.setIndexed(true);
+    
+    Field f = new Field("binary", customType, b, 10, 17);
     f.setTokenStream(new MockTokenizer(new StringReader("doc1field1"), MockTokenizer.WHITESPACE, false));
-    Field f2 = newField("string", "value", Field.Store.YES,Field.Index.ANALYZED);
+
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    
+    Field f2 = newField("string", "value", customType2);
     f2.setTokenStream(new MockTokenizer(new StringReader("doc1field2"), MockTokenizer.WHITESPACE, false));
     doc.add(f);
     doc.add(f2);
@@ -1238,16 +1275,16 @@
     w.close();
 
     IndexReader ir = IndexReader.open(dir, true);
-    doc = ir.document(0);
-    f = doc.getField("binary");
-    b = f.getBinaryValue();
+    Document doc2 = ir.document(0);
+    IndexableField f3 = doc2.getField("binary");
+    b = f3.binaryValue().bytes;
     assertTrue(b != null);
     assertEquals(17, b.length, 17);
     assertEquals(87, b[0]);
 
-    assertTrue(ir.document(0).getFieldable("binary").isBinary());
-    assertTrue(ir.document(1).getFieldable("binary").isBinary());
-    assertTrue(ir.document(2).getFieldable("binary").isBinary());
+    assertTrue(ir.document(0).getField("binary").binaryValue()!=null);
+    assertTrue(ir.document(1).getField("binary").binaryValue()!=null);
+    assertTrue(ir.document(2).getField("binary").binaryValue()!=null);
 
     assertEquals("value", ir.document(0).get("string"));
     assertEquals("value", ir.document(1).get("string"));
@@ -1272,13 +1309,16 @@
     Directory d = newDirectory();
     IndexWriter w = new IndexWriter(d, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("zzz", "a b c", Field.Store.YES, Field.Index.NO));
-    doc.add(newField("aaa", "a b c", Field.Store.YES, Field.Index.NO));
-    doc.add(newField("zzz", "1 2 3", Field.Store.YES, Field.Index.NO));
+
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+    doc.add(newField("zzz", "a b c", customType));
+    doc.add(newField("aaa", "a b c", customType));
+    doc.add(newField("zzz", "1 2 3", customType));
     w.addDocument(doc);
     IndexReader r = w.getReader();
-    doc = r.document(0);
-    Iterator<Fieldable> it = doc.getFields().iterator();
+    Document doc2 = r.document(0);
+    Iterator<IndexableField> it = doc2.getFields().iterator();
     assertTrue(it.hasNext());
     Field f = (Field) it.next();
     assertEquals(f.name(), "zzz");
@@ -1322,7 +1362,7 @@
       s.append(' ').append(i);
     }
     Document d = new Document();
-    Field f = newField("field", s.toString(), Field.Store.NO, Field.Index.ANALYZED);
+    Field f = newField("field", s.toString(), TextField.TYPE_UNSTORED);
     d.add(f);
     w.addDocument(d);
 
@@ -1354,7 +1394,7 @@
               setMergePolicy(mergePolicy)
       );
       Document doc = new Document();
-      doc.add(newField("field", "go", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("field", "go", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
       IndexReader r;
       if (iter == 0) {
@@ -1422,7 +1462,14 @@
 
     // First commit
     Document doc = new Document();
-    doc.add(newField("c", "val", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    
+    doc.add(newField("c", "val", customType));
     writer.addDocument(doc);
     writer.commit();
     assertEquals(1, IndexReader.listCommits(dir).size());
@@ -1432,7 +1479,7 @@
 
     // Second commit - now KeepOnlyLastCommit cannot delete the prev commit.
     doc = new Document();
-    doc.add(newField("c", "val", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    doc.add(newField("c", "val", customType));
     writer.addDocument(doc);
     writer.commit();
     assertEquals(2, IndexReader.listCommits(dir).size());
@@ -1479,14 +1526,19 @@
     }
 
     Document doc = new Document();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
     // create as many files as possible
-    doc.add(newField("c", "val", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    doc.add(newField("c", "val", customType));
     writer.addDocument(doc);
     // Adding just one document does not call flush yet.
     assertEquals("only the stored and term vector files should exist in the directory", 5 + extraFileCount, dir.listAll().length);
 
     doc = new Document();
-    doc.add(newField("c", "val", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    doc.add(newField("c", "val", customType));
     writer.addDocument(doc);
 
     // The second document should cause a flush.
@@ -1509,7 +1561,12 @@
         TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
 
     Document doc = new Document();
-    doc.add(newField("c", "val", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("c", "val", customType));
     w.addDocument(doc);
     w.addDocument(doc);
     IndexWriter w2 = new IndexWriter(dir, newIndexWriterConfig(
@@ -1536,7 +1593,10 @@
 
     final List<Integer> fieldIDs = new ArrayList<Integer>();
 
-    Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    Field idField = newField("id", "", customType);
 
     for(int i=0;i<fieldCount;i++) {
       fieldIDs.add(i);
@@ -1548,6 +1608,8 @@
       System.out.println("TEST: build index docCount=" + docCount);
     }
 
+    FieldType customType2 = new FieldType();
+    customType2.setStored(true);
     for(int i=0;i<docCount;i++) {
       Document doc = new Document();
       doc.add(idField);
@@ -1562,7 +1624,7 @@
         final String s;
         if (rand.nextInt(4) != 3) {
           s = _TestUtil.randomUnicodeString(rand, 1000);
-          doc.add(newField("f"+field, s, Field.Store.YES, Field.Index.NO));
+          doc.add(newField("f"+field, s, customType2));
         } else {
           s = null;
         }
@@ -1628,12 +1690,23 @@
     String BIG="alskjhlaksjghlaksjfhalksvjepgjioefgjnsdfjgefgjhelkgjhqewlrkhgwlekgrhwelkgjhwelkgrhwlkejg";
     BIG=BIG+BIG+BIG+BIG;
 
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setOmitNorms(true);
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    customType2.setTokenized(false);
+    FieldType customType3 = new FieldType(TextField.TYPE_UNSTORED);
+    customType3.setStored(true);
+    customType3.setTokenized(false);
+    customType3.setOmitNorms(true);
+    
     for (int i=0; i<2; i++) {
       Document doc = new Document();
-      doc.add(new Field("id", Integer.toString(i)+BIG, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(new Field("str", Integer.toString(i)+BIG, Field.Store.YES, Field.Index.NOT_ANALYZED));
-      doc.add(new Field("str2", Integer.toString(i)+BIG, Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(new Field("str3", Integer.toString(i)+BIG, Field.Store.YES, Field.Index.ANALYZED_NO_NORMS));
+      doc.add(new Field("id", customType3, Integer.toString(i)+BIG));
+      doc.add(new Field("str", customType2, Integer.toString(i)+BIG));
+      doc.add(new Field("str2", storedTextType, Integer.toString(i)+BIG));
+      doc.add(new Field("str3", customType, Integer.toString(i)+BIG));
       indexWriter.addDocument(doc);
     }
 
@@ -1707,12 +1780,12 @@
 
     // This contents produces a too-long term:
     String contents = "abc xyz x" + bigTerm + " another term";
-    doc.add(new Field("content", contents, Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("content", contents));
     w.addDocument(doc);
 
     // Make sure we can add another normal document
     doc = new Document();
-    doc.add(new Field("content", "abc bbb ccc", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(new TextField("content", "abc bbb ccc"));
     w.addDocument(doc);
 
     IndexReader reader = w.getReader();
@@ -1742,7 +1815,9 @@
     // Make sure we can add a document with exactly the
     // maximum length term, and search on that term:
     doc = new Document();
-    Field contentField = new Field("content", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setTokenized(false);
+    Field contentField = new Field("content", customType, "");
     doc.add(contentField);
 
     w = new RandomIndexWriter(random, dir);
@@ -1779,7 +1854,7 @@
     iwc.setReaderTermsIndexDivisor(1);
     IndexWriter writer = new IndexWriter(dir, iwc);
     Document doc = new Document();
-    doc.add(newField("", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("", "a b c", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.close();
     dir.close();
Index: lucene/src/test/org/apache/lucene/index/TestFieldsReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestFieldsReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestFieldsReader.java	(working copy)
@@ -25,15 +25,9 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.FieldSelectorResult;
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.LoadFirstFieldSelector;
-import org.apache.lucene.document.SetBasedFieldSelector;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.FieldCache;
-import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.BufferedIndexInput;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
@@ -48,7 +42,6 @@
   private static Directory dir;
   private static Document testDoc = new Document();
   private static FieldInfos fieldInfos = null;
-  private final static String TEST_SEGMENT_NAME = "_0";
 
   @BeforeClass
   public static void beforeClass() throws Exception {
@@ -61,14 +54,9 @@
     IndexWriter writer = new IndexWriter(dir, conf);
     writer.addDocument(testDoc);
     writer.close();
-  }
-  
-  @Override
-  public void setUp() throws Exception {
-    super.setUp();
     FaultyIndexInput.doFail = false;
   }
-
+  
   @AfterClass
   public static void afterClass() throws Exception {
     dir.close();
@@ -76,326 +64,49 @@
     fieldInfos = null;
     testDoc = null;
   }
+
   public void test() throws IOException {
     assertTrue(dir != null);
     assertTrue(fieldInfos != null);
-    FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
-    assertTrue(reader.size() == 1);
-    Document doc = reader.doc(0, null);
+    IndexReader reader = IndexReader.open(dir);
+    Document doc = reader.document(0);
     assertTrue(doc != null);
     assertTrue(doc.getField(DocHelper.TEXT_FIELD_1_KEY) != null);
 
-    Fieldable field = doc.getField(DocHelper.TEXT_FIELD_2_KEY);
+    Field field = (Field) doc.getField(DocHelper.TEXT_FIELD_2_KEY);
     assertTrue(field != null);
-    assertTrue(field.isTermVectorStored() == true);
+    assertTrue(field.storeTermVectors() == true);
 
-    assertTrue(field.isStoreOffsetWithTermVector() == true);
-    assertTrue(field.isStorePositionWithTermVector() == true);
-    assertTrue(field.getOmitNorms() == false);
-    assertTrue(field.getIndexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    assertTrue(field.storeTermVectorOffsets() == true);
+    assertTrue(field.storeTermVectorPositions() == true);
+    assertTrue(field.omitNorms() == false);
+    assertTrue(field.indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
 
-    field = doc.getField(DocHelper.TEXT_FIELD_3_KEY);
+    field = (Field) doc.getField(DocHelper.TEXT_FIELD_3_KEY);
     assertTrue(field != null);
-    assertTrue(field.isTermVectorStored() == false);
-    assertTrue(field.isStoreOffsetWithTermVector() == false);
-    assertTrue(field.isStorePositionWithTermVector() == false);
-    assertTrue(field.getOmitNorms() == true);
-    assertTrue(field.getIndexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    assertTrue(field.storeTermVectors() == false);
+    assertTrue(field.storeTermVectorOffsets() == false);
+    assertTrue(field.storeTermVectorPositions() == false);
+    assertTrue(field.omitNorms() == true);
+    assertTrue(field.indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
 
-    field = doc.getField(DocHelper.NO_TF_KEY);
+    field = (Field) doc.getField(DocHelper.NO_TF_KEY);
     assertTrue(field != null);
-    assertTrue(field.isTermVectorStored() == false);
-    assertTrue(field.isStoreOffsetWithTermVector() == false);
-    assertTrue(field.isStorePositionWithTermVector() == false);
-    assertTrue(field.getOmitNorms() == false);
-    assertTrue(field.getIndexOptions() == IndexOptions.DOCS_ONLY);
-    reader.close();
-  }
+    assertTrue(field.storeTermVectors() == false);
+    assertTrue(field.storeTermVectorOffsets() == false);
+    assertTrue(field.storeTermVectorPositions() == false);
+    assertTrue(field.omitNorms() == false);
+    assertTrue(field.indexOptions() == IndexOptions.DOCS_ONLY);
 
-
-  public void testLazyFields() throws Exception {
-    assertTrue(dir != null);
-    assertTrue(fieldInfos != null);
-    FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
-    assertTrue(reader.size() == 1);
-    Set<String> loadFieldNames = new HashSet<String>();
-    loadFieldNames.add(DocHelper.TEXT_FIELD_1_KEY);
-    loadFieldNames.add(DocHelper.TEXT_FIELD_UTF1_KEY);
-    Set<String> lazyFieldNames = new HashSet<String>();
-    //new String[]{DocHelper.LARGE_LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_BINARY_KEY};
-    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
-    lazyFieldNames.add(DocHelper.LAZY_FIELD_KEY);
-    lazyFieldNames.add(DocHelper.LAZY_FIELD_BINARY_KEY);
-    lazyFieldNames.add(DocHelper.TEXT_FIELD_UTF2_KEY);
-    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames);
-    Document doc = reader.doc(0, fieldSelector);
-    assertTrue("doc is null and it shouldn't be", doc != null);
-    Fieldable field = doc.getFieldable(DocHelper.LAZY_FIELD_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("field is not lazy and it should be", field.isLazy());
-    String value = field.stringValue();
-    assertTrue("value is null and it shouldn't be", value != null);
-    assertTrue(value + " is not equal to " + DocHelper.LAZY_FIELD_TEXT, value.equals(DocHelper.LAZY_FIELD_TEXT) == true);
-    assertTrue("calling stringValue() twice should give same reference", field.stringValue() == field.stringValue());
-
-    field = doc.getFieldable(DocHelper.TEXT_FIELD_1_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("Field is lazy and it should not be", field.isLazy() == false);
-    field = doc.getFieldable(DocHelper.TEXT_FIELD_UTF1_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("Field is lazy and it should not be", field.isLazy() == false);
-    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF1_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF1_TEXT) == true);
-
-    field = doc.getFieldable(DocHelper.TEXT_FIELD_UTF2_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("Field is lazy and it should not be", field.isLazy() == true);
-    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF2_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF2_TEXT) == true);
-
-    field = doc.getFieldable(DocHelper.LAZY_FIELD_BINARY_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("stringValue isn't null for lazy binary field", field.stringValue() == null);
-
-    byte [] bytes = field.getBinaryValue();
-    assertTrue("bytes is null and it shouldn't be", bytes != null);
-    assertTrue("", DocHelper.LAZY_FIELD_BINARY_BYTES.length == bytes.length);
-    assertTrue("calling binaryValue() twice should give same reference", field.getBinaryValue() == field.getBinaryValue());
-    for (int i = 0; i < bytes.length; i++) {
-      assertTrue("byte[" + i + "] is mismatched", bytes[i] == DocHelper.LAZY_FIELD_BINARY_BYTES[i]);
-
-    }
+    DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(DocHelper.TEXT_FIELD_3_KEY);
+    reader.document(0, visitor);
+    final List<IndexableField> fields = visitor.getDocument().getFields();
+    assertEquals(1, fields.size());
+    assertEquals(DocHelper.TEXT_FIELD_3_KEY, fields.get(0).name());
     reader.close();
   }
 
-  public void testLatentFields() throws Exception {
-    assertTrue(dir != null);
-    assertTrue(fieldInfos != null);
-    FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
-    assertTrue(reader.size() == 1);
-    Set<String> loadFieldNames = new HashSet<String>();
-    loadFieldNames.add(DocHelper.TEXT_FIELD_1_KEY);
-    loadFieldNames.add(DocHelper.TEXT_FIELD_UTF1_KEY);
-    Set<String> lazyFieldNames = new HashSet<String>();
-    //new String[]{DocHelper.LARGE_LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_BINARY_KEY};
-    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
-    lazyFieldNames.add(DocHelper.LAZY_FIELD_KEY);
-    lazyFieldNames.add(DocHelper.LAZY_FIELD_BINARY_KEY);
-    lazyFieldNames.add(DocHelper.TEXT_FIELD_UTF2_KEY);
 
-    // Use LATENT instead of LAZY
-    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames) {
-        @Override
-        public FieldSelectorResult accept(String fieldName) {
-          final FieldSelectorResult result = super.accept(fieldName);
-          if (result == FieldSelectorResult.LAZY_LOAD) {
-            return FieldSelectorResult.LATENT;
-          } else {
-            return result;
-          }
-        }
-      };
-
-    Document doc = reader.doc(0, fieldSelector);
-    assertTrue("doc is null and it shouldn't be", doc != null);
-    Fieldable field = doc.getFieldable(DocHelper.LAZY_FIELD_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("field is not lazy and it should be", field.isLazy());
-    String value = field.stringValue();
-    assertTrue("value is null and it shouldn't be", value != null);
-    assertTrue(value + " is not equal to " + DocHelper.LAZY_FIELD_TEXT, value.equals(DocHelper.LAZY_FIELD_TEXT) == true);
-    assertTrue("calling stringValue() twice should give different references", field.stringValue() != field.stringValue());
-
-    field = doc.getFieldable(DocHelper.TEXT_FIELD_1_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("Field is lazy and it should not be", field.isLazy() == false);
-    assertTrue("calling stringValue() twice should give same reference", field.stringValue() == field.stringValue());
-
-    field = doc.getFieldable(DocHelper.TEXT_FIELD_UTF1_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("Field is lazy and it should not be", field.isLazy() == false);
-    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF1_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF1_TEXT) == true);
-    assertTrue("calling stringValue() twice should give same reference", field.stringValue() == field.stringValue());
-
-    field = doc.getFieldable(DocHelper.TEXT_FIELD_UTF2_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("Field is lazy and it should not be", field.isLazy() == true);
-    assertTrue(field.stringValue() + " is not equal to " + DocHelper.FIELD_UTF2_TEXT, field.stringValue().equals(DocHelper.FIELD_UTF2_TEXT) == true);
-    assertTrue("calling stringValue() twice should give different references", field.stringValue() != field.stringValue());
-
-    field = doc.getFieldable(DocHelper.LAZY_FIELD_BINARY_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("stringValue isn't null for lazy binary field", field.stringValue() == null);
-    assertTrue("calling binaryValue() twice should give different references", field.getBinaryValue() != field.getBinaryValue());
-
-    byte [] bytes = field.getBinaryValue();
-    assertTrue("bytes is null and it shouldn't be", bytes != null);
-    assertTrue("", DocHelper.LAZY_FIELD_BINARY_BYTES.length == bytes.length);
-    for (int i = 0; i < bytes.length; i++) {
-      assertTrue("byte[" + i + "] is mismatched", bytes[i] == DocHelper.LAZY_FIELD_BINARY_BYTES[i]);
-
-    }
-    reader.close();
-  }
-
-
-
-
-  public void testLazyFieldsAfterClose() throws Exception {
-    assertTrue(dir != null);
-    assertTrue(fieldInfos != null);
-    FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
-    assertTrue(reader.size() == 1);
-    Set<String> loadFieldNames = new HashSet<String>();
-    loadFieldNames.add(DocHelper.TEXT_FIELD_1_KEY);
-    loadFieldNames.add(DocHelper.TEXT_FIELD_UTF1_KEY);
-    Set<String> lazyFieldNames = new HashSet<String>();
-    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
-    lazyFieldNames.add(DocHelper.LAZY_FIELD_KEY);
-    lazyFieldNames.add(DocHelper.LAZY_FIELD_BINARY_KEY);
-    lazyFieldNames.add(DocHelper.TEXT_FIELD_UTF2_KEY);
-    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames);
-    Document doc = reader.doc(0, fieldSelector);
-    assertTrue("doc is null and it shouldn't be", doc != null);
-    Fieldable field = doc.getFieldable(DocHelper.LAZY_FIELD_KEY);
-    assertTrue("field is null and it shouldn't be", field != null);
-    assertTrue("field is not lazy and it should be", field.isLazy());
-    reader.close();
-    try {
-      field.stringValue();
-      fail("did not hit AlreadyClosedException as expected");
-    } catch (AlreadyClosedException e) {
-      // expected
-    }
-  }
-
-  public void testLoadFirst() throws Exception {
-    assertTrue(dir != null);
-    assertTrue(fieldInfos != null);
-    FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
-    assertTrue(reader.size() == 1);
-    LoadFirstFieldSelector fieldSelector = new LoadFirstFieldSelector();
-    Document doc = reader.doc(0, fieldSelector);
-    assertTrue("doc is null and it shouldn't be", doc != null);
-    int count = 0;
-    List<Fieldable> l = doc.getFields();
-    for (final Fieldable fieldable : l ) {
-      Field field = (Field) fieldable;
-
-      assertTrue("field is null and it shouldn't be", field != null);
-      String sv = field.stringValue();
-      assertTrue("sv is null and it shouldn't be", sv != null);
-      count++;
-    }
-    assertTrue(count + " does not equal: " + 1, count == 1);
-    reader.close();
-  }
-
-  /**
-   * Not really a test per se, but we should have some way of assessing whether this is worthwhile.
-   * <p/>
-   * Must test using a File based directory
-   *
-   * @throws Exception
-   */
-  public void testLazyPerformance() throws Exception {
-    String userName = System.getProperty("user.name");
-    File file = _TestUtil.getTempDir("lazyDir" + userName);
-    Directory tmpDir = newFSDirectory(file);
-    assertTrue(tmpDir != null);
-
-    IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE).setMergePolicy(newLogMergePolicy());
-    ((LogMergePolicy) conf.getMergePolicy()).setUseCompoundFile(false);
-    IndexWriter writer = new IndexWriter(tmpDir, conf);
-    writer.addDocument(testDoc);
-    writer.close();
-
-    assertTrue(fieldInfos != null);
-    FieldsReader reader;
-    long lazyTime = 0;
-    long regularTime = 0;
-    int length = 10;
-    Set<String> lazyFieldNames = new HashSet<String>();
-    lazyFieldNames.add(DocHelper.LARGE_LAZY_FIELD_KEY);
-    SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(Collections. <String> emptySet(), lazyFieldNames);
-
-    for (int i = 0; i < length; i++) {
-      reader = new FieldsReader(tmpDir, TEST_SEGMENT_NAME, fieldInfos);
-      assertTrue(reader.size() == 1);
-
-      Document doc;
-      doc = reader.doc(0, null);//Load all of them
-      assertTrue("doc is null and it shouldn't be", doc != null);
-      Fieldable field = doc.getFieldable(DocHelper.LARGE_LAZY_FIELD_KEY);
-      assertTrue("field is null and it shouldn't be", field != null);
-      assertTrue("field is lazy", field.isLazy() == false);
-      String value;
-      long start;
-      long finish;
-      start = System.currentTimeMillis();
-      //On my machine this was always 0ms.
-      value = field.stringValue();
-      finish = System.currentTimeMillis();
-      assertTrue("value is null and it shouldn't be", value != null);
-      regularTime += (finish - start);
-      reader.close();
-      reader = null;
-      doc = null;
-      //Hmmm, are we still in cache???
-      System.gc();
-      reader = new FieldsReader(tmpDir, TEST_SEGMENT_NAME, fieldInfos);
-      doc = reader.doc(0, fieldSelector);
-      field = doc.getFieldable(DocHelper.LARGE_LAZY_FIELD_KEY);
-      assertTrue("field is not lazy", field.isLazy() == true);
-      start = System.currentTimeMillis();
-      //On my machine this took around 50 - 70ms
-      value = field.stringValue();
-      finish = System.currentTimeMillis();
-      assertTrue("value is null and it shouldn't be", value != null);
-      lazyTime += (finish - start);
-      reader.close();
-
-    }
-    tmpDir.close();
-    if (VERBOSE) {
-      System.out.println("Average Non-lazy time (should be very close to zero): " + regularTime / length + " ms for " + length + " reads");
-      System.out.println("Average Lazy Time (should be greater than zero): " + lazyTime / length + " ms for " + length + " reads");
-    }
-  }
-  
-  public void testLoadSize() throws IOException {
-    FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
-    Document doc;
-    
-    doc = reader.doc(0, new FieldSelector(){
-      public FieldSelectorResult accept(String fieldName) {
-        if (fieldName.equals(DocHelper.TEXT_FIELD_1_KEY) ||
-            fieldName.equals(DocHelper.LAZY_FIELD_BINARY_KEY))
-          return FieldSelectorResult.SIZE;
-        else if (fieldName.equals(DocHelper.TEXT_FIELD_3_KEY))
-          return FieldSelectorResult.LOAD;
-        else
-          return FieldSelectorResult.NO_LOAD;
-      }
-    });
-    Fieldable f1 = doc.getFieldable(DocHelper.TEXT_FIELD_1_KEY);
-    Fieldable f3 = doc.getFieldable(DocHelper.TEXT_FIELD_3_KEY);
-    Fieldable fb = doc.getFieldable(DocHelper.LAZY_FIELD_BINARY_KEY);
-    assertTrue(f1.isBinary());
-    assertTrue(!f3.isBinary());
-    assertTrue(fb.isBinary());
-    assertSizeEquals(2*DocHelper.FIELD_1_TEXT.length(), f1.getBinaryValue());
-    assertEquals(DocHelper.FIELD_3_TEXT, f3.stringValue());
-    assertSizeEquals(DocHelper.LAZY_FIELD_BINARY_BYTES.length, fb.getBinaryValue());
-    
-    reader.close();
-  }
-  
-  private void assertSizeEquals(int size, byte[] sizebytes) {
-    assertEquals((byte) (size>>>24), sizebytes[0]);
-    assertEquals((byte) (size>>>16), sizebytes[1]);
-    assertEquals((byte) (size>>> 8), sizebytes[2]);
-    assertEquals((byte)  size      , sizebytes[3]);
-  }
-
   public static class FaultyFSDirectory extends Directory {
 
     Directory fsDir;
@@ -528,7 +239,7 @@
     final NumericField.DataType[] typeAnswers = new NumericField.DataType[numDocs];
     for(int id=0;id<numDocs;id++) {
       Document doc = new Document();
-      NumericField nf = new NumericField("nf", Field.Store.YES, false);
+      NumericField nf = new NumericField("nf", NumericField.TYPE_STORED);
       doc.add(nf);
       final Number answer;
       final NumericField.DataType typeAnswer;
@@ -561,7 +272,7 @@
       }
       answers[id] = answer;
       typeAnswers[id] = typeAnswer;
-      doc.add(new NumericField("id", Integer.MAX_VALUE, Field.Store.NO, true).setIntValue(id));
+      doc.add(new NumericField("id", Integer.MAX_VALUE).setIntValue(id));
       w.addDocument(doc);
     }
     final IndexReader r = w.getReader();
@@ -573,11 +284,11 @@
       final int[] ids = FieldCache.DEFAULT.getInts(sub, "id");
       for(int docID=0;docID<sub.numDocs();docID++) {
         final Document doc = sub.document(docID);
-        final Fieldable f = doc.getFieldable("nf");
+        final Field f = (Field) doc.getField("nf");
         assertTrue("got f=" + f, f instanceof NumericField);
         final NumericField nf = (NumericField) f;
-        assertEquals(answers[ids[docID]], nf.getNumericValue());
-        assertSame(typeAnswers[ids[docID]], nf.getDataType());
+        assertEquals(answers[ids[docID]], nf.numericValue());
+        assertSame(typeAnswers[ids[docID]], nf.numericDataType());
       }
     }
     r.close();
Index: lucene/src/test/org/apache/lucene/index/TestSnapshotDeletionPolicy.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSnapshotDeletionPolicy.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSnapshotDeletionPolicy.java	(working copy)
@@ -23,7 +23,8 @@
 import java.io.IOException;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -115,7 +116,12 @@
         @Override
         public void run() {
           Document doc = new Document();
-          doc.add(newField("content", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+          FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+          customType.setStored(true);
+          customType.setStoreTermVectors(true);
+          customType.setStoreTermVectorPositions(true);
+          customType.setStoreTermVectorOffsets(true);
+          doc.add(newField("content", "aaa", customType));
           do {
             for(int i=0;i<27;i++) {
               try {
@@ -156,7 +162,12 @@
     // final segment, so deletion policy has a chance to
     // delete again:
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("content", "aaa", customType));
     writer.addDocument(doc);
 
     // Make sure we don't have any leftover files in the
Index: lucene/src/test/org/apache/lucene/index/TestPayloadProcessorProvider.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestPayloadProcessorProvider.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestPayloadProcessorProvider.java	(working copy)
@@ -28,9 +28,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.PayloadProcessorProvider.DirPayloadProcessor;
 import org.apache.lucene.index.PayloadProcessorProvider.PayloadProcessor;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -135,12 +134,14 @@
     );
     TokenStream payloadTS1 = new PayloadTokenStream("p1");
     TokenStream payloadTS2 = new PayloadTokenStream("p2");
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
     for (int i = 0; i < NUM_DOCS; i++) {
       Document doc = new Document();
-      doc.add(newField("id", "doc" + i, Store.NO, Index.NOT_ANALYZED_NO_NORMS));
-      doc.add(newField("content", "doc content " + i, Store.NO, Index.ANALYZED));
-      doc.add(new Field("p", payloadTS1));
-      doc.add(new Field("p", payloadTS2));
+      doc.add(newField("id", "doc" + i, customType));
+      doc.add(newField("content", "doc content " + i, TextField.TYPE_UNSTORED));
+      doc.add(new TextField("p", payloadTS1));
+      doc.add(new TextField("p", payloadTS2));
       writer.addDocument(doc);
       if (multipleCommits && (i % 4 == 0)) {
         writer.commit();
Index: lucene/src/test/org/apache/lucene/index/TestDoc.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDoc.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestDoc.java	(working copy)
@@ -32,6 +32,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.store.Directory;
@@ -185,7 +186,7 @@
    {
       File file = new File(workDir, fileName);
       Document doc = new Document();
-      doc.add(new Field("contents", new FileReader(file)));
+      doc.add(new TextField("contents", new FileReader(file)));
       writer.addDocument(doc);
       writer.commit();
       return writer.newestSegment();
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterCommit.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterCommit.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterCommit.java	(working copy)
@@ -30,6 +30,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.search.IndexSearcher;
@@ -342,7 +343,7 @@
             try {
               final Document doc = new Document();
               IndexReader r = IndexReader.open(dir);
-              Field f = newField("f", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+              Field f = newField("f", "", StringField.TYPE_UNSTORED);
               doc.add(f);
               int count = 0;
               do {
Index: lucene/src/test/org/apache/lucene/index/TestIsCurrent.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIsCurrent.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIsCurrent.java	(working copy)
@@ -18,8 +18,8 @@
  */
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.*;
 import org.apache.lucene.store.*;
 
@@ -43,7 +43,9 @@
 
     // write document
     Document doc = new Document();
-    doc.add(newField("UUID", "1", Store.YES, Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("UUID", "1", customType));
     writer.addDocument(doc);
     writer.commit();
   }
Index: lucene/src/test/org/apache/lucene/index/TestSegmentTermEnum.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSegmentTermEnum.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSegmentTermEnum.java	(working copy)
@@ -24,7 +24,7 @@
 import org.apache.lucene.util._TestUtil;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 
@@ -134,7 +134,7 @@
   private void addDoc(IndexWriter writer, String value) throws IOException
   {
     Document doc = new Document();
-    doc.add(newField("content", value, Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("content", value, TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
   }
 }
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterOptimize.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterOptimize.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterOptimize.java	(working copy)
@@ -21,10 +21,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.MockDirectoryWrapper;
@@ -37,7 +34,7 @@
     MockDirectoryWrapper dir = newDirectory();
 
     final Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField("content", "aaa", StringField.TYPE_UNSTORED));
     final int incrMin = TEST_NIGHTLY ? 15 : 40;
     for(int numDocs=10;numDocs<500;numDocs += _TestUtil.nextInt(random, incrMin, 5*incrMin)) {
       LogDocMergePolicy ldmp = new LogDocMergePolicy();
@@ -78,7 +75,7 @@
     MockDirectoryWrapper dir = newDirectory();
 
     final Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(newField("content", "aaa", StringField.TYPE_UNSTORED));
 
     LogDocMergePolicy ldmp = new LogDocMergePolicy();
     ldmp.setMinMergeDocs(1);
@@ -183,7 +180,7 @@
               setMergePolicy(newLogMergePolicy(51))
       );
       Document doc = new Document();
-      doc.add(newField("field", "aaa", Store.NO, Index.NOT_ANALYZED));
+      doc.add(newField("field", "aaa", StringField.TYPE_UNSTORED));
       for(int i=0;i<100;i++)
         writer.addDocument(doc);
       writer.optimize(false);
Index: lucene/src/test/org/apache/lucene/index/Test2BPostings.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/Test2BPostings.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/Test2BPostings.java	(working copy)
@@ -24,6 +24,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.store.MockDirectoryWrapper;
@@ -62,9 +64,10 @@
     }
 
     Document doc = new Document();
-    Field field = new Field("field", new MyTokenStream());
-    field.setIndexOptions(IndexOptions.DOCS_ONLY);
-    field.setOmitNorms(true);
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setOmitNorms(true);
+    ft.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field field = new Field("field", ft, new MyTokenStream());
     doc.add(field);
     
     final int numDocs = (Integer.MAX_VALUE / 26) + 1;
Index: lucene/src/test/org/apache/lucene/index/TestFlex.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestFlex.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestFlex.java	(working copy)
@@ -39,10 +39,10 @@
     for(int iter=0;iter<2;iter++) {
       if (iter == 0) {
         Document doc = new Document();
-        doc.add(newField("field1", "this is field1", Field.Store.NO, Field.Index.ANALYZED));
-        doc.add(newField("field2", "this is field2", Field.Store.NO, Field.Index.ANALYZED));
-        doc.add(newField("field3", "aaa", Field.Store.NO, Field.Index.ANALYZED));
-        doc.add(newField("field4", "bbb", Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(newField("field1", "this is field1", TextField.TYPE_UNSTORED));
+        doc.add(newField("field2", "this is field2", TextField.TYPE_UNSTORED));
+        doc.add(newField("field3", "aaa", TextField.TYPE_UNSTORED));
+        doc.add(newField("field4", "bbb", TextField.TYPE_UNSTORED));
         for(int i=0;i<DOC_COUNT;i++) {
           w.addDocument(doc);
         }
@@ -66,7 +66,7 @@
     IndexWriter w = new IndexWriter(d, newIndexWriterConfig(TEST_VERSION_CURRENT,
                                                              new MockAnalyzer(random)).setCodecProvider(_TestUtil.alwaysCodec("Standard")));
     Document doc = new Document();
-    doc.add(newField("f", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("f", "a b c", TextField.TYPE_UNSTORED));
     w.addDocument(doc);
     IndexReader r = w.getReader();
     TermsEnum terms = r.getSequentialSubReaders()[0].fields().terms("f").iterator();
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterOnDiskFull.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.search.IndexSearcher;
@@ -475,7 +477,11 @@
     _TestUtil.keepFullyDeletedSegments(w);
 
     Document doc = new Document();
-    doc.add(newField("f", "doctor who", Field.Store.YES, Field.Index.ANALYZED));
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(false);
+    
+    doc.add(newField("f", "doctor who", customType));
     w.addDocument(doc);
     w.commit();
 
@@ -511,7 +517,11 @@
         .setMaxBufferedDocs(2).setMergeScheduler(new ConcurrentMergeScheduler()));
     dir.setMaxSizeInBytes(Math.max(1, dir.getRecomputedActualSizeInBytes()));
     final Document doc = new Document();
-    doc.add(newField("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(false);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", customType));
     try {
       writer.addDocument(doc);
       fail("did not hit disk full");
@@ -541,15 +551,17 @@
   private void addDoc(IndexWriter writer) throws IOException
   {
       Document doc = new Document();
-      doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
   }
   
   private void addDocWithIndex(IndexWriter writer, int index) throws IOException
   {
       Document doc = new Document();
-      doc.add(newField("content", "aaa " + index, Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(newField("id", "" + index, Field.Store.YES, Field.Index.ANALYZED));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(false);
+      doc.add(newField("content", "aaa " + index, customType));
+      doc.add(newField("id", "" + index, customType));
       writer.addDocument(doc);
   }
 }
Index: lucene/src/test/org/apache/lucene/index/TestGlobalFieldNumbers.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestGlobalFieldNumbers.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestGlobalFieldNumbers.java	(working copy)
@@ -27,11 +27,11 @@
 import java.util.TreeMap;
 
 import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.BinaryField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInfos.FieldNumberBiMap;
 import org.apache.lucene.index.codecs.DefaultSegmentInfosWriter;
 import org.apache.lucene.store.Directory;
@@ -43,6 +43,8 @@
 
   public void testGlobalFieldNumberFiles() throws IOException {
     int num = atLeast(3);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < num; i++) {
       Directory dir = newDirectory();
       {
@@ -50,10 +52,8 @@
             new MockAnalyzer(random));
         IndexWriter writer = new IndexWriter(dir, config);
         Document d = new Document();
-        d.add(new Field("f1", "d1 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d1 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
+        d.add(new Field("f1", customType, "d1 first field"));
+        d.add(new Field("f2", customType, "d1 second field"));
         writer.addDocument(d);
         for (String string : writer.getIndexFileNames()) {
           assertFalse(string.endsWith(".fnx"));
@@ -67,9 +67,8 @@
 
         assertFNXFiles(dir, "1.fnx");
         d = new Document();
-        d.add(new Field("f1", "d2 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3 }));
+        d.add(new Field("f1", customType, "d2 first field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3 }));
         writer.addDocument(d);
         writer.commit();
         files = writer.getIndexFileNames();
@@ -86,11 +85,9 @@
         IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
             TEST_VERSION_CURRENT, new MockAnalyzer(random)));
         Document d = new Document();
-        d.add(new Field("f1", "d3 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d3 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3, 4, 5 }));
+        d.add(new Field("f1", customType, "d3 first field"));
+        d.add(new Field("f2", customType, "d3 second field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3, 4, 5 }));
         writer.addDocument(d);
         writer.close();
         Collection<String> files = writer.getIndexFileNames();
@@ -115,6 +112,8 @@
 
   public void testIndexReaderCommit() throws IOException {
     int num = atLeast(3);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < num; i++) {
       Directory dir = newDirectory();
       {
@@ -122,17 +121,14 @@
             new MockAnalyzer(random));
         IndexWriter writer = new IndexWriter(dir, config);
         Document d = new Document();
-        d.add(new Field("f1", "d1 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d1 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
+        d.add(new Field("f1", customType, "d1 first field"));
+        d.add(new Field("f2", customType, "d1 second field"));
         writer.addDocument(d);
         writer.commit();
         assertFNXFiles(dir, "1.fnx");
         d = new Document();
-        d.add(new Field("f1", "d2 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3 }));
+        d.add(new Field("f1", customType, "d2 first field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3 }));
         writer.addDocument(d);
         writer.commit();
         assertFNXFiles(dir, "2.fnx");
@@ -159,6 +155,8 @@
 
   public void testGlobalFieldNumberFilesAcrossCommits() throws IOException {
     int num = atLeast(3);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < num; i++) {
       Directory dir = newDirectory();
       {
@@ -166,17 +164,14 @@
             TEST_VERSION_CURRENT, new MockAnalyzer(random)).setIndexDeletionPolicy(
             new KeepAllDeletionPolicy()));
         Document d = new Document();
-        d.add(new Field("f1", "d1 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d1 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
+        d.add(new Field("f1", customType, "d1 first field"));
+        d.add(new Field("f2", customType, "d1 second field"));
         writer.addDocument(d);
         writer.commit();
         assertFNXFiles(dir, "1.fnx");
         d = new Document();
-        d.add(new Field("f1", "d2 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3 }));
+        d.add(new Field("f1", customType, "d2 first field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3 }));
         writer.addDocument(d);
         writer.commit();
         writer.commit();
@@ -190,11 +185,9 @@
         IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
             TEST_VERSION_CURRENT, new MockAnalyzer(random)));
         Document d = new Document();
-        d.add(new Field("f1", "d3 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d3 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3, 4, 5 }));
+        d.add(new Field("f1", customType, "d3 first field"));
+        d.add(new Field("f2", customType, "d3 second field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3, 4, 5 }));
         writer.addDocument(d);
         writer.close();
         assertFNXFiles(dir, "2.fnx");
@@ -211,23 +204,22 @@
 
   public void testGlobalFieldNumberOnOldCommit() throws IOException {
     int num = atLeast(3);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < num; i++) {
       Directory dir = newDirectory();
       IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
           TEST_VERSION_CURRENT, new MockAnalyzer(random)).setIndexDeletionPolicy(
           new KeepAllDeletionPolicy()));
       Document d = new Document();
-      d.add(new Field("f1", "d1 first field", Store.YES, Index.ANALYZED,
-          TermVector.NO));
-      d.add(new Field("f2", "d1 second field", Store.YES, Index.ANALYZED,
-          TermVector.NO));
+      d.add(new Field("f1", customType, "d1 first field"));
+      d.add(new Field("f2", customType, "d1 second field"));
       writer.addDocument(d);
       writer.commit();
       assertFNXFiles(dir, "1.fnx");
       d = new Document();
-      d.add(new Field("f1", "d2 first field", Store.YES, Index.ANALYZED,
-          TermVector.NO));
-      d.add(new Field("f3", new byte[] { 1, 2, 3 }));
+      d.add(new Field("f1", customType, "d2 first field"));
+      d.add(new BinaryField("f3", new byte[] { 1, 2, 3 }));
       writer.addDocument(d);
       assertFNXFiles(dir, "1.fnx");
       writer.close();
@@ -240,9 +232,8 @@
           new KeepAllDeletionPolicy()).setIndexCommit(listCommits.get(0)));
 
       d = new Document();
-      d.add(new Field("f1", "d2 first field", Store.YES, Index.ANALYZED,
-          TermVector.NO));
-      d.add(new Field("f3", new byte[] { 1, 2, 3 }));
+      d.add(new Field("f1", customType, "d2 first field"));
+      d.add(new BinaryField("f3", new byte[] { 1, 2, 3 }));
       writer.addDocument(d);
       writer.commit();
       // now we have 3 files since f3 is not present in the first commit
@@ -271,9 +262,13 @@
       Document doc = new Document();
       final int numFields = 1 + random.nextInt(fieldNames.length);
       for (int j = 0; j < numFields; j++) {
+        FieldType customType = new FieldType();
+        customType.setIndexed(true);
+        customType.setTokenized(random.nextBoolean());
+        customType.setOmitNorms(random.nextBoolean());
         doc.add(newField(fieldNames[random.nextInt(fieldNames.length)],
             _TestUtil.randomRealisticUnicodeString(random),
-            Index.toIndex(true, random.nextBoolean(), random.nextBoolean())));
+            customType));
 
       }
       writer.addDocument(doc);
@@ -322,9 +317,13 @@
           TEST_VERSION_CURRENT, new MockAnalyzer(random)));
       Document doc = new Document();
       for (String string : fieldNames) {
+        FieldType customType = new FieldType();
+        customType.setIndexed(true);
+        customType.setTokenized(random.nextBoolean());
+        customType.setOmitNorms(random.nextBoolean());
         doc.add(newField(string,
             _TestUtil.randomRealisticUnicodeString(random),
-            Index.toIndex(true, random.nextBoolean(), random.nextBoolean())));
+            customType));
 
       }
       writer.addDocument(doc);
@@ -419,8 +418,12 @@
         String name = copySortedMap.get(nextField);
         assertNotNull(name);
 
+        FieldType customType = new FieldType();
+        customType.setIndexed(true);
+        customType.setTokenized(random.nextBoolean());
+        customType.setOmitNorms(random.nextBoolean());
         doc.add(newField(name, _TestUtil.randomRealisticUnicodeString(random),
-            Index.toIndex(true, random.nextBoolean(), random.nextBoolean())));
+            customType));
         writer.addDocument(doc);
         if (random.nextInt(10) == 0) {
           writer.commit();
@@ -480,8 +483,9 @@
       }
       
       Document d = new Document();
-      d.add(new Field("f1", "d1 first field", Store.YES, Index.ANALYZED,
-          TermVector.NO));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      d.add(new Field("f1", customType, "d1 first field"));
       writer.addDocument(d);
       writer.prepareCommit();
       // the fnx file should still be under control of the SIS
Index: lucene/src/test/org/apache/lucene/index/TestSegmentTermDocs.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSegmentTermDocs.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSegmentTermDocs.java	(working copy)
@@ -22,7 +22,7 @@
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.BytesRef;
 
 import java.io.IOException;
@@ -261,7 +261,7 @@
   private void addDoc(IndexWriter writer, String value) throws IOException
   {
       Document doc = new Document();
-      doc.add(newField("content", value, Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", value, TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
   }
 }
Index: lucene/src/test/org/apache/lucene/index/TestCheckIndex.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestCheckIndex.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestCheckIndex.java	(working copy)
@@ -28,6 +28,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.Constants;
 
 public class TestCheckIndex extends LuceneTestCase {
@@ -36,7 +38,12 @@
     Directory dir = newDirectory();
     IndexWriter writer  = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
     Document doc = new Document();
-    doc.add(newField("field", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("field", "aaa", customType));
     for(int i=0;i<19;i++) {
       writer.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java	(working copy)
@@ -34,6 +34,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
@@ -54,7 +57,37 @@
   private static class DocCopyIterator implements Iterable<Document> {
     private final Document doc;
     private final int count;
+    
+    /* private field types */
+    /* private field types */
 
+    private static final FieldType custom1 = new FieldType(TextField.TYPE_UNSTORED);
+    private static final FieldType custom2 = new FieldType();
+    private static final FieldType custom3 = new FieldType();
+    private static final FieldType custom4 = new FieldType(StringField.TYPE_UNSTORED);
+    private static final FieldType custom5 = new FieldType(TextField.TYPE_UNSTORED);
+    
+    static {
+
+      custom1.setStoreTermVectors(true);
+      custom1.setStoreTermVectorPositions(true);
+      custom1.setStoreTermVectorOffsets(true);
+      
+      custom2.setStored(true);
+      custom2.setIndexed(true);
+      
+      custom3.setStored(true);
+
+      custom4.setStoreTermVectors(true);
+      custom4.setStoreTermVectorPositions(true);
+      custom4.setStoreTermVectorOffsets(true);
+      
+      custom5.setStored(true);
+      custom5.setStoreTermVectors(true);
+      custom5.setStoreTermVectorPositions(true);
+      custom5.setStoreTermVectorOffsets(true);
+    }
+
     public DocCopyIterator(Document doc, int count) {
       this.count = count;
       this.doc = doc;
@@ -101,17 +134,17 @@
 
       final Document doc = new Document();
 
-      doc.add(newField("content1", "aaa bbb ccc ddd", Field.Store.YES, Field.Index.ANALYZED));
-      doc.add(newField("content6", "aaa bbb ccc ddd", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-      doc.add(newField("content2", "aaa bbb ccc ddd", Field.Store.YES, Field.Index.NOT_ANALYZED));
-      doc.add(newField("content3", "aaa bbb ccc ddd", Field.Store.YES, Field.Index.NO));
+      doc.add(newField("content1", "aaa bbb ccc ddd", TextField.TYPE_STORED));
+      doc.add(newField("content6", "aaa bbb ccc ddd", DocCopyIterator.custom1));
+      doc.add(newField("content2", "aaa bbb ccc ddd", DocCopyIterator.custom2));
+      doc.add(newField("content3", "aaa bbb ccc ddd", DocCopyIterator.custom3));
 
-      doc.add(newField("content4", "aaa bbb ccc ddd", Field.Store.NO, Field.Index.ANALYZED));
-      doc.add(newField("content5", "aaa bbb ccc ddd", Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("content4", "aaa bbb ccc ddd", TextField.TYPE_UNSTORED));
+      doc.add(newField("content5", "aaa bbb ccc ddd", StringField.TYPE_UNSTORED));
 
-      doc.add(newField("content7", "aaa bbb ccc ddd", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(newField("content7", "aaa bbb ccc ddd", DocCopyIterator.custom4));
 
-      final Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+      final Field idField = newField("id", "", DocCopyIterator.custom2);
       doc.add(idField);
 
       final long stopTime = System.currentTimeMillis() + 500;
@@ -337,8 +370,7 @@
     MockIndexWriter2 w = new MockIndexWriter2(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     w.setInfoStream(VERBOSE ? System.out : null);
     Document doc = new Document();
-    doc.add(newField("field", "a field", Field.Store.YES,
-                      Field.Index.ANALYZED));
+    doc.add(newField("field", "a field", TextField.TYPE_STORED));
     w.addDocument(doc);
     w.doFail = true;
     try {
@@ -357,8 +389,7 @@
     MockIndexWriter w = new MockIndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
     w.setInfoStream(VERBOSE ? System.out : null);
     Document doc = new Document();
-    doc.add(newField("field", "a field", Field.Store.YES,
-                      Field.Index.ANALYZED));
+    doc.add(newField("field", "a field", TextField.TYPE_STORED));
     w.addDocument(doc);
 
     Analyzer analyzer = new Analyzer() {
@@ -371,8 +402,7 @@
     };
 
     Document crashDoc = new Document();
-    crashDoc.add(newField("crash", "do it on token 4", Field.Store.YES,
-                           Field.Index.ANALYZED));
+    crashDoc.add(newField("crash", "do it on token 4", TextField.TYPE_STORED));
     try {
       w.addDocument(crashDoc, analyzer);
       fail("did not hit expected exception");
@@ -413,8 +443,7 @@
     MockIndexWriter3 w = new MockIndexWriter3(dir, conf);
     w.doFail = true;
     Document doc = new Document();
-    doc.add(newField("field", "a field", Field.Store.YES,
-                      Field.Index.ANALYZED));
+    doc.add(newField("field", "a field", TextField.TYPE_STORED));
     for(int i=0;i<10;i++)
       try {
         w.addDocument(doc);
@@ -457,8 +486,7 @@
 
     Document doc = new Document();
     String contents = "aa bb cc dd ee ff gg hh ii jj kk";
-    doc.add(newField("content", contents, Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("content", contents, TextField.TYPE_UNSTORED));
     try {
       writer.addDocument(doc);
       fail("did not hit expected exception");
@@ -467,14 +495,12 @@
 
     // Make sure we can add another normal document
     doc = new Document();
-    doc.add(newField("content", "aa bb cc dd", Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("content", "aa bb cc dd", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
 
     // Make sure we can add another normal document
     doc = new Document();
-    doc.add(newField("content", "aa bb cc dd", Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("content", "aa bb cc dd", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
 
     writer.close();
@@ -545,8 +571,7 @@
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
     Document doc = new Document();
     String contents = "aa bb cc dd ee ff gg hh ii jj kk";
-    doc.add(newField("content", contents, Field.Store.NO,
-        Field.Index.ANALYZED));
+    doc.add(newField("content", contents, TextField.TYPE_UNSTORED));
     boolean hitError = false;
     for(int i=0;i<200;i++) {
       try {
@@ -589,14 +614,11 @@
       lmp.setMergeFactor(Math.max(lmp.getMergeFactor(), 5));
 
       Document doc = new Document();
-      doc.add(newField("contents", "here are some contents", Field.Store.YES,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(newField("contents", "here are some contents", DocCopyIterator.custom5));
       writer.addDocument(doc);
       writer.addDocument(doc);
-      doc.add(newField("crash", "this should crash after 4 terms", Field.Store.YES,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-      doc.add(newField("other", "this will not get indexed", Field.Store.YES,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(newField("crash", "this should crash after 4 terms", DocCopyIterator.custom5));
+      doc.add(newField("other", "this will not get indexed", DocCopyIterator.custom5));
       try {
         writer.addDocument(doc);
         fail("did not hit expected exception");
@@ -609,8 +631,7 @@
 
       if (0 == i) {
         doc = new Document();
-        doc.add(newField("contents", "here are some contents", Field.Store.YES,
-                          Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+        doc.add(newField("contents", "here are some contents", DocCopyIterator.custom5));
         writer.addDocument(doc);
         writer.addDocument(doc);
       }
@@ -642,8 +663,7 @@
       writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT,
           analyzer).setMaxBufferedDocs(10));
       doc = new Document();
-      doc.add(newField("contents", "here are some contents", Field.Store.YES,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(newField("contents", "here are some contents", DocCopyIterator.custom5));
       for(int j=0;j<17;j++)
         writer.addDocument(doc);
       writer.optimize();
@@ -699,14 +719,11 @@
                 try {
                   for(int iter=0;iter<NUM_ITER;iter++) {
                     Document doc = new Document();
-                    doc.add(newField("contents", "here are some contents", Field.Store.YES,
-                                      Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+                    doc.add(newField("contents", "here are some contents", DocCopyIterator.custom5));
                     writer.addDocument(doc);
                     writer.addDocument(doc);
-                    doc.add(newField("crash", "this should crash after 4 terms", Field.Store.YES,
-                                      Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-                    doc.add(newField("other", "this will not get indexed", Field.Store.YES,
-                                      Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+                    doc.add(newField("crash", "this should crash after 4 terms", DocCopyIterator.custom5));
+                    doc.add(newField("other", "this will not get indexed", DocCopyIterator.custom5));
                     try {
                       writer.addDocument(doc);
                       fail("did not hit expected exception");
@@ -715,8 +732,7 @@
 
                     if (0 == finalI) {
                       doc = new Document();
-                      doc.add(newField("contents", "here are some contents", Field.Store.YES,
-                                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+                      doc.add(newField("contents", "here are some contents", DocCopyIterator.custom5));
                       writer.addDocument(doc);
                       writer.addDocument(doc);
                     }
@@ -761,8 +777,7 @@
       IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
           TEST_VERSION_CURRENT, analyzer).setMaxBufferedDocs(10));
       Document doc = new Document();
-      doc.add(newField("contents", "here are some contents", Field.Store.YES,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(newField("contents", "here are some contents", DocCopyIterator.custom5));
       for(int j=0;j<17;j++)
         writer.addDocument(doc);
       writer.optimize();
@@ -805,7 +820,7 @@
   private void addDoc(IndexWriter writer) throws IOException
   {
       Document doc = new Document();
-      doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
   }
 
@@ -901,8 +916,7 @@
       IndexWriter w = new IndexWriter(dir, newIndexWriterConfig(
           TEST_VERSION_CURRENT, new MockAnalyzer(random)));
       Document doc = new Document();
-      doc.add(newField("field", "a field", Field.Store.YES,
-          Field.Index.ANALYZED));
+      doc.add(newField("field", "a field", TextField.TYPE_STORED));
       w.addDocument(doc);
       dir.failOn(failure);
       try {
@@ -1234,13 +1248,12 @@
         int numDocs = 10 + random.nextInt(30);
         for (int i = 0; i < numDocs; i++) {
           Document doc = new Document();
-          Field field = newField(random, "field", "a field", Field.Store.YES,
-              Field.Index.ANALYZED);
+          Field field = newField(random, "field", "a field", TextField.TYPE_STORED);
           doc.add(field);
           // random TV
           try {
             w.addDocument(doc);
-            assertFalse(field.isTermVectorStored());
+            assertFalse(field.storeTermVectors());
           } catch (RuntimeException e) {
             assertTrue(e.getMessage().startsWith(FailOnTermVectors.EXC_MSG));
           }
@@ -1251,19 +1264,17 @@
             
         }
         Document document = new Document();
-        document.add(new Field("field", "a field", Field.Store.YES,
-            Field.Index.ANALYZED));
+        document.add(new Field("field", TextField.TYPE_STORED, "a field"));
         w.addDocument(document);
 
         for (int i = 0; i < numDocs; i++) {
           Document doc = new Document();
-          Field field = newField(random, "field", "a field", Field.Store.YES,
-              Field.Index.ANALYZED);
+          Field field = newField(random, "field", "a field", TextField.TYPE_STORED);
           doc.add(field);
           // random TV
           try {
             w.addDocument(doc);
-            assertFalse(field.isTermVectorStored());
+            assertFalse(field.storeTermVectors());
           } catch (RuntimeException e) {
             assertTrue(e.getMessage().startsWith(FailOnTermVectors.EXC_MSG));
           }
@@ -1273,8 +1284,7 @@
           }
         }
         document = new Document();
-        document.add(new Field("field", "a field", Field.Store.YES,
-            Field.Index.ANALYZED));
+        document.add(new Field("field", TextField.TYPE_STORED, "a field"));
         w.addDocument(document);
         w.close();
         IndexReader reader = IndexReader.open(dir);
@@ -1328,7 +1338,7 @@
     final int numDocs1 = random.nextInt(25);
     for(int docCount=0;docCount<numDocs1;docCount++) {
       Document doc = new Document();
-      doc.add(newField("content", "good content", Field.Index.ANALYZED));
+      doc.add(newField("content", "good content", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
     
@@ -1336,10 +1346,10 @@
     for(int docCount=0;docCount<7;docCount++) {
       Document doc = new Document();
       docs.add(doc);
-      doc.add(newField("id", docCount+"", Field.Index.NOT_ANALYZED));
-      doc.add(newField("content", "silly content " + docCount, Field.Index.ANALYZED));
+      doc.add(newField("id", docCount+"", StringField.TYPE_UNSTORED));
+      doc.add(newField("content", "silly content " + docCount, TextField.TYPE_UNSTORED));
       if (docCount == 4) {
-        Field f = newField("crash", "", Field.Index.ANALYZED);
+        Field f = newField("crash", "", TextField.TYPE_UNSTORED);
         doc.add(f);
         MockTokenizer tokenizer = new MockTokenizer(new StringReader("crash me on the 4th token"), MockTokenizer.WHITESPACE, false);
         tokenizer.setEnableChecks(false); // disable workflow checking as we forcefully close() in exceptional cases.
@@ -1358,7 +1368,7 @@
     final int numDocs2 = random.nextInt(25);
     for(int docCount=0;docCount<numDocs2;docCount++) {
       Document doc = new Document();
-      doc.add(newField("content", "good content", Field.Index.ANALYZED));
+      doc.add(newField("content", "good content", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
 
@@ -1386,7 +1396,7 @@
     final int numDocs1 = random.nextInt(25);
     for(int docCount=0;docCount<numDocs1;docCount++) {
       Document doc = new Document();
-      doc.add(newField("content", "good content", Field.Index.ANALYZED));
+      doc.add(newField("content", "good content", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
 
@@ -1396,16 +1406,16 @@
     for(int docCount=0;docCount<numDocs2;docCount++) {
       Document doc = new Document();
       docs.add(doc);
-      doc.add(newField("subid", "subs", Field.Index.NOT_ANALYZED));
-      doc.add(newField("id", docCount+"", Field.Index.NOT_ANALYZED));
-      doc.add(newField("content", "silly content " + docCount, Field.Index.ANALYZED));
+      doc.add(newField("subid", "subs", StringField.TYPE_UNSTORED));
+      doc.add(newField("id", docCount+"", StringField.TYPE_UNSTORED));
+      doc.add(newField("content", "silly content " + docCount, TextField.TYPE_UNSTORED));
     }
     w.addDocuments(docs);
 
     final int numDocs3 = random.nextInt(25);
     for(int docCount=0;docCount<numDocs3;docCount++) {
       Document doc = new Document();
-      doc.add(newField("content", "good content", Field.Index.ANALYZED));
+      doc.add(newField("content", "good content", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
 
@@ -1415,10 +1425,10 @@
     for(int docCount=0;docCount<limit;docCount++) {
       Document doc = new Document();
       docs.add(doc);
-      doc.add(newField("id", docCount+"", Field.Index.NOT_ANALYZED));
-      doc.add(newField("content", "silly content " + docCount, Field.Index.ANALYZED));
+      doc.add(newField("id", docCount+"", StringField.TYPE_UNSTORED));
+      doc.add(newField("content", "silly content " + docCount, TextField.TYPE_UNSTORED));
       if (docCount == crashAt) {
-        Field f = newField("crash", "", Field.Index.ANALYZED);
+        Field f = newField("crash", "", TextField.TYPE_UNSTORED);
         doc.add(f);
         MockTokenizer tokenizer = new MockTokenizer(new StringReader("crash me on the 4th token"), MockTokenizer.WHITESPACE, false);
         tokenizer.setEnableChecks(false); // disable workflow checking as we forcefully close() in exceptional cases.
@@ -1438,7 +1448,7 @@
     final int numDocs4 = random.nextInt(25);
     for(int docCount=0;docCount<numDocs4;docCount++) {
       Document doc = new Document();
-      doc.add(newField("content", "good content", Field.Index.ANALYZED));
+      doc.add(newField("content", "good content", TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
 
Index: lucene/src/test/org/apache/lucene/index/TestTransactions.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTransactions.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestTransactions.java	(working copy)
@@ -21,7 +21,9 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.MockDirectoryWrapper;
 import org.apache.lucene.store.RAMDirectory;
@@ -145,11 +147,13 @@
 
     public void update(IndexWriter writer) throws IOException {
       // Add 10 docs:
+      FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
       for(int j=0; j<10; j++) {
         Document d = new Document();
         int n = random.nextInt();
-        d.add(newField("id", Integer.toString(nextID++), Field.Store.YES, Field.Index.NOT_ANALYZED));
-        d.add(newField("contents", English.intToEnglish(n), Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField("id", Integer.toString(nextID++), customType));
+        d.add(newField("contents", English.intToEnglish(n), TextField.TYPE_UNSTORED));
         writer.addDocument(d);
       }
 
@@ -193,7 +197,7 @@
     for(int j=0; j<7; j++) {
       Document d = new Document();
       int n = random.nextInt();
-      d.add(newField("contents", English.intToEnglish(n), Field.Store.NO, Field.Index.ANALYZED));
+      d.add(newField("contents", English.intToEnglish(n), TextField.TYPE_UNSTORED));
       writer.addDocument(d);
     }
     writer.close();
Index: lucene/src/test/org/apache/lucene/index/TestDocumentWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDocumentWriter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestDocumentWriter.java	(working copy)
@@ -30,11 +30,9 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IOContext.Context;
@@ -77,15 +75,15 @@
     assertTrue(doc != null);
 
     //System.out.println("Document: " + doc);
-    Fieldable [] fields = doc.getFields("textField2");
+    IndexableField [] fields = doc.getFields("textField2");
     assertTrue(fields != null && fields.length == 1);
     assertTrue(fields[0].stringValue().equals(DocHelper.FIELD_2_TEXT));
-    assertTrue(fields[0].isTermVectorStored());
+    assertTrue(fields[0].storeTermVectors());
 
     fields = doc.getFields("textField1");
     assertTrue(fields != null && fields.length == 1);
     assertTrue(fields[0].stringValue().equals(DocHelper.FIELD_1_TEXT));
-    assertFalse(fields[0].isTermVectorStored());
+    assertFalse(fields[0].storeTermVectors());
 
     fields = doc.getFields("keyField");
     assertTrue(fields != null && fields.length == 1);
@@ -125,8 +123,10 @@
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer));
 
     Document doc = new Document();
-    doc.add(newField("repeated", "repeated one", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("repeated", "repeated two", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("repeated", "repeated one", customType));
+    doc.add(newField("repeated", "repeated two", customType));
 
     writer.addDocument(doc);
     writer.commit();
@@ -190,7 +190,9 @@
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer));
 
     Document doc = new Document();
-    doc.add(newField("f1", "a 5 a a", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("f1", "a 5 a a", customType));
 
     writer.addDocument(doc);
     writer.commit();
@@ -216,8 +218,8 @@
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    
-    doc.add(new Field("preanalyzed", new TokenStream() {
+
+    doc.add(new TextField("preanalyzed", new TokenStream() {
       private String[] tokens = new String[] {"term1", "term2", "term3", "term2"};
       private int index = 0;
       
@@ -234,7 +236,7 @@
         }        
       }
       
-    }, TermVector.NO));
+    }));
     
     writer.addDocument(doc);
     writer.commit();
@@ -267,11 +269,20 @@
   public void testMixedTermVectorSettingsSameField() throws Exception {
     Document doc = new Document();
     // f1 first without tv then with tv
-    doc.add(newField("f1", "v1", Store.YES, Index.NOT_ANALYZED, TermVector.NO));
-    doc.add(newField("f1", "v2", Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    doc.add(newField("f1", "v1", customType));
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    customType2.setTokenized(false);
+    customType2.setStoreTermVectors(true);
+    customType2.setStoreTermVectorOffsets(true);
+    customType2.setStoreTermVectorPositions(true);
+    doc.add(newField("f1", "v2", customType2));
     // f2 first with tv then without tv
-    doc.add(newField("f2", "v1", Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(newField("f2", "v2", Store.YES, Index.NOT_ANALYZED, TermVector.NO));
+    doc.add(newField("f2", "v1", customType2));
+    doc.add(newField("f2", "v2", customType));
 
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
@@ -300,13 +311,18 @@
   public void testLUCENE_1590() throws Exception {
     Document doc = new Document();
     // f1 has no norms
-    doc.add(newField("f1", "v1", Store.NO, Index.ANALYZED_NO_NORMS));
-    doc.add(newField("f1", "v2", Store.YES, Index.NO));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    FieldType customType2 = new FieldType();
+    customType2.setStored(true);
+    doc.add(newField("f1", "v1", customType));
+    doc.add(newField("f1", "v2", customType2));
     // f2 has no TF
-    Field f = newField("f2", "v1", Store.NO, Index.ANALYZED);
-    f.setIndexOptions(IndexOptions.DOCS_ONLY);
+    FieldType customType3 = new FieldType(TextField.TYPE_UNSTORED);
+    customType3.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f = newField("f2", "v1", customType3);
     doc.add(f);
-    doc.add(newField("f2", "v2", Store.YES, Index.NO));
+    doc.add(newField("f2", "v2", customType2));
 
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
Index: lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReaderCloneNorms.java	(working copy)
@@ -26,8 +26,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.SegmentNorms;
 import org.apache.lucene.search.DefaultSimilarity;
@@ -329,8 +330,11 @@
   private Document newDoc() {
     Document d = new Document();
     float boost = nextNorm("anyfield"); // in this test the same similarity is used for all fields so it does not matter what field is passed
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setTokenized(false);
     for (int i = 0; i < 10; i++) {
-      Field f = newField("f" + i, "v" + i, Store.NO, Index.NOT_ANALYZED);
+      Field f = newField("f" + i, "v" + i, customType);
       f.setBoost(boost);
       d.add(f);
     }
Index: lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestMaxTermFrequency.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.Similarity;
@@ -56,7 +57,7 @@
     });
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, config);
     Document doc = new Document();
-    Field foo = newField("foo", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field foo = newField("foo", "", TextField.TYPE_UNSTORED);
     doc.add(foo);
     for (int i = 0; i < 100; i++) {
       foo.setValue(addValue());
Index: lucene/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestConcurrentMergeScheduler.java	(working copy)
@@ -21,6 +21,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 
 import org.apache.lucene.util.LuceneTestCase;
@@ -75,7 +77,10 @@
     IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMaxBufferedDocs(2));
     writer.setInfoStream(VERBOSE ? System.out : null);
     Document doc = new Document();
-    Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    Field idField = newField("id", "", customType);
     doc.add(idField);
     int extraCount = 0;
 
@@ -135,7 +140,10 @@
     writer.setInfoStream(VERBOSE ? System.out : null);
 
     Document doc = new Document();
-    Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    Field idField = newField("id", "", customType);
     doc.add(idField);
     for(int i=0;i<10;i++) {
       if (VERBOSE) {
@@ -180,7 +188,7 @@
 
       for(int j=0;j<21;j++) {
         Document doc = new Document();
-        doc.add(newField("content", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(newField("content", "a b c", TextField.TYPE_UNSTORED));
         writer.addDocument(doc);
       }
         
@@ -202,7 +210,10 @@
   public void testNoWaitClose() throws IOException {
     MockDirectoryWrapper directory = newDirectory();
     Document doc = new Document();
-    Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    Field idField = newField("id", "", customType);
     doc.add(idField);
 
     IndexWriter writer = new IndexWriter(
Index: lucene/src/test/org/apache/lucene/index/TestOmitTf.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestOmitTf.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestOmitTf.java	(working copy)
@@ -28,6 +28,8 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.search.*;
 import org.apache.lucene.search.BooleanClause.Occur;
@@ -54,6 +56,13 @@
     }
   }
 
+  private static final FieldType omitType = new FieldType(TextField.TYPE_UNSTORED);
+  private static final FieldType normalType = new FieldType(TextField.TYPE_UNSTORED);
+  
+  static {
+    omitType.setIndexOptions(IndexOptions.DOCS_ONLY);
+  }
+
   // Tests whether the DocumentWriter correctly enable the
   // omitTermFreqAndPositions bit in the FieldInfo
   public void testOmitTermFreqAndPositions() throws Exception {
@@ -63,12 +72,11 @@
     Document d = new Document();
         
     // this field will have Tf
-    Field f1 = newField("f1", "This field has term freqs", Field.Store.NO, Field.Index.ANALYZED);
+    Field f1 = newField("f1", "This field has term freqs", normalType);
     d.add(f1);
        
     // this field will NOT have Tf
-    Field f2 = newField("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.ANALYZED);
-    f2.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f2 = newField("f2", "This field has NO Tf in all docs", omitType);
     d.add(f2);
         
     writer.addDocument(d);
@@ -78,10 +86,10 @@
     d = new Document();
         
     // Reverse
-    f1.setIndexOptions(IndexOptions.DOCS_ONLY);
+    f1 = newField("f1", "This field has term freqs", omitType);
     d.add(f1);
         
-    f2.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);        
+    f2 = newField("f2", "This field has NO Tf in all docs", normalType);     
     d.add(f2);
         
     writer.addDocument(d);
@@ -115,12 +123,11 @@
     Document d = new Document();
         
     // this field will have Tf
-    Field f1 = newField("f1", "This field has term freqs", Field.Store.NO, Field.Index.ANALYZED);
+    Field f1 = newField("f1", "This field has term freqs", normalType);
     d.add(f1);
        
     // this field will NOT have Tf
-    Field f2 = newField("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.ANALYZED);
-    f2.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f2 = newField("f2", "This field has NO Tf in all docs", omitType);
     d.add(f2);
 
     for(int i=0;i<30;i++)
@@ -131,10 +138,10 @@
     d = new Document();
         
     // Reverese
-    f1.setIndexOptions(IndexOptions.DOCS_ONLY);
+    f1 = newField("f1", "This field has term freqs", omitType);
     d.add(f1);
         
-    f2.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);        
+    f2 = newField("f2", "This field has NO Tf in all docs", normalType);     
     d.add(f2);
         
     for(int i=0;i<30;i++)
@@ -169,18 +176,16 @@
     Document d = new Document();
         
     // this field will have Tf
-    Field f1 = newField("f1", "This field has term freqs", Field.Store.NO, Field.Index.ANALYZED);
+    Field f1 = newField("f1", "This field has term freqs", normalType);
     d.add(f1);
        
     // this field will NOT have Tf
-    Field f2 = newField("f2", "This field has NO Tf in all docs", Field.Store.NO, Field.Index.ANALYZED);
+    Field f2 = newField("f2", "This field has NO Tf in all docs", omitType);
     d.add(f2);
 
     for(int i=0;i<5;i++)
       writer.addDocument(d);
 
-    f2.setIndexOptions(IndexOptions.DOCS_ONLY);
-        
     for(int i=0;i<20;i++)
       writer.addDocument(d);
 
@@ -218,8 +223,7 @@
     lmp.setUseCompoundFile(false);
     Document d = new Document();
         
-    Field f1 = newField("f1", "This field has no term freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f1.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f1 = newField("f1", "This field has term freqs", omitType);
     d.add(f1);
 
     for(int i=0;i<30;i++)
@@ -231,7 +235,7 @@
     
     // now add some documents with positions, and check there is no prox after optimization
     d = new Document();
-    f1 = newField("f1", "This field has positions", Field.Store.NO, Field.Index.ANALYZED);
+    f1 = newField("f1", "This field has positions", TextField.TYPE_UNSTORED);
     d.add(f1);
     
     for(int i=0;i<30;i++)
@@ -265,11 +269,10 @@
       Document d = new Document();
       sb.append(term).append(" ");
       String content  = sb.toString();
-      Field noTf = newField("noTf", content + (i%2==0 ? "" : " notf"), Field.Store.NO, Field.Index.ANALYZED);
-      noTf.setIndexOptions(IndexOptions.DOCS_ONLY);
+      Field noTf = newField("noTf", content + (i%2==0 ? "" : " notf"), omitType);
       d.add(noTf);
           
-      Field tf = newField("tf", content + (i%2==0 ? " tf" : ""), Field.Store.NO, Field.Index.ANALYZED);
+      Field tf = newField("tf", content + (i%2==0 ? " tf" : ""), normalType);
       d.add(tf);
           
       writer.addDocument(d);
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterMergePolicy.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterMergePolicy.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterMergePolicy.java	(working copy)
@@ -22,6 +22,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 
@@ -220,7 +221,7 @@
 
   private void addDoc(IndexWriter writer) throws IOException {
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
   }
 
Index: lucene/src/test/org/apache/lucene/index/TestIndexReaderDelete.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReaderDelete.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReaderDelete.java	(working copy)
@@ -21,7 +21,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.MockDirectoryWrapper;
@@ -276,11 +277,13 @@
     Directory dir = newDirectory();
     RandomIndexWriter w= new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     Document doc = new Document();
-    doc.add(newField("f", "doctor", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setTokenized(false);
+    doc.add(newField("f", "doctor", customType));
     w.addDocument(doc);
     doc = new Document();
     w.commit();
-    doc.add(newField("f", "who", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("f", "who", customType));
     w.addDocument(doc);
     IndexReader r = new SlowMultiReaderWrapper(w.getReader());
     w.close();
Index: lucene/src/test/org/apache/lucene/index/TestNRTThreads.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestNRTThreads.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestNRTThreads.java	(working copy)
@@ -33,6 +33,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.PhraseQuery;
@@ -163,7 +166,7 @@
                 final String addedField;
                 if (random.nextBoolean()) {
                   addedField = "extra" + random.nextInt(10);
-                  doc.add(new Field(addedField, "a random field", Field.Store.NO, Field.Index.ANALYZED));
+                  doc.add(new TextField(addedField, "a random field"));
                 } else {
                   addedField = null;
                 }
@@ -188,7 +191,7 @@
                       packID = packCount.getAndIncrement() + "";
                     }
 
-                    final Field packIDField = newField("packID", packID, Field.Store.YES, Field.Index.NOT_ANALYZED);
+                    final Field packIDField = newField("packID", packID, StringField.TYPE_STORED);
                     final List<String> docIDs = new ArrayList<String>();
                     final SubDocs subDocs = new SubDocs(packID, docIDs);
                     final List<Document> docsList = new ArrayList<Document>();
Index: lucene/src/test/org/apache/lucene/index/TestOmitPositions.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestOmitPositions.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestOmitPositions.java	(working copy)
@@ -21,6 +21,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.store.Directory;
@@ -37,8 +39,9 @@
     Directory dir = newDirectory();
     RandomIndexWriter w = new RandomIndexWriter(random, dir);
     Document doc = new Document();
-    Field f = newField("foo", "this is a test test", Field.Index.ANALYZED);
-    f.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    Field f = newField("foo", "this is a test test", ft);
     doc.add(f);
     for (int i = 0; i < 100; i++) {
       w.addDocument(doc);
@@ -67,42 +70,42 @@
     Document d = new Document();
         
     // f1,f2,f3: docs only
-    Field f1 = newField("f1", "This field has docs only", Field.Store.NO, Field.Index.ANALYZED);
-    f1.setIndexOptions(IndexOptions.DOCS_ONLY);
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setIndexOptions(IndexOptions.DOCS_ONLY);
+    
+    Field f1 = newField("f1", "This field has docs only", ft);
     d.add(f1);
        
-    Field f2 = newField("f2", "This field has docs only", Field.Store.NO, Field.Index.ANALYZED);
-    f2.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f2 = newField("f2", "This field has docs only", ft);
     d.add(f2);
     
-    Field f3 = newField("f3", "This field has docs only", Field.Store.NO, Field.Index.ANALYZED);
-    f3.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f3 = newField("f3", "This field has docs only", ft);
     d.add(f3);
+
+    FieldType ft2 = new FieldType(TextField.TYPE_UNSTORED);
+    ft2.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
     
     // f4,f5,f6 docs and freqs
-    Field f4 = newField("f4", "This field has docs and freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f4.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    Field f4 = newField("f4", "This field has docs and freqs", ft2);
     d.add(f4);
        
-    Field f5 = newField("f5", "This field has docs and freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f5.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    Field f5 = newField("f5", "This field has docs and freqs", ft2);
     d.add(f5);
     
-    Field f6 = newField("f6", "This field has docs and freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f6.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    Field f6 = newField("f6", "This field has docs and freqs", ft2);
     d.add(f6);
     
+    FieldType ft3 = new FieldType(TextField.TYPE_UNSTORED);
+    ft3.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    
     // f7,f8,f9 docs/freqs/positions
-    Field f7 = newField("f7", "This field has docs and freqs and positions", Field.Store.NO, Field.Index.ANALYZED);
-    f7.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    Field f7 = newField("f7", "This field has docs and freqs and positions", ft3);
     d.add(f7);
        
-    Field f8 = newField("f8", "This field has docs and freqs and positions", Field.Store.NO, Field.Index.ANALYZED);
-    f8.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    Field f8 = newField("f8", "This field has docs and freqs and positions", ft3);
     d.add(f8);
     
-    Field f9 = newField("f9", "This field has docs and freqs and positions", Field.Store.NO, Field.Index.ANALYZED);
-    f9.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    Field f9 = newField("f9", "This field has docs and freqs and positions", ft3);
     d.add(f9);
         
     writer.addDocument(d);
@@ -113,42 +116,33 @@
     d = new Document();
     
     // f1,f4,f7: docs only
-    f1 = newField("f1", "This field has docs only", Field.Store.NO, Field.Index.ANALYZED);
-    f1.setIndexOptions(IndexOptions.DOCS_ONLY);
+    f1 = newField("f1", "This field has docs only", ft);
     d.add(f1);
     
-    f4 = newField("f4", "This field has docs only", Field.Store.NO, Field.Index.ANALYZED);
-    f4.setIndexOptions(IndexOptions.DOCS_ONLY);
+    f4 = newField("f4", "This field has docs only", ft);
     d.add(f4);
     
-    f7 = newField("f7", "This field has docs only", Field.Store.NO, Field.Index.ANALYZED);
-    f7.setIndexOptions(IndexOptions.DOCS_ONLY);
+    f7 = newField("f7", "This field has docs only", ft);
     d.add(f7);
 
     // f2, f5, f8: docs and freqs
-    f2 = newField("f2", "This field has docs and freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f2.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    f2 = newField("f2", "This field has docs and freqs", ft2);
     d.add(f2);
     
-    f5 = newField("f5", "This field has docs and freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f5.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    f5 = newField("f5", "This field has docs and freqs", ft2);
     d.add(f5);
     
-    f8 = newField("f8", "This field has docs and freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f8.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    f8 = newField("f8", "This field has docs and freqs", ft2);
     d.add(f8);
     
     // f3, f6, f9: docs and freqs and positions
-    f3 = newField("f3", "This field has docs and freqs and positions", Field.Store.NO, Field.Index.ANALYZED);
-    f3.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    f3 = newField("f3", "This field has docs and freqs and positions", ft3);
     d.add(f3);     
     
-    f6 = newField("f6", "This field has docs and freqs and positions", Field.Store.NO, Field.Index.ANALYZED);
-    f6.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    f6 = newField("f6", "This field has docs and freqs and positions", ft3);
     d.add(f6);
     
-    f9 = newField("f9", "This field has docs and freqs and positions", Field.Store.NO, Field.Index.ANALYZED);
-    f9.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    f9 = newField("f9", "This field has docs and freqs and positions", ft3);
     d.add(f9);
         
     writer.addDocument(d);
@@ -201,9 +195,10 @@
     lmp.setMergeFactor(2);
     lmp.setUseCompoundFile(false);
     Document d = new Document();
-        
-    Field f1 = newField("f1", "This field has term freqs", Field.Store.NO, Field.Index.ANALYZED);
-    f1.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+
+    FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+    ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
+    Field f1 = newField("f1", "This field has term freqs", ft);
     d.add(f1);
 
     for(int i=0;i<30;i++)
@@ -215,7 +210,7 @@
     
     // now add some documents with positions, and check there is no prox after optimization
     d = new Document();
-    f1 = newField("f1", "This field has positions", Field.Store.NO, Field.Index.ANALYZED);
+    f1 = newField("f1", "This field has positions", TextField.TYPE_UNSTORED);
     d.add(f1);
     
     for(int i=0;i<30;i++)
Index: lucene/src/test/org/apache/lucene/index/TestNoDeletionPolicy.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestNoDeletionPolicy.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestNoDeletionPolicy.java	(working copy)
@@ -23,8 +23,8 @@
 import java.util.Arrays;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.junit.Test;
@@ -72,9 +72,11 @@
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random))
         .setIndexDeletionPolicy(NoDeletionPolicy.INSTANCE));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < 10; i++) {
       Document doc = new Document();
-      doc.add(newField("c", "a" + i, Store.YES, Index.ANALYZED));
+      doc.add(newField("c", "a" + i, customType));
       writer.addDocument(doc);
       writer.commit();
       assertEquals("wrong number of commits !", i + 1, IndexReader.listCommits(dir).size());
Index: lucene/src/test/org/apache/lucene/index/TestOmitNorms.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestOmitNorms.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestOmitNorms.java	(working copy)
@@ -25,6 +25,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 
 public class TestOmitNorms extends LuceneTestCase {
@@ -37,12 +39,13 @@
     Document d = new Document();
         
     // this field will have norms
-    Field f1 = newField("f1", "This field has norms", Field.Store.NO, Field.Index.ANALYZED);
+    Field f1 = newField("f1", "This field has norms", TextField.TYPE_UNSTORED);
     d.add(f1);
        
     // this field will NOT have norms
-    Field f2 = newField("f2", "This field has NO norms in all docs", Field.Store.NO, Field.Index.ANALYZED);
-    f2.setOmitNorms(true);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    Field f2 = newField("f2", "This field has NO norms in all docs", customType);
     d.add(f2);
         
     writer.addDocument(d);
@@ -52,11 +55,9 @@
     d = new Document();
         
     // Reverse
-    f1.setOmitNorms(true);
-    d.add(f1);
+    d.add(newField("f1", "This field has norms", customType));
         
-    f2.setOmitNorms(false);        
-    d.add(f2);
+    d.add(newField("f2", "This field has NO norms in all docs", TextField.TYPE_UNSTORED));
         
     writer.addDocument(d);
 
@@ -88,12 +89,13 @@
     Document d = new Document();
         
     // this field will have norms
-    Field f1 = newField("f1", "This field has norms", Field.Store.NO, Field.Index.ANALYZED);
+    Field f1 = newField("f1", "This field has norms", TextField.TYPE_UNSTORED);
     d.add(f1);
        
     // this field will NOT have norms
-    Field f2 = newField("f2", "This field has NO norms in all docs", Field.Store.NO, Field.Index.ANALYZED);
-    f2.setOmitNorms(true);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    Field f2 = newField("f2", "This field has NO norms in all docs", customType);
     d.add(f2);
 
     for (int i = 0; i < 30; i++) {
@@ -105,11 +107,9 @@
     d = new Document();
         
     // Reverese
-    f1.setOmitNorms(true);
-    d.add(f1);
+    d.add(newField("f1", "This field has norms", customType));
         
-    f2.setOmitNorms(false);        
-    d.add(f2);
+    d.add(newField("f2", "This field has NO norms in all docs", TextField.TYPE_UNSTORED));
         
     for (int i = 0; i < 30; i++) {
       writer.addDocument(d);
@@ -144,18 +144,19 @@
     Document d = new Document();
         
     // this field will have norms
-    Field f1 = newField("f1", "This field has norms", Field.Store.NO, Field.Index.ANALYZED);
+    Field f1 = newField("f1", "This field has norms", TextField.TYPE_UNSTORED);
     d.add(f1);
        
     // this field will NOT have norms
-    Field f2 = newField("f2", "This field has NO norms in all docs", Field.Store.NO, Field.Index.ANALYZED);
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    Field f2 = newField("f2", "This field has NO norms in all docs", customType);
     d.add(f2);
 
     for (int i = 0; i < 5; i++) {
       writer.addDocument(d);
     }
-
-    f2.setOmitNorms(true);
         
     for (int i = 0; i < 20; i++) {
       writer.addDocument(d);
@@ -194,9 +195,10 @@
     lmp.setMergeFactor(2);
     lmp.setUseCompoundFile(false);
     Document d = new Document();
-        
-    Field f1 = newField("f1", "This field has no norms", Field.Store.NO, Field.Index.ANALYZED);
-    f1.setOmitNorms(true);
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
+    Field f1 = newField("f1", "This field has no norms", customType);
     d.add(f1);
 
     for (int i = 0; i < 30; i++) {
@@ -224,16 +226,25 @@
    */
   public void testOmitNormsCombos() throws IOException {
     // indexed with norms
-    Field norms = new Field("foo", "a", Field.Store.YES, Field.Index.ANALYZED);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    Field norms = new Field("foo", customType, "a");
     // indexed without norms
-    Field noNorms = new Field("foo", "a", Field.Store.YES, Field.Index.ANALYZED_NO_NORMS);
+    FieldType customType1 = new FieldType(TextField.TYPE_UNSTORED);
+    customType1.setStored(true);
+    customType1.setOmitNorms(true);
+    Field noNorms = new Field("foo", customType1, "a");
     // not indexed, but stored
-    Field noIndex = new Field("foo", "a", Field.Store.YES, Field.Index.NO);
+    FieldType customType2 = new FieldType();
+    customType2.setStored(true);
+    Field noIndex = new Field("foo", customType2, "a");
     // not indexed but stored, omitNorms is set
-    Field noNormsNoIndex = new Field("foo", "a", Field.Store.YES, Field.Index.NO);
-    noNormsNoIndex.setOmitNorms(true);
+    FieldType customType3 = new FieldType();
+    customType3.setStored(true);
+    customType3.setOmitNorms(true);
+    Field noNormsNoIndex = new Field("foo", customType3, "a");
     // not indexed nor stored (doesnt exist at all, we index a different field instead)
-    Field emptyNorms = new Field("bar", "a", Field.Store.YES, Field.Index.ANALYZED);
+    Field emptyNorms = new Field("bar", customType, "a");
     
     assertNotNull(getNorms("foo", norms, norms));
     assertNull(getNorms("foo", norms, noNorms));
Index: lucene/src/test/org/apache/lucene/index/TestDirectoryReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDirectoryReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestDirectoryReader.java	(working copy)
@@ -22,6 +22,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
@@ -202,7 +204,9 @@
         new MockAnalyzer(random)).setOpenMode(
         create ? OpenMode.CREATE : OpenMode.APPEND));
     Document doc = new Document();
-    doc.add(newField("body", s, Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(false);
+    doc.add(newField("body", s, customType));
     iw.addDocument(doc);
     iw.close();
   }
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterReader.java	(working copy)
@@ -28,9 +28,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
@@ -146,7 +146,7 @@
     
     Document newDoc = r1.document(10);
     newDoc.removeField("id");
-    newDoc.add(newField("id", Integer.toString(8000), Store.YES, Index.NOT_ANALYZED));
+    newDoc.add(newField("id", Integer.toString(8000), StringField.TYPE_STORED));
     writer.updateDocument(new Term("id", id10), newDoc);
     assertFalse(r1.isCurrent());
 
@@ -170,7 +170,7 @@
 
     writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a b c", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     assertTrue(r2.isCurrent());
     assertTrue(r3.isCurrent());
@@ -192,14 +192,14 @@
     
     IndexWriter writer = new IndexWriter(dir, iwc);
     Document doc = new Document();
-    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a b c", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.close();
     
     iwc = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
     writer = new IndexWriter(dir, iwc);
     doc = new Document();
-    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a b c", TextField.TYPE_UNSTORED));
     IndexReader nrtReader = writer.getReader();
     assertTrue(nrtReader.isCurrent());
     writer.addDocument(doc);
@@ -580,16 +580,27 @@
   public static Document createDocument(int n, String indexName, int numFields) {
     StringBuilder sb = new StringBuilder();
     Document doc = new Document();
-    doc.add(new Field("id", Integer.toString(n), Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("indexname", indexName, Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+
+    FieldType customType1 = new FieldType(StringField.TYPE_UNSTORED);
+    customType1.setStored(true);
+    customType1.setStoreTermVectors(true);
+    customType1.setStoreTermVectorPositions(true);
+    customType1.setStoreTermVectorOffsets(true);
+    
+    doc.add(new Field("id", customType1, Integer.toString(n)));
+    doc.add(new Field("indexname", customType1, indexName));
     sb.append("a");
     sb.append(n);
-    doc.add(new Field("field1", sb.toString(), Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+    doc.add(new Field("field1", customType, sb.toString()));
     sb.append(" b");
     sb.append(n);
     for (int i = 1; i < numFields; i++) {
-      doc.add(new Field("field" + (i + 1), sb.toString(), Store.YES,
-                        Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS));
+      doc.add(new Field("field" + (i + 1), customType, sb.toString()));
     }
     return doc;
   }
@@ -915,8 +926,8 @@
     Directory dir = newDirectory();
     final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     Document doc = new Document();
-    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
-    Field id = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    doc.add(newField("field", "a b c", TextField.TYPE_UNSTORED));
+    Field id = newField("id", "", StringField.TYPE_UNSTORED);
     doc.add(id);
     id.setValue("0");
     w.addDocument(doc);
@@ -939,8 +950,8 @@
     Directory dir = newDirectory();
     final IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("field", "a b c", Field.Store.NO, Field.Index.ANALYZED));
-    Field id = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    doc.add(newField("field", "a b c", TextField.TYPE_UNSTORED));
+    Field id = newField("id", "", StringField.TYPE_UNSTORED);
     doc.add(id);
     id.setValue("0");
     w.addDocument(doc);
@@ -997,7 +1008,9 @@
     );
 
     Document doc = new Document();
-    doc.add(newField("foo", "bar", Field.Store.YES, Field.Index.NOT_ANALYZED));
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStored(false);
+    doc.add(newField("foo", "bar", customType));
     for(int i=0;i<20;i++) {
       w.addDocument(doc);
     }
@@ -1023,7 +1036,7 @@
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, conf);
     Document doc = new Document();
-    doc.add(new Field("f", "val", Store.NO, Index.ANALYZED));
+    doc.add(new TextField("f", "val"));
     w.addDocument(doc);
     IndexReader r = IndexReader.open(w, true).getSequentialSubReaders()[0];
     try {
Index: lucene/src/test/org/apache/lucene/index/TestRollingUpdates.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestRollingUpdates.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestRollingUpdates.java	(working copy)
@@ -19,7 +19,6 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.*;
-import org.apache.lucene.document.Field.Index;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.store.*;
 import org.apache.lucene.util.*;
@@ -55,7 +54,7 @@
       } else {
         id++;
       }
-      doc.getField("docid").setValue(myID);
+      ((Field) doc.getField("docid")).setValue(myID);
       w.updateDocument(new Term("docid", myID), doc);
 
       if (docIter >= SIZE && random.nextInt(50) == 17) {
@@ -130,7 +129,7 @@
         IndexReader open = null;
         for (int i = 0; i < num; i++) {
           Document doc = new Document();// docs.nextDoc();
-          doc.add(newField("id", "test", Index.NOT_ANALYZED));
+          doc.add(newField("id", "test", StringField.TYPE_UNSTORED));
           writer.updateDocument(new Term("id", "test"), doc);
           if (random.nextInt(3) == 0) {
             if (open == null) {
Index: lucene/src/test/org/apache/lucene/index/TestTransactionRollback.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTransactionRollback.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestTransactionRollback.java	(working copy)
@@ -29,7 +29,8 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.Bits;
 
@@ -128,9 +129,12 @@
     //Build index, of records 1 to 100, committing after each batch of 10
     IndexDeletionPolicy sdp=new KeepAllDeletionPolicy();
     IndexWriter w=new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setIndexDeletionPolicy(sdp));
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for(int currentRecordId=1;currentRecordId<=100;currentRecordId++) {
       Document doc=new Document();
-      doc.add(newField(FIELD_RECORD_ID,""+currentRecordId,Field.Store.YES,Field.Index.ANALYZED));
+      doc.add(newField(FIELD_RECORD_ID,""+currentRecordId,customType));
       w.addDocument(doc);
 			
       if (currentRecordId%10 == 0) {
Index: lucene/src/test/org/apache/lucene/index/TestBinaryTerms.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestBinaryTerms.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestBinaryTerms.java	(working copy)
@@ -21,6 +21,8 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
@@ -47,8 +49,10 @@
       bytes.bytes[1] = (byte) (255 - i);
       bytes.length = 2;
       Document doc = new Document();
-      doc.add(new Field("id", "" + i, Field.Store.YES, Field.Index.NO));
-      doc.add(new Field("bytes", tokenStream));
+      FieldType customType = new FieldType();
+      customType.setStored(true);
+      doc.add(new Field("id", customType, "" + i));
+      doc.add(new TextField("bytes", tokenStream));
       iw.addDocument(doc);
     }
     
Index: lucene/src/test/org/apache/lucene/index/TestFilterIndexReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestFilterIndexReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestFilterIndexReader.java	(working copy)
@@ -23,7 +23,8 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.Bits;
 
@@ -128,16 +129,18 @@
     Directory directory = newDirectory();
     IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
 
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     Document d1 = new Document();
-    d1.add(newField("default","one two", Field.Store.YES, Field.Index.ANALYZED));
+    d1.add(newField("default","one two", customType));
     writer.addDocument(d1);
 
     Document d2 = new Document();
-    d2.add(newField("default","one three", Field.Store.YES, Field.Index.ANALYZED));
+    d2.add(newField("default","one three", customType));
     writer.addDocument(d2);
 
     Document d3 = new Document();
-    d3.add(newField("default","two four", Field.Store.YES, Field.Index.ANALYZED));
+    d3.add(newField("default","two four", customType));
     writer.addDocument(d3);
 
     writer.close();
Index: lucene/src/test/org/apache/lucene/index/TestSegmentMerger.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSegmentMerger.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSegmentMerger.java	(working copy)
@@ -23,9 +23,7 @@
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.util.BytesRef;
 
@@ -142,7 +140,7 @@
     // Create an index w/ .del file
     w.addDocument(new Document());
     Document doc = new Document();
-    doc.add(new Field("c", "test", Store.NO, Index.ANALYZED));
+    doc.add(new TextField("c", "test"));
     w.addDocument(doc);
     w.commit();
     w.deleteDocuments(new Term("c", "test"));
@@ -160,7 +158,7 @@
     // Create an index w/ .s*
     w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE));
     doc = new Document();
-    doc.add(new Field("c", "test", Store.NO, Index.ANALYZED));
+    doc.add(new TextField("c", "test"));
     w.addDocument(doc);
     w.close();
     IndexReader r = IndexReader.open(dir, false);
Index: lucene/src/test/org/apache/lucene/index/TestAddIndexes.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestAddIndexes.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestAddIndexes.java	(working copy)
@@ -25,9 +25,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.codecs.mocksep.MockSepCodec;
@@ -165,11 +165,12 @@
 
     // Adds 10 docs, then replaces them with another 10
     // docs, so 10 pending deletes:
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setTokenized(false);
     for (int i = 0; i < 20; i++) {
       Document doc = new Document();
-      doc.add(newField("id", "" + (i % 10), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("content", "bbb " + i, Field.Store.NO,
-                        Field.Index.ANALYZED));
+      doc.add(newField("id", "" + (i % 10), customType));
+      doc.add(newField("content", "bbb " + i, TextField.TYPE_UNSTORED));
       writer.updateDocument(new Term("id", "" + (i%10)), doc);
     }
     // Deletes one of the 10 added docs, leaving 9:
@@ -201,10 +202,12 @@
 
     // Adds 10 docs, then replaces them with another 10
     // docs, so 10 pending deletes:
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setTokenized(false);
     for (int i = 0; i < 20; i++) {
       Document doc = new Document();
-      doc.add(newField("id", "" + (i % 10), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("content", "bbb " + i, Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("id", "" + (i % 10), customType));
+      doc.add(newField("content", "bbb " + i, TextField.TYPE_UNSTORED));
       writer.updateDocument(new Term("id", "" + (i%10)), doc);
     }
     
@@ -239,11 +242,12 @@
 
     // Adds 10 docs, then replaces them with another 10
     // docs, so 10 pending deletes:
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setTokenized(false);
     for (int i = 0; i < 20; i++) {
       Document doc = new Document();
-      doc.add(newField("id", "" + (i % 10), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("content", "bbb " + i, Field.Store.NO,
-                        Field.Index.ANALYZED));
+      doc.add(newField("id", "" + (i % 10), customType));
+      doc.add(newField("content", "bbb " + i, TextField.TYPE_UNSTORED));
       writer.updateDocument(new Term("id", "" + (i%10)), doc);
     }
 
@@ -503,8 +507,7 @@
   private void addDocs(IndexWriter writer, int numDocs) throws IOException {
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(newField("content", "aaa", Field.Store.NO,
-                        Field.Index.ANALYZED));
+      doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
   }
@@ -512,8 +515,7 @@
   private void addDocs2(IndexWriter writer, int numDocs) throws IOException {
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(newField("content", "bbb", Field.Store.NO,
-                        Field.Index.ANALYZED));
+      doc.add(newField("content", "bbb", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
   }
@@ -582,20 +584,22 @@
         .setMaxBufferedDocs(5).setMergePolicy(lmp));
 
     Document doc = new Document();
-    doc.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES,
-                      Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", customType));
     for(int i=0;i<60;i++)
       writer.addDocument(doc);
 
     Document doc2 = new Document();
-    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES,
-                      Field.Index.NO));
-    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES,
-                      Field.Index.NO));
-    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES,
-                      Field.Index.NO));
-    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES,
-                      Field.Index.NO));
+    FieldType customType2 = new FieldType();
+    customType2.setStored(true);
+    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", customType2));
+    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", customType2));
+    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", customType2));
+    doc2.add(newField("content", "aaa bbb ccc ddd eee fff ggg hhh iii", customType2));
     for(int i=0;i<10;i++)
       writer.addDocument(doc2);
     writer.close();
@@ -619,7 +623,7 @@
   private void addDoc(IndexWriter writer) throws IOException
   {
       Document doc = new Document();
-      doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
   }
   
@@ -944,7 +948,7 @@
       IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random));
       IndexWriter writer = new IndexWriter(dirs[i], conf);
       Document doc = new Document();
-      doc.add(new Field("id", "myid", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+      doc.add(new StringField("id", "myid"));
       writer.addDocument(doc);
       writer.close();
     }
@@ -973,8 +977,10 @@
   private void addDocs3(IndexWriter writer, int numDocs) throws IOException {
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
-      doc.add(newField("id", "" + i, Field.Store.YES, Field.Index.ANALYZED));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
+      doc.add(newField("id", "" + i, customType));
       writer.addDocument(doc);
     }
   }
@@ -1061,7 +1067,10 @@
       dirs[i] = new RAMDirectory();
       IndexWriter w = new IndexWriter(dirs[i], new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
       Document d = new Document();
-      d.add(new Field("c", "v", Store.YES, Index.ANALYZED, TermVector.YES));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setStoreTermVectors(true);
+      d.add(new Field("c", customType, "v"));
       w.addDocument(d);
       w.close();
     }
@@ -1099,10 +1108,12 @@
         new MockAnalyzer(random)).setMergePolicy(lmp2);
     IndexWriter w2 = new IndexWriter(src, conf2);
     Document doc = new Document();
-    doc.add(new Field("c", "some text", Store.YES, Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(new Field("c", customType, "some text"));
     w2.addDocument(doc);
     doc = new Document();
-    doc.add(new Field("d", "delete", Store.NO, Index.NOT_ANALYZED_NO_NORMS));
+    doc.add(new StringField("d", "delete"));
     w2.addDocument(doc);
     w2.commit();
     w2.deleteDocuments(new Term("d", "delete"));
@@ -1152,7 +1163,9 @@
       conf.setCodecProvider(provider);
       IndexWriter w = new IndexWriter(toAdd, conf);
       Document doc = new Document();
-      doc.add(newField("foo", "bar", Index.NOT_ANALYZED));
+      FieldType customType = new FieldType();
+      customType.setIndexed(true); 
+      doc.add(newField("foo", "bar", customType));
       w.addDocument(doc);
       w.close();
     }
Index: lucene/src/test/org/apache/lucene/index/TestTieredMergePolicy.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTieredMergePolicy.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestTieredMergePolicy.java	(working copy)
@@ -19,7 +19,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;
@@ -39,7 +39,7 @@
     w.setInfoStream(VERBOSE ? System.out : null);
     for(int i=0;i<80;i++) {
       Document doc = new Document();
-      doc.add(newField("content", "aaa " + (i%4), Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", "aaa " + (i%4), TextField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
     assertEquals(80, w.maxDoc());
@@ -86,7 +86,7 @@
       final int numDocs = _TestUtil.nextInt(random, 20, 100);
       for(int i=0;i<numDocs;i++) {
         Document doc = new Document();
-        doc.add(newField("content", "aaa " + (i%4), Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(newField("content", "aaa " + (i%4), TextField.TYPE_UNSTORED));
         w.addDocument(doc);
         int count = w.getSegmentCount();
         maxCount = Math.max(count, maxCount);
Index: lucene/src/test/org/apache/lucene/index/TestPayloads.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestPayloads.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestPayloads.java	(working copy)
@@ -35,6 +35,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.store.Directory;
@@ -101,15 +103,15 @@
         IndexWriter writer = new IndexWriter(ram, newIndexWriterConfig( TEST_VERSION_CURRENT, analyzer));
         Document d = new Document();
         // this field won't have any payloads
-        d.add(newField("f1", "This field has no payloads", Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField("f1", "This field has no payloads", TextField.TYPE_UNSTORED));
         // this field will have payloads in all docs, however not for all term positions,
         // so this field is used to check if the DocumentWriter correctly enables the payloads bit
         // even if only some term positions have payloads
-        d.add(newField("f2", "This field has payloads in all docs", Field.Store.NO, Field.Index.ANALYZED));
-        d.add(newField("f2", "This field has payloads in all docs", Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField("f2", "This field has payloads in all docs", TextField.TYPE_UNSTORED));
+        d.add(newField("f2", "This field has payloads in all docs", TextField.TYPE_UNSTORED));
         // this field is used to verify if the SegmentMerger enables payloads for a field if it has payloads 
         // enabled in only some documents
-        d.add(newField("f3", "This field has payloads in some docs", Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField("f3", "This field has payloads in some docs", TextField.TYPE_UNSTORED));
         // only add payload data for field f2
         analyzer.setPayloadData("f2", 1, "somedata".getBytes(), 0, 1);
         writer.addDocument(d);
@@ -128,10 +130,10 @@
         writer = new IndexWriter(ram, newIndexWriterConfig( TEST_VERSION_CURRENT,
             analyzer).setOpenMode(OpenMode.CREATE));
         d = new Document();
-        d.add(newField("f1", "This field has no payloads", Field.Store.NO, Field.Index.ANALYZED));
-        d.add(newField("f2", "This field has payloads in all docs", Field.Store.NO, Field.Index.ANALYZED));
-        d.add(newField("f2", "This field has payloads in all docs", Field.Store.NO, Field.Index.ANALYZED));
-        d.add(newField("f3", "This field has payloads in some docs", Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField("f1", "This field has no payloads", TextField.TYPE_UNSTORED));
+        d.add(newField("f2", "This field has payloads in all docs", TextField.TYPE_UNSTORED));
+        d.add(newField("f2", "This field has payloads in all docs", TextField.TYPE_UNSTORED));
+        d.add(newField("f3", "This field has payloads in some docs", TextField.TYPE_UNSTORED));
         // add payload data for field f2 and f3
         analyzer.setPayloadData("f2", "somedata".getBytes(), 0, 1);
         analyzer.setPayloadData("f3", "somedata".getBytes(), 0, 3);
@@ -188,7 +190,7 @@
         byte[] payloadData = generateRandomData(payloadDataLength);
         
         Document d = new Document();
-        d.add(newField(fieldName, content, Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField(fieldName, content, TextField.TYPE_UNSTORED));
         // add the same document multiple times to have the same payload lengths for all
         // occurrences within two consecutive skip intervals
         int offset = 0;
@@ -319,7 +321,7 @@
         String singleTerm = "lucene";
         
         d = new Document();
-        d.add(newField(fieldName, singleTerm, Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField(fieldName, singleTerm, TextField.TYPE_UNSTORED));
         // add a payload whose length is greater than the buffer size of BufferedIndexOutput
         payloadData = generateRandomData(2000);
         analyzer.setPayloadData(fieldName, payloadData, 100, 1500);
@@ -504,7 +506,7 @@
                     try {
                         for (int j = 0; j < numDocs; j++) {
                             Document d = new Document();
-                            d.add(new Field(field, new PoolingPayloadTokenStream(pool)));
+                            d.add(new TextField(field, new PoolingPayloadTokenStream(pool)));
                             writer.addDocument(d);
                         }
                     } catch (Exception e) {
@@ -605,14 +607,16 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, dir,
                                                      new MockAnalyzer(random, MockTokenizer.WHITESPACE, true));
     Document doc = new Document();
-    doc.add(new Field("hasMaybepayload", "here we go", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(new Field("hasMaybepayload", customType, "here we go"));
     writer.addDocument(doc);
     writer.close();
 
     writer = new RandomIndexWriter(random, dir,
                                    new MockAnalyzer(random, MockTokenizer.WHITESPACE, true));
     doc = new Document();
-    doc.add(new Field("hasMaybepayload2", "here we go", Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("hasMaybepayload2", customType, "here we go"));
     writer.addDocument(doc);
     writer.addDocument(doc);
     writer.optimize();
Index: lucene/src/test/org/apache/lucene/index/TestSameTokenSamePosition.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSameTokenSamePosition.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSameTokenSamePosition.java	(working copy)
@@ -27,6 +27,8 @@
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -41,8 +43,9 @@
     Directory dir = newDirectory();
     RandomIndexWriter riw = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new BugReproAnalyzer()));
     Document doc = new Document();
-    doc.add(new Field("eng", "Six drunken" /*This shouldn't matter. */, 
-                      Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(new Field("eng", customType, "Six drunken" /*This shouldn't matter. */));
     riw.addDocument(doc);
     riw.close();
     dir.close();
@@ -55,8 +58,7 @@
     Directory dir = newDirectory();
     RandomIndexWriter riw = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new BugReproAnalyzer()));
     Document doc = new Document();
-    doc.add(new Field("eng", "Six drunken" /*This shouldn't matter. */, 
-                      Field.Store.YES, Field.Index.ANALYZED));
+    doc.add(new Field("eng", TextField.TYPE_STORED, "Six drunken" /*This shouldn't matter. */));
     for (int i = 0; i < 100; i++) {
       riw.addDocument(doc);
     }
Index: lucene/src/test/org/apache/lucene/index/TestLongPostings.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestLongPostings.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestLongPostings.java	(working copy)
@@ -26,7 +26,9 @@
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
@@ -111,7 +113,7 @@
       for(int idx=0;idx<NUM_DOCS;idx++) {
         final Document doc = new Document();
         String s = isS1.get(idx) ? s1 : s2;
-        final Field f = newField("field", s, Field.Index.ANALYZED);
+        final Field f = newField("field", s, TextField.TYPE_UNSTORED);
         final int count = _TestUtil.nextInt(random, 1, 4);
         for(int ct=0;ct<count;ct++) {
           doc.add(f);
@@ -302,11 +304,12 @@
       iwc.setMaxBufferedDocs(-1);
       final RandomIndexWriter riw = new RandomIndexWriter(random, dir, iwc);
 
+      FieldType ft = new FieldType(TextField.TYPE_UNSTORED);
+      ft.setIndexOptions(options);
       for(int idx=0;idx<NUM_DOCS;idx++) {
         final Document doc = new Document();
         String s = isS1.get(idx) ? s1 : s2;
-        final Field f = newField("field", s, Field.Index.ANALYZED);
-        f.setIndexOptions(options);
+        final Field f = newField("field", s, ft);
         final int count = _TestUtil.nextInt(random, 1, 4);
         for(int ct=0;ct<count;ct++) {
           doc.add(f);
Index: lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestBackwardsCompatibility.java	(working copy)
@@ -29,9 +29,10 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DocIdSetIterator;
@@ -288,11 +289,11 @@
     for(int i=0;i<35;i++) {
       if (liveDocs.get(i)) {
         Document d = reader.document(i);
-        List<Fieldable> fields = d.getFields();
+        List<IndexableField> fields = d.getFields();
         if (d.getField("content3") == null) {
           final int numFields = 5;
           assertEquals(numFields, fields.size());
-          Field f =  d.getField("id");
+          IndexableField f =  d.getField("id");
           assertEquals(""+i, f.stringValue());
 
           f = d.getField("utf8");
@@ -594,12 +595,20 @@
   private void addDoc(IndexWriter writer, int id) throws IOException
   {
     Document doc = new Document();
-    doc.add(new Field("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
-    doc.add(new Field("id", Integer.toString(id), Field.Store.YES, Field.Index.NOT_ANALYZED));
-    doc.add(new Field("autf8", "Lu\uD834\uDD1Ece\uD834\uDD60ne \u0000 \u2620 ab\ud917\udc17cd", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("utf8", "Lu\uD834\uDD1Ece\uD834\uDD60ne \u0000 \u2620 ab\ud917\udc17cd", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("content2", "here is more content with aaa aaa aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
-    doc.add(new Field("fie\u2C77ld", "field with non-ascii name", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    doc.add(new TextField("content", "aaa"));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
+    doc.add(new Field("id", customType, Integer.toString(id)));
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    customType2.setStoreTermVectors(true);
+    customType2.setStoreTermVectorPositions(true);
+    customType2.setStoreTermVectorOffsets(true);
+    doc.add(new Field("autf8", customType2, "Lu\uD834\uDD1Ece\uD834\uDD60ne \u0000 \u2620 ab\ud917\udc17cd"));
+    doc.add(new Field("utf8", customType2, "Lu\uD834\uDD1Ece\uD834\uDD60ne \u0000 \u2620 ab\ud917\udc17cd"));
+    doc.add(new Field("content2", customType2, "here is more content with aaa aaa aaa"));
+    doc.add(new Field("fie\u2C77ld", customType2, "field with non-ascii name"));
     // add numeric fields, to test if flex preserves encoding
     doc.add(new NumericField("trieInt", 4).setIntValue(id));
     doc.add(new NumericField("trieLong", 4).setLongValue(id));
@@ -608,11 +617,14 @@
 
   private void addNoProxDoc(IndexWriter writer) throws IOException {
     Document doc = new Document();
-    Field f = new Field("content3", "aaa", Field.Store.YES, Field.Index.ANALYZED);
-    f.setIndexOptions(IndexOptions.DOCS_ONLY);
+    FieldType customType = new FieldType(TextField.TYPE_STORED);
+    customType.setIndexOptions(IndexOptions.DOCS_ONLY);
+    Field f = new Field("content3", customType, "aaa");
     doc.add(f);
-    f = new Field("content4", "aaa", Field.Store.YES, Field.Index.NO);
-    f.setIndexOptions(IndexOptions.DOCS_ONLY);
+    FieldType customType2 = new FieldType();
+    customType2.setStored(true);
+    customType2.setIndexOptions(IndexOptions.DOCS_ONLY);
+    f = new Field("content4", customType2, "aaa");
     doc.add(f);
     writer.addDocument(doc);
   }
Index: lucene/src/test/org/apache/lucene/index/TestLazyProxSkipping.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestLazyProxSkipping.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestLazyProxSkipping.java	(working copy)
@@ -25,8 +25,9 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.codecs.CodecProvider;
-import org.apache.lucene.document.Field;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.PhraseQuery;
 import org.apache.lucene.search.ScoreDoc;
@@ -85,6 +86,9 @@
                 setMaxBufferedDocs(10).
                 setMergePolicy(newLogMergePolicy(false))
         );
+        FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+        customType.setStored(true);
+        
         for (int i = 0; i < numDocs; i++) {
             Document doc = new Document();
             String content;
@@ -99,7 +103,7 @@
                 content = this.term3 + " " + this.term2;
             }
 
-            doc.add(newField(this.field, content, Field.Store.YES, Field.Index.ANALYZED));
+            doc.add(newField(this.field, content, customType));
             writer.addDocument(doc);
         }
         
@@ -146,9 +150,11 @@
     public void testSeek() throws IOException {
         Directory directory = newDirectory();
         IndexWriter writer = new IndexWriter(directory, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+        FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+        customType.setStored(true);
         for (int i = 0; i < 10; i++) {
             Document doc = new Document();
-            doc.add(newField(this.field, "a b", Field.Store.YES, Field.Index.ANALYZED));
+            doc.add(newField(this.field, "a b", customType));
             writer.addDocument(doc);
         }
         
Index: lucene/src/test/org/apache/lucene/index/TestNorms.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestNorms.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestNorms.java	(working copy)
@@ -25,8 +25,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DefaultSimilarityProvider;
@@ -220,7 +219,7 @@
     Document d = new Document();
     float boost = nextNorm("anyfield"); // in this test the same similarity is used for all fields so it does not matter what field is passed
     for (int i = 0; i < 10; i++) {
-      Field f = newField("f"+i,"v"+i,Store.NO,Index.NOT_ANALYZED);
+      Field f = newField("f"+i,"v"+i,TextField.TYPE_UNSTORED);
       f.setBoost(boost);
       d.add(f);
     }
@@ -277,8 +276,8 @@
     });
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, config);
     Document doc = new Document();
-    Field foo = newField("foo", "", Field.Store.NO, Field.Index.ANALYZED);
-    Field bar = newField("bar", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field foo = newField("foo", "", TextField.TYPE_UNSTORED);
+    Field bar = newField("bar", "", TextField.TYPE_UNSTORED);
     doc.add(foo);
     doc.add(bar);
     
Index: lucene/src/test/org/apache/lucene/index/TestStressAdvance.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestStressAdvance.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestStressAdvance.java	(working copy)
@@ -36,9 +36,11 @@
       RandomIndexWriter w = new RandomIndexWriter(random, dir);
       final Set<Integer> aDocs = new HashSet<Integer>();
       final Document doc = new Document();
-      final Field f = newField("field", "", Field.Index.NOT_ANALYZED_NO_NORMS);
+      FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+      customType.setStored(true);
+      final Field f = newField("field", "", StringField.TYPE_UNSTORED);
       doc.add(f);
-      final Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
+      final Field idField = newField("id", "", customType);
       doc.add(idField);
       int num = atLeast(4097);
       for(int id=0;id<num;id++) {
Index: lucene/src/test/org/apache/lucene/index/TestParallelTermEnum.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestParallelTermEnum.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestParallelTermEnum.java	(working copy)
@@ -22,8 +22,8 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.Bits;
 
@@ -41,11 +41,11 @@
         IndexWriter iw1 = new IndexWriter(rd1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
 
         doc = new Document();
-        doc.add(newField("field1", "the quick brown fox jumps", Store.YES,
-            Index.ANALYZED));
-        doc.add(newField("field2", "the quick brown fox jumps", Store.YES,
-            Index.ANALYZED));
-        doc.add(newField("field4", "", Store.NO, Index.ANALYZED));
+        FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+        customType.setStored(true);
+        doc.add(newField("field1", "the quick brown fox jumps", customType));
+        doc.add(newField("field2", "the quick brown fox jumps", customType));
+        doc.add(newField("field4", "", TextField.TYPE_UNSTORED));
         iw1.addDocument(doc);
 
         iw1.close();
@@ -53,11 +53,9 @@
         IndexWriter iw2 = new IndexWriter(rd2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
 
         doc = new Document();
-        doc.add(newField("field0", "", Store.NO, Index.ANALYZED));
-        doc.add(newField("field1", "the fox jumps over the lazy dog",
-            Store.YES, Index.ANALYZED));
-        doc.add(newField("field3", "the fox jumps over the lazy dog",
-            Store.YES, Index.ANALYZED));
+        doc.add(newField("field0", "", TextField.TYPE_UNSTORED));
+        doc.add(newField("field1", "the fox jumps over the lazy dog", customType));
+        doc.add(newField("field3", "the fox jumps over the lazy dog", customType));
         iw2.addDocument(doc);
 
         iw2.close();
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterUnicode.java	(working copy)
@@ -26,6 +26,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.CharsRef;
@@ -234,10 +237,10 @@
     Directory d = newDirectory();
     IndexWriter w = new IndexWriter(d, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    doc.add(newField("field", "a a\uffffb", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a a\uffffb", TextField.TYPE_UNSTORED));
     w.addDocument(doc);
     doc = new Document();
-    doc.add(newField("field", "a", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "a", TextField.TYPE_UNSTORED));
     w.addDocument(doc);
     IndexReader r = w.getReader();
     assertEquals(1, r.docFreq(new Term("field", "a\uffffb")));
@@ -252,9 +255,12 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new TestIndexWriter.StringSplitAnalyzer()));
     Document doc = new Document();
 
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    
     final int count = utf8Data.length/2;
     for(int i=0;i<count;i++)
-      doc.add(newField("f" + i, utf8Data[2*i], Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField("f" + i, utf8Data[2*i], customType));
     w.addDocument(doc);
     w.close();
 
@@ -276,7 +282,7 @@
     RandomIndexWriter writer = new RandomIndexWriter(rnd, dir);
     Document d = new Document();
     // Single segment
-    Field f = newField("f", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    Field f = newField("f", "", StringField.TYPE_UNSTORED);
     d.add(f);
     char[] chars = new char[2];
     final Set<String> allTerms = new HashSet<String>();
Index: lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReaderClone.java	(working copy)
@@ -22,7 +22,8 @@
 import org.apache.lucene.search.Similarity;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.LockObtainFailedException;
 import org.apache.lucene.util.LuceneTestCase;
@@ -500,7 +501,9 @@
             setMergePolicy(newLogMergePolicy(false))
     );
     Document doc = new Document();
-    doc.add(newField("field", "yes it's stored", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(newField("field", "yes it's stored", customType));
     w.addDocument(doc);
     w.close();
     IndexReader r1 = IndexReader.open(dir, false);
Index: lucene/src/test/org/apache/lucene/index/TestDocsAndPositions.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDocsAndPositions.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestDocsAndPositions.java	(working copy)
@@ -22,7 +22,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader.ReaderContext;
 import org.apache.lucene.store.Directory;
@@ -49,9 +50,11 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     for (int i = 0; i < 39; i++) {
       Document doc = new Document();
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setOmitNorms(true);
       doc.add(newField(fieldName, "1 2 3 4 5 6 7 8 9 10 "
           + "1 2 3 4 5 6 7 8 9 10 " + "1 2 3 4 5 6 7 8 9 10 "
-          + "1 2 3 4 5 6 7 8 9 10", Field.Store.NO, Field.Index.ANALYZED_NO_NORMS));
+          + "1 2 3 4 5 6 7 8 9 10", customType));
       writer.addDocument(doc);
     }
     IndexReader reader = writer.getReader();
@@ -117,6 +120,8 @@
     int max = 1051;
     int term = random.nextInt(max);
     Integer[][] positionsInDoc = new Integer[numDocs][];
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
       ArrayList<Integer> positions = new ArrayList<Integer>();
@@ -133,8 +138,7 @@
         builder.append(term);
         positions.add(num);
       }
-      doc.add(newField(fieldName, builder.toString(), Field.Store.NO,
-          Field.Index.ANALYZED_NO_NORMS));
+      doc.add(newField(fieldName, builder.toString(), customType));
       positionsInDoc[i] = positions.toArray(new Integer[0]);
       writer.addDocument(doc);
     }
@@ -199,6 +203,8 @@
     int max = 15678;
     int term = random.nextInt(max);
     int[] freqInDoc = new int[numDocs];
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
       StringBuilder builder = new StringBuilder();
@@ -209,8 +215,7 @@
           freqInDoc[i]++;
         }
       }
-      doc.add(newField(fieldName, builder.toString(), Field.Store.NO,
-          Field.Index.ANALYZED_NO_NORMS));
+      doc.add(newField(fieldName, builder.toString(), customType));
       writer.addDocument(doc);
     }
 
@@ -275,6 +280,8 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, dir,
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     int howMany = 1000;
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setOmitNorms(true);
     for (int i = 0; i < 39; i++) {
       Document doc = new Document();
       StringBuilder builder = new StringBuilder();
@@ -285,8 +292,7 @@
           builder.append("odd ");
         }
       }
-      doc.add(newField(fieldName, builder.toString(), Field.Store.NO,
-          Field.Index.ANALYZED_NO_NORMS));
+      doc.add(newField(fieldName, builder.toString(), customType));
       writer.addDocument(doc);
     }
 
Index: lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReaderOnDiskFull.java	(working copy)
@@ -21,7 +21,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreDoc;
@@ -50,10 +51,13 @@
       System.out.println("TEST: create initial index");
       writer.setInfoStream(System.out);
     }
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setTokenized(false);
     for(int i=0;i<157;i++) {
       Document d = new Document();
-      d.add(newField("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
-      d.add(newField("content", "aaa " + i, Field.Store.NO, Field.Index.ANALYZED));
+      d.add(newField("id", Integer.toString(i), customType));
+      d.add(newField("content", "aaa " + i, TextField.TYPE_UNSTORED));
       writer.addDocument(d);
       if (0==i%10)
         writer.commit();
Index: lucene/src/test/org/apache/lucene/index/TestRollback.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestRollback.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestRollback.java	(working copy)
@@ -19,8 +19,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -30,9 +30,12 @@
   public void testRollbackIntegrityWithBufferFlush() throws Exception {
     Directory dir = newDirectory();
     RandomIndexWriter rw = new RandomIndexWriter(random, dir);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setOmitNorms(true);
     for (int i = 0; i < 5; i++) {
       Document doc = new Document();
-      doc.add(newField("pk", Integer.toString(i), Store.YES, Index.ANALYZED_NO_NORMS));
+      doc.add(newField("pk", Integer.toString(i), customType));
       rw.addDocument(doc);
     }
     rw.close();
@@ -43,8 +46,8 @@
     for (int i = 0; i < 3; i++) {
       Document doc = new Document();
       String value = Integer.toString(i);
-      doc.add(newField("pk", value, Store.YES, Index.ANALYZED_NO_NORMS));
-      doc.add(newField("text", "foo", Store.YES, Index.ANALYZED_NO_NORMS));
+      doc.add(newField("pk", value, customType));
+      doc.add(newField("text", "foo", customType));
       w.updateDocument(new Term("pk", value), doc);
     }
     w.rollback();
Index: lucene/src/test/org/apache/lucene/index/TestTermVectorsReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTermVectorsReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestTermVectorsReader.java	(working copy)
@@ -31,6 +31,8 @@
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IOContext.Context;
@@ -101,16 +103,24 @@
 
     Document doc = new Document();
     for(int i=0;i<testFields.length;i++) {
-      final Field.TermVector tv;
-      if (testFieldsStorePos[i] && testFieldsStoreOff[i])
-        tv = Field.TermVector.WITH_POSITIONS_OFFSETS;
-      else if (testFieldsStorePos[i] && !testFieldsStoreOff[i])
-        tv = Field.TermVector.WITH_POSITIONS;
-      else if (!testFieldsStorePos[i] && testFieldsStoreOff[i])
-        tv = Field.TermVector.WITH_OFFSETS;
-      else
-        tv = Field.TermVector.YES;
-      doc.add(new Field(testFields[i], "", Field.Store.NO, Field.Index.ANALYZED, tv));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      if (testFieldsStorePos[i] && testFieldsStoreOff[i]) {
+        customType.setStoreTermVectors(true);
+        customType.setStoreTermVectorPositions(true);
+        customType.setStoreTermVectorOffsets(true);
+      }
+      else if (testFieldsStorePos[i] && !testFieldsStoreOff[i]) {
+        customType.setStoreTermVectors(true);
+        customType.setStoreTermVectorPositions(true);
+      }
+      else if (!testFieldsStorePos[i] && testFieldsStoreOff[i]) {
+        customType.setStoreTermVectors(true);
+        customType.setStoreTermVectorOffsets(true);
+      }
+      else {
+        customType.setStoreTermVectors(true);
+      }
+      doc.add(new Field(testFields[i], customType, ""));
     }
 
     //Create 5 documents for testing, they all have the same
Index: lucene/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestMultiLevelSkipList.java	(working copy)
@@ -27,8 +27,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
@@ -76,7 +75,7 @@
     Term term = new Term("test", "a");
     for (int i = 0; i < 5000; i++) {
       Document d1 = new Document();
-      d1.add(newField(term.field(), term.text(), Store.NO, Index.ANALYZED));
+      d1.add(newField(term.field(), term.text(), TextField.TYPE_UNSTORED));
       writer.addDocument(d1);
     }
     writer.commit();
Index: lucene/src/test/org/apache/lucene/index/TestTermVectorsWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTermVectorsWriter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestTermVectorsWriter.java	(working copy)
@@ -28,6 +28,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.MockDirectoryWrapper;
 import org.apache.lucene.store.RAMDirectory;
@@ -41,10 +44,14 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( 
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    Field f = newField("field", "abcd", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = newField("field", "abcd", customType);
     doc.add(f);
     doc.add(f);
-    Field f2 = newField("field", "", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    Field f2 = newField("field", "", customType);
     doc.add(f2);
     doc.add(f);
     w.addDocument(doc);
@@ -76,7 +83,11 @@
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    Field f = newField("field", "abcd", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = newField("field", "abcd", customType);
     doc.add(f);
     doc.add(f);
     w.addDocument(doc);
@@ -98,7 +109,11 @@
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    Field f = newField("field", "abcd   ", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = newField("field", "abcd   ", customType);
     doc.add(f);
     doc.add(f);
     w.addDocument(doc);
@@ -124,7 +139,11 @@
     TokenStream stream = analyzer.tokenStream("field", new StringReader("abcd   "));
     stream.reset(); // TODO: wierd to reset before wrapping with CachingTokenFilter... correct?
     stream = new CachingTokenFilter(stream);
-    Field f = new Field("field", stream, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = new Field("field", customType, stream);
     doc.add(f);
     doc.add(f);
     w.addDocument(doc);
@@ -147,7 +166,11 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( 
         TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.SIMPLE, true, MockTokenFilter.ENGLISH_STOPSET, true)));
     Document doc = new Document();
-    Field f = newField("field", "abcd the", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = newField("field", "abcd the", customType);
     doc.add(f);
     doc.add(f);
     w.addDocument(doc);
@@ -170,10 +193,12 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( 
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    Field f = newField("field", "abcd the  ", Field.Store.NO,
-        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
-    Field f2 = newField("field", "crunch man", Field.Store.NO,
-        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = newField("field", "abcd the  ", customType);
+    Field f2 = newField("field", "crunch man", customType);
     doc.add(f);
     doc.add(f2);
     w.addDocument(doc);
@@ -201,10 +226,12 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( 
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
-    Field f = newField("field", "", Field.Store.NO,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
-    Field f2 = newField("field", "crunch man", Field.Store.NO,
-        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    Field f = newField("field", "", customType);
+    Field f2 = newField("field", "crunch man", customType);
     doc.add(f);
     doc.add(f2);
     w.addDocument(doc);
@@ -229,14 +256,16 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( 
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document doc = new Document();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
 
-    Field f = newField("field", "abcd", Field.Store.NO,
-                        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    Field f = newField("field", "abcd", customType);
     doc.add(f);
-    doc.add(newField("field", "", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    doc.add(newField("field", "", customType));
 
-    Field f2 = newField("field", "crunch", Field.Store.NO,
-        Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+    Field f2 = newField("field", "crunch", customType);
     doc.add(f2);
 
     w.addDocument(doc);
@@ -268,18 +297,21 @@
               new LogDocMergePolicy()));
 
       Document document = new Document();
+      FieldType customType = new FieldType();
+      customType.setStored(true);
 
-      Field storedField = newField("stored", "stored", Field.Store.YES,
-                                    Field.Index.NO);
+      Field storedField = newField("stored", "stored", customType);
       document.add(storedField);
       writer.addDocument(document);
       writer.addDocument(document);
 
       document = new Document();
       document.add(storedField);
-      Field termVectorField = newField("termVector", "termVector",
-                                        Field.Store.NO, Field.Index.NOT_ANALYZED,
-                                        Field.TermVector.WITH_POSITIONS_OFFSETS);
+      FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+      customType2.setStoreTermVectors(true);
+      customType2.setStoreTermVectorPositions(true);
+      customType2.setStoreTermVectorOffsets(true);
+      Field termVectorField = newField("termVector", "termVector", customType2);
 
       document.add(termVectorField);
       writer.addDocument(document);
@@ -320,17 +352,21 @@
 
       Document document = new Document();
 
-      Field storedField = newField("stored", "stored", Field.Store.YES,
-                                    Field.Index.NO);
+      FieldType customType = new FieldType();
+      customType.setStored(true);
+
+      Field storedField = newField("stored", "stored", customType);
       document.add(storedField);
       writer.addDocument(document);
       writer.addDocument(document);
 
       document = new Document();
       document.add(storedField);
-      Field termVectorField = newField("termVector", "termVector",
-                                        Field.Store.NO, Field.Index.NOT_ANALYZED,
-                                        Field.TermVector.WITH_POSITIONS_OFFSETS);
+      FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+      customType2.setStoreTermVectors(true);
+      customType2.setStoreTermVectorPositions(true);
+      customType2.setStoreTermVectorOffsets(true);
+      Field termVectorField = newField("termVector", "termVector", customType2);
       document.add(termVectorField);
       writer.addDocument(document);
       writer.optimize();
@@ -357,12 +393,16 @@
     Document document = new Document();
 
     document = new Document();
-    Field storedField = newField("stored", "stored", Field.Store.YES,
-                                  Field.Index.NO);
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+
+    Field storedField = newField("stored", "stored", customType);
     document.add(storedField);
-    Field termVectorField = newField("termVector", "termVector",
-                                      Field.Store.NO, Field.Index.NOT_ANALYZED,
-                                      Field.TermVector.WITH_POSITIONS_OFFSETS);
+    FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+    customType2.setStoreTermVectors(true);
+    customType2.setStoreTermVectorPositions(true);
+    customType2.setStoreTermVectorOffsets(true);
+    Field termVectorField = newField("termVector", "termVector", customType2);
     document.add(termVectorField);
     for(int i=0;i<10;i++)
       writer.addDocument(document);
@@ -394,18 +434,22 @@
     IndexWriter iw = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document document = new Document();
-    document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
-        Field.TermVector.YES));
+    FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+    customType2.setStoreTermVectors(true);
+    customType2.setStoreTermVectorPositions(true);
+    customType2.setStoreTermVectorOffsets(true);
+    document.add(newField("tvtest", "a b c", customType2));
     iw.addDocument(document);
     document = new Document();
-    document.add(newField("tvtest", "x y z", Field.Store.NO, Field.Index.ANALYZED,
-                           Field.TermVector.NO));
+    document.add(newField("tvtest", "x y z", TextField.TYPE_UNSTORED));
     iw.addDocument(document);
     // Make first segment
     iw.commit();
 
-    document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
-        Field.TermVector.YES));
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    Field termVectorField = newField("termVector", "termVector", customType2);
+    document.add(newField("tvtest", "a b c", customType));
     iw.addDocument(document);
     // Make 2nd segment
     iw.commit();
@@ -421,22 +465,24 @@
     IndexWriter iw = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document document = new Document();
-    document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
-        Field.TermVector.YES));
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    Field termVectorField = newField("termVector", "termVector", customType);
+    document.add(newField("tvtest", "a b c", customType));
     iw.addDocument(document);
     iw.commit();
 
     document = new Document();
-    document.add(newField("tvtest", "x y z", Field.Store.NO, Field.Index.ANALYZED,
-                           Field.TermVector.NO));
+    document.add(newField("tvtest", "x y z", TextField.TYPE_UNSTORED));
     iw.addDocument(document);
     // Make first segment
     iw.commit();
 
     iw.optimize();
 
-    document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
-        Field.TermVector.YES));
+    FieldType customType2 = new FieldType(StringField.TYPE_UNSTORED);
+    customType2.setStoreTermVectors(true);
+    document.add(newField("tvtest", "a b c", customType2));
     iw.addDocument(document);
     // Make 2nd segment
     iw.commit();
Index: lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexFileDeleter.java	(working copy)
@@ -27,7 +27,8 @@
 import org.apache.lucene.store.MockDirectoryWrapper;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 
 import java.io.*;
@@ -230,8 +231,11 @@
   private void addDoc(IndexWriter writer, int id) throws IOException
   {
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
-    doc.add(newField("id", Integer.toString(id), Field.Store.YES, Field.Index.NOT_ANALYZED));
+    doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setIndexed(true);
+    customType.setTokenized(false);
+    doc.add(newField("id", Integer.toString(id), customType));
     writer.addDocument(doc);
   }
 }
Index: lucene/src/test/org/apache/lucene/index/TestMultiFields.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestMultiFields.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestMultiFields.java	(working copy)
@@ -40,9 +40,9 @@
 
       int numDocs = _TestUtil.nextInt(random, 1, 100 * RANDOM_MULTIPLIER);
       Document doc = new Document();
-      Field f = newField("field", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+      Field f = newField("field", "", StringField.TYPE_UNSTORED);
       doc.add(f);
-      Field id = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+      Field id = newField("id", "", StringField.TYPE_UNSTORED);
       doc.add(id);
 
       boolean onlyUniqueTerms = random.nextBoolean();
@@ -136,7 +136,7 @@
     Directory dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document d = new Document();
-    d.add(newField("f", "j", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    d.add(newField("f", "j", StringField.TYPE_UNSTORED));
     w.addDocument(d);
     w.commit();
     w.addDocument(d);
Index: lucene/src/test/org/apache/lucene/index/TestCrash.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestCrash.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestCrash.java	(working copy)
@@ -25,7 +25,8 @@
 import org.apache.lucene.store.NoLockFactory;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 
 public class TestCrash extends LuceneTestCase {
 
@@ -44,8 +45,10 @@
     }
     
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(newField("id", "0", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(false);
+    doc.add(newField("content", "aaa", customType));
+    doc.add(newField("id", "0", customType));
     for(int i=0;i<157;i++)
       writer.addDocument(doc);
 
Index: lucene/src/test/org/apache/lucene/index/TestCodecs.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestCodecs.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestCodecs.java	(working copy)
@@ -24,8 +24,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Store;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.codecs.FieldsConsumer;
 import org.apache.lucene.index.codecs.FieldsProducer;
@@ -342,7 +343,9 @@
       pq.add(new Term("content", "ccc"));
 
       final Document doc = new Document();
-      doc.add(newField("content", "aaa bbb ccc ddd", Store.NO, Field.Index.ANALYZED_NO_NORMS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setOmitNorms(true);
+      doc.add(newField("content", "aaa bbb ccc ddd", customType));
 
       // add document and force commit for creating a first segment
       writer.addDocument(doc);
Index: lucene/src/test/org/apache/lucene/index/TestThreadedOptimize.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestThreadedOptimize.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestThreadedOptimize.java	(working copy)
@@ -22,7 +22,8 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.util.English;
 
@@ -62,10 +63,14 @@
 
       ((LogMergePolicy) writer.getConfig().getMergePolicy()).setMergeFactor(1000);
 
+      final FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setOmitNorms(true);
+      
       for(int i=0;i<200;i++) {
         Document d = new Document();
-        d.add(newField("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-        d.add(newField("contents", English.intToEnglish(i), Field.Store.NO, Field.Index.ANALYZED_NO_NORMS));
+        d.add(newField("id", Integer.toString(i), customType));
+        d.add(newField("contents", English.intToEnglish(i), customType));
         writer.addDocument(d);
       }
 
@@ -85,8 +90,8 @@
                 writerFinal.optimize(false);
                 for(int k=0;k<17*(1+iFinal);k++) {
                   Document d = new Document();
-                  d.add(newField("id", iterFinal + "_" + iFinal + "_" + j + "_" + k, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
-                  d.add(newField("contents", English.intToEnglish(iFinal+k), Field.Store.NO, Field.Index.ANALYZED_NO_NORMS));
+                  d.add(newField("id", iterFinal + "_" + iFinal + "_" + j + "_" + k, customType));
+                  d.add(newField("contents", English.intToEnglish(iFinal+k), customType));
                   writerFinal.addDocument(d);
                 }
                 for(int k=0;k<9*(1+iFinal);k++)
Index: lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestUniqueTermCount.java	(working copy)
@@ -24,6 +24,7 @@
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.DefaultSimilarityProvider;
 import org.apache.lucene.search.Similarity;
@@ -54,7 +55,7 @@
     });
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, config);
     Document doc = new Document();
-    Field foo = newField("foo", "", Field.Store.NO, Field.Index.ANALYZED);
+    Field foo = newField("foo", "", TextField.TYPE_UNSTORED);
     doc.add(foo);
     for (int i = 0; i < 100; i++) {
       foo.setValue(addValue());
Index: lucene/src/test/org/apache/lucene/index/TestSumDocFreq.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSumDocFreq.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSumDocFreq.java	(working copy)
@@ -20,6 +20,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.util._TestUtil;
@@ -37,8 +38,8 @@
     RandomIndexWriter writer = new RandomIndexWriter(random, dir);
     
     Document doc = new Document();
-    Field field1 = newField("foo", "", Field.Index.ANALYZED);
-    Field field2 = newField("bar", "", Field.Index.ANALYZED);
+    Field field1 = newField("foo", "", TextField.TYPE_UNSTORED);
+    Field field2 = newField("bar", "", TextField.TYPE_UNSTORED);
     doc.add(field1);
     doc.add(field2);
     for (int i = 0; i < numDocs; i++) {
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterWithThreads.java	(working copy)
@@ -23,6 +23,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.MockDirectoryWrapper;
@@ -55,7 +57,13 @@
     public void run() {
 
       final Document doc = new Document();
-      doc.add(newField("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setStoreTermVectors(true);
+      customType.setStoreTermVectorPositions(true);
+      customType.setStoreTermVectorOffsets(true);
+      
+      doc.add(newField("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", customType));
 
       int idUpto = 0;
       int fullCount = 0;
@@ -291,7 +299,12 @@
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random))
       .setMaxBufferedDocs(2).setMergeScheduler(new ConcurrentMergeScheduler()));
     final Document doc = new Document();
-    doc.add(newField("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    customType.setStoreTermVectors(true);
+    customType.setStoreTermVectorPositions(true);
+    customType.setStoreTermVectorOffsets(true);
+    doc.add(newField("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", customType));
 
     for(int i=0;i<6;i++)
       writer.addDocument(doc);
@@ -464,8 +477,7 @@
      public void run() {
        try {
          Document doc = new Document();
-         Field field = newField("field", "testData", Field.Store.YES,
-             Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+         Field field = newField("field", "testData", TextField.TYPE_STORED);
          doc.add(field);
          IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
              TEST_VERSION_CURRENT, new MockAnalyzer(random)));
Index: lucene/src/test/org/apache/lucene/index/TestAtomicUpdate.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestAtomicUpdate.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestAtomicUpdate.java	(working copy)
@@ -93,10 +93,12 @@
     @Override
     public void doWork() throws Exception {
       // Update all 100 docs...
+      FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+      customType.setStored(true);
       for(int i=0; i<100; i++) {
         Document d = new Document();
-        d.add(new Field("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
-        d.add(new Field("contents", English.intToEnglish(i+10*count), Field.Store.NO, Field.Index.ANALYZED));
+        d.add(new Field("id", customType, Integer.toString(i)));
+        d.add(new TextField("contents", English.intToEnglish(i+10*count)));
         writer.updateDocument(new Term("id", Integer.toString(i)), d);
       }
     }
@@ -134,10 +136,12 @@
     writer.setInfoStream(VERBOSE ? System.out : null);
 
     // Establish a base index of 100 docs:
+    FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+    customType.setStored(true);
     for(int i=0;i<100;i++) {
       Document d = new Document();
-      d.add(newField("id", Integer.toString(i), Field.Store.YES, Field.Index.NOT_ANALYZED));
-      d.add(newField("contents", English.intToEnglish(i), Field.Store.NO, Field.Index.ANALYZED));
+      d.add(newField("id", Integer.toString(i), customType));
+      d.add(newField("contents", English.intToEnglish(i), TextField.TYPE_UNSTORED));
       if ((i-1)%7 == 0) {
         writer.commit();
       }
Index: lucene/src/test/org/apache/lucene/index/TestDocTermOrds.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDocTermOrds.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestDocTermOrds.java	(working copy)
@@ -28,6 +28,8 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.DocTermOrds.TermOrdsIterator;
 import org.apache.lucene.index.codecs.BlockTermsReader;
 import org.apache.lucene.index.codecs.BlockTermsWriter;
@@ -66,7 +68,7 @@
     Directory dir = newDirectory();
     final RandomIndexWriter w = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     Document doc = new Document();
-    Field field = newField("field", "", Field.Index.ANALYZED);
+    Field field = newField("field", "", TextField.TYPE_UNSTORED);
     doc.add(field);
     field.setValue("a b c");
     w.addDocument(doc);
@@ -281,7 +283,7 @@
       }
       for(int ord : ordsForDocSet) {
         ordsForDoc[upto++] = ord;
-        Field field = newField("field", termsArray[ord].utf8ToString(), Field.Index.NOT_ANALYZED_NO_NORMS);
+        Field field = newField("field", termsArray[ord].utf8ToString(), StringField.TYPE_UNSTORED);
         if (VERBOSE) {
           System.out.println("  f=" + termsArray[ord].utf8ToString());
         }
@@ -384,7 +386,7 @@
       }
       for(int ord : ordsForDocSet) {
         ordsForDoc[upto++] = ord;
-        Field field = newField("field", termsArray[ord].utf8ToString(), Field.Index.NOT_ANALYZED_NO_NORMS);
+        Field field = newField("field", termsArray[ord].utf8ToString(), StringField.TYPE_UNSTORED);
         if (VERBOSE) {
           System.out.println("  f=" + termsArray[ord].utf8ToString());
         }
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterDelete.java	(working copy)
@@ -32,6 +32,9 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
@@ -55,17 +58,18 @@
     IndexWriter modifier = new IndexWriter(dir, newIndexWriterConfig(
         TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)).setMaxBufferedDeleteTerms(1));
 
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
+    FieldType custom1 = new FieldType();
+    custom1.setStored(true);
+    FieldType custom2 = new FieldType(TextField.TYPE_UNSTORED);
+    custom2.setStored(true);
     for (int i = 0; i < keywords.length; i++) {
       Document doc = new Document();
-      doc.add(newField("id", keywords[i], Field.Store.YES,
-                        Field.Index.NOT_ANALYZED));
-      doc.add(newField("country", unindexed[i], Field.Store.YES,
-                        Field.Index.NO));
-      doc.add(newField("contents", unstored[i], Field.Store.NO,
-                        Field.Index.ANALYZED));
-      doc
-        .add(newField("city", text[i], Field.Store.YES,
-                       Field.Index.ANALYZED));
+      doc.add(newField("id", keywords[i], custom));
+      doc.add(newField("country", unindexed[i], custom1));
+      doc.add(newField("contents", unstored[i], TextField.TYPE_UNSTORED));
+      doc.add(newField("city", text[i], custom2));
       modifier.addDocument(doc);
     }
     modifier.optimize();
@@ -383,11 +387,11 @@
   private void updateDoc(IndexWriter modifier, int id, int value)
       throws IOException {
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
-    doc.add(newField("id", String.valueOf(id), Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
-    doc.add(newField("value", String.valueOf(value), Field.Store.NO,
-        Field.Index.NOT_ANALYZED));
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
+    doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
+    doc.add(newField("id", String.valueOf(id), custom));
+    doc.add(newField("value", String.valueOf(value), StringField.TYPE_UNSTORED));
     modifier.updateDocument(new Term("id", String.valueOf(id)), doc);
   }
 
@@ -395,11 +399,11 @@
   private void addDoc(IndexWriter modifier, int id, int value)
       throws IOException {
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
-    doc.add(newField("id", String.valueOf(id), Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
-    doc.add(newField("value", String.valueOf(value), Field.Store.NO,
-        Field.Index.NOT_ANALYZED));
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
+    doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
+    doc.add(newField("id", String.valueOf(id), custom));
+    doc.add(newField("value", String.valueOf(value), StringField.TYPE_UNSTORED));
     modifier.addDocument(doc);
   }
 
@@ -433,12 +437,12 @@
     // TODO: find the resource leak that only occurs sometimes here.
     startDir.setNoDeleteOpenFile(false);
     IndexWriter writer = new IndexWriter(startDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
     for (int i = 0; i < 157; i++) {
       Document d = new Document();
-      d.add(newField("id", Integer.toString(i), Field.Store.YES,
-                      Field.Index.NOT_ANALYZED));
-      d.add(newField("content", "aaa " + i, Field.Store.NO,
-                      Field.Index.ANALYZED));
+      d.add(newField("id", Integer.toString(i), custom));
+      d.add(newField("content", "aaa " + i, TextField.TYPE_UNSTORED));
       writer.addDocument(d);
     }
     writer.close();
@@ -516,10 +520,8 @@
             for (int i = 0; i < 13; i++) {
               if (updates) {
                 Document d = new Document();
-                d.add(newField("id", Integer.toString(i), Field.Store.YES,
-                                Field.Index.NOT_ANALYZED));
-                d.add(newField("content", "bbb " + i, Field.Store.NO,
-                                Field.Index.ANALYZED));
+                d.add(newField("id", Integer.toString(i), custom));
+                d.add(newField("content", "bbb " + i, TextField.TYPE_UNSTORED));
                 modifier.updateDocument(new Term("id", Integer.toString(docId)), d);
               } else { // deletes
                 modifier.deleteDocuments(new Term("id", Integer.toString(docId)));
@@ -708,16 +710,18 @@
 
     dir.failOn(failure.reset());
 
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
+    FieldType custom1 = new FieldType();
+    custom1.setStored(true);
+    FieldType custom2 = new FieldType(TextField.TYPE_UNSTORED);
+    custom2.setStored(true);
     for (int i = 0; i < keywords.length; i++) {
       Document doc = new Document();
-      doc.add(newField("id", keywords[i], Field.Store.YES,
-                        Field.Index.NOT_ANALYZED));
-      doc.add(newField("country", unindexed[i], Field.Store.YES,
-                        Field.Index.NO));
-      doc.add(newField("contents", unstored[i], Field.Store.NO,
-                        Field.Index.ANALYZED));
-      doc.add(newField("city", text[i], Field.Store.YES,
-                        Field.Index.ANALYZED));
+      doc.add(newField("id", keywords[i], StringField.TYPE_UNSTORED));
+      doc.add(newField("country", unindexed[i], custom1));
+      doc.add(newField("contents", unstored[i], TextField.TYPE_UNSTORED));
+      doc.add(newField("city", text[i], custom2));
       modifier.addDocument(doc);
     }
     // flush (and commit if ac)
@@ -831,16 +835,18 @@
     modifier.commit();
     dir.failOn(failure.reset());
 
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
+    FieldType custom1 = new FieldType();
+    custom1.setStored(true);
+    FieldType custom2 = new FieldType(TextField.TYPE_UNSTORED);
+    custom2.setStored(true);
     for (int i = 0; i < keywords.length; i++) {
       Document doc = new Document();
-      doc.add(newField("id", keywords[i], Field.Store.YES,
-                        Field.Index.NOT_ANALYZED));
-      doc.add(newField("country", unindexed[i], Field.Store.YES,
-                        Field.Index.NO));
-      doc.add(newField("contents", unstored[i], Field.Store.NO,
-                        Field.Index.ANALYZED));
-      doc.add(newField("city", text[i], Field.Store.YES,
-                        Field.Index.ANALYZED));
+      doc.add(newField("id", keywords[i], custom));
+      doc.add(newField("country", unindexed[i], custom1));
+      doc.add(newField("contents", unstored[i], TextField.TYPE_UNSTORED));
+      doc.add(newField("city", text[i], custom2));
       try {
         modifier.addDocument(doc);
       } catch (IOException io) {
@@ -883,7 +889,7 @@
     Collections.shuffle(ids, random);
     for(int id : ids) {
       Document doc = new Document();
-      doc.add(newField("id", ""+id, Field.Index.NOT_ANALYZED));
+      doc.add(newField("id", ""+id, StringField.TYPE_UNSTORED));
       w.addDocument(doc);
     }
     Collections.shuffle(ids, random);
@@ -917,7 +923,7 @@
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, analyzer).setRAMBufferSizeMB(1.0).setMaxBufferedDocs(IndexWriterConfig.DISABLE_AUTO_FLUSH).setMaxBufferedDeleteTerms(IndexWriterConfig.DISABLE_AUTO_FLUSH));
     w.setInfoStream(VERBOSE ? System.out : null);
     Document doc = new Document();
-    doc.add(newField("field", "go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field", "go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20", TextField.TYPE_UNSTORED));
     int num = atLeast(3);
     for (int iter = 0; iter < num; iter++) {
       int count = 0;
@@ -962,7 +968,7 @@
     int count = 0;
     while(true) {
       Document doc = new Document();
-      doc.add(new Field("id", count+"", Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(new StringField("id", count+""));
       final Term delTerm;
       if (count == 1010) {
         // This is the only delete that applies
@@ -1008,7 +1014,7 @@
     int count = 0;
     while(true) {
       Document doc = new Document();
-      doc.add(new Field("id", count+"", Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(new StringField("id", count+""));
       final Term delTerm;
       if (count == 1010) {
         // This is the only delete that applies
@@ -1062,8 +1068,8 @@
         w.deleteDocuments(new Term("id", "0"));
       }
       Document doc = new Document();
-      doc.add(newField("id", ""+id, Field.Index.NOT_ANALYZED));
-      doc.add(newField("body", sb.toString(), Field.Index.ANALYZED));
+      doc.add(newField("id", ""+id, StringField.TYPE_UNSTORED));
+      doc.add(newField("body", sb.toString(), TextField.TYPE_UNSTORED));
       w.updateDocument(new Term("id", ""+id), doc);
       docsInSegment.incrementAndGet();
       if (dir.fileExists("_0_1.del")) {
Index: lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexReaderReopen.java	(working copy)
@@ -31,9 +31,10 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.FieldCache;
@@ -168,12 +169,21 @@
     IndexReader reader = IndexReader.open(dir, false);
     try {
       int M = 3;
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setTokenized(false);
+      FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+      customType2.setStored(true);
+      customType2.setTokenized(false);
+      customType2.setOmitNorms(true);
+      FieldType customType3 = new FieldType();
+      customType3.setStored(true);
       for (int i=0; i<4; i++) {
         for (int j=0; j<M; j++) {
           Document doc = new Document();
-          doc.add(newField("id", i+"_"+j, Store.YES, Index.NOT_ANALYZED));
-          doc.add(newField("id2", i+"_"+j, Store.YES, Index.NOT_ANALYZED_NO_NORMS));
-          doc.add(newField("id3", i+"_"+j, Store.YES, Index.NO));
+          doc.add(newField("id", i+"_"+j, customType));
+          doc.add(newField("id2", i+"_"+j, customType2));
+          doc.add(newField("id3", i+"_"+j, customType3));
           iwriter.addDocument(doc);
           if (i>0) {
             int k = i-1;
@@ -957,13 +967,21 @@
     Document doc = new Document();
     sb.append("a");
     sb.append(n);
-    doc.add(new Field("field1", sb.toString(), Store.YES, Index.ANALYZED));
-    doc.add(new Field("fielda", sb.toString(), Store.YES, Index.NOT_ANALYZED_NO_NORMS));
-    doc.add(new Field("fieldb", sb.toString(), Store.YES, Index.NO));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    customType2.setTokenized(false);
+    customType2.setOmitNorms(true);
+    FieldType customType3 = new FieldType();
+    customType3.setStored(true);
+    doc.add(new Field("field1", customType, sb.toString()));
+    doc.add(new Field("fielda", customType2, sb.toString()));
+    doc.add(new Field("fieldb", customType3, sb.toString()));
     sb.append(" b");
     sb.append(n);
     for (int i = 1; i < numFields; i++) {
-      doc.add(new Field("field" + (i+1), sb.toString(), Store.YES, Index.ANALYZED));
+      doc.add(new Field("field" + (i+1), customType, sb.toString()));
     }
     return doc;
   }
@@ -1178,7 +1196,7 @@
     );
     for(int i=0;i<4;i++) {
       Document doc = new Document();
-      doc.add(newField("id", ""+i, Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("id", ""+i, StringField.TYPE_UNSTORED));
       writer.addDocument(doc);
       Map<String,String> data = new HashMap<String,String>();
       data.put("index", i+"");
@@ -1239,7 +1257,7 @@
             setMergePolicy(newLogMergePolicy(10))
     );
     Document doc = new Document();
-    doc.add(newField("number", "17", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("number", "17", StringField.TYPE_UNSTORED));
     writer.addDocument(doc);
     writer.commit();
 
Index: lucene/src/test/org/apache/lucene/index/TestStressIndexing.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestStressIndexing.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestStressIndexing.java	(working copy)
@@ -75,11 +75,13 @@
     @Override
     public void doWork() throws Exception {
       // Add 10 docs:
+      FieldType customType = new FieldType(StringField.TYPE_UNSTORED);
+      customType.setStored(true);
       for(int j=0; j<10; j++) {
         Document d = new Document();
         int n = random.nextInt();
-        d.add(newField("id", Integer.toString(nextID++), Field.Store.YES, Field.Index.NOT_ANALYZED));
-        d.add(newField("contents", English.intToEnglish(n), Field.Store.NO, Field.Index.ANALYZED));
+        d.add(newField("id", Integer.toString(nextID++), customType));
+        d.add(newField("contents", English.intToEnglish(n), TextField.TYPE_UNSTORED));
         writer.addDocument(d);
       }
 
Index: lucene/src/test/org/apache/lucene/index/TestTermdocPerf.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTermdocPerf.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestTermdocPerf.java	(working copy)
@@ -25,7 +25,7 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
@@ -69,7 +69,8 @@
     };
 
     Document doc = new Document();
-    doc.add(newField(field,val, Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS));
+    
+    doc.add(newField(field,val, StringField.TYPE_UNSTORED));
     IndexWriter writer = new IndexWriter(
         dir,
         newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer).
Index: lucene/src/test/org/apache/lucene/index/TestLazyBug.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestLazyBug.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestLazyBug.java	(working copy)
@@ -1,140 +0,0 @@
-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.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.lucene.analysis.MockAnalyzer;
-import org.apache.lucene.document.*;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.util.LuceneTestCase;
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-
-
-/**
- * Test demonstrating EOF bug on the last field of the last doc
- * if other docs have allready been accessed.
- */
-public class TestLazyBug extends LuceneTestCase {
-
-  public static int NUM_DOCS = TEST_NIGHTLY ? 500 : 50;
-  public static int NUM_FIELDS = TEST_NIGHTLY ? 100 : 10;
-
-  private static String[] data = new String[] {
-    "now",
-    "is the time",
-    "for all good men",
-    "to come to the aid",
-    "of their country!",
-    "this string contains big chars:{\u0111 \u0222 \u0333 \u1111 \u2222 \u3333}",
-    "this string is a bigger string, mary had a little lamb, little lamb, little lamb!"
-  };
-
-  private static Set<String> dataset = asSet(data);
-
-  private static String MAGIC_FIELD = "f"+(NUM_FIELDS/3);
-  
-  private static Directory directory;
-  
-  @BeforeClass
-  public static void beforeClass() throws Exception {
-    directory = makeIndex();
-  }
-  
-  @AfterClass
-  public static void afterClass() throws Exception {
-    directory.close();
-    directory = null;
-  }
-
-  private static FieldSelector SELECTOR = new FieldSelector() {
-      public FieldSelectorResult accept(String f) {
-        if (f.equals(MAGIC_FIELD)) {
-          return FieldSelectorResult.LOAD;
-        }
-        return FieldSelectorResult.LAZY_LOAD;
-      }
-    };
-
-  private static Directory makeIndex() throws Exception {
-    Directory dir = newDirectory();
-    try {
-      IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
-                                                                     TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
-      LogMergePolicy lmp = (LogMergePolicy) writer.getConfig().getMergePolicy();
-      lmp.setUseCompoundFile(false);
-      for (int d = 1; d <= NUM_DOCS; d++) {
-        Document doc = new Document();
-        for (int f = 1; f <= NUM_FIELDS; f++ ) {
-          doc.add(newField("f"+f,
-                            data[f % data.length]
-                            + '#' + data[random.nextInt(data.length)],
-                            Field.Store.NO,
-                            Field.Index.ANALYZED));
-        }
-        writer.addDocument(doc);
-      }
-      writer.close();
-    } catch (Exception e) {
-      throw new RuntimeException(e);
-    }
-    return dir;
-  }
-
-  public void doTest(int[] docs) throws Exception {
-    IndexReader reader = IndexReader.open(directory, true);
-    for (int i = 0; i < docs.length; i++) {
-      Document d = reader.document(docs[i], SELECTOR);
-      d.get(MAGIC_FIELD);
-
-      List<Fieldable> fields = d.getFields();
-      for (Iterator<Fieldable> fi = fields.iterator(); fi.hasNext(); ) {
-        Fieldable f=null;
-        try {
-          f =  fi.next();
-          String fname = f.name();
-          String fval = f.stringValue();
-          assertNotNull(docs[i]+" FIELD: "+fname, fval);
-          String[] vals = fval.split("#");
-          if (!dataset.contains(vals[0]) || !dataset.contains(vals[1])) {
-            fail("FIELD:"+fname+",VAL:"+fval);
-          }
-        } catch (Exception e) {
-          throw new Exception(docs[i]+" WTF: "+f.name(), e);
-        }
-      }
-    }
-    reader.close();
-  }
-
-  public void testLazyWorks() throws Exception {
-    doTest(new int[] { NUM_DOCS-1 });
-  }
-
-  public void testLazyAlsoWorks() throws Exception {
-    doTest(new int[] { NUM_DOCS-1, NUM_DOCS/2 });
-  }
-
-  public void testLazyBroken() throws Exception {
-    doTest(new int[] { NUM_DOCS/2, NUM_DOCS-1 });
-  }
-
-}
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java	(working copy)
@@ -19,9 +19,9 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -107,10 +107,12 @@
             setMergePolicy(newLogMergePolicy(2))
     );
 
+    FieldType custom = new FieldType(StringField.TYPE_UNSTORED);
+    custom.setStored(true);
     for (int i = start; i < (start + numDocs); i++)
     {
       Document temp = new Document();
-      temp.add(newField("count", (""+i), Field.Store.YES, Field.Index.NOT_ANALYZED));
+      temp.add(newField("count", (""+i), custom));
 
       writer.addDocument(temp);
     }
@@ -129,12 +131,19 @@
     Document document = new Document();
 
     document = new Document();
-    Field storedField = newField("stored", "stored", Field.Store.YES,
-                                  Field.Index.NO);
+
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+
+    FieldType customType1 = new FieldType(TextField.TYPE_UNSTORED);
+    customType1.setTokenized(false);
+    customType1.setStoreTermVectors(true);
+    customType1.setStoreTermVectorPositions(true);
+    customType1.setStoreTermVectorOffsets(true);
+    
+    Field storedField = newField("stored", "stored", customType);
     document.add(storedField);
-    Field termVectorField = newField("termVector", "termVector",
-                                      Field.Store.NO, Field.Index.NOT_ANALYZED,
-                                      Field.TermVector.WITH_POSITIONS_OFFSETS);
+    Field termVectorField = newField("termVector", "termVector", customType1);
     document.add(termVectorField);
     for(int i=0;i<10;i++)
       writer.addDocument(document);
@@ -175,12 +184,19 @@
     Document document = new Document();
 
     document = new Document();
-    Field storedField = newField("stored", "stored", Store.YES,
-                                  Index.NO);
+
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+
+    FieldType customType1 = new FieldType(TextField.TYPE_UNSTORED);
+    customType1.setTokenized(false);
+    customType1.setStoreTermVectors(true);
+    customType1.setStoreTermVectorPositions(true);
+    customType1.setStoreTermVectorOffsets(true);
+    
+    Field storedField = newField("stored", "stored", customType);
     document.add(storedField);
-    Field termVectorField = newField("termVector", "termVector",
-                                      Store.NO, Index.NOT_ANALYZED,
-                                      TermVector.WITH_POSITIONS_OFFSETS);
+    Field termVectorField = newField("termVector", "termVector", customType1);
     document.add(termVectorField);
     for(int i=0;i<98;i++)
       writer.addDocument(document);
@@ -223,13 +239,19 @@
 
     Document document = new Document();
 
+    FieldType customType = new FieldType();
+    customType.setStored(true);
+
+    FieldType customType1 = new FieldType(TextField.TYPE_UNSTORED);
+    customType1.setTokenized(false);
+    customType1.setStoreTermVectors(true);
+    customType1.setStoreTermVectorPositions(true);
+    customType1.setStoreTermVectorOffsets(true);
+    
     document = new Document();
-    Field storedField = newField("stored", "stored", Field.Store.YES,
-                                  Field.Index.NO);
+    Field storedField = newField("stored", "stored", customType);
     document.add(storedField);
-    Field termVectorField = newField("termVector", "termVector",
-                                      Field.Store.NO, Field.Index.NOT_ANALYZED,
-                                      Field.TermVector.WITH_POSITIONS_OFFSETS);
+    Field termVectorField = newField("termVector", "termVector", customType1);
     document.add(termVectorField);
     for(int i=0;i<98;i++)
       writer.addDocument(document);
@@ -292,8 +314,11 @@
     IndexWriter iw = new IndexWriter(dir, conf);
     iw.setInfoStream(VERBOSE ? System.out : null);
     Document document = new Document();
-    document.add(newField("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED,
-                           Field.TermVector.YES));
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStoreTermVectors(true);
+    
+    document.add(newField("tvtest", "a b c", customType));
     for(int i=0;i<177;i++)
       iw.addDocument(document);
     iw.close();
Index: lucene/src/test/org/apache/lucene/index/Test2BTerms.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/Test2BTerms.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/Test2BTerms.java	(working copy)
@@ -177,9 +177,12 @@
 
       Document doc = new Document();
       final MyTokenStream ts = new MyTokenStream(random, TERMS_PER_DOC);
-      Field field = new Field("field", ts);
-      field.setIndexOptions(IndexOptions.DOCS_ONLY);
-      field.setOmitNorms(true);
+
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setIndexOptions(IndexOptions.DOCS_ONLY);
+      customType.setOmitNorms(true);
+      Field field = new Field("field", customType, ts);
       doc.add(field);
       //w.setInfoStream(System.out);
       final int numDocs = (int) (TERM_COUNT/TERMS_PER_DOC);
Index: lucene/src/test/org/apache/lucene/index/TestSegmentInfo.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSegmentInfo.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSegmentInfo.java	(working copy)
@@ -3,8 +3,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 
@@ -33,7 +33,9 @@
     IndexWriter writer = new IndexWriter(dir, conf);
     writer.setInfoStream(VERBOSE ? System.out : null);
     Document doc = new Document();
-    doc.add(new Field("a", "value", Store.YES, Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    doc.add(new Field("a", customType, "value"));
     writer.addDocument(doc);
     writer.close();
     
Index: lucene/src/test/org/apache/lucene/index/TestParallelReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestParallelReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestParallelReader.java	(working copy)
@@ -18,14 +18,13 @@
  */
 
 import java.io.IOException;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Random;
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.MapFieldSelector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.BooleanClause.Occur;
 import org.apache.lucene.search.*;
 import org.apache.lucene.store.Directory;
@@ -89,30 +88,6 @@
     dir2.close();
   }
   
-  public void testDocument() throws IOException {
-    Directory dir1 = getDir1(random);
-    Directory dir2 = getDir2(random);
-    ParallelReader pr = new ParallelReader();
-    pr.add(IndexReader.open(dir1, false));
-    pr.add(IndexReader.open(dir2, false));
-
-    Document doc11 = pr.document(0, new MapFieldSelector("f1"));
-    Document doc24 = pr.document(1, new MapFieldSelector(Arrays.asList("f4")));
-    Document doc223 = pr.document(1, new MapFieldSelector("f2", "f3"));
-    
-    assertEquals(1, doc11.getFields().size());
-    assertEquals(1, doc24.getFields().size());
-    assertEquals(2, doc223.getFields().size());
-    
-    assertEquals("v1", doc11.get("f1"));
-    assertEquals("v2", doc24.get("f4"));
-    assertEquals("v2", doc223.get("f2"));
-    assertEquals("v2", doc223.get("f3"));
-    pr.close();
-    dir1.close();
-    dir2.close();
-  }
-  
   public void testIncompatibleIndexes() throws IOException {
     // two documents:
     Directory dir1 = getDir1(random);
@@ -121,7 +96,10 @@
     Directory dir2 = newDirectory();
     IndexWriter w2 = new IndexWriter(dir2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document d3 = new Document();
-    d3.add(newField("f3", "v1", Field.Store.YES, Field.Index.ANALYZED));
+
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d3.add(newField("f3", "v1", customType));
     w2.addDocument(d3);
     w2.close();
     
@@ -179,7 +157,9 @@
             setMergePolicy(newLogMergePolicy(10))
     );
     Document d = new Document();
-    d.add(newField("f1", "v1", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d.add(newField("f1", "v1", customType));
     modifier.addDocument(d);
     modifier.close();
 
@@ -189,7 +169,7 @@
             setMergePolicy(newLogMergePolicy(10))
     );
     d = new Document();
-    d.add(newField("f2", "v2", Field.Store.YES, Field.Index.ANALYZED));
+    d.add(newField("f2", "v2", customType));
     modifier.addDocument(d);
     modifier.close();
 
@@ -246,16 +226,18 @@
     dir = newDirectory();
     IndexWriter w = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document d1 = new Document();
-    d1.add(newField("f1", "v1", Field.Store.YES, Field.Index.ANALYZED));
-    d1.add(newField("f2", "v1", Field.Store.YES, Field.Index.ANALYZED));
-    d1.add(newField("f3", "v1", Field.Store.YES, Field.Index.ANALYZED));
-    d1.add(newField("f4", "v1", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d1.add(newField("f1", "v1", customType));
+    d1.add(newField("f2", "v1", customType));
+    d1.add(newField("f3", "v1", customType));
+    d1.add(newField("f4", "v1", customType));
     w.addDocument(d1);
     Document d2 = new Document();
-    d2.add(newField("f1", "v2", Field.Store.YES, Field.Index.ANALYZED));
-    d2.add(newField("f2", "v2", Field.Store.YES, Field.Index.ANALYZED));
-    d2.add(newField("f3", "v2", Field.Store.YES, Field.Index.ANALYZED));
-    d2.add(newField("f4", "v2", Field.Store.YES, Field.Index.ANALYZED));
+    d2.add(newField("f1", "v2", customType));
+    d2.add(newField("f2", "v2", customType));
+    d2.add(newField("f3", "v2", customType));
+    d2.add(newField("f4", "v2", customType));
     w.addDocument(d2);
     w.close();
 
@@ -276,12 +258,14 @@
     Directory dir1 = newDirectory();
     IndexWriter w1 = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document d1 = new Document();
-    d1.add(newField("f1", "v1", Field.Store.YES, Field.Index.ANALYZED));
-    d1.add(newField("f2", "v1", Field.Store.YES, Field.Index.ANALYZED));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d1.add(newField("f1", "v1", customType));
+    d1.add(newField("f2", "v1", customType));
     w1.addDocument(d1);
     Document d2 = new Document();
-    d2.add(newField("f1", "v2", Field.Store.YES, Field.Index.ANALYZED));
-    d2.add(newField("f2", "v2", Field.Store.YES, Field.Index.ANALYZED));
+    d2.add(newField("f1", "v2", customType));
+    d2.add(newField("f2", "v2", customType));
     w1.addDocument(d2);
     w1.close();
     return dir1;
@@ -289,14 +273,16 @@
 
   private Directory getDir2(Random random) throws IOException {
     Directory dir2 = newDirectory();
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     IndexWriter w2 = new IndexWriter(dir2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
     Document d3 = new Document();
-    d3.add(newField("f3", "v1", Field.Store.YES, Field.Index.ANALYZED));
-    d3.add(newField("f4", "v1", Field.Store.YES, Field.Index.ANALYZED));
+    d3.add(newField("f3", "v1", customType));
+    d3.add(newField("f4", "v1", customType));
     w2.addDocument(d3);
     Document d4 = new Document();
-    d4.add(newField("f3", "v2", Field.Store.YES, Field.Index.ANALYZED));
-    d4.add(newField("f4", "v2", Field.Store.YES, Field.Index.ANALYZED));
+    d4.add(newField("f3", "v2", customType));
+    d4.add(newField("f4", "v2", customType));
     w2.addDocument(d4);
     w2.close();
     return dir2;
Index: lucene/src/test/org/apache/lucene/index/codecs/pulsing/Test10KPulsings.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/codecs/pulsing/Test10KPulsings.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/codecs/pulsing/Test10KPulsings.java	(working copy)
@@ -26,6 +26,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.IndexReader;
@@ -60,14 +62,15 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setCodecProvider(cp));
     
     Document document = new Document();
-    Field field = newField("field", "", Field.Store.YES, Field.Index.ANALYZED);
+    FieldType ft = new FieldType(TextField.TYPE_STORED);
     
     switch(_TestUtil.nextInt(random, 0, 2)) {
-      case 0: field.setIndexOptions(IndexOptions.DOCS_ONLY); break;
-      case 1: field.setIndexOptions(IndexOptions.DOCS_AND_FREQS); break;
-      default: field.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); break; 
+      case 0: ft.setIndexOptions(IndexOptions.DOCS_ONLY); break;
+      case 1: ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS); break;
+      default: ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); break; 
     }
 
+    Field field = newField("field", "", ft);
     document.add(field);
     
     NumberFormat df = new DecimalFormat("00000", new DecimalFormatSymbols(Locale.ENGLISH));
@@ -111,14 +114,15 @@
         newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setCodecProvider(cp));
     
     Document document = new Document();
-    Field field = newField("field", "", Field.Store.YES, Field.Index.ANALYZED);
+    FieldType ft = new FieldType(TextField.TYPE_STORED);
     
     switch(_TestUtil.nextInt(random, 0, 2)) {
-      case 0: field.setIndexOptions(IndexOptions.DOCS_ONLY); break;
-      case 1: field.setIndexOptions(IndexOptions.DOCS_AND_FREQS); break;
-      default: field.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); break; 
+      case 0: ft.setIndexOptions(IndexOptions.DOCS_ONLY); break;
+      case 1: ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS); break;
+      default: ft.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS); break; 
     }
 
+    Field field = newField("field", "", ft);
     document.add(field);
     
     NumberFormat df = new DecimalFormat("00000", new DecimalFormatSymbols(Locale.ENGLISH));
Index: lucene/src/test/org/apache/lucene/index/codecs/preflex/TestSurrogates.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/codecs/preflex/TestSurrogates.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/codecs/preflex/TestSurrogates.java	(working copy)
@@ -303,7 +303,9 @@
         uniqueTerms.add(term);
         fieldTerms.add(new Term(field, term));
         Document doc = new Document();
-        doc.add(newField(field, term, Field.Store.NO, Field.Index.NOT_ANALYZED));
+        FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+        customType.setTokenized(false);
+        doc.add(newField(field, term, customType));
         w.addDocument(doc);
       }
       uniqueTermCount += uniqueTerms.size();
Index: lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestDeletionPolicy.java	(working copy)
@@ -26,6 +26,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.search.DefaultSimilarity;
 import org.apache.lucene.search.IndexSearcher;
@@ -853,7 +854,7 @@
   private void addDoc(IndexWriter writer) throws IOException
   {
     Document doc = new Document();
-    doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
     writer.addDocument(doc);
   }
 }
Index: lucene/src/test/org/apache/lucene/index/TestPerFieldCodecSupport.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestPerFieldCodecSupport.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestPerFieldCodecSupport.java	(working copy)
@@ -22,7 +22,8 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.CheckIndex.Status;
 import org.apache.lucene.index.CheckIndex.Status.SegmentInfoStatus;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -63,7 +64,7 @@
   private void addDocs(IndexWriter writer, int numDocs) throws IOException {
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
   }
@@ -71,16 +72,18 @@
   private void addDocs2(IndexWriter writer, int numDocs) throws IOException {
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(newField("content", "bbb", Field.Store.NO, Field.Index.ANALYZED));
+      doc.add(newField("content", "bbb", TextField.TYPE_UNSTORED));
       writer.addDocument(doc);
     }
   }
 
   private void addDocs3(IndexWriter writer, int numDocs) throws IOException {
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < numDocs; i++) {
       Document doc = new Document();
-      doc.add(newField("content", "ccc", Field.Store.NO, Field.Index.ANALYZED));
-      doc.add(newField("id", "" + i, Field.Store.YES, Field.Index.ANALYZED));
+      doc.add(newField("content", "ccc", TextField.TYPE_UNSTORED));
+      doc.add(newField("id", "" + i, customType));
       writer.addDocument(doc);
     }
   }
@@ -271,8 +274,6 @@
   @Test
   public void testStressPerFieldCodec() throws IOException {
     Directory dir = newDirectory(random);
-    Index[] indexValue = new Index[] { Index.ANALYZED, Index.ANALYZED_NO_NORMS,
-        Index.NOT_ANALYZED, Index.NOT_ANALYZED_NO_NORMS };
     final int docsPerRound = 97;
     int numRounds = atLeast(1);
     for (int i = 0; i < numRounds; i++) {
@@ -297,9 +298,11 @@
       for (int j = 0; j < docsPerRound; j++) {
         final Document doc = new Document();
         for (int k = 0; k < num; k++) {
+          FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+          customType.setTokenized(random.nextBoolean());
+          customType.setOmitNorms(random.nextBoolean());
           Field field = newField("" + k, _TestUtil
-              .randomRealisticUnicodeString(random, 128), indexValue[random
-              .nextInt(indexValue.length)]);
+              .randomRealisticUnicodeString(random, 128), customType);
           doc.add(field);
         }
         writer.addDocument(doc);
Index: lucene/src/test/org/apache/lucene/index/TestSegmentReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSegmentReader.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestSegmentReader.java	(working copy)
@@ -26,7 +26,6 @@
 import org.apache.lucene.util.BytesRef;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IOContext.Context;
@@ -68,8 +67,8 @@
     //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<Fieldable> fields = result.getFields();
-    for (final Fieldable field : fields ) { 
+    List<IndexableField> fields = result.getFields();
+    for (final IndexableField field : fields ) { 
       assertTrue(field != null);
       assertTrue(DocHelper.nameValues.containsKey(field.name()));
     }
@@ -176,9 +175,9 @@
   public static void checkNorms(IndexReader reader) throws IOException {
         // test omit norms
     for (int i=0; i<DocHelper.fields.length; i++) {
-      Fieldable f = DocHelper.fields[i];
-      if (f.isIndexed()) {
-        assertEquals(reader.hasNorms(f.name()), !f.getOmitNorms());
+      IndexableField f = DocHelper.fields[i];
+      if (f.indexed()) {
+        assertEquals(reader.hasNorms(f.name()), !f.omitNorms());
         assertEquals(reader.hasNorms(f.name()), !DocHelper.noNorms.containsKey(f.name()));
         if (!reader.hasNorms(f.name())) {
           // test for norms of null
Index: lucene/src/test/org/apache/lucene/index/TestParallelReaderEmptyIndex.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestParallelReaderEmptyIndex.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestParallelReaderEmptyIndex.java	(working copy)
@@ -25,9 +25,8 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 
 /**
@@ -77,11 +76,11 @@
     {
       IndexWriter iw = new IndexWriter(rd1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
       Document doc = new Document();
-      doc.add(newField("test", "", Store.NO, Index.ANALYZED,
-                        TermVector.YES));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStoreTermVectors(true);
+      doc.add(newField("test", "", customType));
       iw.addDocument(doc);
-      doc.add(newField("test", "", Store.NO, Index.ANALYZED,
-                        TermVector.NO));
+      doc.add(newField("test", "", TextField.TYPE_UNSTORED));
       iw.addDocument(doc);
       iw.close();
 
Index: lucene/src/test/org/apache/lucene/index/TestConsistentFieldNumbers.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestConsistentFieldNumbers.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/index/TestConsistentFieldNumbers.java	(working copy)
@@ -20,11 +20,11 @@
 import java.io.IOException;
 
 import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.BinaryField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
 import org.junit.Test;
@@ -38,8 +38,11 @@
       IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(NoMergePolicy.COMPOUND_FILES));
 
       Document d1 = new Document();
-      d1.add(new Field("f1", "first field", Store.YES, Index.ANALYZED, TermVector.NO));
-      d1.add(new Field("f2", "second field", Store.YES, Index.ANALYZED, TermVector.NO));
+      FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+      customType.setStored(true);
+      customType.setTokenized(false);
+      d1.add(new Field("f1", customType, "first field"));
+      d1.add(new Field("f2", customType, "second field"));
       writer.addDocument(d1);
 
       if (i == 1) {
@@ -50,10 +53,13 @@
       }
 
       Document d2 = new Document();
-      d2.add(new Field("f2", "second field", Store.YES, Index.ANALYZED, TermVector.NO));
-      d2.add(new Field("f1", "first field", Store.YES, Index.ANALYZED, TermVector.YES));
-      d2.add(new Field("f3", "third field", Store.YES, Index.ANALYZED, TermVector.NO));
-      d2.add(new Field("f4", "fourth field", Store.YES, Index.ANALYZED, TermVector.NO));
+      FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+      customType2.setStored(true);
+      customType2.setStoreTermVectors(true);
+      d2.add(new TextField("f2", "second field"));
+      d2.add(new Field("f1", customType2, "first field"));
+      d2.add(new TextField("f3", "third field"));
+      d2.add(new TextField("f4", "fourth field"));
       writer.addDocument(d2);
 
       writer.close();
@@ -99,18 +105,23 @@
     IndexWriter writer = new IndexWriter(dir1, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(NoMergePolicy.COMPOUND_FILES));
 
     Document d1 = new Document();
-    d1.add(new Field("f1", "first field", Store.YES, Index.ANALYZED, TermVector.NO));
-    d1.add(new Field("f2", "second field", Store.YES, Index.ANALYZED, TermVector.NO));
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    d1.add(new Field("f1", customType, "first field"));
+    d1.add(new Field("f2", customType, "second field"));
     writer.addDocument(d1);
 
     writer.close();
     writer = new IndexWriter(dir2, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(NoMergePolicy.COMPOUND_FILES));
 
     Document d2 = new Document();
-    d2.add(new Field("f2", "second field", Store.YES, Index.ANALYZED, TermVector.NO));
-    d2.add(new Field("f1", "first field", Store.YES, Index.ANALYZED, TermVector.YES));
-    d2.add(new Field("f3", "third field", Store.YES, Index.ANALYZED, TermVector.NO));
-    d2.add(new Field("f4", "fourth field", Store.YES, Index.ANALYZED, TermVector.NO));
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    customType2.setStoreTermVectors(true);
+    d2.add(new Field("f2", customType, "second field"));
+    d2.add(new Field("f1", customType2, "first field"));
+    d2.add(new Field("f3", customType, "third field"));
+    d2.add(new Field("f4", customType, "fourth field"));
     writer.addDocument(d2);
 
     writer.close();
@@ -156,6 +167,8 @@
   
   public void testFieldNumberGaps() throws IOException {
     int numIters = atLeast(13);
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
     for (int i = 0; i < numIters; i++) {
       Directory dir = newDirectory();
       {
@@ -163,10 +176,8 @@
             TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(
             NoMergePolicy.NO_COMPOUND_FILES));
         Document d = new Document();
-        d.add(new Field("f1", "d1 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d1 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
+        d.add(new Field("f1", customType, "d1 first field"));
+        d.add(new Field("f2", customType, "d1 second field"));
         writer.addDocument(d);
         writer.close();
         SegmentInfos sis = new SegmentInfos();
@@ -185,9 +196,8 @@
             random.nextBoolean() ? NoMergePolicy.NO_COMPOUND_FILES
                 : NoMergePolicy.COMPOUND_FILES));
         Document d = new Document();
-        d.add(new Field("f1", "d2 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3 }));
+        d.add(new Field("f1", customType, "d2 first field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3 }));
         writer.addDocument(d);
         writer.close();
         SegmentInfos sis = new SegmentInfos();
@@ -210,11 +220,9 @@
             random.nextBoolean() ? NoMergePolicy.NO_COMPOUND_FILES
                 : NoMergePolicy.COMPOUND_FILES));
         Document d = new Document();
-        d.add(new Field("f1", "d3 first field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f2", "d3 second field", Store.YES, Index.ANALYZED,
-            TermVector.NO));
-        d.add(new Field("f3", new byte[] { 1, 2, 3, 4, 5 }));
+        d.add(new Field("f1", customType, "d3 first field"));
+        d.add(new Field("f2", customType, "d3 second field"));
+        d.add(new BinaryField("f3", new byte[] { 1, 2, 3, 4, 5 }));
         writer.addDocument(d);
         writer.close();
         SegmentInfos sis = new SegmentInfos();
@@ -303,10 +311,10 @@
 
       for (FieldInfo fi : fis) {
         Field expected = getField(Integer.parseInt(fi.name));
-        assertEquals(expected.isIndexed(), fi.isIndexed);
-        assertEquals(expected.isTermVectorStored(), fi.storeTermVector);
-        assertEquals(expected.isStorePositionWithTermVector(), fi.storePositionWithTermVector);
-        assertEquals(expected.isStoreOffsetWithTermVector(), fi.storeOffsetWithTermVector);
+        assertEquals(expected.indexed(), fi.isIndexed);
+        assertEquals(expected.storeTermVectors(), fi.storeTermVector);
+        assertEquals(expected.storeTermVectorPositions(), fi.storePositionWithTermVector);
+        assertEquals(expected.storeTermVectorOffsets(), fi.storeOffsetWithTermVector);
       }
     }
 
@@ -316,23 +324,99 @@
   private Field getField(int number) {
     int mode = number % 16;
     String fieldName = "" + number;
+    FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
+    customType.setStored(true);
+    
+    FieldType customType2 = new FieldType(TextField.TYPE_UNSTORED);
+    customType2.setStored(true);
+    customType2.setTokenized(false);
+    
+    FieldType customType3 = new FieldType(TextField.TYPE_UNSTORED);
+    customType3.setTokenized(false);
+    
+    FieldType customType4 = new FieldType(TextField.TYPE_UNSTORED);
+    customType4.setTokenized(false);
+    customType4.setStored(false);
+    customType4.setStoreTermVectors(true);
+    customType4.setStoreTermVectorOffsets(true);
+    
+    FieldType customType5 = new FieldType(TextField.TYPE_UNSTORED);
+    customType5.setStoreTermVectors(true);
+    customType5.setStoreTermVectorOffsets(true);
+
+    FieldType customType6 = new FieldType(TextField.TYPE_UNSTORED);
+    customType6.setTokenized(false);
+    customType6.setStored(true);
+    customType6.setStoreTermVectors(true);
+    customType6.setStoreTermVectorOffsets(true);
+
+    FieldType customType7 = new FieldType(TextField.TYPE_UNSTORED);
+    customType7.setTokenized(false);
+    customType7.setStoreTermVectors(true);
+    customType7.setStoreTermVectorOffsets(true);
+
+    FieldType customType8 = new FieldType(TextField.TYPE_UNSTORED);
+    customType8.setTokenized(false);
+    customType8.setStored(true);
+    customType8.setStoreTermVectors(true);
+    customType8.setStoreTermVectorPositions(true);
+
+    FieldType customType9 = new FieldType(TextField.TYPE_UNSTORED);
+    customType9.setStoreTermVectors(true);
+    customType9.setStoreTermVectorPositions(true);
+
+    FieldType customType10 = new FieldType(TextField.TYPE_UNSTORED);
+    customType10.setTokenized(false);
+    customType10.setStored(true);
+    customType10.setStoreTermVectors(true);
+    customType10.setStoreTermVectorPositions(true);
+
+    FieldType customType11 = new FieldType(TextField.TYPE_UNSTORED);
+    customType11.setTokenized(false);
+    customType11.setStoreTermVectors(true);
+    customType11.setStoreTermVectorPositions(true);
+
+    FieldType customType12 = new FieldType(TextField.TYPE_UNSTORED);
+    customType12.setStored(true);
+    customType12.setStoreTermVectors(true);
+    customType12.setStoreTermVectorOffsets(true);
+    customType12.setStoreTermVectorPositions(true);
+
+    FieldType customType13 = new FieldType(TextField.TYPE_UNSTORED);
+    customType13.setStoreTermVectors(true);
+    customType13.setStoreTermVectorOffsets(true);
+    customType13.setStoreTermVectorPositions(true);
+
+    FieldType customType14 = new FieldType(TextField.TYPE_UNSTORED);
+    customType14.setStored(true);
+    customType14.setTokenized(false);
+    customType14.setStoreTermVectors(true);
+    customType14.setStoreTermVectorOffsets(true);
+    customType14.setStoreTermVectorPositions(true);
+
+    FieldType customType15 = new FieldType(TextField.TYPE_UNSTORED);
+    customType15.setTokenized(false);
+    customType15.setStoreTermVectors(true);
+    customType15.setStoreTermVectorOffsets(true);
+    customType15.setStoreTermVectorPositions(true);
+    
     switch (mode) {
-      case 0: return new Field(fieldName, "some text", Store.YES, Index.ANALYZED, TermVector.NO);
-      case 1: return new Field(fieldName, "some text", Store.NO, Index.ANALYZED, TermVector.NO);
-      case 2: return new Field(fieldName, "some text", Store.YES, Index.NOT_ANALYZED, TermVector.NO);
-      case 3: return new Field(fieldName, "some text", Store.NO, Index.NOT_ANALYZED, TermVector.NO);
-      case 4: return new Field(fieldName, "some text", Store.YES, Index.ANALYZED, TermVector.WITH_OFFSETS);
-      case 5: return new Field(fieldName, "some text", Store.NO, Index.ANALYZED, TermVector.WITH_OFFSETS);
-      case 6: return new Field(fieldName, "some text", Store.YES, Index.NOT_ANALYZED, TermVector.WITH_OFFSETS);
-      case 7: return new Field(fieldName, "some text", Store.NO, Index.NOT_ANALYZED, TermVector.WITH_OFFSETS);
-      case 8: return new Field(fieldName, "some text", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS);
-      case 9: return new Field(fieldName, "some text", Store.NO, Index.ANALYZED, TermVector.WITH_POSITIONS);
-      case 10: return new Field(fieldName, "some text", Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS);
-      case 11: return new Field(fieldName, "some text", Store.NO, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS);
-      case 12: return new Field(fieldName, "some text", Store.YES, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS);
-      case 13: return new Field(fieldName, "some text", Store.NO, Index.ANALYZED, TermVector.WITH_POSITIONS_OFFSETS);
-      case 14: return new Field(fieldName, "some text", Store.YES, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS);
-      case 15: return new Field(fieldName, "some text", Store.NO, Index.NOT_ANALYZED, TermVector.WITH_POSITIONS_OFFSETS);
+      case 0: return new Field(fieldName, customType, "some text");
+      case 1: return new TextField(fieldName, "some text");
+      case 2: return new Field(fieldName, customType2, "some text");
+      case 3: return new Field(fieldName, customType3, "some text");
+      case 4: return new Field(fieldName, customType4, "some text");
+      case 5: return new Field(fieldName, customType5, "some text");
+      case 6: return new Field(fieldName, customType6, "some text");
+      case 7: return new Field(fieldName, customType7, "some text");
+      case 8: return new Field(fieldName, customType8, "some text");
+      case 9: return new Field(fieldName, customType9, "some text");
+      case 10: return new Field(fieldName, customType10, "some text");
+      case 11: return new Field(fieldName, customType11, "some text");
+      case 12: return new Field(fieldName, customType12, "some text");
+      case 13: return new Field(fieldName, customType13, "some text");
+      case 14: return new Field(fieldName, customType14, "some text");
+      case 15: return new Field(fieldName, customType15, "some text");
       default: return null;
     }
   }
Index: lucene/src/test/org/apache/lucene/document/TestBinaryDocument.java
===================================================================
--- lucene/src/test/org/apache/lucene/document/TestBinaryDocument.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/document/TestBinaryDocument.java	(working copy)
@@ -1,10 +1,16 @@
 package org.apache.lucene.document;
 
-import org.apache.lucene.util.LuceneTestCase;
-
+import org.apache.lucene.document.BinaryField;
+import org.apache.lucene.document.CompressionTools;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.LuceneTestCase;
 
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -34,8 +40,10 @@
   public void testBinaryFieldInIndex()
     throws Exception
   {
-    Fieldable binaryFldStored = new Field("binaryStored", binaryValStored.getBytes());
-    Fieldable stringFldStored = new Field("stringStored", binaryValStored, Field.Store.YES, Field.Index.NO, Field.TermVector.NO);
+    FieldType ft = new FieldType();
+    ft.setStored(true);
+    IndexableField binaryFldStored = new BinaryField("binaryStored", binaryValStored.getBytes());
+    IndexableField stringFldStored = new Field("stringStored", ft, binaryValStored);
 
     Document doc = new Document();
     
@@ -44,7 +52,7 @@
     doc.add(stringFldStored);
 
     /** test for field count */
-    assertEquals(2, doc.fields.size());
+    assertEquals(2, doc.getFields().size());
     
     /** add the doc to a ram index */
     Directory dir = newDirectory();
@@ -57,7 +65,9 @@
     assertTrue(docFromReader != null);
     
     /** fetch the binary stored field and compare it's content with the original one */
-    String binaryFldStoredTest = new String(docFromReader.getBinaryValue("binaryStored"));
+    BytesRef bytes = docFromReader.getBinaryValue("binaryStored");
+    assertNotNull(bytes);
+    String binaryFldStoredTest = new String(bytes.bytes, bytes.offset, bytes.length);
     assertTrue(binaryFldStoredTest.equals(binaryValStored));
     
     /** fetch the string field and compare it's content with the original one */
@@ -77,8 +87,8 @@
   }
   
   public void testCompressionTools() throws Exception {
-    Fieldable binaryFldCompressed = new Field("binaryCompressed", CompressionTools.compress(binaryValCompressed.getBytes()));
-    Fieldable stringFldCompressed = new Field("stringCompressed", CompressionTools.compressString(binaryValCompressed));
+    IndexableField binaryFldCompressed = new BinaryField("binaryCompressed", CompressionTools.compress(binaryValCompressed.getBytes()));
+    IndexableField stringFldCompressed = new BinaryField("stringCompressed", CompressionTools.compressString(binaryValCompressed));
     
     Document doc = new Document();
     
Index: lucene/src/test/org/apache/lucene/document/TestDocument.java
===================================================================
--- lucene/src/test/org/apache/lucene/document/TestDocument.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/document/TestDocument.java	(working copy)
@@ -1,6 +1,13 @@
 package org.apache.lucene.document;
 
+import org.apache.lucene.document.BinaryField;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.IndexSearcher;
@@ -8,6 +15,7 @@
 import org.apache.lucene.search.ScoreDoc;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.LuceneTestCase;
 
 /**
@@ -37,22 +45,24 @@
   
   public void testBinaryField() throws Exception {
     Document doc = new Document();
-    Fieldable stringFld = new Field("string", binaryVal, Field.Store.YES,
-        Field.Index.NO);
-    Fieldable binaryFld = new Field("binary", binaryVal.getBytes());
-    Fieldable binaryFld2 = new Field("binary", binaryVal2.getBytes());
     
+    FieldType ft = new FieldType();
+    ft.setStored(true);
+    IndexableField stringFld = new Field("string", ft, binaryVal);
+    IndexableField binaryFld = new BinaryField("binary", binaryVal.getBytes());
+    IndexableField binaryFld2 = new BinaryField("binary", binaryVal2.getBytes());
+    
     doc.add(stringFld);
     doc.add(binaryFld);
     
-    assertEquals(2, doc.fields.size());
+    assertEquals(2, doc.getFields().size());
     
-    assertTrue(binaryFld.isBinary());
-    assertTrue(binaryFld.isStored());
-    assertFalse(binaryFld.isIndexed());
-    assertFalse(binaryFld.isTokenized());
+    assertTrue(binaryFld.binaryValue() != null);
+    assertTrue(binaryFld.stored());
+    assertFalse(binaryFld.indexed());
+    assertFalse(binaryFld.tokenized());
     
-    String binaryTest = new String(doc.getBinaryValue("binary"));
+    String binaryTest = doc.getBinaryValue("binary").utf8ToString();
     assertTrue(binaryTest.equals(binaryVal));
     
     String stringTest = doc.get("string");
@@ -60,14 +70,14 @@
     
     doc.add(binaryFld2);
     
-    assertEquals(3, doc.fields.size());
+    assertEquals(3, doc.getFields().size());
     
-    byte[][] binaryTests = doc.getBinaryValues("binary");
+    BytesRef[] binaryTests = doc.getBinaryValues("binary");
     
     assertEquals(2, binaryTests.length);
     
-    binaryTest = new String(binaryTests[0]);
-    String binaryTest2 = new String(binaryTests[1]);
+    binaryTest = binaryTests[0].utf8ToString();
+    String binaryTest2 = binaryTests[1].utf8ToString();
     
     assertFalse(binaryTest.equals(binaryTest2));
     
@@ -75,10 +85,10 @@
     assertTrue(binaryTest2.equals(binaryVal2));
     
     doc.removeField("string");
-    assertEquals(2, doc.fields.size());
+    assertEquals(2, doc.getFields().size());
     
     doc.removeFields("binary");
-    assertEquals(0, doc.fields.size());
+    assertEquals(0, doc.getFields().size());
   }
   
   /**
@@ -89,45 +99,48 @@
    */
   public void testRemoveForNewDocument() throws Exception {
     Document doc = makeDocumentWithFields();
-    assertEquals(8, doc.fields.size());
+    assertEquals(8, doc.getFields().size());
     doc.removeFields("keyword");
-    assertEquals(6, doc.fields.size());
+    assertEquals(6, doc.getFields().size());
     doc.removeFields("doesnotexists"); // removing non-existing fields is
                                        // siltenlty ignored
     doc.removeFields("keyword"); // removing a field more than once
-    assertEquals(6, doc.fields.size());
+    assertEquals(6, doc.getFields().size());
     doc.removeField("text");
-    assertEquals(5, doc.fields.size());
+    assertEquals(5, doc.getFields().size());
     doc.removeField("text");
-    assertEquals(4, doc.fields.size());
+    assertEquals(4, doc.getFields().size());
     doc.removeField("text");
-    assertEquals(4, doc.fields.size());
+    assertEquals(4, doc.getFields().size());
     doc.removeField("doesnotexists"); // removing non-existing fields is
                                       // siltenlty ignored
-    assertEquals(4, doc.fields.size());
+    assertEquals(4, doc.getFields().size());
     doc.removeFields("unindexed");
-    assertEquals(2, doc.fields.size());
+    assertEquals(2, doc.getFields().size());
     doc.removeFields("unstored");
-    assertEquals(0, doc.fields.size());
+    assertEquals(0, doc.getFields().size());
     doc.removeFields("doesnotexists"); // removing non-existing fields is
                                        // siltenlty ignored
-    assertEquals(0, doc.fields.size());
+    assertEquals(0, doc.getFields().size());
   }
   
   public void testConstructorExceptions() {
-    new Field("name", "value", Field.Store.YES, Field.Index.NO); // okay
-    new Field("name", "value", Field.Store.NO, Field.Index.NOT_ANALYZED); // okay
+    FieldType ft = new FieldType();
+    ft.setStored(true);
+    new Field("name", ft, "value"); // okay
+    new StringField("name", "value"); // okay
     try {
-      new Field("name", "value", Field.Store.NO, Field.Index.NO);
+      new Field("name", new FieldType(), "value");
       fail();
     } catch (IllegalArgumentException e) {
       // expected exception
     }
-    new Field("name", "value", Field.Store.YES, Field.Index.NO,
-        Field.TermVector.NO); // okay
+    new Field("name", ft, "value"); // okay
     try {
-      new Field("name", "value", Field.Store.YES, Field.Index.NO,
-          Field.TermVector.YES);
+      FieldType ft2 = new FieldType();
+      ft2.setStored(true);
+      ft2.setStoreTermVectors(true);
+      new Field("name", ft2, "value");
       fail();
     } catch (IllegalArgumentException e) {
       // expected exception
@@ -174,28 +187,26 @@
   
   private Document makeDocumentWithFields() {
     Document doc = new Document();
-    doc.add(new Field("keyword", "test1", Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
-    doc.add(new Field("keyword", "test2", Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
-    doc.add(new Field("text", "test1", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("text", "test2", Field.Store.YES, Field.Index.ANALYZED));
-    doc.add(new Field("unindexed", "test1", Field.Store.YES, Field.Index.NO));
-    doc.add(new Field("unindexed", "test2", Field.Store.YES, Field.Index.NO));
+    FieldType stored = new FieldType();
+    stored.setStored(true);
+    doc.add(new Field("keyword", StringField.TYPE_STORED, "test1"));
+    doc.add(new Field("keyword", StringField.TYPE_STORED, "test2"));
+    doc.add(new Field("text", TextField.TYPE_STORED, "test1"));
+    doc.add(new Field("text", TextField.TYPE_STORED, "test2"));
+    doc.add(new Field("unindexed", stored, "test1"));
+    doc.add(new Field("unindexed", stored, "test2"));
     doc
-        .add(new Field("unstored", "test1", Field.Store.NO,
-            Field.Index.ANALYZED));
+        .add(new TextField("unstored", "test1"));
     doc
-        .add(new Field("unstored", "test2", Field.Store.NO,
-            Field.Index.ANALYZED));
+        .add(new TextField("unstored", "test2"));
     return doc;
   }
   
   private void doAssert(Document doc, boolean fromIndex) {
-    String[] keywordFieldValues = doc.getValues("keyword");
-    String[] textFieldValues = doc.getValues("text");
-    String[] unindexedFieldValues = doc.getValues("unindexed");
-    String[] unstoredFieldValues = doc.getValues("unstored");
+    IndexableField[] keywordFieldValues = doc.getFields("keyword");
+    IndexableField[] textFieldValues = doc.getFields("text");
+    IndexableField[] unindexedFieldValues = doc.getFields("unindexed");
+    IndexableField[] unstoredFieldValues = doc.getFields("unstored");
     
     assertTrue(keywordFieldValues.length == 2);
     assertTrue(textFieldValues.length == 2);
@@ -206,28 +217,26 @@
       assertTrue(unstoredFieldValues.length == 2);
     }
     
-    assertTrue(keywordFieldValues[0].equals("test1"));
-    assertTrue(keywordFieldValues[1].equals("test2"));
-    assertTrue(textFieldValues[0].equals("test1"));
-    assertTrue(textFieldValues[1].equals("test2"));
-    assertTrue(unindexedFieldValues[0].equals("test1"));
-    assertTrue(unindexedFieldValues[1].equals("test2"));
+    assertTrue(keywordFieldValues[0].stringValue().equals("test1"));
+    assertTrue(keywordFieldValues[1].stringValue().equals("test2"));
+    assertTrue(textFieldValues[0].stringValue().equals("test1"));
+    assertTrue(textFieldValues[1].stringValue().equals("test2"));
+    assertTrue(unindexedFieldValues[0].stringValue().equals("test1"));
+    assertTrue(unindexedFieldValues[1].stringValue().equals("test2"));
     // this test cannot work for documents retrieved from the index
     // since unstored fields will obviously not be returned
     if (!fromIndex) {
-      assertTrue(unstoredFieldValues[0].equals("test1"));
-      assertTrue(unstoredFieldValues[1].equals("test2"));
+      assertTrue(unstoredFieldValues[0].stringValue().equals("test1"));
+      assertTrue(unstoredFieldValues[1].stringValue().equals("test2"));
     }
   }
   
   public void testFieldSetValue() throws Exception {
     
-    Field field = new Field("id", "id1", Field.Store.YES,
-        Field.Index.NOT_ANALYZED);
+    Field field = new Field("id", StringField.TYPE_STORED, "id1");
     Document doc = new Document();
     doc.add(field);
-    doc.add(new Field("keyword", "test", Field.Store.YES,
-        Field.Index.NOT_ANALYZED));
+    doc.add(new Field("keyword", StringField.TYPE_STORED, "test"));
     
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, dir);
@@ -248,7 +257,7 @@
     int result = 0;
     for (int i = 0; i < 3; i++) {
       Document doc2 = searcher.doc(hits[i].doc);
-      Field f = doc2.getField("id");
+      Field f = (Field) doc2.getField("id");
       if (f.stringValue().equals("id1")) result |= 1;
       else if (f.stringValue().equals("id2")) result |= 2;
       else if (f.stringValue().equals("id3")) result |= 4;
@@ -262,9 +271,8 @@
   }
   
   public void testFieldSetValueChangeBinary() {
-    Field field1 = new Field("field1", new byte[0]);
-    Field field2 = new Field("field2", "", Field.Store.YES,
-        Field.Index.ANALYZED);
+    Field field1 = new BinaryField("field1", new byte[0]);
+    Field field2 = new Field("field2", TextField.TYPE_STORED, "");
     try {
       field1.setValue("abc");
       fail("did not hit expected exception");
Index: lucene/src/test/org/apache/lucene/document/TestDateTools.java
===================================================================
--- lucene/src/test/org/apache/lucene/document/TestDateTools.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/document/TestDateTools.java	(working copy)
@@ -8,6 +8,7 @@
 import java.util.TimeZone;
 import java.util.Locale;
 
+import org.apache.lucene.document.DateTools;
 import org.apache.lucene.util.LuceneTestCase;
 
 /**
@@ -196,4 +197,4 @@
     }
   }
 
-}
\ No newline at end of file
+}
Index: lucene/src/test/org/apache/lucene/TestMergeSchedulerExternal.java
===================================================================
--- lucene/src/test/org/apache/lucene/TestMergeSchedulerExternal.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/TestMergeSchedulerExternal.java	(working copy)
@@ -33,6 +33,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 
 /**
  * Holds tests cases to verify external APIs are accessible
@@ -90,7 +91,7 @@
     dir.failOn(new FailOnlyOnMerge());
 
     Document doc = new Document();
-    Field idField = newField("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    Field idField = newField("id", "", StringField.TYPE_STORED);
     doc.add(idField);
     
     IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
Index: lucene/src/test/org/apache/lucene/TestExternalCodecs.java
===================================================================
--- lucene/src/test/org/apache/lucene/TestExternalCodecs.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/TestExternalCodecs.java	(working copy)
@@ -529,13 +529,13 @@
     w.setInfoStream(VERBOSE ? System.out : null);
     Document doc = new Document();
     // uses default codec:
-    doc.add(newField("field1", "this field uses the standard codec as the test", Field.Store.NO, Field.Index.ANALYZED));
+    doc.add(newField("field1", "this field uses the standard codec as the test", TextField.TYPE_UNSTORED));
     // uses pulsing codec:
-    Field field2 = newField("field2", "this field uses the pulsing codec as the test", Field.Store.NO, Field.Index.ANALYZED);
+    Field field2 = newField("field2", "this field uses the pulsing codec as the test", TextField.TYPE_UNSTORED);
     provider.setFieldCodec(field2.name(), "Pulsing");
     doc.add(field2);
     
-    Field idField = newField("id", "", Field.Store.NO, Field.Index.NOT_ANALYZED);
+    Field idField = newField("id", "", StringField.TYPE_UNSTORED);
     provider.setFieldCodec(idField.name(), "Pulsing");
 
     doc.add(idField);
Index: lucene/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java
===================================================================
--- lucene/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java	(working copy)
@@ -23,8 +23,7 @@
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
 import org.apache.lucene.index.DocsAndPositionsEnum;
@@ -60,7 +59,7 @@
     
     stream = new CachingTokenFilter(stream);
     
-    doc.add(new Field("preanalyzed", stream, TermVector.NO));
+    doc.add(new TextField("preanalyzed", stream));
     
     // 1) we consume all tokens twice before we add the doc to the index
     checkTokens(stream);
Index: lucene/src/test/org/apache/lucene/TestDemo.java
===================================================================
--- lucene/src/test/org/apache/lucene/TestDemo.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/TestDemo.java	(working copy)
@@ -22,7 +22,8 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.*;
@@ -49,8 +50,9 @@
     Document doc = new Document();
     String longTerm = "longtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongtermlongterm";
     String text = "This is the text to be indexed. " + longTerm;
-    doc.add(newField("fieldname", text, Field.Store.YES,
-        Field.Index.ANALYZED));
+    FieldType textType = new FieldType(TextField.TYPE_UNSTORED);
+    textType.setStored(true);
+    doc.add(newField("fieldname", text, textType));
     iwriter.addDocument(doc);
     iwriter.close();
     
Index: lucene/src/test/org/apache/lucene/TestSearch.java
===================================================================
--- lucene/src/test/org/apache/lucene/TestSearch.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/TestSearch.java	(working copy)
@@ -93,8 +93,8 @@
       };
       for (int j = 0; j < docs.length; j++) {
         Document d = new Document();
-        d.add(newField("contents", docs[j], Field.Store.YES, Field.Index.ANALYZED));
-        d.add(newField("id", ""+j, Field.Index.NOT_ANALYZED_NO_NORMS));
+        d.add(newField("contents", docs[j], TextField.TYPE_STORED));
+        d.add(newField("id", ""+j, StringField.TYPE_UNSTORED));
         writer.addDocument(d);
       }
       writer.close();
Index: lucene/src/test/org/apache/lucene/TestSearchForDuplicates.java
===================================================================
--- lucene/src/test/org/apache/lucene/TestSearchForDuplicates.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/TestSearchForDuplicates.java	(working copy)
@@ -92,8 +92,8 @@
 
       for (int j = 0; j < MAX_DOCS; j++) {
         Document d = new Document();
-        d.add(newField(PRIORITY_FIELD, HIGH_PRIORITY, Field.Store.YES, Field.Index.ANALYZED));
-        d.add(newField(ID_FIELD, Integer.toString(j), Field.Store.YES, Field.Index.ANALYZED));
+        d.add(newField(PRIORITY_FIELD, HIGH_PRIORITY, TextField.TYPE_STORED));
+        d.add(newField(ID_FIELD, Integer.toString(j), TextField.TYPE_STORED));
         writer.addDocument(d);
       }
       writer.close();
Index: lucene/src/test/org/apache/lucene/store/TestLockFactory.java
===================================================================
--- lucene/src/test/org/apache/lucene/store/TestLockFactory.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/store/TestLockFactory.java	(working copy)
@@ -25,7 +25,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.Term;
@@ -415,7 +415,7 @@
 
     private void addDoc(IndexWriter writer) throws IOException {
         Document doc = new Document();
-        doc.add(newField("content", "aaa", Field.Store.NO, Field.Index.ANALYZED));
+        doc.add(newField("content", "aaa", TextField.TYPE_UNSTORED));
         writer.addDocument(doc);
     }
 }
Index: lucene/src/test/org/apache/lucene/store/TestRAMDirectory.java
===================================================================
--- lucene/src/test/org/apache/lucene/store/TestRAMDirectory.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/store/TestRAMDirectory.java	(working copy)
@@ -28,6 +28,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -59,7 +60,7 @@
     Document doc = null;
     for (int i = 0; i < docsToAdd; i++) {
       doc = new Document();
-      doc.add(newField("content", English.intToEnglish(i).trim(), Field.Store.YES, Field.Index.NOT_ANALYZED));
+      doc.add(newField("content", English.intToEnglish(i).trim(), StringField.TYPE_STORED));
       writer.addDocument(doc);
     }
     assertEquals(docsToAdd, writer.maxDoc());
@@ -119,7 +120,7 @@
         public void run() {
           for (int j=1; j<docsPerThread; j++) {
             Document doc = new Document();
-            doc.add(newField("sizeContent", English.intToEnglish(num*docsPerThread+j).trim(), Field.Store.YES, Field.Index.NOT_ANALYZED));
+            doc.add(newField("sizeContent", English.intToEnglish(num*docsPerThread+j).trim(), StringField.TYPE_STORED));
             try {
               writer.addDocument(doc);
             } catch (IOException e) {
Index: lucene/src/test/org/apache/lucene/store/TestMultiMMap.java
===================================================================
--- lucene/src/test/org/apache/lucene/store/TestMultiMMap.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/store/TestMultiMMap.java	(working copy)
@@ -23,6 +23,7 @@
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.util.BytesRef;
@@ -123,8 +124,8 @@
     MockDirectoryWrapper dir = new MockDirectoryWrapper(random, mmapDir);
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).setMergePolicy(newLogMergePolicy()));
     Document doc = new Document();
-    Field docid = newField("docid", "0", Field.Store.YES, Field.Index.NOT_ANALYZED);
-    Field junk = newField("junk", "", Field.Store.YES, Field.Index.NOT_ANALYZED);
+    Field docid = newField("docid", "0", StringField.TYPE_STORED);
+    Field junk = newField("junk", "", StringField.TYPE_STORED);
     doc.add(docid);
     doc.add(junk);
     
Index: lucene/src/test/org/apache/lucene/store/TestWindowsMMap.java
===================================================================
--- lucene/src/test/org/apache/lucene/store/TestWindowsMMap.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/store/TestWindowsMMap.java	(working copy)
@@ -24,7 +24,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -84,7 +84,7 @@
     for(int dx = 0; dx < num; dx ++) {
       String f = randomField();
       Document doc = new Document();
-      doc.add(newField("data", f, Field.Store.YES, Field.Index.ANALYZED));	
+      doc.add(newField("data", f, TextField.TYPE_STORED));	
       writer.addDocument(doc);
     }
     
Index: lucene/src/test/org/apache/lucene/store/TestBufferedIndexInput.java
===================================================================
--- lucene/src/test/org/apache/lucene/store/TestBufferedIndexInput.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/store/TestBufferedIndexInput.java	(working copy)
@@ -28,7 +28,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -251,8 +251,8 @@
         );
         for(int i=0;i<37;i++) {
           Document doc = new Document();
-          doc.add(newField("content", "aaa bbb ccc ddd" + i, Field.Store.YES, Field.Index.ANALYZED));
-          doc.add(newField("id", "" + i, Field.Store.YES, Field.Index.ANALYZED));
+          doc.add(newField("content", "aaa bbb ccc ddd" + i, TextField.TYPE_STORED));
+          doc.add(newField("id", "" + i, TextField.TYPE_STORED));
           writer.addDocument(doc);
         }
         writer.close();
Index: lucene/src/test/org/apache/lucene/util/TestFieldCacheSanityChecker.java
===================================================================
--- lucene/src/test/org/apache/lucene/util/TestFieldCacheSanityChecker.java	(revision 1158028)
+++ lucene/src/test/org/apache/lucene/util/TestFieldCacheSanityChecker.java	(working copy)
@@ -18,7 +18,7 @@
 
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
+import org.apache.lucene.document.StringField;
 import org.apache.lucene.search.FieldCache;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiReader;
@@ -54,12 +54,12 @@
     float theFloat = Float.MAX_VALUE;
     for (int i = 0; i < NUM_DOCS; i++){
       Document doc = new Document();
-      doc.add(newField("theLong", String.valueOf(theLong--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theDouble", String.valueOf(theDouble--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theByte", String.valueOf(theByte--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theShort", String.valueOf(theShort--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theInt", String.valueOf(theInt--), Field.Store.NO, Field.Index.NOT_ANALYZED));
-      doc.add(newField("theFloat", String.valueOf(theFloat--), Field.Store.NO, Field.Index.NOT_ANALYZED));
+      doc.add(newField("theLong", String.valueOf(theLong--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theDouble", String.valueOf(theDouble--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theByte", String.valueOf(theByte--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theShort", String.valueOf(theShort--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theInt", String.valueOf(theInt--), StringField.TYPE_UNSTORED));
+      doc.add(newField("theFloat", String.valueOf(theFloat--), StringField.TYPE_UNSTORED));
       if (0 == i % 3) {
         wA.addDocument(doc);
       } else {
Index: lucene/src/java/org/apache/lucene/analysis/Analyzer.java
===================================================================
--- lucene/src/java/org/apache/lucene/analysis/Analyzer.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/analysis/Analyzer.java	(working copy)
@@ -22,11 +22,10 @@
 import java.io.Closeable;
 import java.lang.reflect.Modifier;
 
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.util.CloseableThreadLocal;
 import org.apache.lucene.store.AlreadyClosedException;
 
-import org.apache.lucene.document.Fieldable;
-
 /** An Analyzer builds TokenStreams, which analyze text.  It thus represents a
  *  policy for extracting index terms from text.
  *  <p>
@@ -111,16 +110,16 @@
   }
 
   /**
-   * Invoked before indexing a Fieldable instance if
+   * Invoked before indexing a IndexableField instance if
    * terms have already been added to that field.  This allows custom
    * analyzers to place an automatic position increment gap between
-   * Fieldable instances using the same field name.  The default value
+   * IndexbleField instances using the same field name.  The default value
    * position increment gap is 0.  With a 0 position increment gap and
    * the typical default token position increment of 1, all terms in a field,
-   * including across Fieldable instances, are in successive positions, allowing
-   * exact PhraseQuery matches, for instance, across Fieldable instance boundaries.
+   * including across IndexableField instances, are in successive positions, allowing
+   * exact PhraseQuery matches, for instance, across IndexableField instance boundaries.
    *
-   * @param fieldName Fieldable name being indexed.
+   * @param fieldName IndexableField name being indexed.
    * @return position increment gap, added to the next token emitted from {@link #tokenStream(String,Reader)}
    */
   public int getPositionIncrementGap(String fieldName) {
@@ -138,11 +137,12 @@
    * @param field the field just indexed
    * @return offset gap, added to the next token emitted from {@link #tokenStream(String,Reader)}
    */
-  public int getOffsetGap(Fieldable field) {
-    if (field.isTokenized())
+  public int getOffsetGap(IndexableField field) {
+    if (field.tokenized()) {
       return 1;
-    else
+    } else {
       return 0;
+    }
   }
 
   /** Frees persistent resources used by this Analyzer */
Index: lucene/src/java/org/apache/lucene/analysis/package.html
===================================================================
--- lucene/src/java/org/apache/lucene/analysis/package.html	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/analysis/package.html	(working copy)
@@ -120,7 +120,7 @@
   Applications usually do not invoke analysis &ndash; Lucene does it for them:
   <ul>
     <li>At indexing, as a consequence of 
-        {@link org.apache.lucene.index.IndexWriter#addDocument(org.apache.lucene.document.Document) addDocument(doc)},
+        {@link org.apache.lucene.index.IndexWriter#addDocument(Iterable) addDocument(doc)},
         the Analyzer in effect for indexing is invoked for each indexed field of the added document.
     </li>
     <li>At search, a QueryParser may invoke the Analyzer during parsing.  Note that for some queries, analysis does not
@@ -170,7 +170,7 @@
 </p>
 <h3>Field Section Boundaries</h3>
 <p>
-  When {@link org.apache.lucene.document.Document#add(org.apache.lucene.document.Fieldable) document.add(field)}
+  When {@link org.apache.lucene.document.Document#add(org.apache.lucene.index.IndexableField) 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 
Index: lucene/src/java/org/apache/lucene/index/DocInverterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocInverterPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocInverterPerField.java	(working copy)
@@ -19,7 +19,6 @@
 
 import java.io.IOException;
 import java.io.Reader;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
@@ -61,27 +60,32 @@
   }
 
   @Override
-  public void processFields(final Fieldable[] fields,
+  public void processFields(final IndexableField[] fields,
                             final int count) throws IOException {
 
-    fieldState.reset(docState.doc.getBoost());
+    fieldState.reset();
 
     final boolean doInvert = consumer.start(fields, count);
 
     for(int i=0;i<count;i++) {
 
-      final Fieldable field = fields[i];
+      final IndexableField field = fields[i];
 
       // TODO FI: this should be "genericized" to querying
       // consumer if it wants to see this particular field
       // tokenized.
-      if (field.isIndexed() && doInvert) {
+      if (field.indexed() && doInvert) {
         
         if (i > 0)
           fieldState.position += docState.analyzer == null ? 0 : docState.analyzer.getPositionIncrementGap(fieldInfo.name);
 
-        if (!field.isTokenized()) {		  // un-tokenized field
-          String stringValue = field.stringValue();
+        // TODO (LUCENE-2309): this analysis logic should be
+        // outside of indexer -- field should simply give us
+        // a TokenStream, even for multi-valued fields
+
+        if (!field.tokenized()) {		  // un-tokenized field
+          final String stringValue = field.stringValue();
+          assert stringValue != null;
           final int valueLength = stringValue.length();
           parent.singleToken.reinit(stringValue, 0, valueLength);
           fieldState.attributeSource = parent.singleToken;
@@ -103,17 +107,17 @@
           final TokenStream stream;
           final TokenStream streamValue = field.tokenStreamValue();
 
-          if (streamValue != null) 
+          if (streamValue != null) {
             stream = streamValue;
-          else {
+          } else {
             // the field does not have a TokenStream,
             // so we have to obtain one from the analyzer
             final Reader reader;			  // find or make Reader
             final Reader readerValue = field.readerValue();
 
-            if (readerValue != null)
+            if (readerValue != null) {
               reader = readerValue;
-            else {
+            } else {
               String stringValue = field.stringValue();
               if (stringValue == null) {
                 throw new IllegalArgumentException("field must have either TokenStream, String or Reader value");
@@ -189,7 +193,7 @@
         }
 
         fieldState.offset += docState.analyzer == null ? 0 : docState.analyzer.getOffsetGap(field);
-        fieldState.boost *= field.getBoost();
+        fieldState.boost *= field.boost();
       }
 
       // LUCENE-2387: don't hang onto the field, so GC can
Index: lucene/src/java/org/apache/lucene/index/FieldsReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FieldsReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FieldsReader.java	(working copy)
@@ -17,13 +17,8 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.document.AbstractField;
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Field;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.FieldSelectorResult;
-import org.apache.lucene.document.Fieldable;
+import java.io.IOException;
+
 import org.apache.lucene.document.NumericField;
 import org.apache.lucene.store.AlreadyClosedException;
 import org.apache.lucene.store.BufferedIndexInput;
@@ -49,7 +44,8 @@
   private final static int FORMAT_SIZE = 4;
 
   private final FieldInfos fieldInfos;
-
+  private CloseableThreadLocal<IndexInput> fieldsStreamTL = new CloseableThreadLocal<IndexInput>();
+  
   // The main fieldStream, used only for cloning.
   private final IndexInput cloneableFieldsStream;
 
@@ -68,7 +64,6 @@
   // file.  This will be 0 if we have our own private file.
   private int docStoreOffset;
 
-  private CloseableThreadLocal<IndexInput> fieldsStreamTL = new CloseableThreadLocal<IndexInput>();
   private boolean isOriginal = false;
 
   /** Returns a cloned FieldsReader that shares open
@@ -200,50 +195,52 @@
     indexStream.seek(FORMAT_SIZE + (docID + docStoreOffset) * 8L);
   }
 
-  public final Document doc(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public final void visitDocument(int n, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
     seekIndex(n);
-    long position = indexStream.readLong();
-    fieldsStream.seek(position);
+    fieldsStream.seek(indexStream.readLong());
 
-    Document doc = new Document();
-    int numFields = fieldsStream.readVInt();
-    out: for (int i = 0; i < numFields; i++) {
+    final int numFields = fieldsStream.readVInt();
+    for (int fieldIDX = 0; fieldIDX < numFields; fieldIDX++) {
       int fieldNumber = fieldsStream.readVInt();
-      FieldInfo fi = fieldInfos.fieldInfo(fieldNumber);
-      FieldSelectorResult acceptField = fieldSelector == null ? FieldSelectorResult.LOAD : fieldSelector.accept(fi.name);
+      FieldInfo fieldInfo = fieldInfos.fieldInfo(fieldNumber);
       
       int bits = fieldsStream.readByte() & 0xFF;
-      assert bits <= (FieldsWriter.FIELD_IS_NUMERIC_MASK | FieldsWriter.FIELD_IS_TOKENIZED | FieldsWriter.FIELD_IS_BINARY): "bits=" + Integer.toHexString(bits);
+      assert bits <= (FieldsWriter.FIELD_IS_NUMERIC_MASK | FieldsWriter.FIELD_IS_BINARY): "bits=" + Integer.toHexString(bits);
 
-      boolean tokenize = (bits & FieldsWriter.FIELD_IS_TOKENIZED) != 0;
-      boolean binary = (bits & FieldsWriter.FIELD_IS_BINARY) != 0;
+      final boolean binary = (bits & FieldsWriter.FIELD_IS_BINARY) != 0;
       final int numeric = bits & FieldsWriter.FIELD_IS_NUMERIC_MASK;
 
-      switch (acceptField) {
-        case LOAD:
-          addField(doc, fi, binary, tokenize, numeric);
+      final boolean doStop;
+      if (binary) {
+        final int numBytes = fieldsStream.readVInt();
+        doStop = visitor.binaryField(fieldInfo, fieldsStream, numBytes);
+      } else if (numeric != 0) {
+        switch(numeric) {
+        case FieldsWriter.FIELD_IS_NUMERIC_INT:
+          doStop = visitor.intField(fieldInfo, fieldsStream.readInt());
           break;
-        case LOAD_AND_BREAK:
-          addField(doc, fi, binary, tokenize, numeric);
-          break out; //Get out of this loop
-        case LAZY_LOAD:
-          addFieldLazy(doc, fi, binary, tokenize, true, numeric);
+        case FieldsWriter.FIELD_IS_NUMERIC_LONG:
+          doStop = visitor.longField(fieldInfo, fieldsStream.readLong());
           break;
-        case LATENT:
-          addFieldLazy(doc, fi, binary, tokenize, false, numeric);
+        case FieldsWriter.FIELD_IS_NUMERIC_FLOAT:
+          doStop = visitor.floatField(fieldInfo, Float.intBitsToFloat(fieldsStream.readInt()));
           break;
-        case SIZE:
-          skipFieldBytes(addFieldSize(doc, fi, binary, numeric));
+        case FieldsWriter.FIELD_IS_NUMERIC_DOUBLE:
+          doStop = visitor.doubleField(fieldInfo, Double.longBitsToDouble(fieldsStream.readLong()));
           break;
-        case SIZE_AND_BREAK:
-          addFieldSize(doc, fi, binary, numeric);
-          break out; //Get out of this loop
         default:
-          skipField(numeric);
+          throw new FieldReaderException("Invalid numeric type: " + Integer.toHexString(numeric));
+        }
+      } else {
+        // Text:
+        final int numUTF8Bytes = fieldsStream.readVInt();
+        doStop = visitor.stringField(fieldInfo, fieldsStream, numUTF8Bytes);
       }
-    }
 
-    return doc;
+      if (doStop) {
+        return;
+      }
+    }
   }
 
   /** Returns the length in bytes of each raw document in a
@@ -300,225 +297,4 @@
   private void skipFieldBytes(int toRead) throws IOException {
     fieldsStream.seek(fieldsStream.getFilePointer() + toRead);
   }
-
-  private NumericField loadNumericField(FieldInfo fi, int numeric) throws IOException {
-    assert numeric != 0;
-    switch(numeric) {
-      case FieldsWriter.FIELD_IS_NUMERIC_INT:
-        return new NumericField(fi.name, Field.Store.YES, fi.isIndexed).setIntValue(fieldsStream.readInt());
-      case FieldsWriter.FIELD_IS_NUMERIC_LONG:
-        return new NumericField(fi.name, Field.Store.YES, fi.isIndexed).setLongValue(fieldsStream.readLong());
-      case FieldsWriter.FIELD_IS_NUMERIC_FLOAT:
-        return new NumericField(fi.name, Field.Store.YES, fi.isIndexed).setFloatValue(Float.intBitsToFloat(fieldsStream.readInt()));
-      case FieldsWriter.FIELD_IS_NUMERIC_DOUBLE:
-        return new NumericField(fi.name, Field.Store.YES, fi.isIndexed).setDoubleValue(Double.longBitsToDouble(fieldsStream.readLong()));
-      default:
-        throw new FieldReaderException("Invalid numeric type: " + Integer.toHexString(numeric));
-    }
-  }
-
-  private void addFieldLazy(Document doc, FieldInfo fi, boolean binary, boolean tokenize, boolean cacheResult, int numeric) throws IOException {
-    final AbstractField f;
-    if (binary) {
-      int toRead = fieldsStream.readVInt();
-      long pointer = fieldsStream.getFilePointer();
-      f = new LazyField(fi.name, Field.Store.YES, toRead, pointer, binary, cacheResult);
-      //Need to move the pointer ahead by toRead positions
-      fieldsStream.seek(pointer + toRead);
-    } else if (numeric != 0) {
-      f = loadNumericField(fi, numeric);
-    } else {
-      Field.Store store = Field.Store.YES;
-      Field.Index index = Field.Index.toIndex(fi.isIndexed, tokenize);
-      Field.TermVector termVector = Field.TermVector.toTermVector(fi.storeTermVector, fi.storeOffsetWithTermVector, fi.storePositionWithTermVector);
-
-      int length = fieldsStream.readVInt();
-      long pointer = fieldsStream.getFilePointer();
-      //Skip ahead of where we are by the length of what is stored
-      fieldsStream.seek(pointer+length);
-      f = new LazyField(fi.name, store, index, termVector, length, pointer, binary, cacheResult);
-    }
-    
-    f.setOmitNorms(fi.omitNorms);
-    f.setIndexOptions(fi.indexOptions);
-    doc.add(f);
-  }
-
-  private void addField(Document doc, FieldInfo fi, boolean binary, boolean tokenize, int numeric) throws CorruptIndexException, IOException {
-    final AbstractField f;
-
-    if (binary) {
-      int toRead = fieldsStream.readVInt();
-      final byte[] b = new byte[toRead];
-      fieldsStream.readBytes(b, 0, b.length);
-      f = new Field(fi.name, b);
-    } else if (numeric != 0) {
-      f = loadNumericField(fi, numeric);
-    } else {
-      Field.Index index = Field.Index.toIndex(fi.isIndexed, tokenize);
-      Field.TermVector termVector = Field.TermVector.toTermVector(fi.storeTermVector, fi.storeOffsetWithTermVector, fi.storePositionWithTermVector);
-      f = new Field(fi.name,     // name
-        fieldsStream.readString(), // read value
-        Field.Store.YES,
-        index,
-        termVector);
-    }
-    
-    f.setIndexOptions(fi.indexOptions);
-    f.setOmitNorms(fi.omitNorms);
-    doc.add(f);
-  }
-  
-  // Add the size of field as a byte[] containing the 4 bytes of the integer byte size (high order byte first; char = 2 bytes)
-  // Read just the size -- caller must skip the field content to continue reading fields
-  // Return the size in bytes or chars, depending on field type
-  private int addFieldSize(Document doc, FieldInfo fi, boolean binary, int numeric) throws IOException {
-    final int bytesize, size;
-    switch(numeric) {
-      case 0:
-        size = fieldsStream.readVInt();
-        bytesize = binary ? size : 2*size;
-        break;
-      case FieldsWriter.FIELD_IS_NUMERIC_INT:
-      case FieldsWriter.FIELD_IS_NUMERIC_FLOAT:
-        size = bytesize = 4;
-        break;
-      case FieldsWriter.FIELD_IS_NUMERIC_LONG:
-      case FieldsWriter.FIELD_IS_NUMERIC_DOUBLE:
-        size = bytesize = 8;
-        break;
-      default:
-        throw new FieldReaderException("Invalid numeric type: " + Integer.toHexString(numeric));
-    }
-    byte[] sizebytes = new byte[4];
-    sizebytes[0] = (byte) (bytesize>>>24);
-    sizebytes[1] = (byte) (bytesize>>>16);
-    sizebytes[2] = (byte) (bytesize>>> 8);
-    sizebytes[3] = (byte)  bytesize      ;
-    doc.add(new Field(fi.name, sizebytes));
-    return size;
-  }
-
-  /**
-   * A Lazy implementation of Fieldable that defers loading of fields until asked for, instead of when the Document is
-   * loaded.
-   */
-  private class LazyField extends AbstractField implements Fieldable {
-    private int toRead;
-    private long pointer;
-    private final boolean cacheResult;
-
-    public LazyField(String name, Field.Store store, int toRead, long pointer, boolean isBinary, boolean cacheResult) {
-      super(name, store, Field.Index.NO, Field.TermVector.NO);
-      this.toRead = toRead;
-      this.pointer = pointer;
-      this.isBinary = isBinary;
-      this.cacheResult = cacheResult;
-      if (isBinary)
-        binaryLength = toRead;
-      lazy = true;
-    }
-
-    public LazyField(String name, Field.Store store, Field.Index index, Field.TermVector termVector, int toRead, long pointer, boolean isBinary, boolean cacheResult) {
-      super(name, store, index, termVector);
-      this.toRead = toRead;
-      this.pointer = pointer;
-      this.isBinary = isBinary;
-      this.cacheResult = cacheResult;
-      if (isBinary)
-        binaryLength = toRead;
-      lazy = true;
-    }
-
-    private IndexInput getFieldStream() {
-      IndexInput localFieldsStream = fieldsStreamTL.get();
-      if (localFieldsStream == null) {
-        localFieldsStream = (IndexInput) cloneableFieldsStream.clone();
-        fieldsStreamTL.set(localFieldsStream);
-      }
-      return localFieldsStream;
-    }
-
-    /** The value of the field as a Reader, or null.  If null, the String value,
-     * binary value, or TokenStream value is used.  Exactly one of stringValue(), 
-     * readerValue(), getBinaryValue(), and tokenStreamValue() must be set. */
-    public Reader readerValue() {
-      ensureOpen();
-      return null;
-    }
-
-    /** The value of the field as a TokenStream, or null.  If null, the Reader value,
-     * String value, or binary value is used. Exactly one of stringValue(), 
-     * readerValue(), getBinaryValue(), and tokenStreamValue() must be set. */
-    public TokenStream tokenStreamValue() {
-      ensureOpen();
-      return null;
-    }
-
-    /** The value of the field as a String, or null.  If null, the Reader value,
-     * binary value, or TokenStream value is used.  Exactly one of stringValue(), 
-     * readerValue(), getBinaryValue(), and tokenStreamValue() must be set. */
-    public String stringValue() {
-      ensureOpen();
-      if (isBinary)
-        return null;
-      else {
-        if (fieldsData == null) {
-          String result = null;
-          IndexInput localFieldsStream = getFieldStream();
-          try {
-            localFieldsStream.seek(pointer);
-            byte[] bytes = new byte[toRead];
-            localFieldsStream.readBytes(bytes, 0, toRead);
-            result = new String(bytes, "UTF-8");
-          } catch (IOException e) {
-            throw new FieldReaderException(e);
-          }
-          if (cacheResult == true){
-            fieldsData = result;
-          }
-          return result;
-        } else {
-          return (String) fieldsData;
-        }
-      }
-    }
-
-    @Override
-    public byte[] getBinaryValue(byte[] result) {
-      ensureOpen();
-
-      if (isBinary) {
-        if (fieldsData == null) {
-          // Allocate new buffer if result is null or too small
-          final byte[] b;
-          if (result == null || result.length < toRead)
-            b = new byte[toRead];
-          else
-            b = result;
-   
-          IndexInput localFieldsStream = getFieldStream();
-
-          // Throw this IOException since IndexReader.document does so anyway, so probably not that big of a change for people
-          // since they are already handling this exception when getting the document
-          try {
-            localFieldsStream.seek(pointer);
-            localFieldsStream.readBytes(b, 0, toRead);
-          } catch (IOException e) {
-            throw new FieldReaderException(e);
-          }
-
-          binaryOffset = 0;
-          binaryLength = toRead;
-          if (cacheResult == true){
-            fieldsData = b;
-          }
-          return b;
-        } else {
-          return (byte[]) fieldsData;
-        }
-      } else
-        return null;     
-    }
-  }
 }
Index: lucene/src/java/org/apache/lucene/index/FieldsWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FieldsWriter.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FieldsWriter.java	(working copy)
@@ -17,19 +17,16 @@
  */
 
 import java.io.IOException;
-import java.util.List;
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.NumericField;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.store.IndexOutput;
+import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.IOUtils;
 
 final class FieldsWriter {
-  static final int FIELD_IS_TOKENIZED = 1 << 0;
+  // NOTE: bit 0 is free here!  You can steal it!
   static final int FIELD_IS_BINARY = 1 << 1;
 
   // the old bit 1 << 2 was compressed, is now left out
@@ -138,15 +135,17 @@
     }
   }
 
-  final void writeField(int fieldNumber, Fieldable field) throws IOException {
+  final void writeField(int fieldNumber, IndexableField field) throws IOException {
     fieldsStream.writeVInt(fieldNumber);
     int bits = 0;
-    if (field.isTokenized())
-      bits |= FIELD_IS_TOKENIZED;
-    if (field.isBinary())
-      bits |= FIELD_IS_BINARY;
-    if (field instanceof NumericField) {
-      switch (((NumericField) field).getDataType()) {
+    final BytesRef bytes;
+    final String string;
+    // TODO: maybe a field should serialize itself?
+    // this way we don't bake into indexer all these
+    // specific encodings for different fields?  and apps
+    // can customize...
+    if (field.numeric()) {
+      switch (field.numericDataType()) {
         case INT:
           bits |= FIELD_IS_NUMERIC_INT; break;
         case LONG:
@@ -158,23 +157,31 @@
         default:
           assert false : "Should never get here";
       }
+      string = null;
+      bytes = null;
+    } else {
+      bytes = field.binaryValue();
+      if (bytes != null) {
+        bits |= FIELD_IS_BINARY;
+        string = null;
+      } else {
+        string = field.stringValue();
+      }
     }
+
     fieldsStream.writeByte((byte) bits);
 
-    if (field.isBinary()) {
-      final byte[] data;
-      final int len;
-      final int offset;
-      data = field.getBinaryValue();
-      len = field.getBinaryLength();
-      offset =  field.getBinaryOffset();
-
-      fieldsStream.writeVInt(len);
-      fieldsStream.writeBytes(data, offset, len);
-    } else if (field instanceof NumericField) {
-      final NumericField nf = (NumericField) field;
-      final Number n = nf.getNumericValue();
-      switch (nf.getDataType()) {
+    if (bytes != null) {
+      fieldsStream.writeVInt(bytes.length);
+      fieldsStream.writeBytes(bytes.bytes, bytes.offset, bytes.length);
+    } else if (string != null) {
+      fieldsStream.writeString(field.stringValue());
+    } else {
+      final Number n = field.numericValue();
+      if (n == null) {
+        throw new IllegalArgumentException("field " + field.name() + " is stored but does not have binaryValue, stringValue nor numericValue");
+      }
+      switch (field.numericDataType()) {
         case INT:
           fieldsStream.writeInt(n.intValue()); break;
         case LONG:
@@ -186,8 +193,6 @@
         default:
           assert false : "Should never get here";
       }
-    } else {
-      fieldsStream.writeString(field.stringValue());
     }
   }
 
@@ -207,21 +212,21 @@
     assert fieldsStream.getFilePointer() == position;
   }
 
-  final void addDocument(Document doc, FieldInfos fieldInfos) throws IOException {
+  final void addDocument(Iterable<? extends IndexableField> doc, FieldInfos fieldInfos) throws IOException {
     indexStream.writeLong(fieldsStream.getFilePointer());
 
     int storedCount = 0;
-    List<Fieldable> fields = doc.getFields();
-    for (Fieldable field : fields) {
-      if (field.isStored())
-          storedCount++;
+    for (IndexableField field : doc) {
+      if (field.stored()) {
+        storedCount++;
+      }
     }
     fieldsStream.writeVInt(storedCount);
 
-
-    for (Fieldable field : fields) {
-      if (field.isStored())
+    for (IndexableField field : doc) {
+      if (field.stored()) {
         writeField(fieldInfos.fieldNumber(field.name()), field);
+      }
     }
   }
 }
Index: lucene/src/java/org/apache/lucene/index/values/IntsImpl.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/values/IntsImpl.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/values/IntsImpl.java	(working copy)
@@ -21,7 +21,6 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.lucene.index.IndexFileNames;
-import org.apache.lucene.index.values.IndexDocValuesArray;
 import org.apache.lucene.index.values.IndexDocValues.Source;
 import org.apache.lucene.index.values.IndexDocValues.SourceEnum;
 import org.apache.lucene.index.values.IndexDocValuesArray.ByteValues;
@@ -319,7 +318,7 @@
       try {
         input = (IndexInput) datIn.clone();
         input.seek(CodecUtil.headerLength(CODEC_NAME) + 1);
-        source  = loadFixedSource(type, input, numDocs);
+        source = loadFixedSource(type, input, numDocs);
         success = true;
         return source;
       } finally {
Index: lucene/src/java/org/apache/lucene/index/values/PerDocFieldValues.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/values/PerDocFieldValues.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/values/PerDocFieldValues.java	(working copy)
@@ -19,14 +19,12 @@
 import java.util.Comparator;
 
 import org.apache.lucene.document.IndexDocValuesField;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.codecs.DocValuesConsumer;
 import org.apache.lucene.util.BytesRef;
 
 /**
  * Per document and field values consumed by {@link DocValuesConsumer}. 
  * @see IndexDocValuesField
- * @see Fieldable#setDocValues(PerDocFieldValues)
  * 
  * @lucene.experimental
  */
@@ -91,11 +89,10 @@
   /**
    * Sets the {@link ValueType}
    */
-  public void setType(ValueType type);
+  public void setDocValuesType(ValueType type);
 
   /**
   * Returns the {@link ValueType}
   */
-  public ValueType type();
-
-}
\ No newline at end of file
+  public ValueType docValuesType();
+}
Index: lucene/src/java/org/apache/lucene/index/IndexableField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/IndexableField.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/index/IndexableField.java	(revision 1160484)
@@ -0,0 +1,104 @@
+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.analysis.TokenStream;
+import org.apache.lucene.document.NumericField;
+import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.values.PerDocFieldValues;
+import org.apache.lucene.index.values.ValueType;
+import org.apache.lucene.util.BytesRef;
+
+// TODO: how to handle versioning here...?
+
+// TODO: we need to break out separate StoredField...
+
+/** Represents a single field for indexing.  IndexWriter
+ *  consumes Iterable<IndexableField> as a document.
+ *
+ *  @lucene.experimental */
+
+public interface IndexableField {
+
+  // TODO: add attrs to this API?
+
+  /* Field name */
+  public String name();
+
+  // NOTE: if doc/field impl has the notion of "doc level boost"
+  // it must be multiplied in w/ this field's boost
+
+  /** Field boost (you must pre-multiply in any doc boost). */
+  public float boost();
+  
+  /* True if the field's value should be stored */
+  public boolean stored();
+
+  /* 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 pre-tokenized ({@link TokenStream}) value */
+  public TokenStream tokenStreamValue();
+
+  // Numeric field:
+  /* True if this field is numeric */
+  public boolean numeric();
+
+  /* Numeric {@link NumericField.DataType}; only used if
+   * the field is numeric */
+  public NumericField.DataType numericDataType();
+
+  /* Numeric value; only used if the field is numeric */
+  public Number numericValue();
+
+  /* True if this field should be indexed (inverted) */
+  public boolean indexed();
+
+  /* True if this field's value should be analyzed */
+  public boolean tokenized();
+
+  /* True if norms should not be indexed */
+  public boolean omitNorms();
+
+  /* {@link IndexOptions}, describing what should be
+   * recorded into the inverted index */
+  public IndexOptions indexOptions();
+
+  /* True if term vectors should be indexed */
+  public boolean storeTermVectors();
+
+  /* True if term vector offsets should be indexed */
+  public boolean storeTermVectorOffsets();
+
+  /* True if term vector positions should be indexed */
+  public boolean storeTermVectorPositions();
+  
+  /* Non-null if doc values should be indexed */
+  public PerDocFieldValues docValues();
+
+  /* DocValues type; only used if docValues is non-null */
+  public ValueType docValuesType();
+}

Property changes on: lucene/src/java/org/apache/lucene/index/IndexableField.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/PersistentSnapshotDeletionPolicy.java	(working copy)
@@ -25,9 +25,7 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.LockObtainFailedException;
@@ -71,12 +69,11 @@
       // index is allowed to have exactly one document or 0.
       if (numDocs == 1) {
         Document doc = r.document(r.maxDoc() - 1);
-        Field sid = doc.getField(SNAPSHOTS_ID);
-        if (sid == null) {
+        if (doc.getField(SNAPSHOTS_ID) == null) {
           throw new IllegalStateException("directory is not a valid snapshots store!");
         }
         doc.removeField(SNAPSHOTS_ID);
-        for (Fieldable f : doc.getFields()) {
+        for (IndexableField f : doc) {
           snapshots.put(f.name(), f.stringValue());
         }
       } else if (numDocs != 0) {
@@ -189,12 +186,14 @@
   private void persistSnapshotInfos(String id, String segment) throws IOException {
     writer.deleteAll();
     Document d = new Document();
-    d.add(new Field(SNAPSHOTS_ID, "", Store.YES, Index.NO));
+    FieldType ft = new FieldType();
+    ft.setStored(true);
+    d.add(new Field(SNAPSHOTS_ID, ft, ""));
     for (Entry<String, String> e : super.getSnapshots().entrySet()) {
-      d.add(new Field(e.getKey(), e.getValue(), Store.YES, Index.NO));
+      d.add(new Field(e.getKey(), ft, e.getValue()));
     }
     if (id != null) {
-      d.add(new Field(id, segment, Store.YES, Index.NO));
+      d.add(new Field(id, ft, segment));
     }
     writer.addDocument(d);
     writer.commit();
Index: lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java	(working copy)
@@ -22,15 +22,13 @@
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.DocumentsWriterPerThread.DocState;
 import org.apache.lucene.index.codecs.Codec;
-import org.apache.lucene.index.codecs.PerDocConsumer;
 import org.apache.lucene.index.codecs.DocValuesConsumer;
+import org.apache.lucene.index.codecs.PerDocConsumer;
+import org.apache.lucene.index.values.PerDocFieldValues;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.IOUtils;
 
@@ -199,22 +197,16 @@
     consumer.startDocument();
     fieldsWriter.startDocument();
 
-    final Document doc = docState.doc;
-
     fieldCount = 0;
 
     final int thisFieldGen = fieldGen++;
 
-    final List<Fieldable> docFields = doc.getFields();
-    final int numDocFields = docFields.size();
-
     // Absorb any new fields first seen in this document.
     // Also absorb any changes to fields we had already
     // seen before (eg suddenly turning on norms or
     // vectors, etc.):
 
-    for(int i=0;i<numDocFields;i++) {
-      Fieldable field = docFields.get(i);
+    for(IndexableField field : docState.doc) {
       final String fieldName = field.name();
 
       // Make sure we have a PerField allocated
@@ -231,21 +223,22 @@
         // 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.isIndexed(), field.isTermVectorStored(),
-                                      field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(),
-                                      field.getOmitNorms(), false, field.getIndexOptions(), field.docValuesType());
+        FieldInfo fi = fieldInfos.addOrUpdate(fieldName, field.indexed(), field.storeTermVectors(),
+                                              field.storeTermVectorPositions(), field.storeTermVectorOffsets(),
+                                              field.omitNorms(), false, field.indexOptions(), field.docValuesType());
 
         fp = new DocFieldProcessorPerField(this, fi);
         fp.next = fieldHash[hashPos];
         fieldHash[hashPos] = fp;
         totalFieldCount++;
 
-        if (totalFieldCount >= fieldHash.length/2)
+        if (totalFieldCount >= fieldHash.length/2) {
           rehash();
+        }
       } else {
-        fieldInfos.addOrUpdate(fp.fieldInfo.name, field.isIndexed(), field.isTermVectorStored(),
-                            field.isStorePositionWithTermVector(), field.isStoreOffsetWithTermVector(),
-                            field.getOmitNorms(), false, field.getIndexOptions(), field.docValuesType());
+        fieldInfos.addOrUpdate(fp.fieldInfo.name, field.indexed(), field.storeTermVectors(),
+                               field.storeTermVectorPositions(), field.storeTermVectorOffsets(),
+                               field.omitNorms(), false, field.indexOptions(), field.docValuesType());
       }
 
       if (thisFieldGen != fp.lastGen) {
@@ -266,12 +259,12 @@
 
       fp.addField(field);
 
-      if (field.isStored()) {
+      if (field.stored()) {
         fieldsWriter.addField(field, fp.fieldInfo);
       }
-      if (field.hasDocValues()) {
-        final DocValuesConsumer docValuesConsumer = docValuesConsumer(docState, fp.fieldInfo);
-        docValuesConsumer.add(docState.docID, field.getDocValues());
+      final PerDocFieldValues docValues = field.docValues();
+      if (docValues != null) {
+        docValuesConsumer(docState, fp.fieldInfo).add(docState.docID, docValues);
       }
     }
 
@@ -339,5 +332,4 @@
     docValues.put(fieldInfo.name, docValuesConsumer);
     return docValuesConsumer;
   }
-
 }
Index: lucene/src/java/org/apache/lucene/index/IndexReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/IndexReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/IndexReader.java	(working copy)
@@ -17,29 +17,28 @@
  * limitations under the License.
  */
 
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.search.FieldCache; // javadocs
-import org.apache.lucene.search.Similarity;
 import org.apache.lucene.index.codecs.Codec;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.codecs.PerDocValues;
 import org.apache.lucene.index.values.IndexDocValues;
+import org.apache.lucene.search.FieldCache; // javadocs
+import org.apache.lucene.search.Similarity;
 import org.apache.lucene.store.*;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.ReaderUtil;         // for javadocs
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.Closeable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
 /** IndexReader is an abstract class, providing an interface for accessing an
  index.  Search of an index is done entirely through this abstract interface,
  so that any subclass which implements it is searchable.
@@ -859,7 +858,6 @@
    * @return array of term frequency vectors. May be null if no term vectors have been
    *  stored for the specified document.
    * @throws IOException if index cannot be accessed
-   * @see org.apache.lucene.document.Field.TermVector
    */
   abstract public TermFreqVector[] getTermFreqVectors(int docNumber)
           throws IOException;
@@ -877,7 +875,6 @@
    * @return term frequency vector May be null if field does not exist in the specified
    * document or term vector was not stored.
    * @throws IOException if index cannot be accessed
-   * @see org.apache.lucene.document.Field.TermVector
    */
   abstract public TermFreqVector getTermFreqVector(int docNumber, String field)
           throws IOException;
@@ -946,57 +943,42 @@
     return maxDoc() - numDocs();
   }
 
+  /** Expert: visits the fields of a stored document, for
+   *  custom processing/loading of each field.  If you
+   *  simply want to load all fields, use {@link
+   *  #document(int)}.  If you want to load a subset, use
+   *  {@link DocumentStoredFieldVisitor}.  */
+  public abstract void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException;
+  
   /**
    * Returns the stored fields of the <code>n</code><sup>th</sup>
-   * <code>Document</code> in this index.
+   * <code>Document</code> in this index.  This is just
+   * sugar for using {@link DocumentStoredFieldVisitor}.
    * <p>
    * <b>NOTE:</b> for performance reasons, this method does not check if the
    * requested document is deleted, and therefore asking for a deleted document
    * may yield unspecified results. Usually this is not required, however you
    * can test if the doc is deleted by checking the {@link
    * Bits} returned from {@link MultiFields#getLiveDocs}.
+   *
+   * <b>NOTE:</b> only the content of a field is returned,
+   * if that field was stored during indexing.  Metadata
+   * like boost, omitNorm, IndexOptions, tokenized, etc.,
+   * are not preserved.
    * 
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public Document document(int n) throws CorruptIndexException, IOException {
+  // TODO: we need a separate StoredField, so that the
+  // Document returned here contains that class not
+  // IndexableField
+  public Document document(int docID) throws CorruptIndexException, IOException {
     ensureOpen();
-    return document(n, null);
+    final DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor();
+    document(docID, visitor);
+    return visitor.getDocument();
   }
 
-  /**
-   * Get the {@link org.apache.lucene.document.Document} at the <code>n</code>
-   * <sup>th</sup> position. The {@link FieldSelector} may be used to determine
-   * what {@link org.apache.lucene.document.Field}s to load and how they should
-   * be loaded. <b>NOTE:</b> If this Reader (more specifically, the underlying
-   * <code>FieldsReader</code>) is closed before the lazy
-   * {@link org.apache.lucene.document.Field} is loaded an exception may be
-   * thrown. If you want the value of a lazy
-   * {@link org.apache.lucene.document.Field} to be available after closing you
-   * must explicitly load it or fetch the Document again with a new loader.
-   * <p>
-   * <b>NOTE:</b> for performance reasons, this method does not check if the
-   * requested document is deleted, and therefore asking for a deleted document
-   * may yield unspecified results. Usually this is not required, however you
-   * can test if the doc is deleted by checking the {@link
-   * Bits} returned from {@link MultiFields#getLiveDocs}.
-   * 
-   * @param n Get the document at the <code>n</code><sup>th</sup> position
-   * @param fieldSelector The {@link FieldSelector} to use to determine what
-   *        Fields should be loaded on the Document. May be null, in which case
-   *        all Fields will be loaded.
-   * @return The stored fields of the
-   *         {@link org.apache.lucene.document.Document} at the nth position
-   * @throws CorruptIndexException if the index is corrupt
-   * @throws IOException if there is a low-level IO error
-   * @see org.apache.lucene.document.Fieldable
-   * @see org.apache.lucene.document.FieldSelector
-   * @see org.apache.lucene.document.SetBasedFieldSelector
-   * @see org.apache.lucene.document.LoadFirstFieldSelector
-   */
-  // TODO (1.5): When we convert to JDK 1.5 make this Set<String>
-  public abstract Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException;
-  
   /** Returns true if any documents have been deleted */
   public abstract boolean hasDeletions();
 
@@ -1017,8 +999,8 @@
   public abstract byte[] norms(String field) throws IOException;
 
   /** Expert: Resets the normalization factor for the named field of the named
-   * document.  By default, The norm represents the product of the field's {@link
-   * org.apache.lucene.document.Fieldable#setBoost(float) boost} and its
+   * document.  By default, the norm represents the product of the field's {@link
+   * org.apache.lucene.document.Field#setBoost(float) boost} and its
    * length normalization}.  Thus, to preserve the length normalization
    * values when resetting this, one should base the new value upon the old.
    *
Index: lucene/src/java/org/apache/lucene/index/DocumentStoredFieldVisitor.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocumentStoredFieldVisitor.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/index/DocumentStoredFieldVisitor.java	(revision 1160484)
@@ -0,0 +1,142 @@
+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.IOException;
+import java.util.Set;
+import java.util.HashSet;
+
+import org.apache.lucene.document.BinaryField;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.NumericField;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.store.IndexInput;
+
+/** A {@link StoredFieldVisitor} that creates a {@link
+ *  Document} containing all stored fields, or only specific
+ *  requested fields provided to {@link #DocumentStoredFieldVisitor(Set)}
+ *  This is used by {@link IndexReader#document(int)} to load a
+ *  document.
+ *
+ * @lucene.experimental */
+
+public class DocumentStoredFieldVisitor extends StoredFieldVisitor {
+  private final Document doc = new Document();
+  private final Set<String> fieldsToAdd;
+
+  /** Load only fields named in the provided <code>Set&lt;String&gt;</code>. */
+  public DocumentStoredFieldVisitor(Set<String> fieldsToAdd) {
+    this.fieldsToAdd = fieldsToAdd;
+  }
+
+  /** Load only fields named in the provided <code>Set&lt;String&gt;</code>. */
+  public DocumentStoredFieldVisitor(String... fields) {
+    fieldsToAdd = new HashSet<String>(fields.length);
+    for(String field : fields) {
+      fieldsToAdd.add(field);
+    }
+  }
+
+  /** Load all stored fields. */
+  public DocumentStoredFieldVisitor() {
+    this.fieldsToAdd = null;
+  }
+
+  @Override
+  public boolean binaryField(FieldInfo fieldInfo, IndexInput in, int numBytes) throws IOException {
+    if (accept(fieldInfo)) {
+      final byte[] b = new byte[numBytes];
+      in.readBytes(b, 0, b.length);
+      doc.add(new BinaryField(fieldInfo.name, b));
+    } else {
+      in.seek(in.getFilePointer() + numBytes);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+    if (accept(fieldInfo)) {
+      final byte[] b = new byte[numUTF8Bytes];
+      in.readBytes(b, 0, b.length);
+      FieldType ft = new FieldType(TextField.TYPE_STORED);
+      ft.setStoreTermVectors(fieldInfo.storeTermVector);
+      ft.setStoreTermVectorPositions(fieldInfo.storePositionWithTermVector);
+      ft.setStoreTermVectorOffsets(fieldInfo.storeOffsetWithTermVector);
+      ft.setStoreTermVectors(fieldInfo.storeTermVector);
+      ft.setOmitNorms(fieldInfo.omitNorms);
+      ft.setIndexOptions(fieldInfo.indexOptions);
+      doc.add(new Field(fieldInfo.name,
+                        ft,
+                        new String(b, "UTF-8")));
+    } else {
+      in.seek(in.getFilePointer() + numUTF8Bytes);
+    }
+    return false;
+  }
+
+  @Override
+  public boolean intField(FieldInfo fieldInfo, int value) {
+    if (accept(fieldInfo)) {
+      FieldType ft = new FieldType(NumericField.TYPE_STORED);
+      ft.setIndexed(fieldInfo.isIndexed);
+      doc.add(new NumericField(fieldInfo.name, ft).setIntValue(value));
+    }
+    return false;
+  }
+
+  @Override
+  public boolean longField(FieldInfo fieldInfo, long value) {
+    if (accept(fieldInfo)) {
+      FieldType ft = new FieldType(NumericField.TYPE_STORED);
+      ft.setIndexed(fieldInfo.isIndexed);
+      doc.add(new NumericField(fieldInfo.name, ft).setLongValue(value));
+    }
+    return false;
+  }
+
+  @Override
+  public boolean floatField(FieldInfo fieldInfo, float value) {
+    if (accept(fieldInfo)) {
+      FieldType ft = new FieldType(NumericField.TYPE_STORED);
+      ft.setIndexed(fieldInfo.isIndexed);
+      doc.add(new NumericField(fieldInfo.name, ft).setFloatValue(value));
+    }
+    return false;
+  }
+
+  @Override
+  public boolean doubleField(FieldInfo fieldInfo, double value) {
+    if (accept(fieldInfo)) {
+      FieldType ft = new FieldType(NumericField.TYPE_STORED);
+      ft.setIndexed(fieldInfo.isIndexed);
+      doc.add(new NumericField(fieldInfo.name, ft).setDoubleValue(value));
+    }
+    return false;
+  }
+
+  private boolean accept(FieldInfo fieldInfo) {
+    return fieldsToAdd == null || fieldsToAdd.contains(fieldInfo.name);
+  }
+
+  public Document getDocument() {
+    return doc;
+  }
+}

Property changes on: lucene/src/java/org/apache/lucene/index/DocumentStoredFieldVisitor.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/index/StoredFieldVisitor.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/StoredFieldVisitor.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/index/StoredFieldVisitor.java	(revision 1159961)
@@ -0,0 +1,87 @@
+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.IOException;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.store.IndexInput;
+
+/**
+ * Expert: provides a low-level means of accessing the stored field
+ * values in an index.  See {@link IndexReader#document(int,
+ * StoredFieldVisitor)}.
+ *
+ * See {@link DocumentStoredFieldVisitor}, which is a
+ * <code>StoredFieldVisitor</code> that builds the
+ * {@link Document} containing all stored fields.  This is
+ * used by {@link IndexReader#document(int)}.
+ *
+ * @lucene.experimental */
+
+public class StoredFieldVisitor {
+  /** Process a binary field.  Note that if you want to
+   *  skip the field you must seek the IndexInput
+   *  (e.g., call <code>in.seek(numUTF8Bytes + in.getFilePointer()</code>)
+   *
+   *  <p>Return true to stop loading fields. */
+  public boolean binaryField(FieldInfo fieldInfo, IndexInput in, int numBytes) throws IOException {
+    in.seek(in.getFilePointer() + numBytes);
+    return false;
+  }
+
+  /** Process a string field by reading numUTF8Bytes.
+   *  Note that if you want to skip the field you must
+   *  seek the IndexInput as if you had read numBytes by
+   *  (e.g., call <code>in.seek(numUTF8Bytes + in.getFilePointer()</code>)
+   *
+   *  <p>Return true to stop loading fields. */
+  public boolean stringField(FieldInfo fieldInfo, IndexInput in, int numUTF8Bytes) throws IOException {
+    in.seek(in.getFilePointer() + numUTF8Bytes);
+    return false;
+  }
+
+  /** Process a int numeric field.
+   *
+   *  <p>Return true to stop loading fields. */
+  public boolean intField(FieldInfo fieldInfo, int value) throws IOException {
+    return false;
+  }
+
+  /** Process a long numeric field.
+   *
+   *  <p>Return true to stop loading fields. */
+  public boolean longField(FieldInfo fieldInfo, long value) throws IOException {
+    return false;
+  }
+
+  /** Process a float numeric field.
+   *
+   *  <p>Return true to stop loading fields. */
+  public boolean floatField(FieldInfo fieldInfo, float value) throws IOException {
+    return false;
+  }
+
+  /** Process a double numeric field.
+   *
+   *  <p>Return true to stop loading fields. */
+  public boolean doubleField(FieldInfo fieldInfo, double value) throws IOException {
+    return false;
+  }
+}
+

Property changes on: lucene/src/java/org/apache/lucene/index/StoredFieldVisitor.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/index/FieldInfos.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FieldInfos.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FieldInfos.java	(working copy)
@@ -39,8 +39,8 @@
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.util.CodecUtil;
 
-/** Access to the Fieldable Info file that describes document fields and whether or
- *  not they are indexed. Each segment has a separate Fieldable Info file. Objects
+/** Access to the Field Info file that describes document fields and whether or
+ *  not they are indexed. Each segment has a separate Field Info file. Objects
  *  of this class are thread-safe for multiple readers, but only one thread can
  *  be adding documents at a time, with no other reader or writer threads
  *  accessing this object.
@@ -381,7 +381,7 @@
   /**
    * Calls 5 parameter add with false for all TermVector parameters.
    * 
-   * @param name The name of the Fieldable
+   * @param name The name of the IndexableField
    * @param isIndexed true if the field is indexed
    * @see #addOrUpdate(String, boolean, boolean, boolean, boolean)
    */
Index: lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocumentsWriterPerThread.java	(working copy)
@@ -26,7 +26,6 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DocumentsWriterDeleteQueue.DeleteSlice;
 import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.store.Directory;
@@ -90,7 +89,7 @@
     PrintStream infoStream;
     SimilarityProvider similarityProvider;
     int docID;
-    Document doc;
+    Iterable<? extends IndexableField> doc;
     String maxTermPrefix;
 
     DocState(DocumentsWriterPerThread docWriter) {
@@ -213,7 +212,7 @@
     return retval;
   }
 
-  public void updateDocument(Document doc, Analyzer analyzer, Term delTerm) throws IOException {
+  public void updateDocument(Iterable<? extends IndexableField> doc, Analyzer analyzer, Term delTerm) throws IOException {
     assert writer.testPoint("DocumentsWriterPerThread addDocument start");
     assert deleteQueue != null;
     docState.doc = doc;
@@ -263,7 +262,7 @@
     finishDocument(delTerm);
   }
   
-  public int updateDocuments(Iterable<Document> docs, Analyzer analyzer, Term delTerm) throws IOException {
+  public int updateDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer analyzer, Term delTerm) throws IOException {
     assert writer.testPoint("DocumentsWriterPerThread addDocuments start");
     assert deleteQueue != null;
     docState.analyzer = analyzer;
@@ -280,7 +279,7 @@
     }
     int docCount = 0;
     try {
-      for(Document doc : docs) {
+      for(Iterable<? extends IndexableField> doc : docs) {
         docState.doc = doc;
         docState.docID = numDocsInRAM;
         docCount++;
Index: lucene/src/java/org/apache/lucene/index/ParallelReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/ParallelReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/ParallelReader.java	(working copy)
@@ -18,9 +18,6 @@
  */
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
-import org.apache.lucene.document.FieldSelectorResult;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.codecs.PerDocValues;
 import org.apache.lucene.index.values.IndexDocValues;
 import org.apache.lucene.util.Bits;
@@ -351,30 +348,12 @@
     hasDeletions = false;
   }
 
-  // append fields from storedFieldReaders
   @Override
-  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
     ensureOpen();
-    Document result = new Document();
     for (final IndexReader reader: storedFieldReaders) {
-
-      boolean include = (fieldSelector==null);
-      if (!include) {
-        Collection<String> fields = readerToFields.get(reader);
-        for (final String field : fields)
-          if (fieldSelector.accept(field) != FieldSelectorResult.NO_LOAD) {
-            include = true;
-            break;
-          }
-      }
-      if (include) {
-        List<Fieldable> fields = reader.document(n, fieldSelector).getFields();
-        for (Fieldable field : fields) {
-          result.add(field);
-        }
-      }
+      reader.document(docID, visitor);
     }
-    return result;
   }
 
   // get all vectors
Index: lucene/src/java/org/apache/lucene/index/SegmentReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/SegmentReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/SegmentReader.java	(working copy)
@@ -28,7 +28,9 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
+import org.apache.lucene.store.BufferedIndexInput;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IndexInput;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.codecs.PerDocValues;
 import org.apache.lucene.store.Directory;
@@ -455,10 +457,9 @@
     return core.fieldInfos;
   }
 
-  @Override
-  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
     ensureOpen();
-    return getFieldsReader().doc(n, fieldSelector);
+    getFieldsReader().visitDocument(docID, visitor);
   }
 
   @Override
Index: lucene/src/java/org/apache/lucene/index/InvertedDocConsumerPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/InvertedDocConsumerPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/InvertedDocConsumerPerField.java	(working copy)
@@ -19,24 +19,22 @@
 
 import java.io.IOException;
 
-import org.apache.lucene.document.Fieldable;
-
 abstract class InvertedDocConsumerPerField {
 
-  // Called once per field, and is given all Fieldable
+  // Called once per field, and is given all IndexableField
   // occurrences for this field in the document.  Return
   // true if you wish to see inverted tokens for these
   // fields:
-  abstract boolean start(Fieldable[] fields, int count) throws IOException;
+  abstract boolean start(IndexableField[] fields, int count) throws IOException;
 
   // Called before a field instance is being processed
-  abstract void start(Fieldable field);
+  abstract void start(IndexableField field);
   
   // Called once per inverted token
   abstract void add() throws IOException;
 
-  // Called once per field per document, after all Fieldable
-  // occurrences are inverted
+  // Called once per field per document, after all IndexableFields
+  // are inverted
   abstract void finish() throws IOException;
 
   // Called on hitting an aborting exception
Index: lucene/src/java/org/apache/lucene/index/DocFieldConsumerPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocFieldConsumerPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocFieldConsumerPerField.java	(working copy)
@@ -18,11 +18,10 @@
  */
 
 import java.io.IOException;
-import org.apache.lucene.document.Fieldable;
 
 abstract class DocFieldConsumerPerField {
   /** Processes all occurrences of a single field */
-  abstract void processFields(Fieldable[] fields, int count) throws IOException;
+  abstract void processFields(IndexableField[] fields, int count) throws IOException;
   abstract void abort();
   abstract FieldInfo getFieldInfo();
 }
Index: lucene/src/java/org/apache/lucene/index/DocFieldConsumersPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocFieldConsumersPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocFieldConsumersPerField.java	(working copy)
@@ -18,7 +18,6 @@
  */
 
 import java.io.IOException;
-import org.apache.lucene.document.Fieldable;
 
 final class DocFieldConsumersPerField extends DocFieldConsumerPerField {
 
@@ -35,7 +34,7 @@
   }
 
   @Override
-  public void processFields(Fieldable[] fields, int count) throws IOException {
+  public void processFields(IndexableField[] fields, int count) throws IOException {
     one.processFields(fields, count);
     two.processFields(fields, count);
   }
Index: lucene/src/java/org/apache/lucene/index/StoredFieldsWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/StoredFieldsWriter.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/StoredFieldsWriter.java	(working copy)
@@ -19,7 +19,6 @@
 
 import java.io.IOException;
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.RamUsageEstimator;
@@ -41,12 +40,12 @@
   }
 
   private int numStoredFields;
-  private Fieldable[] storedFields;
+  private IndexableField[] storedFields;
   private int[] fieldNumbers;
 
   public void reset() {
     numStoredFields = 0;
-    storedFields = new Fieldable[1];
+    storedFields = new IndexableField[1];
     fieldNumbers = new int[1];
   }
 
@@ -123,10 +122,10 @@
     assert docWriter.writer.testPoint("StoredFieldsWriter.finishDocument end");
   }
 
-  public void addField(Fieldable field, FieldInfo fieldInfo) throws IOException {
+  public void addField(IndexableField field, FieldInfo fieldInfo) throws IOException {
     if (numStoredFields == storedFields.length) {
       int newSize = ArrayUtil.oversize(numStoredFields + 1, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
-      Fieldable[] newArray = new Fieldable[newSize];
+      IndexableField[] newArray = new IndexableField[newSize];
       System.arraycopy(storedFields, 0, newArray, 0, numStoredFields);
       storedFields = newArray;
     }
Index: lucene/src/java/org/apache/lucene/index/TermsHashConsumerPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermsHashConsumerPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/TermsHashConsumerPerField.java	(working copy)
@@ -24,13 +24,11 @@
 
 import java.io.IOException;
 
-import org.apache.lucene.document.Fieldable;
-
 abstract class TermsHashConsumerPerField {
-  abstract boolean start(Fieldable[] fields, int count) throws IOException;
+  abstract boolean start(IndexableField[] fields, int count) throws IOException;
   abstract void finish() throws IOException;
   abstract void skippingLongTerm() throws IOException;
-  abstract void start(Fieldable field);
+  abstract void start(IndexableField field);
   abstract void newTerm(int termID) throws IOException;
   abstract void addTerm(int termID) throws IOException;
   abstract int getStreamCount();
Index: lucene/src/java/org/apache/lucene/index/CheckIndex.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/CheckIndex.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/CheckIndex.java	(working copy)
@@ -17,6 +17,7 @@
  * limitations under the License.
  */
 
+import org.apache.lucene.document.FieldType; // for javadocs
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.TermQuery;
@@ -24,6 +25,9 @@
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.IndexInput;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.codecs.CodecProvider;
+import org.apache.lucene.index.codecs.DefaultSegmentInfosWriter;
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
@@ -34,7 +38,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.apache.lucene.document.AbstractField;  // for javadocs
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.codecs.CodecProvider;
 import org.apache.lucene.index.codecs.DefaultSegmentInfosWriter;
@@ -187,7 +190,7 @@
 
       /** True if at least one of the fields in this segment
        *  has position data
-       *  @see AbstractField#setIndexOptions(org.apache.lucene.index.FieldInfo.IndexOptions) */
+       *  @see FieldType#setIndexOptions(org.apache.lucene.index.FieldInfo.IndexOptions) */
       public boolean hasProx;
 
       /** Map that includes certain
Index: lucene/src/java/org/apache/lucene/index/MultiReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/MultiReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/MultiReader.java	(working copy)
@@ -23,7 +23,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.index.codecs.PerDocValues;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
@@ -258,12 +257,11 @@
     return maxDoc;
   }
 
-  // inherit javadoc
   @Override
-  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
     ensureOpen();
-    int i = readerIndex(n);                          // find segment num
-    return subReaders[i].document(n - starts[i], fieldSelector);    // dispatch to segment reader
+    int i = readerIndex(docID);                          // find segment num
+    subReaders[i].document(docID - starts[i], visitor);    // dispatch to segment reader
   }
 
   @Override
Index: lucene/src/java/org/apache/lucene/index/DirectoryReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DirectoryReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DirectoryReader.java	(working copy)
@@ -29,8 +29,6 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.Lock;
@@ -559,12 +557,11 @@
     return maxDoc;
   }
 
-  // inherit javadoc
   @Override
-  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
     ensureOpen();
-    int i = readerIndex(n);                          // find segment num
-    return subReaders[i].document(n - starts[i], fieldSelector);    // dispatch to segment reader
+    int i = readerIndex(docID);                          // find segment num
+    subReaders[i].document(docID - starts[i], visitor);    // dispatch to segment reader
   }
 
   @Override
Index: lucene/src/java/org/apache/lucene/index/FilterIndexReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FilterIndexReader.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FilterIndexReader.java	(working copy)
@@ -18,8 +18,8 @@
  */
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.index.codecs.PerDocValues;
+import org.apache.lucene.index.IndexReader.ReaderContext;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
@@ -351,9 +351,9 @@
   }
 
   @Override
-  public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
+  public void document(int docID, StoredFieldVisitor visitor) throws CorruptIndexException, IOException {
     ensureOpen();
-    return in.document(n, fieldSelector);
+    in.document(docID, visitor);
   }
 
   @Override
Index: lucene/src/java/org/apache/lucene/index/SegmentMerger.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/SegmentMerger.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/SegmentMerger.java	(working copy)
@@ -335,6 +335,10 @@
           // skip deleted docs
           continue;
         }
+        // TODO: this could be more efficient using
+        // FieldVisitor instead of loading/writing entire
+        // doc; ie we just have to renumber the field number
+        // on the fly?
         // NOTE: it's very important to first assign to doc then pass it to
         // termVectorsWriter.addAllDocVectors; see LUCENE-1282
         Document doc = reader.reader.document(j);
Index: lucene/src/java/org/apache/lucene/index/TermsHashPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermsHashPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/TermsHashPerField.java	(working copy)
@@ -22,7 +22,6 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.util.ByteBlockPool;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.BytesRefHash;
@@ -116,7 +115,7 @@
   private boolean doNextCall;
 
   @Override
-  void start(Fieldable f) {
+  void start(IndexableField f) {
     termAtt = fieldState.attributeSource.getAttribute(TermToBytesRefAttribute.class);
     termBytesRef = termAtt.getBytesRef();
     consumer.start(f);
@@ -126,11 +125,12 @@
   }
 
   @Override
-  boolean start(Fieldable[] fields, int count) throws IOException {
+  boolean start(IndexableField[] fields, int count) throws IOException {
     doCall = consumer.start(fields, count);
     bytesHash.reinit();
-    if (nextPerField != null)
+    if (nextPerField != null) {
       doNextCall = nextPerField.start(fields, count);
+    }
     return doCall || doNextCall;
   }
 
Index: lucene/src/java/org/apache/lucene/index/DocFieldProcessorPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocFieldProcessorPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocFieldProcessorPerField.java	(working copy)
@@ -17,7 +17,6 @@
  * limitations under the License.
  */
 
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.util.ArrayUtil;
 import org.apache.lucene.util.RamUsageEstimator;
 
@@ -34,17 +33,17 @@
   int lastGen = -1;
 
   int fieldCount;
-  Fieldable[] fields = new Fieldable[1];
+  IndexableField[] fields = new IndexableField[1];
 
   public DocFieldProcessorPerField(final DocFieldProcessor docFieldProcessor, final FieldInfo fieldInfo) {
     this.consumer = docFieldProcessor.consumer.addField(fieldInfo);
     this.fieldInfo = fieldInfo;
   }
 
-  public void addField(Fieldable field) {
+  public void addField(IndexableField field) {
     if (fieldCount == fields.length) {
       int newSize = ArrayUtil.oversize(fieldCount + 1, RamUsageEstimator.NUM_BYTES_OBJECT_REF);
-      Fieldable[] newArray = new Fieldable[newSize];
+      IndexableField[] newArray = new IndexableField[newSize];
       System.arraycopy(fields, 0, newArray, 0, fieldCount);
       fields = newArray;
     }
Index: lucene/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java	(working copy)
@@ -22,7 +22,6 @@
 import java.util.Map;
 
 import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.codecs.FieldsConsumer;
 import org.apache.lucene.index.codecs.PostingsConsumer;
@@ -82,15 +81,17 @@
   }
 
   @Override
-  boolean start(Fieldable[] fields, int count) {
-    for(int i=0;i<count;i++)
-      if (fields[i].isIndexed())
+  boolean start(IndexableField[] fields, int count) {
+    for(int i=0;i<count;i++) {
+      if (fields[i].indexed()) {
         return true;
+      }
+    }
     return false;
   }
 
   @Override
-  void start(Fieldable f) {
+  void start(IndexableField f) {
     if (fieldState.attributeSource.hasAttribute(PayloadAttribute.class)) {
       payloadAttribute = fieldState.attributeSource.getAttribute(PayloadAttribute.class);
     } else {
Index: lucene/src/java/org/apache/lucene/index/FieldInfo.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FieldInfo.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FieldInfo.java	(working copy)
@@ -30,9 +30,9 @@
 
 
   // true if term vector for this field should be stored
-  boolean storeTermVector;
-  boolean storeOffsetWithTermVector;
-  boolean storePositionWithTermVector;
+  public boolean storeTermVector;
+  public boolean storeOffsetWithTermVector;
+  public boolean storePositionWithTermVector;
 
   public boolean omitNorms; // omit norms associated with indexed fields  
   public IndexOptions indexOptions;
Index: lucene/src/java/org/apache/lucene/index/FieldInvertState.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FieldInvertState.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/FieldInvertState.java	(working copy)
@@ -50,14 +50,14 @@
    * Re-initialize the state, using this boost value.
    * @param docBoost boost value to use.
    */
-  void reset(float docBoost) {
+  void reset() {
     position = 0;
     length = 0;
     numOverlap = 0;
     offset = 0;
     maxTermFrequency = 0;
     uniqueTermCount = 0;
-    boost = docBoost;
+    boost = 1.0f;
     attributeSource = null;
   }
 
Index: lucene/src/java/org/apache/lucene/index/DocumentsWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocumentsWriter.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/DocumentsWriter.java	(working copy)
@@ -27,7 +27,6 @@
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DocumentsWriterPerThread.FlushedSegment;
 import org.apache.lucene.index.DocumentsWriterPerThread.IndexingChain;
 import org.apache.lucene.index.DocumentsWriterPerThreadPool.ThreadState;
@@ -320,7 +319,7 @@
     return maybeMerge;
   }
 
-  boolean updateDocuments(final Iterable<Document> docs, final Analyzer analyzer,
+  boolean updateDocuments(final Iterable<? extends Iterable<? extends IndexableField>> docs, final Analyzer analyzer,
                           final Term delTerm) throws CorruptIndexException, IOException {
     boolean maybeMerge = preUpdate();
 
@@ -351,7 +350,7 @@
     return postUpdate(flushingDWPT, maybeMerge);
   }
 
-  boolean updateDocument(final Document doc, final Analyzer analyzer,
+  boolean updateDocument(final Iterable<? extends IndexableField> doc, final Analyzer analyzer,
       final Term delTerm) throws CorruptIndexException, IOException {
 
     boolean maybeMerge = preUpdate();
Index: lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java	(working copy)
@@ -20,7 +20,6 @@
 import java.io.IOException;
 
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.store.IndexOutput;
 import org.apache.lucene.util.ByteBlockPool;
 import org.apache.lucene.util.BytesRef;
@@ -55,17 +54,17 @@
   }
 
   @Override
-  boolean start(Fieldable[] fields, int count) {
+  boolean start(IndexableField[] fields, int count) {
     doVectors = false;
     doVectorPositions = false;
     doVectorOffsets = false;
 
     for(int i=0;i<count;i++) {
-      Fieldable field = fields[i];
-      if (field.isIndexed() && field.isTermVectorStored()) {
+      IndexableField field = fields[i];
+      if (field.indexed() && field.storeTermVectors()) {
         doVectors = true;
-        doVectorPositions |= field.isStorePositionWithTermVector();
-        doVectorOffsets |= field.isStoreOffsetWithTermVector();
+        doVectorPositions |= field.storeTermVectorPositions();
+        doVectorOffsets |= field.storeTermVectorOffsets();
       }
     }
 
@@ -188,7 +187,7 @@
   }
 
   @Override
-  void start(Fieldable f) {
+  void start(IndexableField f) {
     if (doVectorOffsets) {
       offsetAttribute = fieldState.attributeSource.addAttribute(OffsetAttribute.class);
     } else {
Index: lucene/src/java/org/apache/lucene/index/IndexWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/IndexWriter.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/IndexWriter.java	(working copy)
@@ -36,7 +36,6 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.document.Document;
 import org.apache.lucene.index.DocumentsWriterPerThread.FlushedSegment;
 import org.apache.lucene.index.FieldInfos.FieldNumberBiMap;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
@@ -74,10 +73,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(Document)
+  <p>In either case, documents are added with {@link #addDocument(Iterable)
   addDocument} and removed with {@link #deleteDocuments(Term)} or {@link
   #deleteDocuments(Query)}. A document can be updated with {@link
-  #updateDocument(Term, Document) updateDocument} (which just deletes
+  #updateDocument(Term, Iterable) updateDocument} (which just deletes
   and then adds the entire document). When finished adding, deleting 
   and updating documents, {@link #close() close} should be called.</p>
 
@@ -1283,7 +1282,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void addDocument(Document doc) throws CorruptIndexException, IOException {
+  public void addDocument(Iterable<? extends IndexableField> doc) throws CorruptIndexException, IOException {
     addDocument(doc, analyzer);
   }
 
@@ -1291,7 +1290,7 @@
    * Adds a document to this index, using the provided analyzer instead of the
    * value of {@link #getAnalyzer()}.
    *
-   * <p>See {@link #addDocument(Document)} for details on
+   * <p>See {@link #addDocument(Iterable)} for details on
    * index and IndexWriter state after an Exception, and
    * flushing/merging temporary free space requirements.</p>
    *
@@ -1302,7 +1301,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void addDocument(Document doc, Analyzer analyzer) throws CorruptIndexException, IOException {
+  public void addDocument(Iterable<? extends IndexableField> doc, Analyzer analyzer) throws CorruptIndexException, IOException {
     updateDocument(null, doc, analyzer);
   }
 
@@ -1320,7 +1319,7 @@
    * compression), in which case you may need to fully
    * re-index your documents at that time.
    *
-   * <p>See {@link #addDocument(Document)} for details on
+   * <p>See {@link #addDocument(Iterable)} for details on
    * index and IndexWriter state after an Exception, and
    * flushing/merging temporary free space requirements.</p>
    *
@@ -1340,7 +1339,7 @@
    *
    * @lucene.experimental
    */
-  public void addDocuments(Iterable<Document> docs) throws CorruptIndexException, IOException {
+  public void addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs) throws CorruptIndexException, IOException {
     addDocuments(docs, analyzer);
   }
 
@@ -1355,7 +1354,7 @@
    *
    * @lucene.experimental
    */
-  public void addDocuments(Iterable<Document> docs, Analyzer analyzer) throws CorruptIndexException, IOException {
+  public void addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer analyzer) throws CorruptIndexException, IOException {
     updateDocuments(null, docs, analyzer);
   }
 
@@ -1372,7 +1371,7 @@
    *
    * @lucene.experimental
    */
-  public void updateDocuments(Term delTerm, Iterable<Document> docs) throws CorruptIndexException, IOException {
+  public void updateDocuments(Term delTerm, Iterable<? extends Iterable<? extends IndexableField>> docs) throws CorruptIndexException, IOException {
     updateDocuments(delTerm, docs, analyzer);
   }
 
@@ -1390,7 +1389,7 @@
    *
    * @lucene.experimental
    */
-  public void updateDocuments(Term delTerm, Iterable<Document> docs, Analyzer analyzer) throws CorruptIndexException, IOException {
+  public void updateDocuments(Term delTerm, Iterable<? extends Iterable<? extends IndexableField>> docs, Analyzer analyzer) throws CorruptIndexException, IOException {
     ensureOpen();
     try {
       boolean success = false;
@@ -1513,7 +1512,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void updateDocument(Term term, Document doc) throws CorruptIndexException, IOException {
+  public void updateDocument(Term term, Iterable<? extends IndexableField> doc) throws CorruptIndexException, IOException {
     ensureOpen();
     updateDocument(term, doc, getAnalyzer());
   }
@@ -1536,7 +1535,7 @@
    * @throws CorruptIndexException if the index is corrupt
    * @throws IOException if there is a low-level IO error
    */
-  public void updateDocument(Term term, Document doc, Analyzer analyzer)
+  public void updateDocument(Term term, Iterable<? extends IndexableField> doc, Analyzer analyzer)
       throws CorruptIndexException, IOException {
     ensureOpen();
     try {
@@ -3036,7 +3035,7 @@
   DocumentsWriter getDocsWriter() {
     boolean test = false;
     assert test = true;
-    return test?docWriter: null;
+    return test ? docWriter : null;
   }
 
   /** Expert:  Return the number of documents currently
Index: lucene/src/java/org/apache/lucene/index/TermFreqVector.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermFreqVector.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/index/TermFreqVector.java	(working copy)
@@ -26,7 +26,7 @@
  */
 public interface TermFreqVector {
   /**
-   * The {@link org.apache.lucene.document.Fieldable} name. 
+   * The {@link org.apache.lucene.index.IndexableField} name. 
    * @return The name of the field this vector is associated with.
    * 
    */ 
Index: lucene/src/java/org/apache/lucene/document/IndexDocValuesField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/IndexDocValuesField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/IndexDocValuesField.java	(working copy)
@@ -20,16 +20,13 @@
 import java.util.Comparator;
 
 import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
 import org.apache.lucene.index.values.PerDocFieldValues;
 import org.apache.lucene.index.values.ValueType;
 import org.apache.lucene.util.BytesRef;
 
 /**
  * <p>
- * This class provides a {@link AbstractField} that enables storing of typed
+ * This class provides a {@link Field} that enables storing of typed
  * per-document values for scoring, sorting or value retrieval. Here's an
  * example usage, adding an int value:
  * 
@@ -54,9 +51,9 @@
  * </pre>
  * 
  * <p>
- * If doc values are stored in addition to an indexed ({@link Index}) or stored
- * ({@link Store}) value it's recommended to use the {@link IndexDocValuesField}'s
- * {@link #set(AbstractField)} API:
+ * If doc values are stored in addition to an indexed ({@link FieldType#setIndexed(boolean)}) or stored
+ * ({@link FieldType#setStored(boolean)}) value it's recommended to use the {@link IndexDocValuesField}'s
+ * {@link #set(Field)} API:
  * 
  * <pre>
  *  IndexDocValuesField field = new IndexDocValuesField(name);
@@ -73,7 +70,8 @@
  * </pre>
  * 
  * */
-public class IndexDocValuesField extends AbstractField implements PerDocFieldValues {
+// TODO: maybe rename to DocValuesField?
+public class IndexDocValuesField extends Field implements PerDocFieldValues {
 
   protected BytesRef bytes;
   protected double doubleValue;
@@ -85,21 +83,27 @@
    * Creates a new {@link IndexDocValuesField} with the given name.
    */
   public IndexDocValuesField(String name) {
-    super(name, Store.NO, Index.NO, TermVector.NO);
-    setDocValues(this);
+    this(name, new FieldType());
   }
 
-  /**
-   * Creates a {@link IndexDocValuesField} prototype
-   */
-  IndexDocValuesField() {
-    this("");
+  public IndexDocValuesField(String name, FieldType type) {
+    this(name, type, null);
   }
 
+  public IndexDocValuesField(String name, FieldType type, String value) {
+    super(name, type);
+    fieldsData = value;
+  }
+
+  @Override
+  public PerDocFieldValues docValues() {
+    return this;
+  }
+
   /**
    * Sets the given <code>long</code> value and sets the field's {@link ValueType} to
    * {@link ValueType#VAR_INTS} unless already set. If you want to change the
-   * default type use {@link #setType(ValueType)}.
+   * default type use {@link #setDocValuesType(ValueType)}.
    */
   public void setInt(long value) {
     setInt(value, false);
@@ -124,7 +128,7 @@
   /**
    * Sets the given <code>int</code> value and sets the field's {@link ValueType} to
    * {@link ValueType#VAR_INTS} unless already set. If you want to change the
-   * default type use {@link #setType(ValueType)}.
+   * default type use {@link #setDocValuesType(ValueType)}.
    */
   public void setInt(int value) {
     setInt(value, false);
@@ -149,7 +153,7 @@
   /**
    * Sets the given <code>short</code> value and sets the field's {@link ValueType} to
    * {@link ValueType#VAR_INTS} unless already set. If you want to change the
-   * default type use {@link #setType(ValueType)}.
+   * default type use {@link #setDocValuesType(ValueType)}.
    */
   public void setInt(short value) {
     setInt(value, false);
@@ -174,11 +178,12 @@
   /**
    * Sets the given <code>byte</code> value and sets the field's {@link ValueType} to
    * {@link ValueType#VAR_INTS} unless already set. If you want to change the
-   * default type use {@link #setType(ValueType)}.
+   * default type use {@link #setDocValuesType(ValueType)}.
    */
   public void setInt(byte value) {
     setInt(value, false);
   }
+
   /**
    * Sets the given <code>byte</code> value as a 8 bit signed integer.
    * 
@@ -198,7 +203,7 @@
   /**
    * Sets the given <code>float</code> value and sets the field's {@link ValueType}
    * to {@link ValueType#FLOAT_32} unless already set. If you want to
-   * change the type use {@link #setType(ValueType)}.
+   * change the type use {@link #setDocValuesType(ValueType)}.
    */
   public void setFloat(float value) {
     if (type == null) {
@@ -210,7 +215,7 @@
   /**
    * Sets the given <code>double</code> value and sets the field's {@link ValueType}
    * to {@link ValueType#FLOAT_64} unless already set. If you want to
-   * change the default type use {@link #setType(ValueType)}.
+   * change the default type use {@link #setDocValuesType(ValueType)}.
    */
   public void setFloat(double value) {
     if (type == null) {
@@ -241,7 +246,7 @@
     if (value == null) {
       throw new IllegalArgumentException("value must not be null");
     }
-    setType(type);
+    setDocValuesType(type);
     if (bytes == null) {
       bytes = new BytesRef(value);
     } else {
@@ -289,7 +294,7 @@
   /**
    * Sets the {@link ValueType} for this field.
    */
-  public void setType(ValueType type) {
+  public void setDocValuesType(ValueType type) {
     if (type == null) {
       throw new IllegalArgumentException("Type must not be null");
     }
@@ -297,13 +302,6 @@
   }
 
   /**
-   * Returns the field's {@link ValueType}
-   */
-  public ValueType type() {
-    return type;
-  }
-
-  /**
    * Returns always <code>null</code>
    */
   public Reader readerValue() {
@@ -313,36 +311,54 @@
   /**
    * Returns always <code>null</code>
    */
-  public String stringValue() {
+  public TokenStream tokenStreamValue() {
     return null;
   }
 
-  /**
-   * Returns always <code>null</code>
-   */
-  public TokenStream tokenStreamValue() {
-    return null;
+  @Override
+  public ValueType docValuesType() {
+    return type;
   }
 
-  /**
-   * Sets this {@link IndexDocValuesField} to the given {@link AbstractField} and
-   * returns the given field. Any modifications to this instance will be visible
-   * to the given field.
-   */
-  public <T extends AbstractField> T set(T field) {
-    field.setDocValues(this);
-    return field;
+  @Override
+  public String toString() {
+    final String value;
+    switch (type) {
+    case BYTES_FIXED_DEREF:
+    case BYTES_FIXED_SORTED:
+    case BYTES_FIXED_STRAIGHT:
+    case BYTES_VAR_DEREF:
+    case BYTES_VAR_SORTED:
+    case BYTES_VAR_STRAIGHT:
+      value = "bytes:bytes.utf8ToString();";
+      break;
+    case VAR_INTS:
+      value = "int:" + longValue;
+      break;
+    case FLOAT_32:
+      value = "float32:" + doubleValue;
+      break;
+    case FLOAT_64:
+      value = "float64:" + doubleValue;
+      break;
+    default:
+      throw new IllegalArgumentException("unknown type: " + type);
+    }
+    return "<" + name() + ": IndexDocValuesField " + value + ">";
   }
 
   /**
-   * Sets a new {@link PerDocFieldValues} instance on the given field with the
-   * given type and returns it.
-   * 
+   * Returns an IndexDocValuesField holding the value from
+   * the provided string field, as the specified type.  The
+   * incoming field must have a string value.  The name, {@link
+   * FieldType} and string value are carried over from the
+   * incoming Field.
    */
-  public static <T extends AbstractField> T set(T field, ValueType type) {
-    if (field instanceof IndexDocValuesField)
-      return field;
-    final IndexDocValuesField valField = new IndexDocValuesField();
+  public static IndexDocValuesField build(Field field, ValueType type) {
+    if (field instanceof IndexDocValuesField) {
+      return (IndexDocValuesField) field;
+    }
+    final IndexDocValuesField valField = new IndexDocValuesField(field.name(), field.getFieldType(), field.stringValue());
     switch (type) {
     case BYTES_FIXED_DEREF:
     case BYTES_FIXED_SORTED:
@@ -350,9 +366,7 @@
     case BYTES_VAR_DEREF:
     case BYTES_VAR_SORTED:
     case BYTES_VAR_STRAIGHT:
-      BytesRef ref = field.isBinary() ? new BytesRef(field.getBinaryValue(),
-          field.getBinaryOffset(), field.getBinaryLength()) : new BytesRef(
-          field.stringValue());
+      BytesRef ref = field.isBinary() ? field.binaryValue() : new BytesRef(field.stringValue());
       valField.setBytes(ref, type);
       break;
     case VAR_INTS:
@@ -367,7 +381,6 @@
     default:
       throw new IllegalArgumentException("unknown type: " + type);
     }
-    return valField.set(field);
+    return valField;
   }
-
 }
Index: lucene/src/java/org/apache/lucene/document/CompressionTools.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/CompressionTools.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/CompressionTools.java	(working copy)
@@ -92,16 +92,24 @@
     return compress(result.bytes, 0, result.length, compressionLevel);
   }
 
+  public static byte[] decompress(BytesRef bytes) throws DataFormatException {
+    return decompress(bytes.bytes, bytes.offset, bytes.length);
+  }
+
+  public static byte[] decompress(byte[] value) throws DataFormatException {
+    return decompress(value, 0, value.length);
+  }
+
   /** Decompress the byte array previously returned by
    *  compress */
-  public static byte[] decompress(byte[] value) throws DataFormatException {
+  public static byte[] decompress(byte[] value, int offset, int length) throws DataFormatException {
     // Create an expandable byte array to hold the decompressed data
-    ByteArrayOutputStream bos = new ByteArrayOutputStream(value.length);
+    ByteArrayOutputStream bos = new ByteArrayOutputStream(length);
 
     Inflater decompressor = new Inflater();
 
     try {
-      decompressor.setInput(value);
+      decompressor.setInput(value, offset, length);
 
       // Decompress the data
       final byte[] buf = new byte[1024];
@@ -119,9 +127,17 @@
   /** Decompress the byte array previously returned by
    *  compressString back into a String */
   public static String decompressString(byte[] value) throws DataFormatException {
-    final byte[] bytes = decompress(value);
+    return decompressString(value, 0, value.length);
+  }
+
+  public static String decompressString(byte[] value, int offset, int length) throws DataFormatException {
+    final byte[] bytes = decompress(value, offset, length);
     CharsRef result = new CharsRef(bytes.length);
     UnicodeUtil.UTF8toUTF16(bytes, 0, bytes.length, result);
     return new String(result.chars, 0, result.length);
   }
+
+  public static String decompressString(BytesRef bytes) throws DataFormatException {
+    return decompressString(bytes.bytes, bytes.offset, bytes.length);
+  }
 }
Index: lucene/src/java/org/apache/lucene/document/Field.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/Field.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/Field.java	(working copy)
@@ -21,514 +21,325 @@
 
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
-import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.index.values.PerDocFieldValues;
+import org.apache.lucene.index.values.ValueType;
+import org.apache.lucene.util.BytesRef;
 
 /**
-  A field is a section of a Document.  Each field has two parts, a name and a
-  value.  Values may be free text, provided as a String or as a Reader, or they
-  may be atomic keywords, which are not further processed.  Such keywords may
-  be used to represent dates, urls, etc.  Fields are optionally stored in the
-  index, so that they may be returned with hits on the document.
-  */
+ * A field is a section of a Document. Each field has two parts, a name and a
+ * value. Values may be free text, provided as a String or as a Reader, or they
+ * may be atomic keywords, which are not further processed. Such keywords may be
+ * used to represent dates, urls, etc. Fields are optionally stored in the
+ * index, so that they may be returned with hits on the document.
+ */
 
-public final class Field extends AbstractField implements Fieldable {
+public class Field implements IndexableField {
   
-  /** Specifies whether and how a field should be stored. */
-  public static enum Store {
+  protected FieldType type;
+  protected String name = "body";
+  // the data object for all different kind of field values
+  protected Object fieldsData;
+  // pre-analyzed tokenStream for indexed fields
+  protected TokenStream tokenStream;
+  // length/offset for all primitive types
+  protected PerDocFieldValues docValues;
+  
+  protected float boost = 1.0f;
 
-    /** Store the original field value in the index. This is useful for short texts
-     * like a document's title which should be displayed with the results. The
-     * value is stored in its original form, i.e. no analyzer is used before it is
-     * stored.
-     */
-    YES {
-      @Override
-      public boolean isStored() { return true; }
-    },
-
-    /** Do not store the field value in the index. */
-    NO {
-      @Override
-      public boolean isStored() { return false; }
-    };
-
-    public abstract boolean isStored();
+  public Field(String name, FieldType type) {
+    this.name = name;
+    this.type = type;
   }
-
-  /** Specifies whether and how a field should be indexed. */
-  public static enum Index {
-
-    /** Do not index the field value. This field can thus not be searched,
-     * but one can still access its contents provided it is
-     * {@link Field.Store stored}. */
-    NO {
-      @Override
-      public boolean isIndexed()  { return false; }
-      @Override
-      public boolean isAnalyzed() { return false; }
-      @Override
-      public boolean omitNorms()  { return true;  }   
-    },
-
-    /** Index the tokens produced by running the field's
-     * value through an Analyzer.  This is useful for
-     * common text. */
-    ANALYZED {
-      @Override
-      public boolean isIndexed()  { return true;  }
-      @Override
-      public boolean isAnalyzed() { return true;  }
-      @Override
-      public boolean omitNorms()  { return false; }   	
-    },
-
-    /** Index the field's value without using an Analyzer, so it can be searched.
-     * As no analyzer is used the value will be stored as a single term. This is
-     * useful for unique Ids like product numbers.
-     */
-    NOT_ANALYZED {
-      @Override
-      public boolean isIndexed()  { return true;  }
-      @Override
-      public boolean isAnalyzed() { return false; }
-      @Override
-      public boolean omitNorms()  { return false; }   	
-    },
-
-    /** Expert: Index the field's value without an Analyzer,
-     * and also disable the indexing of norms.  Note that you
-     * can also separately enable/disable norms by calling
-     * {@link Field#setOmitNorms}.  No norms means that
-     * index-time field and document boosting and field
-     * length normalization are disabled.  The benefit is
-     * less memory usage as norms take up one byte of RAM
-     * per indexed field for every document in the index,
-     * during searching.  Note that once you index a given
-     * field <i>with</i> norms disabled, enabling norms will
-     * have no effect.  In other words, for this to have the
-     * above described effect on a field, one instance of
-     * that field must be indexed with NOT_ANALYZED_NO_NORMS
-     * at some point. */
-    NOT_ANALYZED_NO_NORMS {
-      @Override
-      public boolean isIndexed()  { return true;  }
-      @Override
-      public boolean isAnalyzed() { return false; }
-      @Override
-      public boolean omitNorms()  { return true;  }   	
-    },
-
-    /** Expert: Index the tokens produced by running the
-     *  field's value through an Analyzer, and also
-     *  separately disable the storing of norms.  See
-     *  {@link #NOT_ANALYZED_NO_NORMS} for what norms are
-     *  and why you may want to disable them. */
-    ANALYZED_NO_NORMS {
-      @Override
-      public boolean isIndexed()  { return true;  }
-      @Override
-      public boolean isAnalyzed() { return true;  }
-      @Override
-      public boolean omitNorms()  { return true;  }   	
-    };
-
-    /** Get the best representation of the index given the flags. */
-    public static Index toIndex(boolean indexed, boolean analyzed) {
-      return toIndex(indexed, analyzed, false);
+  
+  public Field(String name, FieldType type, Reader reader) {
+    if (name == null) {
+      throw new NullPointerException("name cannot be null");
     }
-
-    /** Expert: Get the best representation of the index given the flags. */
-    public static Index toIndex(boolean indexed, boolean analyzed, boolean omitNorms) {
-
-      // If it is not indexed nothing else matters
-      if (!indexed) {
-        return Index.NO;
-      }
-
-      // typical, non-expert
-      if (!omitNorms) {
-        if (analyzed) {
-          return Index.ANALYZED;
-        }
-        return Index.NOT_ANALYZED;
-      }
-
-      // Expert: Norms omitted
-      if (analyzed) {
-        return Index.ANALYZED_NO_NORMS;
-      }
-      return Index.NOT_ANALYZED_NO_NORMS;
+    if (reader == null) {
+      throw new NullPointerException("reader cannot be null");
     }
-
-    public abstract boolean isIndexed();
-    public abstract boolean isAnalyzed();
-    public abstract boolean omitNorms();  	
+    
+    this.name = name;
+    this.fieldsData = reader;
+    this.type = type;
   }
-
-  /** Specifies whether and how a field should have term vectors. */
-  public static enum TermVector {
+  
+  public Field(String name, FieldType type, TokenStream tokenStream) {
+    if (name == null) {
+      throw new NullPointerException("name cannot be null");
+    }
+    if (tokenStream == null) {
+      throw new NullPointerException("tokenStream cannot be null");
+    }
     
-    /** Do not store term vectors. 
-     */
-    NO {
-      @Override
-      public boolean isStored()      { return false; }
-      @Override
-      public boolean withPositions() { return false; }
-      @Override
-      public boolean withOffsets()   { return false; }
-    },
-    
-    /** Store the term vectors of each document. A term vector is a list
-     * of the document's terms and their number of occurrences in that document. */
-    YES {
-      @Override
-      public boolean isStored()      { return true;  }
-      @Override
-      public boolean withPositions() { return false; }
-      @Override
-      public boolean withOffsets()   { return false; }
-    },
-    
-    /**
-     * Store the term vector + token position information
-     * 
-     * @see #YES
-     */ 
-    WITH_POSITIONS {
-      @Override
-      public boolean isStored()      { return true;  }
-      @Override
-      public boolean withPositions() { return true;  }
-      @Override
-      public boolean withOffsets()   { return false; }
-    },
-    
-    /**
-     * Store the term vector + Token offset information
-     * 
-     * @see #YES
-     */ 
-    WITH_OFFSETS {
-      @Override
-      public boolean isStored()      { return true;  }
-      @Override
-      public boolean withPositions() { return false; }
-      @Override
-      public boolean withOffsets()   { return true;  }
-    },
-    
-    /**
-     * Store the term vector + Token position and offset information
-     * 
-     * @see #YES
-     * @see #WITH_POSITIONS
-     * @see #WITH_OFFSETS
-     */ 
-    WITH_POSITIONS_OFFSETS {
-      @Override
-      public boolean isStored()      { return true;  }
-      @Override
-      public boolean withPositions() { return true;  }
-      @Override
-      public boolean withOffsets()   { return true;  }
-    };
+    this.name = name;
+    this.fieldsData = null;
+    this.tokenStream = tokenStream;
+    this.type = type;
+  }
+  
+  public Field(String name, FieldType type, byte[] value) {
+    this(name, type, value, 0, value.length);
+  }
 
-    /** Get the best representation of a TermVector given the flags. */
-    public static TermVector toTermVector(boolean stored, boolean withOffsets, boolean withPositions) {
+  public Field(String name, FieldType type, byte[] value, int offset, int length) {
+    this.fieldsData = new BytesRef(value, offset, length);
+    this.type = type;
+    this.name = name;
+  }
 
-      // If it is not stored, nothing else matters.
-      if (!stored) {
-        return TermVector.NO;
-      }
-
-      if (withOffsets) {
-        if (withPositions) {
-          return Field.TermVector.WITH_POSITIONS_OFFSETS;
-        }
-        return Field.TermVector.WITH_OFFSETS;
-      }
-
-      if (withPositions) {
-        return Field.TermVector.WITH_POSITIONS;
-      }
-      return Field.TermVector.YES;
+  public Field(String name, FieldType type, BytesRef bytes) {
+    this.fieldsData = bytes;
+    this.type = type;
+    this.name = name;
+  }
+  
+  public Field(String name, FieldType type, String value) {
+    if (name == null) {
+      throw new IllegalArgumentException("name cannot be null");
     }
+    if (value == null) {
+      throw new IllegalArgumentException("value cannot be null");
+    }
+    if (!type.stored() && !type.indexed()) {
+      throw new IllegalArgumentException("it doesn't make sense to have a field that "
+        + "is neither indexed nor stored");
+    }
+    if (!type.indexed() && !type.tokenized() && (type.storeTermVectors())) {
+      throw new IllegalArgumentException("cannot store term vector information "
+          + "for a field that is not indexed");
+    }
+    
+    this.type = type;
+    this.name = name;
+    this.fieldsData = value;
+  }
 
-    public abstract boolean isStored();
-    public abstract boolean withPositions();
-    public abstract boolean withOffsets();
+  /**
+   * The value of the field as a String, or null. If null, the Reader value or
+   * binary value is used. Exactly one of stringValue(), readerValue(), and
+   * getBinaryValue() must be set.
+   */
+  public String stringValue() {
+    return fieldsData instanceof String ? (String) fieldsData : null;
   }
   
+  /**
+   * The value of the field as a Reader, or null. If null, the String value or
+   * binary value is used. Exactly one of stringValue(), readerValue(), and
+   * getBinaryValue() must be set.
+   */
+  public Reader readerValue() {
+    return fieldsData instanceof Reader ? (Reader) fieldsData : null;
+  }
   
-  /** The value of the field as a String, or null.  If null, the Reader value or
-   * binary value is used.  Exactly one of stringValue(),
-   * readerValue(), and getBinaryValue() must be set. */
-  public String stringValue()   { return fieldsData instanceof String ? (String)fieldsData : null; }
+  /**
+   * The TokesStream for this field to be used when indexing, or null. If null,
+   * the Reader value or String value is analyzed to produce the indexed tokens.
+   */
+  public TokenStream tokenStreamValue() {
+    return tokenStream;
+  }
   
-  /** The value of the field as a Reader, or null.  If null, the String value or
-   * binary value is used.  Exactly one of stringValue(),
-   * readerValue(), and getBinaryValue() must be set. */
-  public Reader readerValue()   { return fieldsData instanceof Reader ? (Reader)fieldsData : null; }
-    
-  /** The TokesStream for this field to be used when indexing, or null.  If null, the Reader value
-   * or String value is analyzed to produce the indexed tokens. */
-  public TokenStream tokenStreamValue()   { return tokenStream; }
-  
-
-  /** <p>Expert: change the value of this field.  This can
-   *  be used during indexing to re-use a single Field
-   *  instance to improve indexing speed by avoiding GC cost
-   *  of new'ing and reclaiming Field instances.  Typically
-   *  a single {@link Document} instance is re-used as
-   *  well.  This helps most on small documents.</p>
+  /**
+   * <p>
+   * Expert: change the value of this field. This can be used during indexing to
+   * re-use a single Field instance to improve indexing speed by avoiding GC
+   * cost of new'ing and reclaiming Field instances. Typically a single
+   * {@link Document} instance is re-used as well. This helps most on small
+   * documents.
+   * </p>
    * 
-   *  <p>Each Field instance should only be used once
-   *  within a single {@link Document} instance.  See <a
-   *  href="http://wiki.apache.org/lucene-java/ImproveIndexingSpeed">ImproveIndexingSpeed</a>
-   *  for details.</p> */
+   * <p>
+   * Each Field instance should only be used once within a single
+   * {@link Document} instance. See <a
+   * href="http://wiki.apache.org/lucene-java/ImproveIndexingSpeed"
+   * >ImproveIndexingSpeed</a> for details.
+   * </p>
+   */
   public void setValue(String value) {
-    if (isBinary) {
-      throw new IllegalArgumentException("cannot set a String value on a binary field");
+    if (isBinary()) {
+      throw new IllegalArgumentException(
+          "cannot set a String value on a binary field");
     }
     fieldsData = value;
   }
-
-  /** Expert: change the value of this field.  See <a href="#setValue(java.lang.String)">setValue(String)</a>. */
+  
+  /**
+   * Expert: change the value of this field. See <a
+   * href="#setValue(java.lang.String)">setValue(String)</a>.
+   */
   public void setValue(Reader value) {
-    if (isBinary) {
-      throw new IllegalArgumentException("cannot set a Reader value on a binary field");
+    if (isBinary()) {
+      throw new IllegalArgumentException(
+          "cannot set a Reader value on a binary field");
     }
-    if (isStored) {
-      throw new IllegalArgumentException("cannot set a Reader value on a stored field");
+    if (stored()) {
+      throw new IllegalArgumentException(
+          "cannot set a Reader value on a stored field");
     }
     fieldsData = value;
   }
-
-  /** Expert: change the value of this field.  See <a href="#setValue(java.lang.String)">setValue(String)</a>. */
+  
+  /**
+   * Expert: change the value of this field. See <a
+   * href="#setValue(java.lang.String)">setValue(String)</a>.
+   */
   public void setValue(byte[] value) {
-    if (!isBinary) {
-      throw new IllegalArgumentException("cannot set a byte[] value on a non-binary field");
+    if (!isBinary()) {
+      throw new IllegalArgumentException(
+          "cannot set a byte[] value on a non-binary field");
     }
-    fieldsData = value;
-    binaryLength = value.length;
-    binaryOffset = 0;
+    fieldsData = new BytesRef(value);
   }
-
-  /** Expert: change the value of this field.  See <a href="#setValue(java.lang.String)">setValue(String)</a>. */
+  
+  /**
+   * Expert: change the value of this field. See <a
+   * href="#setValue(java.lang.String)">setValue(String)</a>.
+   */
+  /*
   public void setValue(byte[] value, int offset, int length) {
     if (!isBinary) {
-      throw new IllegalArgumentException("cannot set a byte[] value on a non-binary field");
+      throw new IllegalArgumentException(
+          "cannot set a byte[] value on a non-binary field");
     }
     fieldsData = value;
     binaryLength = length;
     binaryOffset = offset;
   }
+  */
   
-  /** Expert: sets the token stream to be used for indexing and causes isIndexed() and isTokenized() to return true.
-   *  May be combined with stored values from stringValue() or getBinaryValue() */
+  /**
+   * Expert: sets the token stream to be used for indexing and causes
+   * isIndexed() and isTokenized() to return true. May be combined with stored
+   * values from stringValue() or getBinaryValue()
+   */
   public void setTokenStream(TokenStream tokenStream) {
-    this.isIndexed = true;
-    this.isTokenized = true;
+    if (!indexed() || !tokenized()) {
+      throw new IllegalArgumentException(
+          "cannot set token stream on non indexed and tokenized field");
+    }
     this.tokenStream = tokenStream;
   }
+  
+  public String name() {
+    return name;
+  }
+  
+  public float boost() {
+    return boost;
+  }
 
-  /**
-   * Create a field by specifying its name, value and how it will
-   * be saved in the index. Term vectors will not be stored in the index.
-   * 
-   * @param name The name of the field
-   * @param value The string to process
-   * @param store Whether <code>value</code> should be stored in the index
-   * @param index Whether the field should be indexed, and if so, if it should
-   *  be tokenized before indexing 
-   * @throws NullPointerException if name or value is <code>null</code>
-   * @throws IllegalArgumentException if the field is neither stored nor indexed 
+  /** Sets the boost factor hits on this field.  This value will be
+   * multiplied into the score of all hits on this this field of this
+   * document.
+   *
+   * <p>The boost is used to compute the norm factor for the field.  By
+   * default, in the {@link org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)} method, 
+   * the boost value is multiplied by the length normalization factor and then
+   * rounded by {@link org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)} before it is stored in the
+   * index.  One should attempt to ensure that this product does not overflow
+   * the range of that encoding.
+   *
+   * @see org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)
+   * @see org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)
    */
-  public Field(String name, String value, Store store, Index index) {
-    this(name, value, store, index, TermVector.NO);
+  public void setBoost(float boost) {
+    this.boost = boost;
   }
   
-  /**
-   * Create a field by specifying its name, value and how it will
-   * be saved in the index.
-   * 
-   * @param name The name of the field
-   * @param value The string to process
-   * @param store Whether <code>value</code> should be stored in the index
-   * @param index Whether the field should be indexed, and if so, if it should
-   *  be tokenized before indexing 
-   * @param termVector Whether term vector should be stored
-   * @throws NullPointerException if name or value is <code>null</code>
-   * @throws IllegalArgumentException in any of the following situations:
-   * <ul> 
-   *  <li>the field is neither stored nor indexed</li> 
-   *  <li>the field is not indexed but termVector is <code>TermVector.YES</code></li>
-   * </ul> 
-   */ 
-  public Field(String name, String value, Store store, Index index, TermVector termVector) {
-    if (name == null)
-      throw new NullPointerException("name cannot be null");
-    if (value == null)
-      throw new NullPointerException("value cannot be null");
-    if (name.length() == 0 && value.length() == 0)
-      throw new IllegalArgumentException("name and value cannot both be empty");
-    if (index == Index.NO && store == Store.NO)
-      throw new IllegalArgumentException("it doesn't make sense to have a field that "
-         + "is neither indexed nor stored");
-    if (index == Index.NO && termVector != TermVector.NO)
-      throw new IllegalArgumentException("cannot store term vector information "
-         + "for a field that is not indexed");
-          
-    this.name = name; 
-    
-    this.fieldsData = value;
+  public boolean numeric() {
+    return false;
+  }
 
-    this.isStored = store.isStored();
-   
-    this.isIndexed = index.isIndexed();
-    this.isTokenized = index.isAnalyzed();
-    this.omitNorms = index.omitNorms();
-    if (index == Index.NO) {
-      // note: now this reads even wierder than before
-      this.indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
-    }    
+  public Number numericValue() {
+    return null;
+  }
 
-    this.isBinary = false;
-
-    setStoreTermVector(termVector);
+  public NumericField.DataType numericDataType() {
+    return null;
   }
   
-  /**
-   * Create a tokenized and indexed field that is not stored. Term vectors will
-   * not be stored.  The Reader is read only when the Document is added to the index,
-   * i.e. you may not close the Reader until {@link IndexWriter#addDocument(Document)}
-   * has been called.
-   * 
-   * @param name The name of the field
-   * @param reader The reader with the content
-   * @throws NullPointerException if name or reader is <code>null</code>
-   */
-  public Field(String name, Reader reader) {
-    this(name, reader, TermVector.NO);
+  public BytesRef binaryValue() {
+    if (!isBinary()) {
+      return null;
+    } else {
+      return (BytesRef) fieldsData;
+    }
   }
-
-  /**
-   * Create a tokenized and indexed field that is not stored, optionally with 
-   * storing term vectors.  The Reader is read only when the Document is added to the index,
-   * i.e. you may not close the Reader until {@link IndexWriter#addDocument(Document)}
-   * has been called.
-   * 
-   * @param name The name of the field
-   * @param reader The reader with the content
-   * @param termVector Whether term vector should be stored
-   * @throws NullPointerException if name or reader is <code>null</code>
-   */ 
-  public Field(String name, Reader reader, TermVector termVector) {
-    if (name == null)
-      throw new NullPointerException("name cannot be null");
-    if (reader == null)
-      throw new NullPointerException("reader cannot be null");
-    
-    this.name = name;
-    this.fieldsData = reader;
-    
-    this.isStored = false;
-    
-    this.isIndexed = true;
-    this.isTokenized = true;
-    
-    this.isBinary = false;
-    
-    setStoreTermVector(termVector);
+  
+  /** methods from inner FieldType */
+  
+  public boolean isBinary() {
+    return fieldsData instanceof BytesRef;
   }
-
-  /**
-   * Create a tokenized and indexed field that is not stored. Term vectors will
-   * not be stored. This is useful for pre-analyzed fields.
-   * The TokenStream is read only when the Document is added to the index,
-   * i.e. you may not close the TokenStream until {@link IndexWriter#addDocument(Document)}
-   * has been called.
-   * 
-   * @param name The name of the field
-   * @param tokenStream The TokenStream with the content
-   * @throws NullPointerException if name or tokenStream is <code>null</code>
-   */ 
-  public Field(String name, TokenStream tokenStream) {
-    this(name, tokenStream, TermVector.NO);
+  
+  public boolean stored() {
+    return type.stored();
   }
   
-  /**
-   * Create a tokenized and indexed field that is not stored, optionally with 
-   * storing term vectors.  This is useful for pre-analyzed fields.
-   * The TokenStream is read only when the Document is added to the index,
-   * i.e. you may not close the TokenStream until {@link IndexWriter#addDocument(Document)}
-   * has been called.
-   * 
-   * @param name The name of the field
-   * @param tokenStream The TokenStream with the content
-   * @param termVector Whether term vector should be stored
-   * @throws NullPointerException if name or tokenStream is <code>null</code>
-   */ 
-  public Field(String name, TokenStream tokenStream, TermVector termVector) {
-    if (name == null)
-      throw new NullPointerException("name cannot be null");
-    if (tokenStream == null)
-      throw new NullPointerException("tokenStream cannot be null");
-    
-    this.name = name;
-    this.fieldsData = null;
-    this.tokenStream = tokenStream;
+  public boolean indexed() {
+    return type.indexed();
+  }
+  
+  public boolean tokenized() {
+    return type.tokenized();
+  }
+  
+  public boolean omitNorms() {
+    return type.omitNorms();
+  }
+  
+  public IndexOptions indexOptions() {
+    return type.indexOptions();
+  }
+  
+  public boolean storeTermVectors() {
+    return type.storeTermVectors();
+  }
+  
+  public boolean storeTermVectorOffsets() {
+    return type.storeTermVectorOffsets();
+  }
+  
+  public boolean storeTermVectorPositions() {
+    return type.storeTermVectorPositions();
+  }
+  
+  /** Prints a Field for human consumption. */
+  @Override
+  public String toString() {
+    StringBuilder result = new StringBuilder();
+    result.append(type.toString());
+    result.append('<');
+    result.append(name);
+    result.append(':');
 
-    this.isStored = false;
-    
-    this.isIndexed = true;
-    this.isTokenized = true;
-    
-    this.isBinary = false;
-    
-    setStoreTermVector(termVector);
+    if (fieldsData != null && type.lazy() == false) {
+      result.append(fieldsData);
+    }
+
+    result.append('>');
+    return result.toString();
   }
+  
+  public void setDocValues(PerDocFieldValues docValues) {
+    this.docValues = docValues;
+  }
 
+  @Override
+  public PerDocFieldValues docValues() {
+    return null;
+  }
   
-  /**
-   * Create a stored field with binary value. Optionally the value may be compressed.
-   * 
-   * @param name The name of the field
-   * @param value The binary value
-   */
-  public Field(String name, byte[] value) {
-    this(name, value, 0, value.length);
+  @Override
+  public ValueType docValuesType() {
+    return null;
   }
 
-  /**
-   * Create a stored field with binary value. Optionally the value may be compressed.
-   * 
-   * @param name The name of the field
-   * @param value The binary value
-   * @param offset Starting offset in value where this Field's bytes are
-   * @param length Number of bytes to use for this Field, starting at offset
-   */
-  public Field(String name, byte[] value, int offset, int length) {
-
-    if (name == null)
-      throw new IllegalArgumentException("name cannot be null");
-    if (value == null)
-      throw new IllegalArgumentException("value cannot be null");
-    
-    this.name = name;
-    fieldsData = value;
-    
-    isStored = true;
-    isIndexed   = false;
-    isTokenized = false;
-    indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
-    omitNorms = true;
-    
-    isBinary    = true;
-    binaryLength = length;
-    binaryOffset = offset;
-    
-    setStoreTermVector(TermVector.NO);
+  /** Returns FieldType for this field. */
+  public FieldType getFieldType() {
+    return type;
   }
 }
Index: lucene/src/java/org/apache/lucene/document/NumericField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/NumericField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/NumericField.java	(working copy)
@@ -22,28 +22,30 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.analysis.NumericTokenStream;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.NumericField.DataType;
 import org.apache.lucene.util.NumericUtils;
 import org.apache.lucene.search.NumericRangeQuery; // javadocs
 import org.apache.lucene.search.NumericRangeFilter; // javadocs
 import org.apache.lucene.search.FieldCache; // javadocs
 
 /**
- * <p>This class provides a {@link Field} that enables indexing
- * of numeric values for efficient range filtering and
- * sorting.  Here's an example usage, adding an int value:
+ * <p>
+ * This class provides a {@link Field} that enables indexing of numeric values
+ * for efficient range filtering and sorting. Here's an example usage, adding an
+ * int value:
+ * 
  * <pre>
- *  document.add(new NumericField(name).setIntValue(value));
+ * document.add(new NumericField(name).setIntValue(value));
  * </pre>
- *
- * For optimal performance, re-use the
- * <code>NumericField</code> and {@link Document} instance for more than
- * one document:
- *
+ * 
+ * For optimal performance, re-use the <code>NumericField</code> and
+ * {@link Document} instance for more than one document:
+ * 
  * <pre>
  *  NumericField field = new NumericField(name);
  *  Document document = new Document();
  *  document.add(field);
- *
+ * 
  *  for(all documents) {
  *    ...
  *    field.setIntValue(value)
@@ -74,7 +76,7 @@
  *
  * <p>By default, a <code>NumericField</code>'s value is not stored but
  * is indexed for range filtering and sorting.  You can use
- * the {@link #NumericField(String,Field.Store,boolean)}
+ * the {@link #NumericField(String, FieldType)}
  * constructor if you need to change these defaults.</p>
  *
  * <p>You may add the same field name as a <code>NumericField</code> to
@@ -102,7 +104,7 @@
  * default value, 4, was selected for a reasonable tradeoff
  * of disk space consumption versus performance.  You can
  * use the expert constructor {@link
- * #NumericField(String,int,Field.Store,boolean)} if you'd
+ * #NumericField(String,int,FieldType)} if you'd
  * like to change the value.  Note that you must also
  * specify a congruent value when creating {@link
  * NumericRangeQuery} or {@link NumericRangeFilter}.
@@ -129,94 +131,136 @@
  *
  * @since 2.9
  */
-public final class NumericField extends AbstractField {
-
+public final class NumericField extends Field {
+  
   /** Data type of the value in {@link NumericField}.
    * @since 3.2
    */
   public static enum DataType { INT, LONG, FLOAT, DOUBLE }
 
+  public static final FieldType TYPE_UNSTORED = new FieldType();
+  public static final FieldType TYPE_STORED = new FieldType();
+  static {
+    TYPE_UNSTORED.setIndexed(true);
+    TYPE_UNSTORED.setTokenized(true);
+    TYPE_UNSTORED.setOmitNorms(true);
+    TYPE_UNSTORED.setIndexOptions(IndexOptions.DOCS_ONLY);
+    TYPE_UNSTORED.freeze();
+
+    TYPE_STORED.setIndexed(true);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.setTokenized(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS_ONLY);
+    TYPE_STORED.freeze();
+  }
+
+  //public static enum DataType { INT, LONG, FLOAT, DOUBLE }
+  
+  private DataType dataType;
   private transient NumericTokenStream numericTS;
-  private DataType type;
   private final int precisionStep;
-
+  
   /**
-   * Creates a field for numeric values using the default <code>precisionStep</code>
-   * {@link NumericUtils#PRECISION_STEP_DEFAULT} (4). The instance is not yet initialized with
-   * a numeric value, before indexing a document containing this field,
-   * set a value using the various set<em>???</em>Value() methods.
-   * This constructor creates an indexed, but not stored field.
-   * @param name the field name
+   * Creates a field for numeric values using the default
+   * <code>precisionStep</code> {@link NumericUtils#PRECISION_STEP_DEFAULT} (4).
+   * The instance is not yet initialized with a numeric value, before indexing a
+   * document containing this field, set a value using the various set
+   * <em>???</em>Value() methods. This constructor creates an indexed, but not
+   * stored field.
+   * 
+   * @param name
+   *          the field name
    */
   public NumericField(String name) {
-    this(name, NumericUtils.PRECISION_STEP_DEFAULT, Field.Store.NO, true);
+    this(name, NumericUtils.PRECISION_STEP_DEFAULT, NumericField.TYPE_UNSTORED);
   }
   
   /**
-   * Creates a field for numeric values using the default <code>precisionStep</code>
-   * {@link NumericUtils#PRECISION_STEP_DEFAULT} (4). The instance is not yet initialized with
-   * a numeric value, before indexing a document containing this field,
-   * set a value using the various set<em>???</em>Value() methods.
-   * @param name the field name
-   * @param store if the field should be stored, {@link Document#getFieldable}
-   * then returns {@code NumericField} instances on search results.
-   * @param index if the field should be indexed using {@link NumericTokenStream}
+   * Creates a field for numeric values using the default
+   * <code>precisionStep</code> {@link NumericUtils#PRECISION_STEP_DEFAULT} (4).
+   * The instance is not yet initialized with a numeric value, before indexing a
+   * document containing this field, set a value using the various set
+   * <em>???</em>Value() methods.
+   * 
+   * @param name
+   *          the field name
+   * @param type
+   *          if the defualt field should be altered, e.g. stored, 
+   *          {@link Document#getField} then returns {@code NumericField} 
+   *          instances on search results, or indexed using 
+   *          {@link NumericTokenStream}
    */
-  public NumericField(String name, Field.Store store, boolean index) {
-    this(name, NumericUtils.PRECISION_STEP_DEFAULT, store, index);
+  public NumericField(String name, FieldType type) {
+    this(name, NumericUtils.PRECISION_STEP_DEFAULT, type);
   }
   
   /**
    * Creates a field for numeric values with the specified
-   * <code>precisionStep</code>. The instance is not yet initialized with
-   * a numeric value, before indexing a document containing this field,
-   * set a value using the various set<em>???</em>Value() methods.
-   * This constructor creates an indexed, but not stored field.
-   * @param name the field name
-   * @param precisionStep the used <a href="../search/NumericRangeQuery.html#precisionStepDesc">precision step</a>
+   * <code>precisionStep</code>. The instance is not yet initialized with a
+   * numeric value, before indexing a document containing this field, set a
+   * value using the various set<em>???</em>Value() methods. This constructor
+   * creates an indexed, but not stored field.
+   * 
+   * @param name
+   *          the field name
+   * @param precisionStep
+   *          the used <a
+   *          href="../search/NumericRangeQuery.html#precisionStepDesc"
+   *          >precision step</a>
    */
   public NumericField(String name, int precisionStep) {
-    this(name, precisionStep, Field.Store.NO, true);
+    this(name, precisionStep, NumericField.TYPE_UNSTORED);
   }
-
+  
   /**
    * Creates a field for numeric values with the specified
-   * <code>precisionStep</code>. The instance is not yet initialized with
-   * a numeric value, before indexing a document containing this field,
-   * set a value using the various set<em>???</em>Value() methods.
-   * @param name the field name
-   * @param precisionStep the used <a href="../search/NumericRangeQuery.html#precisionStepDesc">precision step</a>
-   * @param store if the field should be stored, {@link Document#getFieldable}
-   * then returns {@code NumericField} instances on search results.
-   * @param index if the field should be indexed using {@link NumericTokenStream}
+   * <code>precisionStep</code>. The instance is not yet initialized with a
+   * numeric value, before indexing a document containing this field, set a
+   * value using the various set<em>???</em>Value() methods.
+   * 
+   * @param name
+   *          the field name
+   * @param precisionStep
+   *          the used <a
+   *          href="../search/NumericRangeQuery.html#precisionStepDesc"
+   *          >precision step</a>
+   * @param type
+   *          if the defualt field should be altered, e.g. stored, 
+   *          {@link Document#getField} then returns {@code NumericField} 
+   *          instances on search results, or indexed using 
+   *          {@link NumericTokenStream}
    */
-  public NumericField(String name, int precisionStep, Field.Store store, boolean index) {
-    super(name, store, index ? Field.Index.ANALYZED_NO_NORMS : Field.Index.NO, Field.TermVector.NO);
+  public NumericField(String name, int precisionStep, FieldType type) {
+    super(name, type);
     this.precisionStep = precisionStep;
-    setIndexOptions(IndexOptions.DOCS_ONLY);
   }
-
+  
   /** Returns a {@link NumericTokenStream} for indexing the numeric value. */
-  public TokenStream tokenStreamValue()   {
-    if (!isIndexed())
-      return null;
+  public TokenStream tokenStreamValue() {
+    if (!indexed()) return null;
     if (numericTS == null) {
-      // lazy init the TokenStream as it is heavy to instantiate (attributes,...),
+      // lazy init the TokenStream as it is heavy to instantiate
+      // (attributes,...),
       // if not needed (stored field loading)
       numericTS = new NumericTokenStream(precisionStep);
       // initialize value in TokenStream
       if (fieldsData != null) {
-        assert type != null;
+        assert dataType != null;
         final Number val = (Number) fieldsData;
-        switch (type) {
+        switch (dataType) {
           case INT:
-            numericTS.setIntValue(val.intValue()); break;
+            numericTS.setIntValue(val.intValue());
+            break;
           case LONG:
-            numericTS.setLongValue(val.longValue()); break;
+            numericTS.setLongValue(val.longValue());
+            break;
           case FLOAT:
-            numericTS.setFloatValue(val.floatValue()); break;
+            numericTS.setFloatValue(val.floatValue());
+            break;
           case DOUBLE:
-            numericTS.setDoubleValue(val.doubleValue()); break;
+            numericTS.setDoubleValue(val.doubleValue());
+            break;
           default:
             assert false : "Should never get here";
         }
@@ -226,26 +270,27 @@
   }
   
   /** Returns always <code>null</code> for numeric fields */
-  @Override
-  public byte[] getBinaryValue(byte[] result){
-    return null;
-  }
-
-  /** Returns always <code>null</code> for numeric fields */
   public Reader readerValue() {
     return null;
   }
-    
-  /** Returns the numeric value as a string. This format is also returned if you call {@link Document#get(String)}
-   * on search results. It is recommended to use {@link Document#getFieldable} instead
-   * that returns {@code NumericField} instances. You can then use {@link #getNumericValue}
-   * to return the stored value. */
-  public String stringValue()   {
+  
+  /**
+   * Returns the numeric value as a string. It is recommended to
+   * use {@link Document#getField} instead that returns {@code NumericField}
+   * instances. You can then use {@link #numericValue} to return the stored
+   * value.
+   */
+  @Override
+  public String stringValue() {
     return (fieldsData == null) ? null : fieldsData.toString();
   }
   
-  /** Returns the current numeric value as a subclass of {@link Number}, <code>null</code> if not yet initialized. */
-  public Number getNumericValue() {
+  /**
+   * Returns the current numeric value as a subclass of {@link Number},
+   * <code>null</code> if not yet initialized.
+   */
+  @Override
+  public Number numericValue() {
     return (Number) fieldsData;
   }
   
@@ -254,63 +299,79 @@
     return precisionStep;
   }
   
-  /** Returns the data type of the current value, {@code null} if not yet set.
+  /**
+   * Returns the data type of the current value, {@code null} if not yet set.
+   * 
    * @since 3.2
    */
-  public DataType getDataType() {
-    return type;
+  @Override
+  public DataType numericDataType() {
+    return dataType;
   }
-  
+
+  @Override
+  public boolean numeric() {
+    return true;
+  }
+
   /**
    * Initializes the field with the supplied <code>long</code> value.
-   * @param value the numeric value
+   * 
+   * @param value
+   *          the numeric value
    * @return this instance, because of this you can use it the following way:
-   * <code>document.add(new NumericField(name, precisionStep).setLongValue(value))</code>
+   *         <code>document.add(new NumericField(name, precisionStep).setLongValue(value))</code>
    */
   public NumericField setLongValue(final long value) {
     if (numericTS != null) numericTS.setLongValue(value);
     fieldsData = Long.valueOf(value);
-    type = DataType.LONG;
+    dataType = DataType.LONG;
     return this;
   }
   
   /**
    * Initializes the field with the supplied <code>int</code> value.
-   * @param value the numeric value
+   * 
+   * @param value
+   *          the numeric value
    * @return this instance, because of this you can use it the following way:
-   * <code>document.add(new NumericField(name, precisionStep).setIntValue(value))</code>
+   *         <code>document.add(new NumericField(name, precisionStep).setIntValue(value))</code>
    */
   public NumericField setIntValue(final int value) {
     if (numericTS != null) numericTS.setIntValue(value);
     fieldsData = Integer.valueOf(value);
-    type = DataType.INT;
+    dataType = DataType.INT;
     return this;
   }
   
   /**
    * Initializes the field with the supplied <code>double</code> value.
-   * @param value the numeric value
+   * 
+   * @param value
+   *          the numeric value
    * @return this instance, because of this you can use it the following way:
-   * <code>document.add(new NumericField(name, precisionStep).setDoubleValue(value))</code>
+   *         <code>document.add(new NumericField(name, precisionStep).setDoubleValue(value))</code>
    */
   public NumericField setDoubleValue(final double value) {
     if (numericTS != null) numericTS.setDoubleValue(value);
     fieldsData = Double.valueOf(value);
-    type = DataType.DOUBLE;
+    dataType = DataType.DOUBLE;
     return this;
   }
   
   /**
    * Initializes the field with the supplied <code>float</code> value.
-   * @param value the numeric value
+   * 
+   * @param value
+   *          the numeric value
    * @return this instance, because of this you can use it the following way:
-   * <code>document.add(new NumericField(name, precisionStep).setFloatValue(value))</code>
+   *         <code>document.add(new NumericField(name, precisionStep).setFloatValue(value))</code>
    */
   public NumericField setFloatValue(final float value) {
     if (numericTS != null) numericTS.setFloatValue(value);
     fieldsData = Float.valueOf(value);
-    type = DataType.FLOAT;
+    dataType = DataType.FLOAT;
     return this;
   }
-
+  
 }
Index: lucene/src/java/org/apache/lucene/document/BinaryField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/BinaryField.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/document/BinaryField.java	(revision 1160484)
@@ -0,0 +1,49 @@
+package org.apache.lucene.document;
+
+import org.apache.lucene.util.BytesRef;
+
+/**
+ * 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.
+ */
+
+public final class BinaryField extends Field {
+
+  public static final FieldType TYPE_STORED = new FieldType();
+  static {
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.freeze();
+  }
+
+  public BinaryField(String name, byte[] value) {
+    super(name, BinaryField.TYPE_STORED, value);
+  }
+  
+  public BinaryField(String name, byte[] value, int offset, int length) {
+    super(name, BinaryField.TYPE_STORED, value, offset, length);
+  }
+
+  public BinaryField(String name, BytesRef bytes) {
+    super(name, BinaryField.TYPE_STORED, bytes.bytes, bytes.offset, bytes.length);
+  }
+  
+  public BinaryField(String name, FieldType custom, byte[] value) {
+    super(name, custom, value);
+  }
+    
+  public boolean isNumeric() {
+    return false;
+  }  
+}

Property changes on: lucene/src/java/org/apache/lucene/document/BinaryField.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/document/StringField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/StringField.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/document/StringField.java	(revision 1160484)
@@ -0,0 +1,51 @@
+package org.apache.lucene.document;
+
+import org.apache.lucene.index.FieldInfo.IndexOptions;
+
+/**
+ * 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.
+ */
+
+public final class StringField extends Field {
+
+  public static final FieldType TYPE_UNSTORED = new FieldType();
+  public static final FieldType TYPE_STORED = new FieldType();
+  static {
+    TYPE_UNSTORED.setIndexed(true);
+    TYPE_UNSTORED.setOmitNorms(true);
+    TYPE_UNSTORED.setIndexOptions(IndexOptions.DOCS_ONLY);
+    TYPE_UNSTORED.freeze();
+
+    TYPE_STORED.setIndexed(true);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.setOmitNorms(true);
+    TYPE_STORED.setIndexOptions(IndexOptions.DOCS_ONLY);
+    TYPE_STORED.freeze();
+  }
+  
+  public StringField(String name, String value) {
+    super(name, TYPE_UNSTORED, value);
+  }
+  
+  @Override
+  public String stringValue() {
+    return (fieldsData == null) ? null : fieldsData.toString();
+  }
+  
+  public boolean isNumeric() {
+    return false;
+  }  
+}

Property changes on: lucene/src/java/org/apache/lucene/document/StringField.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/document/Document.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/Document.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/Document.java	(working copy)
@@ -17,61 +17,55 @@
  * limitations under the License.
  */
 
-import java.util.*;             // for javadoc
+import java.util.*;
+
+import org.apache.lucene.index.IndexReader;  // for javadoc
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.IndexSearcher;  // for javadoc
 import org.apache.lucene.search.ScoreDoc; // for javadoc
-import org.apache.lucene.index.IndexReader;  // for javadoc
+import org.apache.lucene.util.BytesRef;
 
 /** Documents are the unit of indexing and search.
  *
  * A Document is a set of fields.  Each field has a name and a textual value.
- * A field may be {@link Fieldable#isStored() stored} with the document, in which
+ * A field may be {@link IndexableField#stored() stored} with the document, in which
  * case it is returned with search hits on the document.  Thus each document
  * should typically contain one or more stored fields which uniquely identify
  * it.
  *
- * <p>Note that fields which are <i>not</i> {@link Fieldable#isStored() stored} are
+ * <p>Note that fields which are <i>not</i> {@link IndexableField#stored() stored} are
  * <i>not</i> available in documents retrieved from the index, e.g. with {@link
  * ScoreDoc#doc} or {@link IndexReader#document(int)}.
  */
 
-public final class Document {
-  List<Fieldable> fields = new ArrayList<Fieldable>();
-  private float boost = 1.0f;
+public final class Document implements Iterable<IndexableField> {
 
+  private final List<IndexableField> fields = new ArrayList<IndexableField>();
+
   /** Constructs a new document with no fields. */
   public Document() {}
 
+  @Override
+  public Iterator<IndexableField> iterator() {
 
-  /** Sets a boost factor for hits on any field of this document.  This value
-   * will be multiplied into the score of all hits on this document.
-   *
-   * <p>The default value is 1.0.
-   * 
-   * <p>Values are multiplied into the value of {@link Fieldable#getBoost()} of
-   * each field in this document.  Thus, this method in effect sets a default
-   * boost for the fields of this document.
-   *
-   * @see Fieldable#setBoost(float)
-   */
-  public void setBoost(float boost) {
-    this.boost = boost;
-  }
+    return new Iterator<IndexableField>() {
+      private int fieldUpto = 0;
+      
+      @Override
+      public boolean hasNext() {
+        return fieldUpto < fields.size();
+      }
 
-  /** Returns, at indexing time, the boost factor as set by {@link #setBoost(float)}. 
-   *
-   * <p>Note that once a document is indexed this value is no longer available
-   * from the index.  At search time, for retrieved documents, this method always 
-   * returns 1. This however does not mean that the boost value set at  indexing 
-   * time was ignored - it was just combined with other indexing time factors and 
-   * stored elsewhere, for better indexing and search performance. (For more 
-   * information see the "norm(t,d)" part of the scoring formula in 
-   * {@link org.apache.lucene.search.Similarity Similarity}.)
-   *
-   * @see #setBoost(float)
-   */
-  public float getBoost() {
-    return boost;
+      @Override
+      public void remove() {
+        throw new UnsupportedOperationException();
+      }
+
+      @Override
+      public IndexableField next() {
+        return fields.get(fieldUpto++);
+      }
+    };
   }
 
   /**
@@ -84,7 +78,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(Fieldable field) {
+  public final void add(IndexableField field) {
     fields.add(field);
   }
   
@@ -99,9 +93,9 @@
    * document has to be added.</p>
    */
   public final void removeField(String name) {
-    Iterator<Fieldable> it = fields.iterator();
+    Iterator<IndexableField> it = fields.iterator();
     while (it.hasNext()) {
-      Fieldable field = it.next();
+      IndexableField field = it.next();
       if (field.name().equals(name)) {
         it.remove();
         return;
@@ -119,150 +113,17 @@
    * document has to be added.</p>
    */
   public final void removeFields(String name) {
-    Iterator<Fieldable> it = fields.iterator();
+    Iterator<IndexableField> it = fields.iterator();
     while (it.hasNext()) {
-      Fieldable field = it.next();
+      IndexableField field = it.next();
       if (field.name().equals(name)) {
         it.remove();
       }
     }
   }
 
-  /** 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.
-   * Do not use this method with lazy loaded fields or {@link NumericField}.
-   * @deprecated use {@link #getFieldable} instead and cast depending on
-   * data type.
-   * @throws ClassCastException if you try to retrieve a numerical or
-   * lazy loaded field.
-   */
-  @Deprecated
-  public final Field getField(String name) {
-    return (Field) getFieldable(name);
-  }
 
-
- /** 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 Fieldable getFieldable(String name) {
-   for (Fieldable field : fields) {
-     if (field.name().equals(name))
-       return field;
-   }
-   return null;
- }
-
-  /** 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 NumericField} it returns the string value of the number. If you want
-   * the actual {@code NumericField} instance back, use {@link #getFieldable}.
-   */
-  public final String get(String name) {
-   for (Fieldable field : fields) {
-      if (field.name().equals(name) && (!field.isBinary()))
-        return field.stringValue();
-    }
-    return null;
-  }
-
-  /** Returns a List of all the fields in a document.
-   * <p>Note that fields which are <i>not</i> {@link Fieldable#isStored() stored} are
-   * <i>not</i> available in documents retrieved from the
-   * index, e.g. {@link IndexSearcher#doc(int)} or {@link
-   * IndexReader#document(int)}.
-   */
-  public final List<Fieldable> getFields() {
-    return fields;
-  }
-
-  private final static Field[] NO_FIELDS = new Field[0];
-  
   /**
-   * Returns an array of {@link Field}s with the given name.
-   * This method returns an empty array when there are no
-   * matching fields.  It never returns null.
-   * Do not use this method with lazy loaded fields or {@link NumericField}.
-   *
-   * @param name the name of the field
-   * @return a <code>Field[]</code> array
-   * @deprecated use {@link #getFieldable} instead and cast depending on
-   * data type.
-   * @throws ClassCastException if you try to retrieve a numerical or
-   * lazy loaded field.
-   */
-   @Deprecated
-   public final Field[] getFields(String name) {
-     List<Field> result = new ArrayList<Field>();
-     for (Fieldable field : fields) {
-       if (field.name().equals(name)) {
-         result.add((Field) field);
-       }
-     }
-
-     if (result.size() == 0)
-       return NO_FIELDS;
-
-     return result.toArray(new Field[result.size()]);
-   }
-
-
-   private final static Fieldable[] NO_FIELDABLES = new Fieldable[0];
-
-   /**
-   * Returns an array of {@link Fieldable}s with the given name.
-   * 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>Fieldable[]</code> array
-   */
-   public Fieldable[] getFieldables(String name) {
-     List<Fieldable> result = new ArrayList<Fieldable>();
-     for (Fieldable field : fields) {
-       if (field.name().equals(name)) {
-         result.add(field);
-       }
-     }
-
-     if (result.size() == 0)
-       return NO_FIELDABLES;
-
-     return result.toArray(new Fieldable[result.size()]);
-   }
-
-
-   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 NumericField}s it returns the string value of the number. If you want
-   * the actual {@code NumericField} instances back, use {@link #getFieldables}.
-   * @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 (Fieldable field : fields) {
-      if (field.name().equals(name) && (!field.isBinary()))
-        result.add(field.stringValue());
-    }
-    
-    if (result.size() == 0)
-      return NO_STRINGS;
-    
-    return result.toArray(new String[result.size()]);
-  }
-
-  private final static byte[][] NO_BYTES = new byte[0][];
-
-  /**
   * 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
@@ -271,17 +132,18 @@
   * @param name the name of the field
   * @return a <code>byte[][]</code> of binary field values
   */
-  public final byte[][] getBinaryValues(String name) {
-    List<byte[]> result = new ArrayList<byte[]>();
-    for (Fieldable field : fields) {
-      if (field.name().equals(name) && (field.isBinary()))
-        result.add(field.getBinaryValue());
+  public final BytesRef[] getBinaryValues(String name) {
+    final List<BytesRef> result = new ArrayList<BytesRef>();
+    for (IndexableField field : fields) {
+      if (field.name().equals(name)) {
+        final BytesRef bytes = field.binaryValue();
+        if (bytes != null) {
+          result.add(bytes);
+        }
+      }
     }
   
-    if (result.size() == 0)
-      return NO_BYTES;
-  
-    return result.toArray(new byte[result.size()][]);
+    return result.toArray(new BytesRef[result.size()]);
   }
   
   /**
@@ -293,21 +155,83 @@
   * @param name the name of the field.
   * @return a <code>byte[]</code> containing the binary field value or <code>null</code>
   */
-  public final byte[] getBinaryValue(String name) {
-    for (Fieldable field : fields) {
-      if (field.name().equals(name) && (field.isBinary()))
-        return field.getBinaryValue();
+  public final BytesRef getBinaryValue(String name) {
+    for (IndexableField field : fields) {
+      if (field.name().equals(name)) {
+        final BytesRef bytes = field.binaryValue();
+        if (bytes != null) {
+          return bytes;
+        }
+      }
     }
     return null;
   }
+
+  /** 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 IndexableField getField(String name) {
+    for (IndexableField field : fields) {
+      if (field.name().equals(name)) {
+        return field;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Returns an array of {@link IndexablField}s with the given name.
+   * 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>Fieldable[]</code> array
+   */
+  public IndexableField[] getFields(String name) {
+    List<IndexableField> result = new ArrayList<IndexableField>();
+    for (IndexableField field : fields) {
+      if (field.name().equals(name)) {
+        result.add(field);
+      }
+    }
+
+    return result.toArray(new IndexableField[result.size()]);
+  }
   
+  /** 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)}.
+   */
+  public final List<IndexableField> getFields() {
+    return fields;
+  }
+  
+  /** 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 NumericField} it returns the string value of the number. If you want
+   * the actual {@code NumericField} instance back, use {@link #getFieldable}.
+   */
+  public final String get(String name) {
+    for (IndexableField 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("Document<");
     for (int i = 0; i < fields.size(); i++) {
-      Fieldable field = fields.get(i);
+      IndexableField field = fields.get(i);
       buffer.append(field.toString());
       if (i != fields.size()-1)
         buffer.append(" ");
Index: lucene/src/java/org/apache/lucene/document/FieldType.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/FieldType.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/document/FieldType.java	(revision 1159961)
@@ -0,0 +1,186 @@
+package org.apache.lucene.document;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.index.FieldInfo.IndexOptions;
+
+public class FieldType {
+
+  private boolean indexed;
+  private boolean stored;
+  private boolean tokenized;
+  private boolean storeTermVectors;
+  private boolean storeTermVectorOffsets;
+  private boolean storeTermVectorPositions;
+  private boolean omitNorms;
+  private IndexOptions indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
+  private boolean lazy;
+  private boolean frozen;
+
+  public FieldType(FieldType ref) {
+    this.indexed = ref.indexed();
+    this.stored = ref.stored();
+    this.tokenized = ref.tokenized();
+    this.storeTermVectors = ref.storeTermVectors();
+    this.storeTermVectorOffsets = ref.storeTermVectorOffsets();
+    this.storeTermVectorPositions = ref.storeTermVectorPositions();
+    this.omitNorms = ref.omitNorms();
+    this.indexOptions = ref.indexOptions();
+    this.lazy = ref.lazy();
+  }
+  
+  public FieldType() {
+  }
+
+  private void checkIfFrozen() {
+    if (frozen) {
+      throw new IllegalStateException();
+    }
+  }
+  
+  public void freeze() {
+    this.frozen = true;
+  }
+  
+  public boolean indexed() {
+    return this.indexed;
+  }
+  
+  public void setIndexed(boolean value) {
+    checkIfFrozen();
+    this.indexed = value;
+  }
+
+  public boolean stored() {
+    return this.stored;
+  }
+  
+  public void setStored(boolean value) {
+    checkIfFrozen();
+    this.stored = value;
+  }
+
+  public boolean tokenized() {
+    return this.tokenized;
+  }
+  
+  public void setTokenized(boolean value) {
+    checkIfFrozen();
+    this.tokenized = value;
+  }
+
+  public boolean storeTermVectors() {
+    return this.storeTermVectors;
+  }
+  
+  public void setStoreTermVectors(boolean value) {
+    checkIfFrozen();
+    this.storeTermVectors = value;
+  }
+
+  public boolean storeTermVectorOffsets() {
+    return this.storeTermVectorOffsets;
+  }
+  
+  public void setStoreTermVectorOffsets(boolean value) {
+    checkIfFrozen();
+    this.storeTermVectorOffsets = value;
+  }
+
+  public boolean storeTermVectorPositions() {
+    return this.storeTermVectorPositions;
+  }
+  
+  public void setStoreTermVectorPositions(boolean value) {
+    checkIfFrozen();
+    this.storeTermVectorPositions = value;
+  }
+  
+  public boolean omitNorms() {
+    return this.omitNorms;
+  }
+  
+  public void setOmitNorms(boolean value) {
+    checkIfFrozen();
+    this.omitNorms = value;
+  }
+
+  public IndexOptions indexOptions() {
+    return this.indexOptions;
+  }
+  
+  public void setIndexOptions(IndexOptions value) {
+    checkIfFrozen();
+    this.indexOptions = value;
+  }
+
+  public boolean lazy() {
+    return this.lazy;
+  }
+  
+  public void setLazy(boolean value) {
+    checkIfFrozen();
+    this.lazy = value;
+  }
+
+  /** Prints a Field for human consumption. */
+  @Override
+  public final String toString() {
+    StringBuilder result = new StringBuilder();
+    if (stored()) {
+      result.append("stored");
+    }
+    if (indexed()) {
+      if (result.length() > 0)
+        result.append(",");
+      result.append("indexed");
+    }
+    if (tokenized()) {
+      if (result.length() > 0)
+        result.append(",");
+      result.append("tokenized");
+    }
+    if (storeTermVectors()) {
+      if (result.length() > 0)
+        result.append(",");
+      result.append("termVector");
+    }
+    if (storeTermVectorOffsets()) {
+      if (result.length() > 0)
+        result.append(",");
+      result.append("termVectorOffsets");
+    }
+    if (storeTermVectorPositions()) {
+      if (result.length() > 0)
+        result.append(",");
+      result.append("termVectorPosition");
+    }
+    if (omitNorms()) {
+      result.append(",omitNorms");
+    }
+    if (indexOptions != IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) {
+      result.append(",indexOptions=");
+      result.append(indexOptions);
+    }
+    if (lazy()){
+      result.append(",lazy");
+    }
+    
+    return result.toString();
+  }
+}

Property changes on: lucene/src/java/org/apache/lucene/document/FieldType.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/document/TextField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/TextField.java	(revision 0)
+++ lucene/src/java/org/apache/lucene/document/TextField.java	(revision 1159961)
@@ -0,0 +1,54 @@
+package org.apache.lucene.document;
+
+/**
+ * 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.analysis.TokenStream;
+
+public final class TextField extends Field {
+
+  public static final FieldType TYPE_UNSTORED = new FieldType();
+  public static final FieldType TYPE_STORED = new FieldType();
+  static {
+    TYPE_UNSTORED.setIndexed(true);
+    TYPE_UNSTORED.setTokenized(true);
+    TYPE_UNSTORED.freeze();
+
+    TYPE_STORED.setIndexed(true);
+    TYPE_STORED.setStored(true);
+    TYPE_STORED.setTokenized(true);
+    TYPE_STORED.freeze();
+  }
+  
+  public TextField(String name, Reader reader) {
+    super(name, TextField.TYPE_UNSTORED, reader);
+  }
+
+  public TextField(String name, String value) {
+    super(name, TextField.TYPE_UNSTORED, value);
+  }
+  
+  public TextField(String name, TokenStream stream) {
+    super(name, TextField.TYPE_UNSTORED, stream);
+  }
+
+  public boolean isNumeric() {
+    return false;
+  }
+}

Property changes on: lucene/src/java/org/apache/lucene/document/TextField.java
___________________________________________________________________
Added: svn:eol-style
   + native

Index: lucene/src/java/org/apache/lucene/document/SetBasedFieldSelector.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/SetBasedFieldSelector.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/SetBasedFieldSelector.java	(working copy)
@@ -1,58 +0,0 @@
-package org.apache.lucene.document;
-
-import java.util.Set;
-/**
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed 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.
- */
-
-/**
- * Declare what fields to load normally and what fields to load lazily
- *
- **/
-public class SetBasedFieldSelector implements FieldSelector {
-  
-  private Set<String> fieldsToLoad;
-  private Set<String> lazyFieldsToLoad;
-  
-  /**
-   * Pass in the Set of {@link Field} names to load and the Set of {@link Field} names to load lazily.  If both are null, the
-   * Document will not have any {@link Field} on it.  
-   * @param fieldsToLoad A Set of {@link String} field names to load.  May be empty, but not null
-   * @param lazyFieldsToLoad A Set of {@link String} field names to load lazily.  May be empty, but not null  
-   */
-  public SetBasedFieldSelector(Set<String> fieldsToLoad, Set<String> lazyFieldsToLoad) {
-    this.fieldsToLoad = fieldsToLoad;
-    this.lazyFieldsToLoad = lazyFieldsToLoad;
-  }
-
-  /**
-   * Indicate whether to load the field with the given name or not. If the {@link Field#name()} is not in either of the 
-   * initializing Sets, then {@link org.apache.lucene.document.FieldSelectorResult#NO_LOAD} is returned.  If a Field name
-   * is in both <code>fieldsToLoad</code> and <code>lazyFieldsToLoad</code>, lazy has precedence.
-   * 
-   * @param fieldName The {@link Field} name to check
-   * @return The {@link FieldSelectorResult}
-   */
-  public FieldSelectorResult accept(String fieldName) {
-    FieldSelectorResult result = FieldSelectorResult.NO_LOAD;
-    if (fieldsToLoad.contains(fieldName) == true){
-      result = FieldSelectorResult.LOAD;
-    }
-    if (lazyFieldsToLoad.contains(fieldName) == true){
-      result = FieldSelectorResult.LAZY_LOAD;
-    }                                           
-    return result;
-  }
-}
\ No newline at end of file
Index: lucene/src/java/org/apache/lucene/document/MapFieldSelector.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/MapFieldSelector.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/MapFieldSelector.java	(working copy)
@@ -1,67 +0,0 @@
-package org.apache.lucene.document;
-
-/**
- * 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.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A {@link FieldSelector} based on a Map of field names to {@link FieldSelectorResult}s
- *
- */
-public class MapFieldSelector implements FieldSelector {
-    
-    Map<String,FieldSelectorResult> fieldSelections;
-    
-    /** Create a a MapFieldSelector
-     * @param fieldSelections maps from field names (String) to {@link FieldSelectorResult}s
-     */
-    public MapFieldSelector(Map<String,FieldSelectorResult> fieldSelections) {
-        this.fieldSelections = fieldSelections;
-    }
-    
-    /** Create a a MapFieldSelector
-     * @param fields fields to LOAD.  List of Strings.  All other fields are NO_LOAD.
-     */
-    public MapFieldSelector(List<String> fields) {
-        fieldSelections = new HashMap<String,FieldSelectorResult>(fields.size()*5/3);
-        for (final String field : fields)
-            fieldSelections.put(field, FieldSelectorResult.LOAD);
-    }
-    
-    /** Create a a MapFieldSelector
-     * @param fields fields to LOAD.  All other fields are NO_LOAD.
-     */
-    public MapFieldSelector(String... fields) {
-      this(Arrays.asList(fields));
-    }
-
-
-    
-    /** Load field according to its associated value in fieldSelections
-     * @param field a field name
-     * @return the fieldSelections value that field maps to or NO_LOAD if none.
-     */
-    public FieldSelectorResult accept(String field) {
-        FieldSelectorResult selection = fieldSelections.get(field);
-        return selection!=null ? selection : FieldSelectorResult.NO_LOAD;
-    }
-    
-}
Index: lucene/src/java/org/apache/lucene/document/FieldSelectorResult.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/FieldSelectorResult.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/FieldSelectorResult.java	(working copy)
@@ -1,76 +0,0 @@
-package org.apache.lucene.document;
-
-/**
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed 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.
- */
-
-/**
- *  Provides information about what should be done with this Field 
- *
- **/
-public enum FieldSelectorResult {
-
-    /**
-     * Load this {@link Field} every time the {@link Document} is loaded, reading in the data as it is encountered.
-     *  {@link Document#getField(String)} and {@link Document#getFieldable(String)} should not return null.
-     *<p/>
-     * {@link Document#add(Fieldable)} should be called by the Reader.
-     */
-  LOAD,
-
-    /**
-     * Lazily load this {@link Field}.  This means the {@link Field} is valid, but it may not actually contain its data until
-     * invoked.  {@link Document#getField(String)} SHOULD NOT BE USED.  {@link Document#getFieldable(String)} is safe to use and should
-     * return a valid instance of a {@link Fieldable}.
-     *<p/>
-     * {@link Document#add(Fieldable)} should be called by the Reader.
-     */
-  LAZY_LOAD,
-
-    /**
-     * Do not load the {@link Field}.  {@link Document#getField(String)} and {@link Document#getFieldable(String)} should return null.
-     * {@link Document#add(Fieldable)} is not called.
-     * <p/>
-     * {@link Document#add(Fieldable)} should not be called by the Reader.
-     */
-  NO_LOAD,
-
-    /**
-     * Load this field as in the {@link #LOAD} case, but immediately return from {@link Field} loading for the {@link Document}.  Thus, the
-     * Document may not have its complete set of Fields.  {@link Document#getField(String)} and {@link Document#getFieldable(String)} should
-     * both be valid for this {@link Field}
-     * <p/>
-     * {@link Document#add(Fieldable)} should be called by the Reader.
-     */
-  LOAD_AND_BREAK,
-
-    /** Expert:  Load the size of this {@link Field} rather than its value.
-     * Size is measured as number of bytes required to store the field == bytes for a binary or any compressed value, and 2*chars for a String value.
-     * The size is stored as a binary value, represented as an int in a byte[], with the higher order byte first in [0]
-     */
-  SIZE,
-
-    /** Expert: Like {@link #SIZE} but immediately break from the field loading loop, i.e., stop loading further fields, after the size is loaded */         
-  SIZE_AND_BREAK,
-
-  /**
-     * Lazily load this {@link Field}, but do not cache the result.  This means the {@link Field} is valid, but it may not actually contain its data until
-     * invoked.  {@link Document#getField(String)} SHOULD NOT BE USED.  {@link Document#getFieldable(String)} is safe to use and should
-     * return a valid instance of a {@link Fieldable}.
-     *<p/>
-     * {@link Document#add(Fieldable)} should be called by the Reader.
-     */
-  LATENT
-}
Index: lucene/src/java/org/apache/lucene/document/FieldSelector.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/FieldSelector.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/FieldSelector.java	(working copy)
@@ -1,33 +0,0 @@
-package org.apache.lucene.document;
-
-/**
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed 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.
- */
-
-/**
- * Similar to a {@link java.io.FileFilter}, the FieldSelector allows one to make decisions about
- * what Fields get loaded on a {@link Document} by {@link org.apache.lucene.index.IndexReader#document(int,org.apache.lucene.document.FieldSelector)}
- *
- **/
-public interface FieldSelector {
-
-  /**
-   * 
-   * @param fieldName the field to accept or reject
-   * @return an instance of {@link FieldSelectorResult}
-   * if the {@link Field} named <code>fieldName</code> should be loaded.
-   */
-  FieldSelectorResult accept(String fieldName);
-}
Index: lucene/src/java/org/apache/lucene/document/AbstractField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/AbstractField.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/AbstractField.java	(working copy)
@@ -1,312 +0,0 @@
-package org.apache.lucene.document;
-/**
- * Copyright 2006 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.apache.lucene.search.PhraseQuery; // for javadocs
-import org.apache.lucene.search.spans.SpanQuery; // for javadocs
-import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.index.FieldInfo.IndexOptions;
-import org.apache.lucene.index.FieldInvertState;  // for javadocs
-import org.apache.lucene.index.values.PerDocFieldValues;
-import org.apache.lucene.index.values.ValueType;
-
-
-/**
- *
- *
- **/
-public abstract class AbstractField implements Fieldable {
-
-  protected String name = "body";
-  protected boolean storeTermVector = false;
-  protected boolean storeOffsetWithTermVector = false;
-  protected boolean storePositionWithTermVector = false;
-  protected boolean omitNorms = false;
-  protected boolean isStored = false;
-  protected boolean isIndexed = true;
-  protected boolean isTokenized = true;
-  protected boolean isBinary = false;
-  protected boolean lazy = false;
-  protected IndexOptions indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
-  protected float boost = 1.0f;
-  // the data object for all different kind of field values
-  protected Object fieldsData = null;
-  // pre-analyzed tokenStream for indexed fields
-  protected TokenStream tokenStream;
-  // length/offset for all primitive types
-  protected int binaryLength;
-  protected int binaryOffset;
-  protected PerDocFieldValues docValues;
-
-  protected AbstractField()
-  {
-  }
-
-  protected AbstractField(String name, Field.Store store, Field.Index index, Field.TermVector termVector) {
-    if (name == null)
-      throw new NullPointerException("name cannot be null");
-    this.name = name;
-
-    this.isStored = store.isStored();
-    this.isIndexed = index.isIndexed();
-    this.isTokenized = index.isAnalyzed();
-    this.omitNorms = index.omitNorms();
-
-    this.isBinary = false;
-
-    setStoreTermVector(termVector);
-  }
-
-  /** Sets the boost factor hits on this field.  This value will be
-   * multiplied into the score of all hits on this this field of this
-   * document.
-   *
-   * <p>The boost is multiplied by {@link org.apache.lucene.document.Document#getBoost()} of the document
-   * containing this field.  If a document has multiple fields with the same
-   * name, all such values are multiplied together.  This product is then
-   * used to compute the norm factor for the field.  By
-   * default, in the {@link
-   * org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)} method, the boost value is multiplied
-   * by the length normalization factor and then
-   * rounded by {@link org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)} before it is stored in the
-   * index.  One should attempt to ensure that this product does not overflow
-   * the range of that encoding.
-   *
-   * @see org.apache.lucene.document.Document#setBoost(float)
-   * @see org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)
-   * @see org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)
-   */
-  public void setBoost(float boost) {
-    this.boost = boost;
-  }
-
-  /** Returns the boost factor for hits for this field.
-   *
-   * <p>The default value is 1.0.
-   *
-   * <p>Note: this value is not stored directly with the document in the index.
-   * Documents returned from {@link org.apache.lucene.index.IndexReader#document(int)} and
-   * {@link org.apache.lucene.search.IndexSearcher#doc(int)} may thus not have the same value present as when
-   * this field was indexed.
-   *
-   * @see #setBoost(float)
-   */
-  public float getBoost() {
-    return boost;
-  }
-
-  /** Returns the name of the field.
-   * For example "date", "title", "body", ...
-   */
-  public String name()    { return name; }
-
-  protected void setStoreTermVector(Field.TermVector termVector) {
-    this.storeTermVector = termVector.isStored();
-    this.storePositionWithTermVector = termVector.withPositions();
-    this.storeOffsetWithTermVector = termVector.withOffsets();
-  }
-
-  /** True iff the value of the field is to be stored in the index for return
-    with search hits.  It is an error for this to be true if a field is
-    Reader-valued. */
-  public final boolean  isStored()  { return isStored; }
-
-  /** True iff the value of the field is to be indexed, so that it may be
-    searched on. */
-  public final boolean  isIndexed()   { return isIndexed; }
-
-  /** True iff the value of the field should be tokenized as text prior to
-    indexing.  Un-tokenized fields are indexed as a single word and may not be
-    Reader-valued. */
-  public final boolean  isTokenized()   { return isTokenized; }
-
-  /** True iff the term or terms used to index this field are stored as a term
-   *  vector, available from {@link org.apache.lucene.index.IndexReader#getTermFreqVector(int,String)}.
-   *  These methods do not provide access to the original content of the field,
-   *  only to terms used to index it. If the original content must be
-   *  preserved, use the <code>stored</code> attribute instead.
-   *
-   * @see org.apache.lucene.index.IndexReader#getTermFreqVector(int, String)
-   */
-  public final boolean isTermVectorStored() { return storeTermVector; }
-
-  /**
-   * True iff terms are stored as term vector together with their offsets 
-   * (start and end position in source text).
-   */
-  public boolean isStoreOffsetWithTermVector(){
-    return storeOffsetWithTermVector;
-  }
-
-  /**
-   * True iff terms are stored as term vector together with their token positions.
-   */
-  public boolean isStorePositionWithTermVector(){
-    return storePositionWithTermVector;
-  }
-
-  /** True iff the value of the filed is stored as binary */
-  public final boolean  isBinary() {
-    return isBinary;
-  }
-
-
-  /**
-   * Return the raw byte[] for the binary field.  Note that
-   * you must also call {@link #getBinaryLength} and {@link
-   * #getBinaryOffset} to know which range of bytes in this
-   * returned array belong to the field.
-   * @return reference to the Field value as byte[].
-   */
-  public byte[] getBinaryValue() {
-    return getBinaryValue(null);
-  }
-  
-  public byte[] getBinaryValue(byte[] result){
-    if (isBinary || fieldsData instanceof byte[])
-      return (byte[]) fieldsData;
-    else
-      return null;
-  }
-
-  /**
-   * Returns length of byte[] segment that is used as value, if Field is not binary
-   * returned value is undefined
-   * @return length of byte[] segment that represents this Field value
-   */
-  public int getBinaryLength() {
-    if (isBinary) {
-      return binaryLength;
-    } else if (fieldsData instanceof byte[])
-      return ((byte[]) fieldsData).length;
-    else
-      return 0;
-  }
-
-  /**
-   * Returns offset into byte[] segment that is used as value, if Field is not binary
-   * returned value is undefined
-   * @return index of the first character in byte[] segment that represents this Field value
-   */
-  public int getBinaryOffset() {
-    return binaryOffset;
-  }
-
-  /** True if norms are omitted for this indexed field */
-  public boolean getOmitNorms() { return omitNorms; }
-
-  /** @see #setIndexOptions */
-  public IndexOptions getIndexOptions() { return indexOptions; }
-  
-  /** Expert:
-   *
-   * If set, omit normalization factors associated with this indexed field.
-   * This effectively disables indexing boosts and length normalization for this field.
-   */
-  public void setOmitNorms(boolean omitNorms) { this.omitNorms=omitNorms; }
-
-  /** Expert:
-   *
-   * If set, omit term freq, and optionally also positions and payloads from
-   * postings for this field.
-   *
-   * <p><b>NOTE</b>: While this option reduces storage space
-   * required in the index, it also means any query
-   * requiring positional information, such as {@link
-   * PhraseQuery} or {@link SpanQuery} subclasses will
-   * silently fail to find results.
-   */
-  public void setIndexOptions(IndexOptions indexOptions) { this.indexOptions=indexOptions; }
- 
-  public boolean isLazy() {
-    return lazy;
-  }
-
-  /** Prints a Field for human consumption. */
-  @Override
-  public final String toString() {
-    StringBuilder result = new StringBuilder();
-    if (isStored) {
-      result.append("stored");
-    }
-    if (isIndexed) {
-      if (result.length() > 0)
-        result.append(",");
-      result.append("indexed");
-    }
-    if (isTokenized) {
-      if (result.length() > 0)
-        result.append(",");
-      result.append("tokenized");
-    }
-    if (storeTermVector) {
-      if (result.length() > 0)
-        result.append(",");
-      result.append("termVector");
-    }
-    if (storeOffsetWithTermVector) {
-      if (result.length() > 0)
-        result.append(",");
-      result.append("termVectorOffsets");
-    }
-    if (storePositionWithTermVector) {
-      if (result.length() > 0)
-        result.append(",");
-      result.append("termVectorPosition");
-    }
-    if (isBinary) {
-      if (result.length() > 0)
-        result.append(",");
-      result.append("binary");
-    }
-    if (omitNorms) {
-      result.append(",omitNorms");
-    }
-    if (indexOptions != IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) {
-      result.append(",indexOptions=");
-      result.append(indexOptions);
-    }
-    if (lazy){
-      result.append(",lazy");
-    }
-    result.append('<');
-    result.append(name);
-    result.append(':');
-
-    if (fieldsData != null && lazy == false) {
-      result.append(fieldsData);
-    }
-
-    result.append('>');
-    return result.toString();
-  }
-
-  public PerDocFieldValues getDocValues() {
-    return docValues;
-  }
-  
-  public void setDocValues(PerDocFieldValues docValues) {
-    this.docValues = docValues;
-  }
-  
-  public boolean hasDocValues() {
-    return docValues != null && docValues.type() != null;
-  }
-  
-  public ValueType docValuesType() {
-    return docValues == null? null : docValues.type();
-  }
-}
Index: lucene/src/java/org/apache/lucene/document/Fieldable.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/Fieldable.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/Fieldable.java	(working copy)
@@ -1,238 +0,0 @@
-package org.apache.lucene.document;
-
-/**
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.index.FieldInfo.IndexOptions;
-import org.apache.lucene.index.FieldInvertState; // for javadocs
-import org.apache.lucene.index.values.IndexDocValues;
-import org.apache.lucene.index.values.PerDocFieldValues;
-import org.apache.lucene.index.values.ValueType;
-import org.apache.lucene.search.PhraseQuery; // for javadocs
-import org.apache.lucene.search.spans.SpanQuery; // for javadocs
-
-import java.io.Reader;
-
-/**
- * Synonymous with {@link Field}.
- *
- * <p><bold>WARNING</bold>: This interface may change within minor versions, despite Lucene's backward compatibility requirements.
- * This means new methods may be added from version to version.  This change only affects the Fieldable API; other backwards
- * compatibility promises remain intact. For example, Lucene can still
- * read and write indices created within the same major version.
- * </p>
- *
- **/
-public interface Fieldable {
-  /** Sets the boost factor hits on this field.  This value will be
-   * multiplied into the score of all hits on this this field of this
-   * document.
-   *
-   * <p>The boost is multiplied by {@link org.apache.lucene.document.Document#getBoost()} of the document
-   * containing this field.  If a document has multiple fields with the same
-   * name, all such values are multiplied together.  This product is then
-   * used to compute the norm factor for the field.  By
-   * default, in the {@link
-   * org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)} method, the boost value is multiplied
-   * by the length normalization factor
-   * and then rounded by {@link org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)} before it is stored in the
-   * index.  One should attempt to ensure that this product does not overflow
-   * the range of that encoding.
-   *
-   * @see org.apache.lucene.document.Document#setBoost(float)
-   * @see org.apache.lucene.search.Similarity#computeNorm(FieldInvertState)
-   * @see org.apache.lucene.search.DefaultSimilarity#encodeNormValue(float)
-   */
-  void setBoost(float boost);
-
-  /** Returns the boost factor for hits for this field.
-   *
-   * <p>The default value is 1.0.
-   *
-   * <p>Note: this value is not stored directly with the document in the index.
-   * Documents returned from {@link org.apache.lucene.index.IndexReader#document(int)} and
-   * {@link org.apache.lucene.search.IndexSearcher#doc(int)} may thus not have the same value present as when
-   * this field was indexed.
-   *
-   * @see #setBoost(float)
-   */
-  float getBoost();
-
-  /** Returns the name of the field.
-   * For example "date", "title", "body", ...
-   */
-  String name();
-
-  /** The value of the field as a String, or null.
-   * <p>
-   * For indexing, if isStored()==true, the stringValue() will be used as the stored field value
-   * unless isBinary()==true, in which case getBinaryValue() will be used.
-   *
-   * If isIndexed()==true and isTokenized()==false, this String value will be indexed as a single token.
-   * If isIndexed()==true and isTokenized()==true, then tokenStreamValue() will be used to generate indexed tokens if not null,
-   * else readerValue() will be used to generate indexed tokens if not null, else stringValue() will be used to generate tokens.
-   */
-  public String stringValue();
-  
-  /** The value of the field as a Reader, which can be used at index time to generate indexed tokens.
-   * @see #stringValue()
-   */
-  public Reader readerValue();
-  
-  /** The TokenStream for this field to be used when indexing, or null.
-   * @see #stringValue()
-   */
-  public TokenStream tokenStreamValue();
-
-  /** True if the value of the field is to be stored in the index for return
-    with search hits. */
-  boolean  isStored();
-
-  /** True if the value of the field is to be indexed, so that it may be
-    searched on. */
-  boolean  isIndexed();
-
-  /** True if the value of the field should be tokenized as text prior to
-    indexing.  Un-tokenized fields are indexed as a single word and may not be
-    Reader-valued. */
-  boolean  isTokenized();
-
-  /** True if the term or terms used to index this field are stored as a term
-   *  vector, available from {@link org.apache.lucene.index.IndexReader#getTermFreqVector(int,String)}.
-   *  These methods do not provide access to the original content of the field,
-   *  only to terms used to index it. If the original content must be
-   *  preserved, use the <code>stored</code> attribute instead.
-   *
-   * @see org.apache.lucene.index.IndexReader#getTermFreqVector(int, String)
-   */
-  boolean isTermVectorStored();
-
-  /**
-   * True if terms are stored as term vector together with their offsets 
-   * (start and end positon in source text).
-   */
-  boolean isStoreOffsetWithTermVector();
-
-  /**
-   * True if terms are stored as term vector together with their token positions.
-   */
-  boolean isStorePositionWithTermVector();
-
-  /** True if the value of the field is stored as binary */
-  boolean  isBinary();
-
-  /** True if norms are omitted for this indexed field */
-  boolean getOmitNorms();
-
-  /** Expert:
-   *
-   * If set, omit normalization factors associated with this indexed field.
-   * This effectively disables indexing boosts and length normalization for this field.
-   */
-  void setOmitNorms(boolean omitNorms);
-
-  /**
-   * Indicates whether a Field is Lazy or not.  The semantics of Lazy loading are such that if a Field is lazily loaded, retrieving
-   * it's values via {@link #stringValue()} or {@link #getBinaryValue()} is only valid as long as the {@link org.apache.lucene.index.IndexReader} that
-   * retrieved the {@link Document} is still open.
-   *  
-   * @return true if this field can be loaded lazily
-   */
-  boolean isLazy();
-  
-  /**
-   * Returns offset into byte[] segment that is used as value, if Field is not binary
-   * returned value is undefined
-   * @return index of the first character in byte[] segment that represents this Field value
-   */
-  abstract int getBinaryOffset();
-  
-  /**
-   * Returns length of byte[] segment that is used as value, if Field is not binary
-   * returned value is undefined
-   * @return length of byte[] segment that represents this Field value
-   */
-  abstract int getBinaryLength();
-
-  /**
-   * Return the raw byte[] for the binary field.  Note that
-   * you must also call {@link #getBinaryLength} and {@link
-   * #getBinaryOffset} to know which range of bytes in this
-   * returned array belong to the field.
-   * @return reference to the Field value as byte[].
-   */
-  abstract byte[] getBinaryValue();
-
-  /**
-   * Return the raw byte[] for the binary field.  Note that
-   * you must also call {@link #getBinaryLength} and {@link
-   * #getBinaryOffset} to know which range of bytes in this
-   * returned array belong to the field.<p>
-   * About reuse: if you pass in the result byte[] and it is
-   * used, likely the underlying implementation will hold
-   * onto this byte[] and return it in future calls to
-   * {@link #getBinaryValue()}.
-   * So if you subsequently re-use the same byte[] elsewhere
-   * it will alter this Fieldable's value.
-   * @param result  User defined buffer that will be used if
-   *  possible.  If this is null or not large enough, a new
-   *  buffer is allocated
-   * @return reference to the Field value as byte[].
-   */
-  abstract byte[] getBinaryValue(byte[] result);
-  
-  /** @see #setIndexOptions */
-  IndexOptions getIndexOptions();
-  
-  /** Expert:
-  *
-  * If set, omit term freq, and optionally positions and payloads from
-  * postings for this field.
-  *
-  * <p><b>NOTE</b>: While this option reduces storage space
-  * required in the index, it also means any query
-  * requiring positional information, such as {@link
-  * PhraseQuery} or {@link SpanQuery} subclasses will
-  * fail with an exception.
-  */
-  void setIndexOptions(IndexOptions indexOptions);
-  
-  /**
-   * Returns the {@link PerDocFieldValues}
-   */
-  public PerDocFieldValues getDocValues();
-
-  /**
-   * Sets the {@link PerDocFieldValues} for this field. If
-   * {@link PerDocFieldValues} is set this field will store per-document values
-   * 
-   * @see IndexDocValues
-   */
-  public void setDocValues(PerDocFieldValues docValues);
-
-  /**
-   * Returns <code>true</code> iff {@link PerDocFieldValues} are set on this
-   * field.
-   */
-  public boolean hasDocValues();
-
-  /**
-   * Returns the {@link ValueType} of the set {@link PerDocFieldValues} or
-   * <code>null</code> if not set.
-   */
-  public ValueType docValuesType();
-}
Index: lucene/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/LoadFirstFieldSelector.java	(working copy)
@@ -1,29 +0,0 @@
-package org.apache.lucene.document;
-/**
- * Copyright 2004 The Apache Software Foundation
- *
- * Licensed 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.
- */
-
-
-/**
- * Load the First field and break.
- * <p/>
- * See {@link FieldSelectorResult#LOAD_AND_BREAK}
- */
-public class LoadFirstFieldSelector implements FieldSelector {
-
-  public FieldSelectorResult accept(String fieldName) {
-    return FieldSelectorResult.LOAD_AND_BREAK;
-  }
-}
\ No newline at end of file
Index: lucene/src/java/org/apache/lucene/document/package.html
===================================================================
--- lucene/src/java/org/apache/lucene/document/package.html	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/document/package.html	(working copy)
@@ -22,16 +22,16 @@
 <body>
 <p>The logical representation of a {@link org.apache.lucene.document.Document} for indexing and searching.</p>
 <p>The document package provides the user level logical representation of content to be indexed and searched.  The
-package also provides utilities for working with {@link org.apache.lucene.document.Document}s and {@link org.apache.lucene.document.Fieldable}s.</p>
-<h2>Document and Fieldable</h2>
-<p>A {@link org.apache.lucene.document.Document} is a collection of {@link org.apache.lucene.document.Fieldable}s.  A
-  {@link org.apache.lucene.document.Fieldable} is a logical representation of a user's content that needs to be indexed or stored.
-  {@link org.apache.lucene.document.Fieldable}s have a number of properties that tell Lucene how to treat the content (like indexed, tokenized,
-  stored, etc.)  See the {@link org.apache.lucene.document.Field} implementation of {@link org.apache.lucene.document.Fieldable}
+package also provides utilities for working with {@link org.apache.lucene.document.Document}s and {@link org.apache.lucene.index.IndexableField}s.</p>
+<h2>Document and IndexableField</h2>
+<p>A {@link org.apache.lucene.document.Document} is a collection of {@link org.apache.lucene.index.IndexableField}s.  A
+  {@link org.apache.lucene.index.IndexableField} is a logical representation of a user's content that needs to be indexed or stored.
+  {@link org.apache.lucene.index.IndexableField}s have a number of properties that tell Lucene how to treat the content (like indexed, tokenized,
+  stored, etc.)  See the {@link org.apache.lucene.document.Field} implementation of {@link org.apache.lucene.index.IndexableField}
   for specifics on these properties.
 </p>
 <p>Note: it is common to refer to {@link org.apache.lucene.document.Document}s having {@link org.apache.lucene.document.Field}s, even though technically they have
-{@link org.apache.lucene.document.Fieldable}s.</p>
+{@link org.apache.lucene.index.IndexableField}s.</p>
 <h2>Working with Documents</h2>
 <p>First and foremost, a {@link org.apache.lucene.document.Document} is something created by the user application.  It is your job
   to create Documents based on the content of the files you are working with in your application (Word, txt, PDF, Excel or any other format.)
@@ -45,7 +45,7 @@
 to simplify indexing of numeric values (and also dates) for fast range range queries with {@link org.apache.lucene.search.NumericRangeQuery}
 (using a special sortable string representation of numeric values).</p>
 <p>The {@link org.apache.lucene.document.FieldSelector} class provides a mechanism to tell Lucene how to load Documents from
-storage.  If no FieldSelector is used, all Fieldables on a Document will be loaded.  As an example of the FieldSelector usage, consider
+storage.  If no FieldSelector is used, all IndexableFields on a Document will be loaded.  As an example of the FieldSelector usage, consider
   the common use case of
 displaying search results on a web page and then having users click through to see the full document.  In this scenario, it is often
   the case that there are many small fields and one or two large fields (containing the contents of the original file). Before the FieldSelector,
Index: lucene/src/java/org/apache/lucene/search/FieldCache.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/FieldCache.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/FieldCache.java	(working copy)
@@ -24,7 +24,7 @@
 import org.apache.lucene.util.NumericUtils;
 import org.apache.lucene.util.RamUsageEstimator;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.document.NumericField; // for javadocs
+import org.apache.lucene.document.NumericField;
 import org.apache.lucene.analysis.NumericTokenStream; // for javadocs
 import org.apache.lucene.util.packed.PackedInts;
 
Index: lucene/src/java/org/apache/lucene/search/NumericRangeFilter.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/NumericRangeFilter.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/NumericRangeFilter.java	(working copy)
@@ -18,7 +18,7 @@
  */
 
 import org.apache.lucene.analysis.NumericTokenStream; // for javadocs
-import org.apache.lucene.document.NumericField; // for javadocs
+import org.apache.lucene.document.NumericField;
 import org.apache.lucene.util.NumericUtils; // for javadocs
 
 /**
Index: lucene/src/java/org/apache/lucene/search/Similarity.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/Similarity.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/Similarity.java	(working copy)
@@ -221,4 +221,4 @@
      */
     public abstract void normalize(float queryNorm, float topLevelBoost);
   }
-}
+}
\ No newline at end of file
Index: lucene/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/FieldCacheRangeFilter.java	(working copy)
@@ -23,7 +23,7 @@
 import org.apache.lucene.util.NumericUtils;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.document.NumericField; // for javadocs
+import org.apache.lucene.document.NumericField;
 
 /**
  * A range filter built on top of a cached single term field (in {@link FieldCache}).
Index: lucene/src/java/org/apache/lucene/search/NumericRangeQuery.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/NumericRangeQuery.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/NumericRangeQuery.java	(working copy)
@@ -22,7 +22,7 @@
 import java.util.Comparator;
 
 import org.apache.lucene.analysis.NumericTokenStream; // for javadocs
-import org.apache.lucene.document.NumericField; // for javadocs
+import org.apache.lucene.document.NumericField;
 import org.apache.lucene.util.NumericUtils;
 import org.apache.lucene.util.ToStringUtils;
 import org.apache.lucene.index.Terms;
Index: lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/TFIDFSimilarity.java	(working copy)
@@ -454,12 +454,8 @@
  *      <b><i>norm(t,d)</i></b> encapsulates a few (indexing time) boost and length factors:
  *
  *      <ul>
- *        <li><b>Document boost</b> - set by calling
- *        {@link org.apache.lucene.document.Document#setBoost(float) doc.setBoost()}
- *        before adding the document to the index.
- *        </li>
  *        <li><b>Field boost</b> - set by calling
- *        {@link org.apache.lucene.document.Fieldable#setBoost(float) field.setBoost()}
+ *        {@link org.apache.lucene.document.Field#setBoost(float) field.setBoost()}
  *        before adding the field to a document.
  *        </li>
  *        <li><b>lengthNorm</b> - computed
@@ -480,8 +476,6 @@
  *        <tr>
  *          <td valign="middle" align="right" rowspan="1">
  *            norm(t,d) &nbsp; = &nbsp;
- *            {@link org.apache.lucene.document.Document#getBoost() doc.getBoost()}
- *            &nbsp;&middot;&nbsp;
  *            lengthNorm
  *            &nbsp;&middot;&nbsp;
  *          </td>
@@ -489,7 +483,7 @@
  *            <big><big><big>&prod;</big></big></big>
  *          </td>
  *          <td valign="middle" align="right" rowspan="1">
- *            {@link org.apache.lucene.document.Fieldable#getBoost() f.getBoost}()
+ *            {@link org.apache.lucene.index.IndexableField#boost() f.boost}()
  *          </td>
  *        </tr>
  *        <tr valigh="top">
Index: lucene/src/java/org/apache/lucene/search/IndexSearcher.java
===================================================================
--- lucene/src/java/org/apache/lucene/search/IndexSearcher.java	(revision 1158028)
+++ lucene/src/java/org/apache/lucene/search/IndexSearcher.java	(working copy)
@@ -31,11 +31,11 @@
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.lucene.document.Document;
-import org.apache.lucene.document.FieldSelector;
 import org.apache.lucene.index.CorruptIndexException;
-import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReader.AtomicReaderContext;
 import org.apache.lucene.index.IndexReader.ReaderContext;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.StoredFieldVisitor;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.search.Weight.ScorerContext;
 import org.apache.lucene.store.Directory;
@@ -239,16 +239,16 @@
     }
   }
 
-  /* Sugar for .getIndexReader().document(docID) */
+  /* Sugar for <code>.getIndexReader().document(docID)</code> */
   public Document doc(int docID) throws CorruptIndexException, IOException {
     return reader.document(docID);
   }
-  
-  /* Sugar for .getIndexReader().document(docID, fieldSelector) */
-  public Document doc(int docID, FieldSelector fieldSelector) throws CorruptIndexException, IOException {
-    return reader.document(docID, fieldSelector);
+
+  /* Sugar for <code>.getIndexReader().document(docID, fieldVisitor)</code> */
+  public void doc(int docID, StoredFieldVisitor fieldVisitor) throws CorruptIndexException, IOException {
+    reader.document(docID, fieldVisitor);
   }
-  
+
   /** Expert: Set the SimilarityProvider implementation used by this Searcher.
    *
    */
Index: lucene/src/test-framework/org/apache/lucene/index/DocHelper.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/index/DocHelper.java	(revision 1158028)
+++ lucene/src/test-framework/org/apache/lucene/index/DocHelper.java	(working copy)
@@ -26,10 +26,12 @@
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
+import org.apache.lucene.document.BinaryField;
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.TextField;
 import org.apache.lucene.search.SimilarityProvider;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;
@@ -37,63 +39,107 @@
 import static org.apache.lucene.util.LuceneTestCase.TEST_VERSION_CURRENT;
 
 class DocHelper {
+  
+  public static final FieldType customType;
   public static final String FIELD_1_TEXT = "field one text";
   public static final String TEXT_FIELD_1_KEY = "textField1";
-  public static Field textField1 = new Field(TEXT_FIELD_1_KEY, FIELD_1_TEXT,
-      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
-  
+  public static Field textField1;
+  static {
+    customType = new FieldType(TextField.TYPE_STORED);
+    textField1 = new Field(TEXT_FIELD_1_KEY, customType, FIELD_1_TEXT);
+  }
+
+  public static final FieldType customType2;
   public static final String FIELD_2_TEXT = "field field field two text";
   //Fields will be lexicographically sorted.  So, the order is: field, text, two
   public static final int [] FIELD_2_FREQS = {3, 1, 1}; 
   public static final String TEXT_FIELD_2_KEY = "textField2";
-  public static Field textField2 = new Field(TEXT_FIELD_2_KEY, FIELD_2_TEXT, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+  public static Field textField2;
+  static {
+    customType2 = new FieldType(TextField.TYPE_STORED);
+    customType2.setStoreTermVectors(true);
+    customType2.setStoreTermVectorPositions(true);
+    customType2.setStoreTermVectorOffsets(true);
+    textField2 = new Field(TEXT_FIELD_2_KEY, customType2, FIELD_2_TEXT);
+  }
   
+  public static final FieldType customType3;
   public static final String FIELD_3_TEXT = "aaaNoNorms aaaNoNorms bbbNoNorms";
   public static final String TEXT_FIELD_3_KEY = "textField3";
-  public static Field textField3 = new Field(TEXT_FIELD_3_KEY, FIELD_3_TEXT, Field.Store.YES, Field.Index.ANALYZED);
-  static { textField3.setOmitNorms(true); }
+  public static Field textField3;
+  
+  static {
+    customType3 = new FieldType(TextField.TYPE_STORED);
+    customType3.setOmitNorms(true);
+    textField3 = new Field(TEXT_FIELD_3_KEY, customType3, FIELD_3_TEXT);
+  }
 
+  public static final FieldType customType4;
   public static final String KEYWORD_TEXT = "Keyword";
   public static final String KEYWORD_FIELD_KEY = "keyField";
-  public static Field keyField = new Field(KEYWORD_FIELD_KEY, KEYWORD_TEXT,
-      Field.Store.YES, Field.Index.NOT_ANALYZED);
+  public static Field keyField;
+  static {
+    customType4 = new FieldType(TextField.TYPE_UNSTORED);
+    customType4.setStored(true);
+    customType4.setTokenized(false);
+    keyField = new Field(KEYWORD_FIELD_KEY, customType4,  KEYWORD_TEXT);
+  }
 
+  public static final FieldType customType5;
   public static final String NO_NORMS_TEXT = "omitNormsText";
   public static final String NO_NORMS_KEY = "omitNorms";
-  public static Field noNormsField = new Field(NO_NORMS_KEY, NO_NORMS_TEXT,
-      Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
+  public static Field noNormsField;
+  static {
+    customType5 = new FieldType(TextField.TYPE_UNSTORED);
+    customType5.setOmitNorms(true);
+    customType5.setStored(true);
+    customType5.setTokenized(false);
+    noNormsField = new Field(NO_NORMS_KEY, customType5, NO_NORMS_TEXT);
+  }
 
+  public static final FieldType customType6;
   public static final String NO_TF_TEXT = "analyzed with no tf and positions";
   public static final String NO_TF_KEY = "omitTermFreqAndPositions";
-  public static Field noTFField = new Field(NO_TF_KEY, NO_TF_TEXT,
-      Field.Store.YES, Field.Index.ANALYZED);
+  public static Field noTFField;
   static {
-    noTFField.setIndexOptions(IndexOptions.DOCS_ONLY);
+    customType6 = new FieldType(TextField.TYPE_UNSTORED);
+    customType6.setIndexOptions(IndexOptions.DOCS_ONLY);
+    customType6.setStored(true);
+    noTFField = new Field(NO_TF_KEY, customType6, NO_TF_TEXT);
   }
 
+  public static final FieldType customType7;
   public static final String UNINDEXED_FIELD_TEXT = "unindexed field text";
   public static final String UNINDEXED_FIELD_KEY = "unIndField";
-  public static Field unIndField = new Field(UNINDEXED_FIELD_KEY, UNINDEXED_FIELD_TEXT,
-      Field.Store.YES, Field.Index.NO);
+  public static Field unIndField;
+  static {
+    customType7 = new FieldType();
+    customType7.setStored(true);
+    unIndField = new Field(UNINDEXED_FIELD_KEY, customType7, UNINDEXED_FIELD_TEXT);
+  }
 
 
   public static final String UNSTORED_1_FIELD_TEXT = "unstored field text";
   public static final String UNSTORED_FIELD_1_KEY = "unStoredField1";
-  public static Field unStoredField1 = new Field(UNSTORED_FIELD_1_KEY, UNSTORED_1_FIELD_TEXT,
-      Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO);
+  public static Field unStoredField1 = new Field(UNSTORED_FIELD_1_KEY, TextField.TYPE_UNSTORED, UNSTORED_1_FIELD_TEXT);
 
+  public static final FieldType customType8;
   public static final String UNSTORED_2_FIELD_TEXT = "unstored field text";
   public static final String UNSTORED_FIELD_2_KEY = "unStoredField2";
-  public static Field unStoredField2 = new Field(UNSTORED_FIELD_2_KEY, UNSTORED_2_FIELD_TEXT,
-      Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES);
+  public static Field unStoredField2;
+  static {
+    customType8 = new FieldType(TextField.TYPE_UNSTORED);
+    customType8.setStoreTermVectors(true);
+    unStoredField2 = new Field(UNSTORED_FIELD_2_KEY, customType8, UNSTORED_2_FIELD_TEXT);
+  }
 
   public static final String LAZY_FIELD_BINARY_KEY = "lazyFieldBinary";
   public static byte [] LAZY_FIELD_BINARY_BYTES;
   public static Field lazyFieldBinary;
-  
+
   public static final String LAZY_FIELD_KEY = "lazyField";
   public static final String LAZY_FIELD_TEXT = "These are some field bytes";
-  public static Field lazyField = new Field(LAZY_FIELD_KEY, LAZY_FIELD_TEXT, Field.Store.YES, Field.Index.ANALYZED);
+  public static Field lazyField = new Field(LAZY_FIELD_KEY, customType, LAZY_FIELD_TEXT);
   
   public static final String LARGE_LAZY_FIELD_KEY = "largeLazyField";
   public static String LARGE_LAZY_FIELD_TEXT;
@@ -102,15 +148,13 @@
   //From Issue 509
   public static final String FIELD_UTF1_TEXT = "field one \u4e00text";
   public static final String TEXT_FIELD_UTF1_KEY = "textField1Utf8";
-  public static Field textUtfField1 = new Field(TEXT_FIELD_UTF1_KEY, FIELD_UTF1_TEXT,
-      Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
+  public static Field textUtfField1 = new Field(TEXT_FIELD_UTF1_KEY, customType, FIELD_UTF1_TEXT);
 
   public static final String FIELD_UTF2_TEXT = "field field field \u4e00two text";
   //Fields will be lexicographically sorted.  So, the order is: field, text, two
   public static final int [] FIELD_UTF2_FREQS = {3, 1, 1};
   public static final String TEXT_FIELD_UTF2_KEY = "textField2Utf8";
-  public static Field textUtfField2 = new Field(TEXT_FIELD_UTF2_KEY, FIELD_UTF2_TEXT, Field.Store.YES, 
-          Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+  public static Field textUtfField2 = new Field(TEXT_FIELD_UTF2_KEY, customType2, FIELD_UTF2_TEXT);
  
   
   
@@ -136,16 +180,16 @@
     largeLazyField//placeholder for large field, since this is null.  It must always be last
   };
 
-  public static Map<String,Fieldable> all     =new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> indexed =new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> stored  =new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> unstored=new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> unindexed=new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> termvector=new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> notermvector=new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> lazy= new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> noNorms=new HashMap<String,Fieldable>();
-  public static Map<String,Fieldable> noTf=new HashMap<String,Fieldable>();
+  public static Map<String,IndexableField> all     =new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> indexed =new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> stored  =new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> unstored=new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> unindexed=new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> termvector=new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> notermvector=new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> lazy= new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> noNorms=new HashMap<String,IndexableField>();
+  public static Map<String,IndexableField> noTf=new HashMap<String,IndexableField>();
 
   static {
     //Initialize the large Lazy Field
@@ -159,28 +203,29 @@
       LAZY_FIELD_BINARY_BYTES = "These are some binary field bytes".getBytes("UTF8");
     } catch (UnsupportedEncodingException e) {
     }
-    lazyFieldBinary = new Field(LAZY_FIELD_BINARY_KEY, LAZY_FIELD_BINARY_BYTES);
+    lazyFieldBinary = new BinaryField(LAZY_FIELD_BINARY_KEY, LAZY_FIELD_BINARY_BYTES);
     fields[fields.length - 2] = lazyFieldBinary;
     LARGE_LAZY_FIELD_TEXT = buffer.toString();
-    largeLazyField = new Field(LARGE_LAZY_FIELD_KEY, LARGE_LAZY_FIELD_TEXT, Field.Store.YES, Field.Index.ANALYZED);
+    largeLazyField = new Field(LARGE_LAZY_FIELD_KEY, customType, LARGE_LAZY_FIELD_TEXT);
     fields[fields.length - 1] = largeLazyField;
     for (int i=0; i<fields.length; i++) {
-      Fieldable f = fields[i];
+      IndexableField f = fields[i];
       add(all,f);
-      if (f.isIndexed()) add(indexed,f);
+      if (f.indexed()) add(indexed,f);
       else add(unindexed,f);
-      if (f.isTermVectorStored()) add(termvector,f);
-      if (f.isIndexed() && !f.isTermVectorStored()) add(notermvector,f);
-      if (f.isStored()) add(stored,f);
+      if (f.storeTermVectors()) add(termvector,f);
+      if (f.indexed() && !f.storeTermVectors()) add(notermvector,f);
+      if (f.stored()) add(stored,f);
       else add(unstored,f);
-      if (f.getOmitNorms()) add(noNorms,f);
-      if (f.getIndexOptions() == IndexOptions.DOCS_ONLY) add(noTf,f);
-      if (f.isLazy()) add(lazy, f);
+      if (f.indexOptions() == IndexOptions.DOCS_ONLY) add(noTf,f);
+      if (f.omitNorms()) add(noNorms,f);
+      if (f.indexOptions() == IndexOptions.DOCS_ONLY) add(noTf,f);
+      //if (f.isLazy()) add(lazy, f);
     }
   }
 
 
-  private static void add(Map<String,Fieldable> map, Fieldable field) {
+  private static void add(Map<String,IndexableField> map, IndexableField field) {
     map.put(field.name(), field);
   }
 
Index: lucene/src/test-framework/org/apache/lucene/index/RandomIndexWriter.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/index/RandomIndexWriter.java	(revision 1158028)
+++ lucene/src/test-framework/org/apache/lucene/index/RandomIndexWriter.java	(working copy)
@@ -120,23 +120,22 @@
   
   /**
    * Adds a Document.
-   * @see IndexWriter#addDocument(Document)
+   * @see IndexWriter#addDocument(Iterable)
    */
-  public void addDocument(final Document doc) throws IOException {
-    if (doDocValues) {
-      randomPerDocFieldValues(r, doc);
+  public <T extends IndexableField> void addDocument(final Iterable<T> doc) throws IOException {
+    if (doDocValues && doc instanceof Document) {
+      randomPerDocFieldValues(r, (Document) doc);
     }
-
     if (r.nextInt(5) == 3) {
       // TODO: maybe, we should simply buffer up added docs
       // (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<Document>() {
+      w.addDocuments(new Iterable<Iterable<T>>() {
 
         @Override
-        public Iterator<Document> iterator() {
-          return new Iterator<Document>() {
+        public Iterator<Iterable<T>> iterator() {
+          return new Iterator<Iterable<T>>() {
             boolean done;
             
             @Override
@@ -150,7 +149,7 @@
             }
 
             @Override
-            public Document next() {
+            public Iterable<T> next() {
               if (done) {
                 throw new IllegalStateException();
               }
@@ -172,7 +171,7 @@
     ValueType[] values = ValueType.values();
     ValueType type = values[random.nextInt(values.length)];
     String name = "random_" + type.name() + "" + docValuesFieldPrefix;
-    if ("PreFlex".equals(codecProvider.getFieldCodec(name)) || doc.getFieldable(name) != null)
+    if ("PreFlex".equals(codecProvider.getFieldCodec(name)) || doc.getField(name) != null)
         return;
     IndexDocValuesField docValuesField = new IndexDocValuesField(name);
     switch (type) {
@@ -238,31 +237,30 @@
     }
   }
   
-  public void addDocuments(Iterable<Document> docs) throws IOException {
+  public void addDocuments(Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
     w.addDocuments(docs);
     maybeCommit();
   }
 
-  public void updateDocuments(Term delTerm, Iterable<Document> docs) throws IOException {
+  public void updateDocuments(Term delTerm, Iterable<? extends Iterable<? extends IndexableField>> docs) throws IOException {
     w.updateDocuments(delTerm, docs);
     maybeCommit();
   }
 
   /**
    * Updates a document.
-   * @see IndexWriter#updateDocument(Term, Document)
+   * @see IndexWriter#updateDocument(Term, Iterable)
    */
-  public void updateDocument(final Term t, final Document doc) throws IOException {
+  public <T extends IndexableField> void updateDocument(Term t, final Iterable<T> doc) throws IOException {
     if (doDocValues) {
-      randomPerDocFieldValues(r, doc);
+      randomPerDocFieldValues(r, (Document) doc);
     }
-    
     if (r.nextInt(5) == 3) {
-      w.updateDocuments(t, new Iterable<Document>() {
+      w.updateDocuments(t, new Iterable<Iterable<T>>() {
 
         @Override
-        public Iterator<Document> iterator() {
-          return new Iterator<Document>() {
+        public Iterator<Iterable<T>> iterator() {
+          return new Iterator<Iterable<T>>() {
             boolean done;
             
             @Override
@@ -276,7 +274,7 @@
             }
 
             @Override
-            public Document next() {
+            public Iterable<T> next() {
               if (done) {
                 throw new IllegalStateException();
               }
Index: lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java	(revision 1158028)
+++ lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java	(working copy)
@@ -36,11 +36,11 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Fieldable;
 import org.apache.lucene.index.CheckIndex;
 import org.apache.lucene.index.ConcurrentMergeScheduler;
 import org.apache.lucene.index.FieldInfos;
 import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.LogMergePolicy;
 import org.apache.lucene.index.MergePolicy;
 import org.apache.lucene.index.MergeScheduler;
@@ -424,10 +424,9 @@
   
   /** Adds field info for a Document. */
   public static void add(Document doc, FieldInfos fieldInfos) {
-    List<Fieldable> fields = doc.getFields();
-    for (Fieldable field : fields) {
-      fieldInfos.addOrUpdate(field.name(), field.isIndexed(), field.isTermVectorStored(), field.isStorePositionWithTermVector(),
-              field.isStoreOffsetWithTermVector(), field.getOmitNorms(), false, field.getIndexOptions(), field.docValuesType());
+    for (IndexableField field : doc) {
+      fieldInfos.addOrUpdate(field.name(), field.indexed(), field.storeTermVectors(), field.storeTermVectorPositions(),
+              field.storeTermVectorOffsets(), field.omitNorms(), false, field.indexOptions(), field.docValuesType());
     }
   }
   
@@ -504,15 +503,13 @@
   // TODO: is there a pre-existing way to do this!!!
   public static Document cloneDocument(Document doc1) {
     final Document doc2 = new Document();
-    for(Fieldable f : doc1.getFields()) {
+    for(IndexableField f : doc1) {
       Field field1 = (Field) f;
       
       Field field2 = new Field(field1.name(),
-                               field1.stringValue(),
-                               field1.isStored() ? Field.Store.YES : Field.Store.NO,
-                               field1.isIndexed() ? (field1.isTokenized() ? Field.Index.ANALYZED : Field.Index.NOT_ANALYZED) : Field.Index.NO);
-      field2.setOmitNorms(field1.getOmitNorms());
-      field2.setIndexOptions(field1.getIndexOptions());
+                               field1.getFieldType(),
+                               field1.stringValue()
+                               );
       doc2.add(field2);
     }
 
Index: lucene/src/test-framework/org/apache/lucene/util/LineFileDocs.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/util/LineFileDocs.java	(revision 1158028)
+++ lucene/src/test-framework/org/apache/lucene/util/LineFileDocs.java	(working copy)
@@ -30,6 +30,9 @@
 
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.document.FieldType;
+import org.apache.lucene.document.StringField;
+import org.apache.lucene.document.TextField;
 
 /** Minimal port of contrib/benchmark's LneDocSource +
  * DocMaker, so tests can enum docs from a line file created
@@ -117,19 +120,24 @@
     public DocState() {
       doc = new Document();
       
-      title = new Field("title", "", Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS);
+      title = new StringField("title", "");
       doc.add(title);
 
-      titleTokenized = new Field("titleTokenized", "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+      FieldType ft = new FieldType(TextField.TYPE_STORED);
+      ft.setStoreTermVectors(true);
+      ft.setStoreTermVectorOffsets(true);
+      ft.setStoreTermVectorPositions(true);
+      
+      titleTokenized = new Field("titleTokenized", ft, "");
       doc.add(titleTokenized);
 
-      body = new Field("body", "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
+      body = new Field("body", ft, "");
       doc.add(body);
 
-      id = new Field("docid", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
+      id = new Field("docid", StringField.TYPE_STORED, "");
       doc.add(id);
 
-      date = new Field("date", "", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
+      date = new Field("date", StringField.TYPE_STORED, "");
       doc.add(date);
     }
   }
Index: lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java	(revision 1158028)
+++ lucene/src/test-framework/org/apache/lucene/util/LuceneTestCase.java	(working copy)
@@ -37,9 +37,7 @@
 
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.document.Field;
-import org.apache.lucene.document.Field.Index;
-import org.apache.lucene.document.Field.Store;
-import org.apache.lucene.document.Field.TermVector;
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.index.*;
 import org.apache.lucene.index.codecs.Codec;
 import org.apache.lucene.index.codecs.CodecProvider;
@@ -1108,85 +1106,46 @@
     return dir;
   }
   
-  /** Returns a new field instance. 
-   * See {@link #newField(String, String, Field.Store, Field.Index, Field.TermVector)} for more information */
-  public static Field newField(String name, String value, Index index) {
-    return newField(random, name, value, index);
+  public static Field newField(String name, String value, FieldType type) {
+    return newField(random, name, value, type);
   }
   
-  /** Returns a new field instance. 
-   * See {@link #newField(String, String, Field.Store, Field.Index, Field.TermVector)} for more information */
-  public static Field newField(String name, String value, Store store, Index index) {
-    return newField(random, name, value, store, index);
-  }
-  
-  /**
-   * Returns a new Field instance. Use this when the test does not
-   * care about some specific field settings (most tests)
-   * <ul>
-   *  <li>If the store value is set to Store.NO, sometimes the field will be randomly stored.
-   *  <li>More term vector data than you ask for might be indexed, for example if you choose YES
-   *      it might index term vectors with offsets too.
-   * </ul>
-   */
-  public static Field newField(String name, String value, Store store, Index index, TermVector tv) {
-    return newField(random, name, value, store, index, tv);
-  }
-  
-  /** Returns a new field instance, using the specified random. 
-   * See {@link #newField(String, String, Field.Store, Field.Index, Field.TermVector)} for more information */
-  public static Field newField(Random random, String name, String value, Index index) {
-    return newField(random, name, value, Store.NO, index);
-  }
-  
-  /** Returns a new field instance, using the specified random. 
-   * See {@link #newField(String, String, Field.Store, Field.Index, Field.TermVector)} for more information */
-  public static Field newField(Random random, String name, String value, Store store, Index index) {
-    return newField(random, name, value, store, index, TermVector.NO);
-  }
-  
-  /** Returns a new field instance, using the specified random. 
-   * See {@link #newField(String, String, Field.Store, Field.Index, Field.TermVector)} for more information */
-  public static Field newField(Random random, String name, String value, Store store, Index index, TermVector tv) {
-    
+  public static Field newField(Random random, String name, String value, FieldType type) {
     if (usually(random)) {
       // most of the time, don't modify the params
-      return new Field(name, value, store, index, tv);
+      return new Field(name, type, value);
     }
 
-    if (random.nextBoolean()) {
-      // tickle any code still relying on field names being interned:
-      name = new String(name);
+    FieldType newType = new FieldType(type);
+    if (!newType.stored() && random.nextBoolean()) {
+      newType.setStored(true); // randomly store it
     }
 
-    if (!index.isIndexed())
-      return new Field(name, value, store, index, tv);
+    if (newType.indexed() && !newType.storeTermVectors()) {
+      newType.setStoreTermVectors(random.nextBoolean());
+    }
 
-    if (!store.isStored() && random.nextBoolean())
-      store = Store.YES; // randomly store it
+    if (!newType.storeTermVectors()) {
+      if (!newType.storeTermVectorOffsets()) {
+        newType.setStoreTermVectorOffsets(random.nextBoolean());
+      }
+      if (!newType.storeTermVectorPositions()) {
+        newType.setStoreTermVectorPositions(random.nextBoolean());
+      }
+    }
 
-    tv = randomTVSetting(random, tv);
-
-    return new Field(name, value, store, index, tv);
-  }
-
-  static final TermVector tvSettings[] = {
-    TermVector.NO, TermVector.YES, TermVector.WITH_OFFSETS,
-    TermVector.WITH_POSITIONS, TermVector.WITH_POSITIONS_OFFSETS
-  };
-
-  private static TermVector randomTVSetting(Random random, TermVector minimum) {
-    switch(minimum) {
-      case NO: return tvSettings[_TestUtil.nextInt(random, 0, tvSettings.length-1)];
-      case YES: return tvSettings[_TestUtil.nextInt(random, 1, tvSettings.length-1)];
-      case WITH_OFFSETS: return random.nextBoolean() ? TermVector.WITH_OFFSETS
-          : TermVector.WITH_POSITIONS_OFFSETS;
-      case WITH_POSITIONS: return random.nextBoolean() ? TermVector.WITH_POSITIONS
-          : TermVector.WITH_POSITIONS_OFFSETS;
-      default: return TermVector.WITH_POSITIONS_OFFSETS;
+    // TODO: we need to do this, but smarter, ie, most of
+    // the time we set the same value for a given field but
+    // sometimes (rarely) we change it up:
+    /*
+    if (newType.omitNorms()) {
+      newType.setOmitNorms(random.nextBoolean());
     }
+    */
+    
+    return new Field(name, newType, value);
   }
-
+  
   /** return a random Locale from the available locales on the system */
   public static Locale randomLocale(Random random) {
     Locale locales[] = Locale.getAvailableLocales();
Index: lucene/CHANGES.txt
===================================================================
--- lucene/CHANGES.txt	(revision 1158028)
+++ lucene/CHANGES.txt	(working copy)
@@ -251,6 +251,11 @@
 
 * LUCENE-3146: IndexReader.setNorm throws IllegalStateException if the field
   does not store norms. (Shai Erera, Mike McCandless)
+
+* LUCENE-3309: Stored fields no longer record whether they were
+  tokenized or not.  In general you should not rely on stored fields
+  to record any "metadata" from indexing (tokenized, omitNorms,
+  IndexOptions, boost, etc.)  (Mike McCandless)
   
 API Changes
 
