Index: src/java/org/apache/lucene/index/FieldsReader.java =================================================================== --- src/java/org/apache/lucene/index/FieldsReader.java (revision 962932) +++ src/java/org/apache/lucene/index/FieldsReader.java (working copy) @@ -352,9 +352,10 @@ final byte[] b = new byte[toRead]; fieldsStream.readBytes(b, 0, b.length); if (compressed) { - doc.add(new Field(fi.name, uncompress(b), Field.Store.YES)); + byte[] ucb = uncompress(b); + doc.add(new Field(fi.name, false, ucb, 0, ucb.length, Field.Store.YES)); } else { - doc.add(new Field(fi.name, b, Field.Store.YES)); + doc.add(new Field(fi.name, false, b, 0, b.length, Field.Store.YES)); } } else { Field.Store store = Field.Store.YES; @@ -377,7 +378,7 @@ f.setOmitNorms(fi.omitNorms); } else { f = new Field(fi.name, // name - false, + false, fieldsStream.readString(), // read value store, index, @@ -394,19 +395,20 @@ // 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, boolean compressed) throws IOException { - int size = fieldsStream.readVInt(), bytesize = binary || compressed ? size : 2*size; + int fieldsize = fieldsStream.readVInt(), bytesize = binary || compressed ? fieldsize : 2*fieldsize; 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, Field.Store.YES)); - return size; + doc.add(new Field(fi.name, false, sizebytes, 0, sizebytes.length, Field.Store.YES)); + return fieldsize; } /** * A Lazy implementation of Fieldable that differs loading of fields until asked for, instead of when the Document is * loaded. + * This is a private class, all possible uses provide a name string that is already interned. */ private class LazyField extends AbstractField implements Fieldable { private int toRead; @@ -415,7 +417,7 @@ private boolean isCompressed; public LazyField(String name, Field.Store store, int toRead, long pointer, boolean isBinary, boolean isCompressed) { - super(name, store, Field.Index.NO, Field.TermVector.NO); + super(name, false, store, Field.Index.NO, Field.TermVector.NO); this.toRead = toRead; this.pointer = pointer; this.isBinary = isBinary; @@ -426,7 +428,7 @@ } public LazyField(String name, Field.Store store, Field.Index index, Field.TermVector termVector, int toRead, long pointer, boolean isBinary, boolean isCompressed) { - super(name, store, index, termVector); + super(name, false, store, index, termVector); this.toRead = toRead; this.pointer = pointer; this.isBinary = isBinary; Index: src/java/org/apache/lucene/document/NumericField.java =================================================================== --- src/java/org/apache/lucene/document/NumericField.java (revision 962932) +++ src/java/org/apache/lucene/document/NumericField.java (working copy) @@ -153,7 +153,7 @@ * @param name the field name */ public NumericField(String name) { - this(name, NumericUtils.PRECISION_STEP_DEFAULT, Field.Store.NO, true); + this(name, true, NumericUtils.PRECISION_STEP_DEFAULT, Field.Store.NO, true); } /** @@ -167,7 +167,7 @@ * @param index if the field should be indexed using {@link NumericTokenStream} */ public NumericField(String name, Field.Store store, boolean index) { - this(name, NumericUtils.PRECISION_STEP_DEFAULT, store, index); + this(name, true, NumericUtils.PRECISION_STEP_DEFAULT, store, index); } /** @@ -180,22 +180,35 @@ * @param precisionStep the used precision step */ public NumericField(String name, int precisionStep) { - this(name, precisionStep, Field.Store.NO, true); + this(name, true, precisionStep, Field.Store.NO, true); } /** + * @see #NumericField(String, boolean, int, org.apache.lucene.document.Field.Store, boolean) + * @param name the field name + * @param precisionStep the used precision step + * @param store if the field should be stored in plain text form + * (according to toString(value) of the used data type) + * @param index if the field should be indexed using {@link NumericTokenStream} + */ + public NumericField(String name, int precisionStep, Field.Store store, boolean index) { + this(name, true, precisionStep, store, index); + } + + /** * Creates a field for numeric values with the specified * precisionStep. The instance is not yet initialized with * a numeric value, before indexing a document containing this field, * set a value using the various set???Value() methods. * @param name the field name + * @param internName Whether to .intern() name or not * @param precisionStep the used precision step * @param store if the field should be stored in plain text form * (according to toString(value) of the used data type) * @param index if the field should be 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, boolean internName, int precisionStep, Field.Store store, boolean index) { + super(name, internName, store, index ? Field.Index.ANALYZED_NO_NORMS : Field.Index.NO, Field.TermVector.NO); setOmitTermFreqAndPositions(true); tokenStream = new NumericTokenStream(precisionStep); } Index: src/java/org/apache/lucene/document/AbstractField.java =================================================================== --- src/java/org/apache/lucene/document/AbstractField.java (revision 962932) +++ src/java/org/apache/lucene/document/AbstractField.java (working copy) @@ -51,10 +51,31 @@ { } - protected AbstractField(String name, Field.Store store, Field.Index index, Field.TermVector termVector) { + /** + * construct the abstract field. name will be interned. + * @see #AbstractField(String, boolean, Store, Index, TermVector) + * @param name + * @param store + * @param index + * @param termVector + */ + protected AbstractField(final String name, Field.Store store, Field.Index index, Field.TermVector termVector) { + this(name, true, store, index, termVector); + } + + /** + * construct the abstract field, optionally intern the name. + * None of the arguments may be null, or a {@link NullPointerException} will be thrown. + * @param name the name of the field + * @param internName Whether to .intern() name or not + * @param store used for .isStored() + * @param index used for .isIndexed(), .isAnalyzed() + * @param termVector used for setStoreTermVector() + */ + protected AbstractField(final String name, boolean internName, Field.Store store, Field.Index index, Field.TermVector termVector) { if (name == null) throw new NullPointerException("name cannot be null"); - this.name = StringHelper.intern(name); // field names are interned + this.name = internName ? StringHelper.intern(name) : name; // field can be interned this.isStored = store.isStored(); this.isIndexed = index.isIndexed(); Index: src/java/org/apache/lucene/document/Field.java =================================================================== --- src/java/org/apache/lucene/document/Field.java (revision 962932) +++ src/java/org/apache/lucene/document/Field.java (working copy) @@ -389,7 +389,7 @@ *
  • the field is not indexed but termVector is TermVector.YES
  • * */ - public Field(String name, boolean internName, String value, Store store, Index index, TermVector termVector) { + public Field(final String name, boolean internName, String value, Store store, Index index, TermVector termVector) { if (name == null) throw new NullPointerException("name cannot be null"); if (value == null) @@ -403,11 +403,8 @@ throw new IllegalArgumentException("cannot store term vector information " + "for a field that is not indexed"); - if (internName) // field names are optionally interned - name = StringHelper.intern(name); + this.name = internName ? StringHelper.intern(name) : name; // field can be interned - this.name = name; - this.fieldsData = value; this.isStored = store.isStored(); @@ -449,13 +446,29 @@ * @param termVector Whether term vector should be stored * @throws NullPointerException if name or reader is null */ - public Field(String name, Reader reader, TermVector termVector) { + public Field(final String name, Reader reader, TermVector termVector) { + this(name, true, reader, termVector); + } + + /** + * 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 internName Whether to .intern() name or not + * @param reader The reader with the content + * @param termVector Whether term vector should be stored + * @throws NullPointerException if name or reader is null + */ + public Field(final String name, boolean internName, 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 = StringHelper.intern(name); // field names are interned + + this.name = internName ? StringHelper.intern(name) : name; // field can be interned this.fieldsData = reader; this.isStored = false; @@ -495,13 +508,30 @@ * @param termVector Whether term vector should be stored * @throws NullPointerException if name or tokenStream is null */ - public Field(String name, TokenStream tokenStream, TermVector termVector) { + public Field(final String name, final TokenStream tokenStream, TermVector termVector) { + this(name, true, tokenStream, termVector); + } + + /** + * 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 internName Whether to .intern() name or not + * @param tokenStream The TokenStream with the content + * @param termVector Whether term vector should be stored + * @throws NullPointerException if name or tokenStream is null + */ + public Field(final String name, boolean internName, final 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 = StringHelper.intern(name); // field names are interned + + this.name = internName ? StringHelper.intern(name) : name; // field can be interned this.fieldsData = null; this.tokenStream = tokenStream; @@ -538,14 +568,28 @@ * @param store How value should be stored (compressed or not) * @throws IllegalArgumentException if store is Store.NO */ - public Field(String name, byte[] value, int offset, int length, Store store) { + public Field(final String name, byte[] value, int offset, int length, Store store) { + this(name, true, value, offset, length, store); + } + /** + * Create a stored field with binary value. Optionally the value may be compressed. + * + * @param name The name of the field + * @param internName Whether to .intern() name or not + * @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 + * @param store How value should be stored (compressed or not) + * @throws IllegalArgumentException if store is Store.NO + */ + public Field(final String name, boolean internName, byte[] value, int offset, int length, Store store) { if (name == null) throw new IllegalArgumentException("name cannot be null"); if (value == null) throw new IllegalArgumentException("value cannot be null"); - - this.name = StringHelper.intern(name); // field names are interned + + this.name = internName ? StringHelper.intern(name) : name; // field can be interned fieldsData = value; if (store == Store.NO)