diff -u -r -x '*.svn*' lucene-3.0.2.patched/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java lucene-3.0.2/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java --- lucene-3.0.2.patched/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java 2010-07-14 00:38:40.000000000 -0700 +++ lucene-3.0.2/contrib/instantiated/src/java/org/apache/lucene/store/instantiated/InstantiatedIndexReader.java 2010-07-14 01:30:49.000000000 -0700 @@ -276,6 +276,42 @@ * @see org.apache.lucene.document.LoadFirstFieldSelector */ @Override + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return document(n); + } + + /** + * Return the {@link org.apache.lucene.document.Document} at the nth + * position. +

+ * Warning! + * 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! + *

+ * 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. +

+ * This implementation ignores the field selector! All stored fields are always returned! + *

+ * + * @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); } @@ -300,7 +336,6 @@ * @throws CorruptIndexException if the index is corrupt * @throws IOException if there is a low-level IO error */ - @Override public Document document(int n) throws IOException { return isDeleted(n) ? null : getIndex().getDocumentsByNumber()[n].getDocument(); diff -u -r -x '*.svn*' lucene-3.0.2.patched/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java lucene-3.0.2/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java --- lucene-3.0.2.patched/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java 2010-07-14 00:38:50.000000000 -0700 +++ lucene-3.0.2/contrib/memory/src/java/org/apache/lucene/index/memory/MemoryIndex.java 2010-07-13 21:00:28.000000000 -0700 @@ -1140,16 +1140,16 @@ } @Override - public Document document(int n) { + public Document document(int n, FieldSelector fieldSelector) { if (DEBUG) System.err.println("MemoryIndexReader.document"); return new Document(); // there are no stored fields } //When we convert to JDK 1.5 make this Set @Override - public Document document(int n, FieldSelector fieldSelector) throws IOException { + public Document document(int n, Document doc, FieldSelector fieldSelector) throws IOException { if (DEBUG) System.err.println("MemoryIndexReader.document"); - return new Document(); // there are no stored fields + return (doc != null) ? doc : new Document(); // there are no stored fields } @Override diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/DirectoryReader.java lucene-3.0.2/src/java/org/apache/lucene/index/DirectoryReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/DirectoryReader.java 2010-07-14 00:38:14.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/DirectoryReader.java 2010-07-13 20:55:06.000000000 -0700 @@ -520,9 +520,15 @@ // inherit javadoc @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return document(n, null, fieldSelector); + } + + // inherit javadoc + @Override + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { ensureOpen(); int i = readerIndex(n); // find segment num - return subReaders[i].document(n - starts[i], fieldSelector); // dispatch to segment reader + return subReaders[i].document(n - starts[i], doc, fieldSelector); // dispatch to segment reader } @Override diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/FieldsReader.java lucene-3.0.2/src/java/org/apache/lucene/index/FieldsReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/FieldsReader.java 2010-07-14 00:54:07.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/FieldsReader.java 2010-07-12 23:59:19.000000000 -0700 @@ -213,13 +213,34 @@ return format >= FieldsWriter.FORMAT_LUCENE_3_0_NO_COMPRESSED_FIELDS; } + /** + * legacy signature, will create Document as needed + * @param n + * @param fieldSelector + * @return a new Document filled with fields as per fieldSelector + * @throws CorruptIndexException + * @throws IOException + */ final Document doc(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return doc(n, null, fieldSelector); + } + + /** + * method signature to allow re-use or aggregation of fields into an existing Document. + * @param n + * @param d + * @param fieldSelector + * @return a Document with fields added as per fieldSelector + * @throws CorruptIndexException + * @throws IOException + */ + final Document doc(int n, Document d, FieldSelector fieldSelector) throws CorruptIndexException, IOException { seekIndex(n); long position = indexStream.readLong(); fieldsStream.seek(position); - Document doc = new Document(); - int numFields = fieldsStream.readVInt(); + final int numFields = fieldsStream.readVInt(); + final Document doc = (d != null) ? d : new Document(); for (int i = 0; i < numFields; i++) { int fieldNumber = fieldsStream.readVInt(); FieldInfo fi = fieldInfos.fieldInfo(fieldNumber); diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/FilterIndexReader.java lucene-3.0.2/src/java/org/apache/lucene/index/FilterIndexReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/FilterIndexReader.java 2010-07-14 00:38:14.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/FilterIndexReader.java 2010-07-13 20:58:21.000000000 -0700 @@ -157,8 +157,13 @@ @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return document(n, null, fieldSelector); + } + + @Override + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { ensureOpen(); - return in.document(n, fieldSelector); + return in.document(n, doc, fieldSelector); } @Override diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/IndexReader.java lucene-3.0.2/src/java/org/apache/lucene/index/IndexReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/IndexReader.java 2010-07-14 00:38:14.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/IndexReader.java 2010-07-13 20:54:00.000000000 -0700 @@ -19,6 +19,7 @@ import org.apache.lucene.document.Document; import org.apache.lucene.document.FieldSelector; +import org.apache.lucene.document.Fieldable; import org.apache.lucene.search.Similarity; import org.apache.lucene.store.*; @@ -655,7 +656,7 @@ */ public Document document(int n) throws CorruptIndexException, IOException { ensureOpen(); - return document(n, null); + return document(n, null, null); } /** @@ -688,8 +689,36 @@ * @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 public abstract Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException; + + /** + * Override this to provide a more efficient implementation. + * @param n Get the document at the nth position + * @param doc a {@link Document}, must be in what caller wishes to constitute + * initialized and empty state. If null a new document is created + * @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 IndexReader#document(int, FieldSelector) + * @see org.apache.lucene.document.Fieldable + * @see org.apache.lucene.document.FieldSelector + * @see org.apache.lucene.document.SetBasedFieldSelector + * @see org.apache.lucene.document.LoadFirstFieldSelector + */ + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + Document d = document(n, fieldSelector); + if (doc != null) { + for (Fieldable f : d.getFields()) { + doc.add(f); + } + return doc; + } + return d; + } /** Returns true if document n has been deleted */ public abstract boolean isDeleted(int n); diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/MultiReader.java lucene-3.0.2/src/java/org/apache/lucene/index/MultiReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/MultiReader.java 2010-07-14 00:38:14.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/MultiReader.java 2010-07-13 21:00:49.000000000 -0700 @@ -246,9 +246,15 @@ // inherit javadoc @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return document(n, null, fieldSelector); + } + + // inherit javadoc + @Override + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { ensureOpen(); int i = readerIndex(n); // find segment num - return subReaders[i].document(n - starts[i], fieldSelector); // dispatch to segment reader + return subReaders[i].document(n - starts[i], doc, fieldSelector); // dispatch to segment reader } @Override diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/ParallelReader.java lucene-3.0.2/src/java/org/apache/lucene/index/ParallelReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/ParallelReader.java 2010-07-14 00:54:07.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/ParallelReader.java 2010-07-13 21:01:11.000000000 -0700 @@ -269,11 +269,16 @@ hasDeletions = false; } - // append fields from storedFieldReaders @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return document(n, null, fieldSelector); + } + + // append fields from storedFieldReaders + @Override + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { ensureOpen(); - Document result = new Document(); + Document result = (doc != null) ? doc : new Document(); for (final IndexReader reader: storedFieldReaders) { boolean include = (fieldSelector==null); @@ -290,9 +295,12 @@ } } if (include) { - List fields = reader.document(n, fieldSelector).getFields(); - for (Fieldable field : fields) { - result.add(field); + // pass document, if yields a different doc, manually copy the fields + Document pdoc = reader.document(n, result, fieldSelector); + if (pdoc != result) { + for (Fieldable field : pdoc.getFields()) { + result.add(field); + } } } } diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/java/org/apache/lucene/index/SegmentReader.java lucene-3.0.2/src/java/org/apache/lucene/index/SegmentReader.java --- lucene-3.0.2.patched/src/java/org/apache/lucene/index/SegmentReader.java 2010-07-14 00:38:14.000000000 -0700 +++ lucene-3.0.2/src/java/org/apache/lucene/index/SegmentReader.java 2010-07-13 21:01:55.000000000 -0700 @@ -897,8 +897,13 @@ @Override public Document document(int n, FieldSelector fieldSelector) throws CorruptIndexException, IOException { + return document(n, null, fieldSelector); + } + + @Override + public Document document(int n, Document doc, FieldSelector fieldSelector) throws CorruptIndexException, IOException { ensureOpen(); - return getFieldsReader().doc(n, fieldSelector); + return getFieldsReader().doc(n, doc, fieldSelector); } @Override diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/test/org/apache/lucene/index/TestDirectoryReader.java lucene-3.0.2/src/test/org/apache/lucene/index/TestDirectoryReader.java --- lucene-3.0.2.patched/src/test/org/apache/lucene/index/TestDirectoryReader.java 2010-07-14 00:38:12.000000000 -0700 +++ lucene-3.0.2/src/test/org/apache/lucene/index/TestDirectoryReader.java 2010-07-13 20:45:46.000000000 -0700 @@ -22,10 +22,12 @@ import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.document.Fieldable; import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; import java.io.IOException; +import java.util.List; public class TestDirectoryReader extends LuceneTestCase { protected Directory dir; @@ -85,6 +87,32 @@ assertTrue(vector != null); TestSegmentReader.checkNorms(reader); } + + /** + * tests reader.document(int, Document, FieldSelector) + * test that provided Document is reused if non-null, else created + * @throws IOException + */ + public void doTestDocumentWithDoc() throws IOException { + sis.read(dir); + IndexReader reader = openReader(); + assertTrue(reader != null); + + Document newDoc1 = reader.document(0, null, null); + assertTrue(newDoc1 != null); + assertTrue(DocHelper.numFields(newDoc1) == DocHelper.numFields(doc1) - DocHelper.unstored.size()); + + Document newDoc1a = new Document(); + Document newDoc1b = reader.document(0, newDoc1a, null); + assertSame(newDoc1a, newDoc1b); + assertTrue(DocHelper.numFields(newDoc1a) == DocHelper.numFields(doc1) - DocHelper.unstored.size()); + + Document newDoc1c = reader.document(0, newDoc1a, null); + assertSame(newDoc1a, newDoc1c); + assertTrue(DocHelper.numFields(newDoc1a) == 2 * (DocHelper.numFields(doc1) - DocHelper.unstored.size())); + List f = newDoc1a.getFields(); + assertEquals(f.get(0).stringValue(), f.get(f.size()/2).stringValue()); + } public void doTestUndeleteAll() throws IOException { sis.read(dir); diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/test/org/apache/lucene/index/TestParallelReader.java lucene-3.0.2/src/test/org/apache/lucene/index/TestParallelReader.java --- lucene-3.0.2.patched/src/test/org/apache/lucene/index/TestParallelReader.java 2010-07-14 00:54:07.000000000 -0700 +++ lucene-3.0.2/src/test/org/apache/lucene/index/TestParallelReader.java 2010-07-14 01:23:23.000000000 -0700 @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -29,6 +30,7 @@ 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 org.apache.lucene.document.LoadFirstFieldSelector; import org.apache.lucene.document.MapFieldSelector; import org.apache.lucene.search.BooleanQuery; @@ -128,7 +130,35 @@ assertEquals("v2", doc2.get("f3")); assertEquals("v2", doc2.get("f3")); } - + + /** + * tests reader.document(int, Document, FieldSelector) + * test that provided Document is reused if non-null, else created + * @throws IOException + */ + public void doTestDocumentWithDoc() throws IOException { + Directory dir1 = getDir1(); + Directory dir2 = getDir2(); + ParallelReader pr = new ParallelReader(); + pr.add(IndexReader.open(dir1, false)); + pr.add(IndexReader.open(dir2, false)); + + Document newDoc1 = pr.document(0, null, null); + assertTrue(newDoc1 != null); + assertEquals(4, DocHelper.numFields(newDoc1)); + + Document newDoc1a = new Document(); + Document newDoc1b = pr.document(0, newDoc1a, null); + assertSame(newDoc1a, newDoc1b); + assertEquals(4, DocHelper.numFields(newDoc1a)); + + Document newDoc1c = pr.document(0, newDoc1a, null); + assertSame(newDoc1a, newDoc1c); + assertEquals(8, DocHelper.numFields(newDoc1a)); + List f = newDoc1a.getFields(); + assertEquals(f.get(0).stringValue(), f.get(f.size()/2).stringValue()); + } + public void testDocumentAcceptF2BlockedByBreak() throws IOException { Directory dir1 = getDir1(); Directory dir2 = getDir2(); diff -u -r -x '*.svn*' lucene-3.0.2.patched/src/test/org/apache/lucene/index/TestSegmentReader.java lucene-3.0.2/src/test/org/apache/lucene/index/TestSegmentReader.java --- lucene-3.0.2.patched/src/test/org/apache/lucene/index/TestSegmentReader.java 2010-07-14 00:38:12.000000000 -0700 +++ lucene-3.0.2/src/test/org/apache/lucene/index/TestSegmentReader.java 2010-07-14 01:20:00.000000000 -0700 @@ -69,7 +69,29 @@ assertTrue(DocHelper.nameValues.containsKey(field.name())); } } - + + /** + * tests reader.document(int, Document, FieldSelector) + * test that provided Document is reused if non-null, else created + * @throws IOException + */ + public void doTestDocumentWithDoc() throws IOException { + Document newDoc1 = reader.document(0, null, null); + assertTrue(newDoc1 != null); + assertTrue(DocHelper.numFields(newDoc1) == DocHelper.numFields(testDoc) - DocHelper.unstored.size()); + + Document newDoc1a = new Document(); + Document newDoc1b = reader.document(0, newDoc1a, null); + assertSame(newDoc1a, newDoc1b); + assertTrue(DocHelper.numFields(newDoc1a) == DocHelper.numFields(testDoc) - DocHelper.unstored.size()); + + Document newDoc1c = reader.document(0, newDoc1a, null); + assertSame(newDoc1a, newDoc1c); + assertTrue(DocHelper.numFields(newDoc1a) == 2 * (DocHelper.numFields(testDoc) - DocHelper.unstored.size())); + List f = newDoc1a.getFields(); + assertEquals(f.get(0).stringValue(), f.get(f.size()/2).stringValue()); + } + public void testDelete() throws IOException { Document docToDelete = new Document(); DocHelper.setupDoc(docToDelete);