Index: solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java	(revision 1167468)
+++ solr/core/src/test/org/apache/solr/BasicFunctionalityTest.java	(working copy)
@@ -363,27 +363,27 @@
     f = ischema.getField("test_basictv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector());
-    assertTrue(luf.storeTermVectors());
+    assertTrue(luf.fieldType().storeTermVectors());
 
     f = ischema.getField("test_notv");
     luf = f.createField("test", 0f);
     assertTrue(!f.storeTermVector());
-    assertTrue(!luf.storeTermVectors());    
+    assertTrue(!luf.fieldType().storeTermVectors());
 
     f = ischema.getField("test_postv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector() && f.storeTermPositions());
-    assertTrue(luf.storeTermVectorPositions());
+    assertTrue(luf.fieldType().storeTermVectorPositions());
 
     f = ischema.getField("test_offtv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector() && f.storeTermOffsets());
-    assertTrue(luf.storeTermVectorOffsets());
+    assertTrue(luf.fieldType().storeTermVectorOffsets());
 
     f = ischema.getField("test_posofftv");
     luf = f.createField("test", 0f);
     assertTrue(f.storeTermVector() && f.storeTermPositions() && f.storeTermOffsets());
-    assertTrue(luf.storeTermVectorOffsets() && luf.storeTermVectorPositions());
+    assertTrue(luf.fieldType().storeTermVectorOffsets() && luf.fieldType().storeTermVectorPositions());
 
   }
 
Index: solr/core/src/java/org/apache/solr/schema/TrieField.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/TrieField.java	(revision 1167468)
+++ solr/core/src/java/org/apache/solr/schema/TrieField.java	(working copy)
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.schema;
 
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.document.NumericField;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.search.*;
@@ -63,7 +64,7 @@
  * @see org.apache.lucene.search.NumericRangeQuery
  * @since solr 1.4
  */
-public class TrieField extends FieldType {
+public class TrieField extends org.apache.solr.schema.FieldType {
   public static final int DEFAULT_PRECISION_STEP = 8;
 
   protected int precisionStepArg = TrieField.DEFAULT_PRECISION_STEP;  // the one passed in or defaulted
@@ -482,7 +483,7 @@
       return null;
     }
     
-    org.apache.lucene.document.FieldType ft = new org.apache.lucene.document.FieldType();
+    FieldType ft = new FieldType();
     ft.setStored(stored);
     ft.setTokenized(true);
     ft.setIndexed(indexed);
@@ -545,7 +546,7 @@
    * Returns null if no prefix or prefix not needed, or the prefix of the main value of a trie field
    * that indexes multiple precisions per value.
    */
-  public static String getMainValuePrefix(FieldType ft) {
+  public static String getMainValuePrefix(org.apache.solr.schema.FieldType ft) {
     if (ft instanceof TrieDateField)
       ft = ((TrieDateField) ft).wrappedField;
     if (ft instanceof TrieField) {
Index: solr/core/src/java/org/apache/solr/schema/PointType.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/PointType.java	(revision 1167468)
+++ solr/core/src/java/org/apache/solr/schema/PointType.java	(working copy)
@@ -17,6 +17,7 @@
 
 package org.apache.solr.schema;
 
+import org.apache.lucene.document.FieldType;
 import org.apache.lucene.queries.function.ValueSource;
 import org.apache.lucene.queries.function.valuesource.VectorValueSource;
 import org.apache.lucene.index.IndexableField;
@@ -87,7 +88,7 @@
 
     if (field.stored()) {
       String storedVal = externalVal;  // normalize or not?
-      org.apache.lucene.document.FieldType customType = new org.apache.lucene.document.FieldType();
+      FieldType customType = new FieldType();
       customType.setStored(true);
       f[f.length - 1] = createField(field.getName(), storedVal, customType, boost);
     }
Index: solr/core/src/java/org/apache/solr/schema/FieldType.java
===================================================================
--- solr/core/src/java/org/apache/solr/schema/FieldType.java	(revision 1167468)
+++ solr/core/src/java/org/apache/solr/schema/FieldType.java	(working copy)
@@ -492,7 +492,7 @@
   public void setQueryAnalyzer(Analyzer analyzer) {
     SolrException e = new SolrException
       (ErrorCode.SERVER_ERROR,
-       "FieldType: " + this.getClass().getSimpleName() + 
+       "FieldType: " + this.getClass().getSimpleName() +
        " (" + typeName + ") does not support specifying an analyzer");
     SolrException.logOnce(log,null,e);
     throw e;
Index: solr/core/src/java/org/apache/solr/update/DocumentBuilder.java
===================================================================
--- solr/core/src/java/org/apache/solr/update/DocumentBuilder.java	(revision 1167468)
+++ solr/core/src/java/org/apache/solr/update/DocumentBuilder.java	(working copy)
@@ -336,7 +336,7 @@
   public SolrDocument loadStoredFields( SolrDocument doc, Document luceneDoc  )
   {
     for( IndexableField field : luceneDoc) {
-      if( field.stored() ) {
+      if( field.fieldType().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/handler/admin/LukeRequestHandler.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java	(revision 1167468)
+++ solr/core/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java	(working copy)
@@ -168,14 +168,14 @@
   private static String getFieldFlags( IndexableField f )
   {
     StringBuilder flags = new StringBuilder();
-    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( (f != null && f.fieldType().indexed())                     ? FieldFlag.INDEXED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.fieldType().tokenized())                   ? FieldFlag.TOKENIZED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.fieldType().stored())                      ? FieldFlag.STORED.getAbbreviation() : '-' );
     flags.append( (false)                                          ? FieldFlag.MULTI_VALUED.getAbbreviation() : '-' ); // SchemaField Specific
-    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.fieldType().storeTermVectors())            ? FieldFlag.TERM_VECTOR_STORED.getAbbreviation() : '-' );
+    flags.append( (f != null && f.fieldType().storeTermVectorOffsets())   ? FieldFlag.TERM_VECTOR_OFFSET.getAbbreviation() : '-' );
+    flags.append( (f != null && f.fieldType().storeTermVectorPositions()) ? FieldFlag.TERM_VECTOR_POSITION.getAbbreviation() : '-' );
+    flags.append( (f != null && f.fieldType().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
@@ -264,7 +264,7 @@
       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( field.storeTermVectors() ) {
+      if( field.fieldType().storeTermVectors() ) {
         try {
           TermFreqVector v = reader.getTermFreqVector( docId, field.name() );
           if( v != null ) {
Index: solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java
===================================================================
--- solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java	(revision 1167468)
+++ solr/core/src/java/org/apache/solr/handler/component/RealTimeGetComponent.java	(working copy)
@@ -1,4 +1,6 @@
-/**
+package org.apache.solr.handler.component;
+
+/*
  * 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.
@@ -15,8 +17,6 @@
  * limitations under the License.
  */
 
-package org.apache.solr.handler.component;
-
 import org.apache.lucene.document.Document;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.Term;
@@ -189,7 +189,7 @@
     // copy the stored fields only
     Document out = new Document();
     for (IndexableField f : doc.getFields()) {
-      if (f.stored()) {
+      if (f.fieldType().stored()) {
         out.add(f);
       }
     }
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 1167468)
+++ modules/benchmark/src/test/org/apache/lucene/benchmark/byTask/feeds/DocMakerTest.java	(working copy)
@@ -136,28 +136,28 @@
     
     // Don't set anything, use the defaults
     doc = createTestNormsDocument(false, false, false, false);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).fieldType().omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).fieldType().omitNorms());
     
     // Set norms to false
     doc = createTestNormsDocument(true, false, false, false);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).fieldType().omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).fieldType().omitNorms());
     
     // Set norms to true
     doc = createTestNormsDocument(true, true, false, false);
-    assertFalse(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
+    assertFalse(doc.getField(DocMaker.TITLE_FIELD).fieldType().omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).fieldType().omitNorms());
     
     // Set body norms to false
     doc = createTestNormsDocument(false, false, true, false);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
-    assertTrue(doc.getField(DocMaker.BODY_FIELD).omitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).fieldType().omitNorms());
+    assertTrue(doc.getField(DocMaker.BODY_FIELD).fieldType().omitNorms());
     
     // Set body norms to true
     doc = createTestNormsDocument(false, false, true, true);
-    assertTrue(doc.getField(DocMaker.TITLE_FIELD).omitNorms());
-    assertFalse(doc.getField(DocMaker.BODY_FIELD).omitNorms());
+    assertTrue(doc.getField(DocMaker.TITLE_FIELD).fieldType().omitNorms());
+    assertFalse(doc.getField(DocMaker.BODY_FIELD).fieldType().omitNorms());
   }
   
 }
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 1167468)
+++ modules/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ReadTokensTask.java	(working copy)
@@ -69,7 +69,7 @@
     Analyzer analyzer = getRunData().getAnalyzer();
     int tokenCount = 0;
     for(final IndexableField field : fields) {
-      if (!field.tokenized() || field instanceof NumericField) continue;
+      if (!field.fieldType().tokenized() || field instanceof NumericField) continue;
       
       final TokenStream stream;
       final TokenStream streamValue = field.tokenStreamValue();
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 1167468)
+++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexWriter.java	(working copy)
@@ -484,28 +484,28 @@
 
 
       // once fieldSettings, always fieldSettings.
-      if (field.omitNorms()) {
+      if (field.fieldType().omitNorms()) {
         fieldSetting.omitNorms = true;
       }
-      if (field.indexed() ) {
+      if (field.fieldType().indexed() ) {
         fieldSetting.indexed = true;
       }
-      if (field.tokenized()) {
+      if (field.fieldType().tokenized()) {
         fieldSetting.tokenized = true;
       }
-      if (field.stored()) {
+      if (field.fieldType().stored()) {
         fieldSetting.stored = true;
       }
       if (field.binaryValue() != null) {
         fieldSetting.isBinary = true;
       }
-      if (field.storeTermVectors()) {
+      if (field.fieldType().storeTermVectors()) {
         fieldSetting.storeTermVector = true;
       }
-      if (field.storeTermVectorPositions()) {
+      if (field.fieldType().storeTermVectorPositions()) {
         fieldSetting.storePositionWithTermVector = true;
       }
-      if (field.storeTermVectorOffsets()) {
+      if (field.fieldType().storeTermVectorOffsets()) {
         fieldSetting.storeOffsetWithTermVector = true;
       }
     }
@@ -519,12 +519,12 @@
 
       FieldSetting fieldSetting = fieldSettingsByFieldName.get(field.name());
 
-      if (field.indexed()) {
+      if (field.fieldType().indexed()) {
 
         LinkedList<Token> tokens = new LinkedList<Token>();
         tokensByField.put(field, tokens);
 
-        if (field.tokenized()) {
+        if (field.fieldType().tokenized()) {
           final TokenStream tokenStream;
           // todo readerValue(), binaryValue()
           if (field.tokenStreamValue() != null) {
@@ -564,7 +564,7 @@
         }
       }
 
-      if (!field.stored()) {
+      if (!field.fieldType().stored()) {
         //it.remove();
       }
     }
@@ -610,7 +610,7 @@
           termDocumentInformationFactory.payloads.add(null);
         }
 
-        if (eField_Tokens.getKey().storeTermVectorOffsets()) {
+        if (eField_Tokens.getKey().fieldType().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().storeTermVectorOffsets()) {
+      if (eField_Tokens.getKey().fieldType().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 1167468)
+++ lucene/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndex.java	(working copy)
@@ -199,7 +199,7 @@
         documentsByNumber[i] = document;
         for (IndexableField field : document.getDocument()) {
           if (fields == null || fields.contains(field.name())) {
-            if (field.storeTermVectors()) {
+            if (field.fieldType().storeTermVectors()) {
               if (document.getVectorSpace() == null) {
                 document.setVectorSpace(new HashMap<String, List<InstantiatedTermDocumentInformation>>());
               }
@@ -291,7 +291,7 @@
         continue; // deleted
       }
       for (IndexableField field : document.getDocument()) {
-        if (field.storeTermVectors() && field.storeTermVectorOffsets()) {
+        if (field.fieldType().storeTermVectors() && field.fieldType().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/misc/src/test/org/apache/lucene/index/TestTermVectorAccessor.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestTermVectorAccessor.java	(revision 1167468)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestTermVectorAccessor.java	(working copy)
@@ -28,9 +28,7 @@
     Directory dir = newDirectory();
     IndexWriter iw = new IndexWriter(dir, newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)));
 
-    Document doc;
-
-    doc = new Document();
+    Document doc = new Document();
     FieldType customType = new FieldType(TextField.TYPE_UNSTORED);
     customType.setStoreTermVectors(true);
     customType.setStoreTermVectorPositions(true);
Index: lucene/contrib/misc/src/test/org/apache/lucene/index/TestNRTManager.java
===================================================================
--- lucene/contrib/misc/src/test/org/apache/lucene/index/TestNRTManager.java	(revision 1167468)
+++ lucene/contrib/misc/src/test/org/apache/lucene/index/TestNRTManager.java	(working copy)
@@ -82,7 +82,7 @@
       Field field1 = (Field) f;
       
       Field field2 = new Field(field1.name(),
-                              ((Field) f).getFieldType(),
+                              ((Field) f).fieldType(),
                                field1.stringValue());
       doc2.add(field2);
     }
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 1167468)
+++ lucene/contrib/highlighter/src/test/org/apache/lucene/search/highlight/HighlighterPhraseTest.java	(working copy)
@@ -26,9 +26,9 @@
 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
 import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.document.FieldType;
 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.IndexReader;
Index: lucene/MIGRATE.txt
===================================================================
--- lucene/MIGRATE.txt	(revision 1167468)
+++ lucene/MIGRATE.txt	(working copy)
@@ -410,14 +410,14 @@
 
 
 
-* LUCENE-2308: Separate FieldType from Field instances
+* LUCENE-2308: Separate IndexableFieldType from Field instances
 
 With this change, the indexing details (indexed, tokenized, norms,
 indexOptions, stored, etc.) are moved into a separate FieldType
 instance (rather than being stored directly on the Field).
 
-This means you can create the FieldType instance once, up front, for a
-given field, and then re-use that instance whenever you instantiate
+This means you can create the IndexableFieldType instance once, up front,
+for a given field, and then re-use that instance whenever you instantiate
 the Field.
 
 Certain field types are pre-defined since they are common cases:
@@ -454,9 +454,7 @@
   t.setOmitNorms(true);
   t.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
 
-FieldType has a freeze() method to prevent further changes.  Note that
-once a FieldType is bound to a Field, it's frozen, to help prevent
-confusing bugs.
+FieldType has a freeze() method to prevent further changes.
 
 When migrating from the 3.x API, if you did this before:
 
Index: lucene/src/test/org/apache/lucene/search/TestTermVectors.java
===================================================================
--- lucene/src/test/org/apache/lucene/search/TestTermVectors.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/search/TestTermVectors.java	(working copy)
@@ -110,7 +110,7 @@
   public void testTermVectorsFieldOrder() throws IOException {
     Directory dir = newDirectory();
     RandomIndexWriter writer = new RandomIndexWriter(random, dir, new MockAnalyzer(random, MockTokenizer.SIMPLE, true));
-    Document doc = new Document();;
+    Document doc = new Document();
     FieldType ft = new FieldType(TextField.TYPE_STORED);
     ft.setStoreTermVectors(true);
     ft.setStoreTermVectorOffsets(true);
Index: lucene/src/test/org/apache/lucene/index/TestIndexableField.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexableField.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestIndexableField.java	(working copy)
@@ -44,7 +44,48 @@
   private class MyField implements IndexableField {
 
     private final int counter;
+    private final IndexableFieldType fieldType = new IndexableFieldType() {
+      @Override
+      public boolean indexed() {
+        return (counter % 10) != 3;
+      }
 
+      @Override
+      public boolean stored() {
+        return (counter & 1) == 0 || (counter % 10) == 3;
+      }
+
+      @Override
+      public boolean tokenized() {
+        return true;
+      }
+
+      @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;
+      }
+
+      @Override
+      public boolean omitNorms() {
+        return false;
+      }
+
+      @Override
+      public FieldInfo.IndexOptions indexOptions() {
+        return FieldInfo.IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
+      }
+    };
+
     public MyField(int counter) {
       this.counter = counter;
     }
@@ -58,11 +99,6 @@
     public float boost() {
       return 1.0f + random.nextFloat();
     }
-  
-    @Override
-    public boolean stored() {
-      return (counter & 1) == 0 || (counter % 10) == 3;
-    }
 
     @Override
     public BytesRef binaryValue() {
@@ -121,42 +157,11 @@
       return counter;
     }
 
-    // If this returns true then we index this field:
     @Override
-    public boolean indexed() {
-      return (counter % 10) != 3;
+    public IndexableFieldType fieldType() {
+      return fieldType;
     }
 
-    @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() {
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterExceptions.java	(working copy)
@@ -1257,7 +1257,7 @@
           // random TV
           try {
             w.addDocument(doc);
-            assertFalse(field.storeTermVectors());
+            assertFalse(field.fieldType().storeTermVectors());
           } catch (RuntimeException e) {
             assertTrue(e.getMessage().startsWith(FailOnTermVectors.EXC_MSG));
           }
@@ -1278,7 +1278,7 @@
           // random TV
           try {
             w.addDocument(doc);
-            assertFalse(field.storeTermVectors());
+            assertFalse(field.fieldType().storeTermVectors());
           } catch (RuntimeException e) {
             assertTrue(e.getMessage().startsWith(FailOnTermVectors.EXC_MSG));
           }
Index: lucene/src/test/org/apache/lucene/index/TestDocumentWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestDocumentWriter.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestDocumentWriter.java	(working copy)
@@ -77,12 +77,12 @@
     IndexableField [] fields = doc.getFields("textField2");
     assertTrue(fields != null && fields.length == 1);
     assertTrue(fields[0].stringValue().equals(DocHelper.FIELD_2_TEXT));
-    assertTrue(fields[0].storeTermVectors());
+    assertTrue(fields[0].fieldType().storeTermVectors());
 
     fields = doc.getFields("textField1");
     assertTrue(fields != null && fields.length == 1);
     assertTrue(fields[0].stringValue().equals(DocHelper.FIELD_1_TEXT));
-    assertFalse(fields[0].storeTermVectors());
+    assertFalse(fields[0].fieldType().storeTermVectors());
 
     fields = doc.getFields("keyField");
     assertTrue(fields != null && fields.length == 1);
Index: lucene/src/test/org/apache/lucene/index/TestTermVectorsWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestTermVectorsWriter.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestTermVectorsWriter.java	(working copy)
@@ -391,8 +391,6 @@
             new SerialMergeScheduler()).setMergePolicy(new LogDocMergePolicy()));
 
     Document document = new Document();
-
-    document = new Document();
     FieldType customType = new FieldType();
     customType.setStored(true);
 
Index: lucene/src/test/org/apache/lucene/index/TestFieldsReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestFieldsReader.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestFieldsReader.java	(working copy)
@@ -77,28 +77,28 @@
 
     Field field = (Field) doc.getField(DocHelper.TEXT_FIELD_2_KEY);
     assertTrue(field != null);
-    assertTrue(field.storeTermVectors() == true);
+    assertTrue(field.fieldType().storeTermVectors());
 
-    assertTrue(field.storeTermVectorOffsets() == true);
-    assertTrue(field.storeTermVectorPositions() == true);
-    assertTrue(field.omitNorms() == false);
-    assertTrue(field.indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
+    assertTrue(field.fieldType().storeTermVectorOffsets());
+    assertTrue(field.fieldType().storeTermVectorPositions());
+    assertFalse(field.fieldType().omitNorms());
+    assertTrue(field.fieldType().indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
 
     field = (Field) doc.getField(DocHelper.TEXT_FIELD_3_KEY);
     assertTrue(field != null);
-    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);
+    assertFalse(field.fieldType().storeTermVectors());
+    assertFalse(field.fieldType().storeTermVectorOffsets());
+    assertFalse(field.fieldType().storeTermVectorPositions());
+    assertTrue(field.fieldType().omitNorms());
+    assertTrue(field.fieldType().indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS);
 
     field = (Field) doc.getField(DocHelper.NO_TF_KEY);
     assertTrue(field != null);
-    assertTrue(field.storeTermVectors() == false);
-    assertTrue(field.storeTermVectorOffsets() == false);
-    assertTrue(field.storeTermVectorPositions() == false);
-    assertTrue(field.omitNorms() == false);
-    assertTrue(field.indexOptions() == IndexOptions.DOCS_ONLY);
+    assertFalse(field.fieldType().storeTermVectors());
+    assertFalse(field.fieldType().storeTermVectorOffsets());
+    assertFalse(field.fieldType().storeTermVectorPositions());
+    assertFalse(field.fieldType().omitNorms());
+    assertTrue(field.fieldType().indexOptions() == IndexOptions.DOCS_ONLY);
 
     DocumentStoredFieldVisitor visitor = new DocumentStoredFieldVisitor(DocHelper.TEXT_FIELD_3_KEY);
     reader.document(0, visitor);
@@ -308,8 +308,8 @@
     w.addDocument(doc);
     IndexReader r = w.getReader();
     w.close();
-    assertFalse(r.document(0).getField("field").indexed());
-    assertTrue(r.document(0).getField("field2").indexed());
+    assertFalse(r.document(0).getField("field").fieldType().indexed());
+    assertTrue(r.document(0).getField("field2").fieldType().indexed());
     r.close();
     dir.close();
   }
Index: lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriterMerging.java	(working copy)
@@ -181,8 +181,6 @@
 
     Document document = new Document();
 
-    document = new Document();
-
     FieldType customType = new FieldType();
     customType.setStored(true);
 
@@ -237,8 +235,6 @@
 
     writer.setInfoStream(VERBOSE ? System.out : null);
 
-    Document document = new Document();
-
     FieldType customType = new FieldType();
     customType.setStored(true);
 
@@ -248,7 +244,7 @@
     customType1.setStoreTermVectorPositions(true);
     customType1.setStoreTermVectorOffsets(true);
     
-    document = new Document();
+    Document document = new Document();
     Field storedField = newField("stored", "stored", customType);
     document.add(storedField);
     Field termVectorField = newField("termVector", "termVector", customType1);
Index: lucene/src/test/org/apache/lucene/index/TestSegmentReader.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestSegmentReader.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestSegmentReader.java	(working copy)
@@ -175,8 +175,8 @@
         // test omit norms
     for (int i=0; i<DocHelper.fields.length; i++) {
       IndexableField f = DocHelper.fields[i];
-      if (f.indexed()) {
-        assertEquals(reader.hasNorms(f.name()), !f.omitNorms());
+      if (f.fieldType().indexed()) {
+        assertEquals(reader.hasNorms(f.name()), !f.fieldType().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/TestConsistentFieldNumbers.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestConsistentFieldNumbers.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/index/TestConsistentFieldNumbers.java	(working copy)
@@ -303,10 +303,10 @@
 
       for (FieldInfo fi : fis) {
         Field expected = getField(Integer.parseInt(fi.name));
-        assertEquals(expected.indexed(), fi.isIndexed);
-        assertEquals(expected.storeTermVectors(), fi.storeTermVector);
-        assertEquals(expected.storeTermVectorPositions(), fi.storePositionWithTermVector);
-        assertEquals(expected.storeTermVectorOffsets(), fi.storeOffsetWithTermVector);
+        assertEquals(expected.fieldType().indexed(), fi.isIndexed);
+        assertEquals(expected.fieldType().storeTermVectors(), fi.storeTermVector);
+        assertEquals(expected.fieldType().storeTermVectorPositions(), fi.storePositionWithTermVector);
+        assertEquals(expected.fieldType().storeTermVectorOffsets(), fi.storeOffsetWithTermVector);
       }
     }
 
Index: lucene/src/test/org/apache/lucene/document/TestDocument.java
===================================================================
--- lucene/src/test/org/apache/lucene/document/TestDocument.java	(revision 1167468)
+++ lucene/src/test/org/apache/lucene/document/TestDocument.java	(working copy)
@@ -52,9 +52,9 @@
     assertEquals(2, doc.getFields().size());
     
     assertTrue(binaryFld.binaryValue() != null);
-    assertTrue(binaryFld.stored());
-    assertFalse(binaryFld.indexed());
-    assertFalse(binaryFld.tokenized());
+    assertTrue(binaryFld.fieldType().stored());
+    assertFalse(binaryFld.fieldType().indexed());
+    assertFalse(binaryFld.fieldType().tokenized());
     
     String binaryTest = doc.getBinaryValue("binary").utf8ToString();
     assertTrue(binaryTest.equals(binaryVal));
Index: lucene/src/java/org/apache/lucene/analysis/Analyzer.java
===================================================================
--- lucene/src/java/org/apache/lucene/analysis/Analyzer.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/analysis/Analyzer.java	(working copy)
@@ -138,7 +138,7 @@
    * @return offset gap, added to the next token emitted from {@link #tokenStream(String,Reader)}
    */
   public int getOffsetGap(IndexableField field) {
-    if (field.tokenized()) {
+    if (field.fieldType().tokenized()) {
       return 1;
     } else {
       return 0;
Index: lucene/src/java/org/apache/lucene/index/DocInverterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocInverterPerField.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/DocInverterPerField.java	(working copy)
@@ -74,7 +74,7 @@
       // TODO FI: this should be "genericized" to querying
       // consumer if it wants to see this particular field
       // tokenized.
-      if (field.indexed() && doInvert) {
+      if (field.fieldType().indexed() && doInvert) {
         
         if (i > 0)
           fieldState.position += docState.analyzer == null ? 0 : docState.analyzer.getPositionIncrementGap(fieldInfo.name);
@@ -83,7 +83,7 @@
         // outside of indexer -- field should simply give us
         // a TokenStream, even for multi-valued fields
 
-        if (!field.tokenized()) {		  // un-tokenized field
+        if (!field.fieldType().tokenized()) {		  // un-tokenized field
           final String stringValue = field.stringValue();
           assert stringValue != null;
           final int valueLength = stringValue.length();
Index: lucene/src/java/org/apache/lucene/index/IndexableFieldType.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/IndexableFieldType.java	(revision 1163903)
+++ lucene/src/java/org/apache/lucene/index/IndexableFieldType.java	(working copy)
@@ -1,4 +1,4 @@
-package org.apache.lucene.document;
+package org.apache.lucene.index;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -19,157 +19,30 @@
 
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 
-public class FieldType {
+public interface IndexableFieldType {
 
-  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 frozen;
+  /* True if this field should be indexed (inverted) */
+  public boolean indexed();
 
-  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();
-    // Do not copy frozen!
-  }
-  
-  public FieldType() {
-  }
+  /* True if the field's value should be stored */
+  public boolean stored();
 
-  private void checkIfFrozen() {
-    if (frozen) {
-      throw new IllegalStateException();
-    }
-  }
+  /* True if this field's value should be analyzed */
+  public boolean tokenized();
 
-  /** Prevents future changes.  Note that when a FieldType
-   *  is first bound to a Field instance, it is frozen. */
-  public void freeze() {
-    this.frozen = true;
-  }
-  
-  public boolean indexed() {
-    return this.indexed;
-  }
-  
-  public void setIndexed(boolean value) {
-    checkIfFrozen();
-    this.indexed = value;
-  }
+  /* True if term vectors should be indexed */
+  public boolean storeTermVectors();
 
-  public boolean stored() {
-    return this.stored;
-  }
-  
-  public void setStored(boolean value) {
-    checkIfFrozen();
-    this.stored = value;
-  }
+  /* True if term vector offsets should be indexed */
+  public boolean storeTermVectorOffsets();
 
-  public boolean tokenized() {
-    return this.tokenized;
-  }
-  
-  public void setTokenized(boolean value) {
-    checkIfFrozen();
-    this.tokenized = value;
-  }
+  /* True if term vector positions should be indexed */
+  public boolean storeTermVectorPositions();
 
-  public boolean storeTermVectors() {
-    return this.storeTermVectors;
-  }
-  
-  public void setStoreTermVectors(boolean value) {
-    checkIfFrozen();
-    this.storeTermVectors = value;
-  }
+  /* True if norms should not be indexed */
+  public boolean omitNorms();
 
-  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;
-  }
-
-  /** 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);
-    }
-    
-    return result.toString();
-  }
+  /* {@link IndexOptions}, describing what should be
+   * recorded into the inverted index */
+  public IndexOptions indexOptions();
 }

Property changes on: lucene/src/java/org/apache/lucene/index/IndexableFieldType.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 1167468)
+++ lucene/src/java/org/apache/lucene/index/FieldInfos.java	(working copy)
@@ -456,6 +456,12 @@
                                storeOffsetWithTermVector, omitNorms, storePayloads, indexOptions, docValues);
   }
 
+  synchronized public FieldInfo addOrUpdate(String name, IndexableFieldType fieldType, boolean scorePayloads, ValueType docValues) {
+    return addOrUpdateInternal(name, -1, fieldType.indexed(), fieldType.storeTermVectors(),
+        fieldType.storeTermVectorPositions(), fieldType.storeTermVectorOffsets(), fieldType.omitNorms(), scorePayloads,
+        fieldType.indexOptions(), docValues);
+  }
+
   synchronized private FieldInfo addOrUpdateInternal(String name, int preferredFieldNumber, boolean isIndexed,
       boolean storeTermVector, boolean storePositionWithTermVector, boolean storeOffsetWithTermVector,
       boolean omitNorms, boolean storePayloads, IndexOptions indexOptions, ValueType docValues) {
Index: lucene/src/java/org/apache/lucene/index/FieldsWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FieldsWriter.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/FieldsWriter.java	(working copy)
@@ -217,14 +217,14 @@
 
     int storedCount = 0;
     for (IndexableField field : doc) {
-      if (field.stored()) {
+      if (field.fieldType().stored()) {
         storedCount++;
       }
     }
     fieldsStream.writeVInt(storedCount);
 
     for (IndexableField field : doc) {
-      if (field.stored()) {
+      if (field.fieldType().stored()) {
         writeField(fieldInfos.fieldNumber(field.name()), field);
       }
     }
Index: lucene/src/java/org/apache/lucene/index/IndexableField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/IndexableField.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/IndexableField.java	(working copy)
@@ -21,7 +21,6 @@
 
 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;
@@ -48,9 +47,6 @@
   /** 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();
 
@@ -74,27 +70,12 @@
   /* 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();
+  /**
+   * Returns the IndexableFieldType describing the properties of this field
+   *
+   * @return IndexableFieldType for this field
+   */
+  public IndexableFieldType fieldType();
   
   /* Non-null if doc values should be indexed */
   public PerDocFieldValues docValues();
Index: lucene/src/java/org/apache/lucene/index/CheckIndex.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/CheckIndex.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/CheckIndex.java	(working copy)
@@ -189,7 +189,7 @@
 
       /** True if at least one of the fields in this segment
        *  has position data
-       *  @see FieldType#setIndexOptions(org.apache.lucene.index.FieldInfo.IndexOptions) */
+       *  @see IndexableFieldType#setIndexOptions(org.apache.lucene.index.FieldInfo.IndexOptions) */
       public boolean hasProx;
 
       /** Map that includes certain
Index: lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/DocFieldProcessor.java	(working copy)
@@ -223,9 +223,7 @@
         // 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.indexed(), field.storeTermVectors(),
-                                              field.storeTermVectorPositions(), field.storeTermVectorOffsets(),
-                                              field.omitNorms(), false, field.indexOptions(), field.docValuesType());
+        FieldInfo fi = fieldInfos.addOrUpdate(fieldName, field.fieldType(), false, field.docValuesType());
 
         fp = new DocFieldProcessorPerField(this, fi);
         fp.next = fieldHash[hashPos];
@@ -236,9 +234,7 @@
           rehash();
         }
       } else {
-        fieldInfos.addOrUpdate(fp.fieldInfo.name, field.indexed(), field.storeTermVectors(),
-                               field.storeTermVectorPositions(), field.storeTermVectorOffsets(),
-                               field.omitNorms(), false, field.indexOptions(), field.docValuesType());
+        fieldInfos.addOrUpdate(fp.fieldInfo.name, field.fieldType(), false, field.docValuesType());
       }
 
       if (thisFieldGen != fp.lastGen) {
@@ -259,7 +255,7 @@
 
       fp.addField(field);
 
-      if (field.stored()) {
+      if (field.fieldType().stored()) {
         fieldsWriter.addField(field, fp.fieldInfo);
       }
       final PerDocFieldValues docValues = field.docValues();
Index: lucene/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/FreqProxTermsWriterPerField.java	(working copy)
@@ -83,7 +83,7 @@
   @Override
   boolean start(IndexableField[] fields, int count) {
     for(int i=0;i<count;i++) {
-      if (fields[i].indexed()) {
+      if (fields[i].fieldType().indexed()) {
         return true;
       }
     }
Index: lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/index/TermVectorsTermsWriterPerField.java	(working copy)
@@ -61,10 +61,10 @@
 
     for(int i=0;i<count;i++) {
       IndexableField field = fields[i];
-      if (field.indexed() && field.storeTermVectors()) {
+      if (field.fieldType().indexed() && field.fieldType().storeTermVectors()) {
         doVectors = true;
-        doVectorPositions |= field.storeTermVectorPositions();
-        doVectorOffsets |= field.storeTermVectorOffsets();
+        doVectorPositions |= field.fieldType().storeTermVectorPositions();
+        doVectorOffsets |= field.fieldType().storeTermVectorOffsets();
       }
     }
 
Index: lucene/src/java/org/apache/lucene/document/IndexDocValuesField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/IndexDocValuesField.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/document/IndexDocValuesField.java	(working copy)
@@ -20,6 +20,7 @@
 import java.util.Comparator;
 
 import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.index.IndexableFieldType;
 import org.apache.lucene.index.values.PerDocFieldValues;
 import org.apache.lucene.index.values.ValueType;
 import org.apache.lucene.util.BytesRef;
@@ -84,11 +85,11 @@
     this(name, new FieldType());
   }
 
-  public IndexDocValuesField(String name, FieldType type) {
+  public IndexDocValuesField(String name, IndexableFieldType type) {
     this(name, type, null);
   }
 
-  public IndexDocValuesField(String name, FieldType type, String value) {
+  public IndexDocValuesField(String name, IndexableFieldType type, String value) {
     super(name, type);
     fieldsData = value;
   }
@@ -356,7 +357,7 @@
     if (field instanceof IndexDocValuesField) {
       return (IndexDocValuesField) field;
     }
-    final IndexDocValuesField valField = new IndexDocValuesField(field.name(), field.getFieldType(), field.stringValue());
+    final IndexDocValuesField valField = new IndexDocValuesField(field.name(), field.fieldType(), field.stringValue());
     switch (type) {
     case BYTES_FIXED_DEREF:
     case BYTES_FIXED_SORTED:
Index: lucene/src/java/org/apache/lucene/document/Field.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/Field.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/document/Field.java	(working copy)
@@ -20,7 +20,7 @@
 import java.io.Reader;
 
 import org.apache.lucene.analysis.TokenStream;
-import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.IndexableFieldType;
 import org.apache.lucene.index.IndexableField;
 import org.apache.lucene.index.values.PerDocFieldValues;
 import org.apache.lucene.index.values.ValueType;
@@ -32,11 +32,14 @@
  * 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.
+ * <p/>
+ * Note, Field instances are instantiated with a {@link IndexableFieldType}.  Making changes
+ * to the state of the FieldType will impact any Field it is used in, therefore
+ * it is strongly recommended that no changes are made after Field instantiation.
  */
-
 public class Field implements IndexableField {
   
-  protected FieldType type;
+  protected IndexableFieldType type;
   protected String name = "body";
   // the data object for all different kind of field values
   protected Object fieldsData;
@@ -47,13 +50,12 @@
   
   protected float boost = 1.0f;
 
-  public Field(String name, FieldType type) {
+  public Field(String name, IndexableFieldType type) {
     this.name = name;
     this.type = type;
-    type.freeze();
   }
   
-  public Field(String name, FieldType type, Reader reader) {
+  public Field(String name, IndexableFieldType type, Reader reader) {
     if (name == null) {
       throw new NullPointerException("name cannot be null");
     }
@@ -64,10 +66,9 @@
     this.name = name;
     this.fieldsData = reader;
     this.type = type;
-    type.freeze();
   }
   
-  public Field(String name, FieldType type, TokenStream tokenStream) {
+  public Field(String name, IndexableFieldType type, TokenStream tokenStream) {
     if (name == null) {
       throw new NullPointerException("name cannot be null");
     }
@@ -79,28 +80,25 @@
     this.fieldsData = null;
     this.tokenStream = tokenStream;
     this.type = type;
-    type.freeze();
   }
   
-  public Field(String name, FieldType type, byte[] value) {
+  public Field(String name, IndexableFieldType type, byte[] value) {
     this(name, type, value, 0, value.length);
   }
 
-  public Field(String name, FieldType type, byte[] value, int offset, int length) {
+  public Field(String name, IndexableFieldType type, byte[] value, int offset, int length) {
     this.fieldsData = new BytesRef(value, offset, length);
     this.type = type;
     this.name = name;
-    type.freeze();
   }
 
-  public Field(String name, FieldType type, BytesRef bytes) {
+  public Field(String name, IndexableFieldType type, BytesRef bytes) {
     this.fieldsData = bytes;
     this.type = type;
     this.name = name;
-    type.freeze();
   }
   
-  public Field(String name, FieldType type, String value) {
+  public Field(String name, IndexableFieldType type, String value) {
     if (name == null) {
       throw new IllegalArgumentException("name cannot be null");
     }
@@ -119,7 +117,6 @@
     this.type = type;
     this.name = name;
     this.fieldsData = value;
-    type.freeze();
   }
 
   /**
@@ -181,7 +178,7 @@
       throw new IllegalArgumentException(
           "cannot set a Reader value on a binary field");
     }
-    if (stored()) {
+    if (type.stored()) {
       throw new IllegalArgumentException(
           "cannot set a Reader value on a stored field");
     }
@@ -206,7 +203,7 @@
    * values from stringValue() or getBinaryValue()
    */
   public void setTokenStream(TokenStream tokenStream) {
-    if (!indexed() || !tokenized()) {
+    if (!type.indexed() || !type.tokenized()) {
       throw new IllegalArgumentException(
           "cannot set token stream on non indexed and tokenized field");
     }
@@ -259,44 +256,12 @@
     }
   }
   
-  /** methods from inner FieldType */
+  /** methods from inner IndexableFieldType */
   
   public boolean isBinary() {
     return fieldsData instanceof BytesRef;
   }
   
-  public boolean stored() {
-    return type.stored();
-  }
-  
-  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() {
@@ -329,7 +294,7 @@
   }
 
   /** Returns FieldType for this field. */
-  public FieldType getFieldType() {
+  public IndexableFieldType fieldType() {
     return type;
   }
 }
Index: lucene/src/java/org/apache/lucene/document/FieldType.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/FieldType.java	(revision 1166160)
+++ lucene/src/java/org/apache/lucene/document/FieldType.java	(working copy)
@@ -18,8 +18,9 @@
  */
 
 import org.apache.lucene.index.FieldInfo.IndexOptions;
+import org.apache.lucene.index.IndexableFieldType;
 
-public class FieldType {
+public class FieldType implements IndexableFieldType {
 
   private boolean indexed;
   private boolean stored;
@@ -31,7 +32,7 @@
   private IndexOptions indexOptions = IndexOptions.DOCS_AND_FREQS_AND_POSITIONS;
   private boolean frozen;
 
-  public FieldType(FieldType ref) {
+  public FieldType(IndexableFieldType ref) {
     this.indexed = ref.indexed();
     this.stored = ref.stored();
     this.tokenized = ref.tokenized();
@@ -52,8 +53,11 @@
     }
   }
 
-  /** Prevents future changes.  Note that when a FieldType
-   *  is first bound to a Field instance, it is frozen. */
+  /**
+   * Prevents future changes. Note, it is recommended that this is called once
+   * the FieldTypes's properties have been set, to prevent unintential state
+   * changes.
+   */
   public void freeze() {
     this.frozen = true;
   }
Index: lucene/src/java/org/apache/lucene/document/NumericField.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/NumericField.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/document/NumericField.java	(working copy)
@@ -104,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,FieldType)} 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}.
@@ -238,7 +238,7 @@
   
   /** Returns a {@link NumericTokenStream} for indexing the numeric value. */
   public TokenStream tokenStreamValue() {
-    if (!indexed()) return null;
+    if (!type.indexed()) return null;
     if (numericTS == null) {
       // lazy init the TokenStream as it is heavy to instantiate
       // (attributes,...),
Index: lucene/src/java/org/apache/lucene/document/Document.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/Document.java	(revision 1167468)
+++ lucene/src/java/org/apache/lucene/document/Document.java	(working copy)
@@ -28,12 +28,12 @@
 /** 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 IndexableField#stored() stored} with the document, in which
+ * A field may be {@link org.apache.lucene.index.IndexableFieldType#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 IndexableField#stored() stored} are
+ * <p>Note that fields which are <i>not</i> {@link org.apache.lucene.index.IndexableFieldType#stored() stored} are
  * <i>not</i> available in documents retrieved from the index, e.g. with {@link
  * ScoreDoc#doc} or {@link IndexReader#document(int)}.
  */
Index: lucene/src/test-framework/org/apache/lucene/index/DocHelper.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/index/DocHelper.java	(revision 1167468)
+++ lucene/src/test-framework/org/apache/lucene/index/DocHelper.java	(working copy)
@@ -205,15 +205,15 @@
     for (int i=0; i<fields.length; i++) {
       IndexableField f = fields[i];
       add(all,f);
-      if (f.indexed()) add(indexed,f);
+      if (f.fieldType().indexed()) add(indexed,f);
       else add(unindexed,f);
-      if (f.storeTermVectors()) add(termvector,f);
-      if (f.indexed() && !f.storeTermVectors()) add(notermvector,f);
-      if (f.stored()) add(stored,f);
+      if (f.fieldType().storeTermVectors()) add(termvector,f);
+      if (f.fieldType().indexed() && !f.fieldType().storeTermVectors()) add(notermvector,f);
+      if (f.fieldType().stored()) add(stored,f);
       else add(unstored,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.fieldType().indexOptions() == IndexOptions.DOCS_ONLY) add(noTf,f);
+      if (f.fieldType().omitNorms()) add(noNorms,f);
+      if (f.fieldType().indexOptions() == IndexOptions.DOCS_ONLY) add(noTf,f);
       //if (f.isLazy()) add(lazy, f);
     }
   }
Index: lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java
===================================================================
--- lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java	(revision 1167468)
+++ lucene/src/test-framework/org/apache/lucene/util/_TestUtil.java	(working copy)
@@ -433,8 +433,7 @@
   /** Adds field info for a Document. */
   public static void add(Document doc, FieldInfos fieldInfos) {
     for (IndexableField field : doc) {
-      fieldInfos.addOrUpdate(field.name(), field.indexed(), field.storeTermVectors(), field.storeTermVectorPositions(),
-              field.storeTermVectorOffsets(), field.omitNorms(), false, field.indexOptions(), field.docValuesType());
+      fieldInfos.addOrUpdate(field.name(), field.fieldType(), false, field.docValuesType());
     }
   }
   
@@ -515,7 +514,7 @@
       Field field1 = (Field) f;
       
       Field field2 = new Field(field1.name(),
-                               field1.getFieldType(),
+                               field1.fieldType(),
                                field1.stringValue()
                                );
       doc2.add(field2);
