lucene-java-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mikemcc...@apache.org
Subject svn commit: r738219 [2/3] - in /lucene/java/trunk: ./ contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/feeds/ contrib/benchmark/src/java/org/apache/lucene/benchmark/byTask/tasks/ contrib/miscellaneous/src/test/org/apache/lucene/index/ cont...
Date Tue, 27 Jan 2009 20:15:23 GMT
Modified: lucene/java/trunk/src/java/org/apache/lucene/search/SortField.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/SortField.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/SortField.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/SortField.java Tue Jan 27 20:15:21 2009
@@ -17,9 +17,12 @@
  * limitations under the License.
  */
 
+import java.io.IOException;
 import java.io.Serializable;
 import java.util.Locale;
 
+import org.apache.lucene.index.IndexReader;
+
 /**
  * Stores information about how to sort documents by terms in an individual
  * field.  Fields must be indexed in order to sort by them.
@@ -67,33 +70,34 @@
    * lower values are at the front. */
   public static final int DOUBLE = 7;
 
-    /**
-   * Sort using term values as encoded Shorts.  Sort values are shorts and lower values are at the front
-   */
+  /** Sort using term values as encoded Shorts.  Sort values are Short and
+   * lower values are at the front. */
   public static final int SHORT = 8;
 
-
   /** Sort using a custom Comparator.  Sort values are any Comparable and
    * sorting is done according to natural order. */
   public static final int CUSTOM = 9;
-  /**
-   * Sort using term values as encoded bytes.  Sort values are bytes and lower values are at the front
-   */
-  public static final int BYTE = 10;
-
 
+  /** Sort using term values as encoded Bytes.  Sort values are Byte and
+   * lower values are at the front. */
+  public static final int BYTE = 10;
+  
+  /** Sort using term values as Strings, but comparing by
+   * value (using String.compareTo) for all comparisons.
+   * This is typically slower than {@link #STRING}, which
+   * uses ordinals to do the sorting. */
+  public static final int STRING_VAL = 11;
+  
   // IMPLEMENTATION NOTE: the FieldCache.STRING_INDEX is in the same "namespace"
   // as the above static int values.  Any new values must not have the same value
   // as FieldCache.STRING_INDEX.
 
-
   /** Represents sorting by document score (relevancy). */
   public static final SortField FIELD_SCORE = new SortField (null, SCORE);
 
   /** Represents sorting by document number (index order). */
   public static final SortField FIELD_DOC = new SortField (null, DOC);
 
-
   private String field;
   private int type = AUTO;  // defaults to determining type dynamically
   private Locale locale;    // defaults to "natural order" (no Locale)
@@ -101,6 +105,11 @@
   private SortComparatorSource factory;
   private FieldCache.Parser parser;
 
+  // Used for CUSTOM sort
+  private FieldComparatorSource comparatorSource;
+
+  private boolean useLegacy = false; // remove in Lucene 3.0
+
   /** Creates a sort by terms in the given field where the type of term value
    * is determined dynamically ({@link #AUTO AUTO}).
    * @param field Name of field to sort by, cannot be <code>null</code>.
@@ -206,22 +215,46 @@
   /** Creates a sort with a custom comparison function.
    * @param field Name of field to sort by; cannot be <code>null</code>.
    * @param comparator Returns a comparator for sorting hits.
+   * @deprecated use SortField (String field, FieldComparatorSource comparator)
    */
   public SortField (String field, SortComparatorSource comparator) {
     initFieldType(field, CUSTOM);
+    setUseLegacySearch(true);
     this.factory = comparator;
   }
+  
+  /** Creates a sort with a custom comparison function.
+   * @param field Name of field to sort by; cannot be <code>null</code>.
+   * @param comparator Returns a comparator for sorting hits.
+   */
+  public SortField (String field, FieldComparatorSource comparator) {
+    initFieldType(field, CUSTOM);
+    this.comparatorSource = comparator;
+  }
 
   /** Creates a sort, possibly in reverse, with a custom comparison function.
    * @param field Name of field to sort by; cannot be <code>null</code>.
    * @param comparator Returns a comparator for sorting hits.
    * @param reverse True if natural order should be reversed.
+   * @deprecated use SortField (String field, FieldComparatorSource comparator, boolean reverse)
    */
   public SortField (String field, SortComparatorSource comparator, boolean reverse) {
     initFieldType(field, CUSTOM);
+    setUseLegacySearch(true);
     this.reverse = reverse;
     this.factory = comparator;
   }
+  
+  /** Creates a sort, possibly in reverse, with a custom comparison function.
+   * @param field Name of field to sort by; cannot be <code>null</code>.
+   * @param comparator Returns a comparator for sorting hits.
+   * @param reverse True if natural order should be reversed.
+   */
+  public SortField (String field, FieldComparatorSource comparator, boolean reverse) {
+    initFieldType(field, CUSTOM);
+    this.reverse = reverse;
+    this.comparatorSource = comparator;
+  }
 
   // Sets field & type, and ensures field is not NULL unless
   // type is SCORE or DOC
@@ -273,26 +306,91 @@
     return reverse;
   }
 
+  /**
+   * @deprecated use {@link #getComparatorSource()}
+   */
   public SortComparatorSource getFactory() {
     return factory;
   }
+  
+  public FieldComparatorSource getComparatorSource() {
+    return comparatorSource;
+  }
+  
+  /**
+   * Use legacy IndexSearch implementation: search with a MultiSegmentReader rather
+   * than passing a single hit collector to multiple SegmentReaders.
+   * 
+   * @param legacy true for legacy behavior
+   * @deprecated will be removed in Lucene 3.0.
+   */
+  public void setUseLegacySearch(boolean legacy) {
+    this.useLegacy = legacy;
+  }
+  
+  /**
+   * @return if true, IndexSearch will use legacy sorting search implementation.
+   * eg. multiple Priority Queues.
+   * @deprecated will be removed in Lucene 3.0.
+   */
+  public boolean getUseLegacySearch() {
+    return this.useLegacy;
+  }
 
   public String toString() {
     StringBuffer buffer = new StringBuffer();
     switch (type) {
-      case SCORE: buffer.append("<score>");
-                  break;
-
-      case DOC: buffer.append("<doc>");
-                break;
+      case SCORE:
+        buffer.append("<score>");
+        break;
+
+      case DOC:
+        buffer.append("<doc>");
+        break;
+
+      case AUTO:
+        buffer.append("<auto: \"").append(field).append("\">");
+        break;
+
+      case STRING:
+        buffer.append("<string: \"").append(field).append("\">");
+        break;
+
+      case STRING_VAL:
+        buffer.append("<string_val: \"").append(field).append("\">");
+        break;
+
+      case BYTE:
+        buffer.append("<byte: \"").append(field).append("\">");
+        break;
+
+      case SHORT:
+        buffer.append("<short: \"").append(field).append("\">");
+        break;
+
+      case INT:
+        buffer.append("<int: \"").append(field).append("\">");
+        break;
+
+      case LONG:
+        buffer.append("<long: \"").append(field).append("\">");
+        break;
+
+      case FLOAT:
+        buffer.append("<float: \"").append(field).append("\">");
+        break;
+
+      case DOUBLE:
+        buffer.append("<double: \"").append(field).append("\">");
+        break;
 
       case CUSTOM:
-                buffer.append("<custom:\"").append(field).append("\": ").append(factory).append('>');
-                break;
+        buffer.append("<custom:\"").append(field).append("\": ").append(factory).append('>');
+        break;
 
       default:
-               buffer.append('\"').append(field).append('\"');
-               break;
+        buffer.append("<???: \"").append(field).append("\">");
+        break;
     }
 
     if (locale != null) buffer.append('(').append(locale).append(')');
@@ -333,4 +431,65 @@
     if (parser != null) hash += parser.hashCode()^0x3aaf56ff;
     return hash;
   }
+
+
+  /** Returns the {@link FieldComparator} to use for sorting.
+   * @param subReaders array of {@link IndexReader} search
+   *   will step through
+   * @param numHits number of top hits the queue will store
+   * @param sortPos position of this SortField within {@link
+   *   Sort}.  The comparator is primary if sortPos==0,
+   *   secondary if sortPos==1, etc.  Some comparators can
+   *   optimize themselves when they are the primary sort.
+   * @param reversed True if the SortField is reversed
+   * @return {@link FieldComparator} to use when sorting
+   */
+  protected FieldComparator getComparator(final IndexReader[] subReaders, final int numHits, final int sortPos, final boolean reversed) throws IOException {
+
+    if (locale != null) {
+      // TODO: it'd be nice to allow FieldCache.getStringIndex
+      // to optionally accept a Locale so sorting could then use
+      // the faster StringComparator impls
+      return new FieldComparator.StringComparatorLocale(numHits, field, locale);
+    }
+
+    switch (type) {
+    case SortField.SCORE:
+      return new FieldComparator.RelevanceComparator(numHits);
+
+    case SortField.DOC:
+      return new FieldComparator.DocComparator(numHits);
+
+    case SortField.INT:
+      return new FieldComparator.IntComparator(numHits, field, parser);
+
+    case SortField.FLOAT:
+      return new FieldComparator.FloatComparator(numHits, field, parser);
+
+    case SortField.LONG:
+      return new FieldComparator.LongComparator(numHits, field, parser);
+
+    case SortField.DOUBLE:
+      return new FieldComparator.DoubleComparator(numHits, field, parser);
+
+    case SortField.BYTE:
+      return new FieldComparator.ByteComparator(numHits, field, parser);
+
+    case SortField.SHORT:
+      return new FieldComparator.ShortComparator(numHits, field, parser);
+
+    case SortField.CUSTOM:
+      assert factory == null && comparatorSource != null;
+      return comparatorSource.newComparator(field, subReaders, numHits, sortPos, reversed);
+
+    case SortField.STRING:
+      return new FieldComparator.StringOrdValComparator(numHits, field, sortPos, reversed);
+
+    case SortField.STRING_VAL:
+      return new FieldComparator.StringValComparator(numHits, field);
+        
+    default:
+      throw new IllegalStateException("Illegal sort type: " + type);
+    }
+  }
 }

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/TimeLimitedCollector.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/TimeLimitedCollector.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/TimeLimitedCollector.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/TimeLimitedCollector.java Tue Jan 27 20:15:21 2009
@@ -1,5 +1,7 @@
 package org.apache.lucene.search;
 
+import org.apache.lucene.index.IndexReader;
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -17,13 +19,16 @@
  * limitations under the License.
  */
 
+import java.io.IOException;
+
 /**
  * <p>The TimeLimitedCollector is used to timeout search requests that
  * take longer than the maximum allowed search time limit.  After this
  * time is exceeded, the search thread is stopped by throwing a
  * TimeExceeded Exception.</p>
+ * 
  */
-public class TimeLimitedCollector extends HitCollector {
+public class TimeLimitedCollector extends MultiReaderHitCollector {
   
   /** 
    * Default timer resolution.
@@ -138,7 +143,7 @@
 
   private final long t0;
   private final long timeout;
-  private final HitCollector hc;
+  private final MultiReaderHitCollector hc;
 
   /**
    * Create a TimeLimitedCollector wrapper over another HitCollector with a specified timeout.
@@ -146,7 +151,11 @@
    * @param timeAllowed max time allowed for collecting hits after which {@link TimeExceededException} is thrown
    */
   public TimeLimitedCollector( final HitCollector hc, final long timeAllowed ) {
-    this.hc = hc;
+    if (hc instanceof MultiReaderHitCollector) {
+      this.hc = (MultiReaderHitCollector) hc;
+    } else {
+      this.hc = new IndexSearcher.MultiReaderCollectorWrapper(hc);
+    }
     t0 = TIMER_THREAD.getMilliseconds();
     this.timeout = t0 + timeAllowed;
   }
@@ -216,4 +225,8 @@
   public void setGreedy(boolean greedy) {
     this.greedy = greedy;
   }
+  
+  public void setNextReader(IndexReader reader, int base) throws IOException {
+    hc.setNextReader(reader, base);
+  }
 }

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/TopDocCollector.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/TopDocCollector.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/TopDocCollector.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/TopDocCollector.java Tue Jan 27 20:15:21 2009
@@ -26,6 +26,9 @@
  * <p>This may be extended, overriding the collect method to, e.g.,
  * conditionally invoke <code>super()</code> in order to filter which
  * documents are collected.
+ *
+ * @deprecated Please use {@link TopScoreDocCollector}
+ * instead, which has better performance.
  **/
 public class TopDocCollector extends HitCollector {
 

Added: lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldCollector.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldCollector.java?rev=738219&view=auto
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldCollector.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldCollector.java Tue Jan 27 20:15:21 2009
@@ -0,0 +1,221 @@
+package org.apache.lucene.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.FieldValueHitQueue.Entry;
+
+/**
+ * A {@link HitCollector} that sorts by {@link SortField} using 
+ * {@link FieldComparator}s.
+ *
+ * <b>NOTE:</b> This API is experimental and might change in
+ * incompatible ways in the next release.
+ */
+public final class TopFieldCollector extends MultiReaderHitCollector {
+
+  private final FieldValueHitQueue queue;
+
+  private final FieldComparator[] comparators;
+  private FieldComparator comparator1;
+  private final int numComparators;
+  private int[] reverseMul;
+  private int reverseMul1 = 0;
+
+  private final int numHits;
+  private int totalHits;
+  private FieldValueHitQueue.Entry bottom = null;
+
+  /** Stores the maximum score value encountered, needed for normalizing. */
+  private float maxScore = Float.NEGATIVE_INFINITY;
+
+  private boolean queueFull;
+
+  private boolean fillFields;
+
+  public TopFieldCollector(Sort sort, int numHits,  IndexReader[] subReaders, boolean fillFields)
+      throws IOException {
+
+    if (sort.fields.length == 0) {
+      throw new IllegalArgumentException("Sort must contain at least one field");
+    }
+
+    queue = new FieldValueHitQueue(sort.fields, numHits, subReaders);
+    comparators = queue.getComparators(); 
+    reverseMul = queue.getReverseMul(); 
+    numComparators = comparators.length;
+
+    if (numComparators == 1) {
+      comparator1 = comparators[0];
+      reverseMul1 = reverseMul[0];
+    } else {
+      comparator1 = null;
+      reverseMul1 = 0;
+    }
+    this.numHits = numHits;
+    this.fillFields = fillFields;
+  }
+
+  int currentDocBase;
+
+  // javadoc inherited
+  public void setNextReader(IndexReader reader, int docBase) throws IOException {
+    final int numSlotsFull;
+    if (queueFull)
+      numSlotsFull = numHits;
+    else
+      numSlotsFull = totalHits;
+
+    currentDocBase = docBase;
+
+    for (int i = 0; i < numComparators; i++) {
+      comparators[i].setNextReader(reader, docBase, numSlotsFull);
+    }
+  }
+
+  private final void updateBottom(int doc, float score) {
+    bottom.docID = currentDocBase + doc;
+    bottom.score = score;
+    queue.adjustTop();
+    bottom = (FieldValueHitQueue.Entry) queue.top();
+  }
+
+  private final void add(int slot, int doc, float score) {
+    queue.put(new FieldValueHitQueue.Entry(slot, currentDocBase+doc, score));
+    bottom = (FieldValueHitQueue.Entry) queue.top();
+    queueFull = totalHits == numHits;
+  }     
+
+  // javadoc inherited
+  public void collect(int doc, float score) {
+    if (score > 0.0f) {
+
+      maxScore = Math.max(maxScore, score);
+      totalHits++;
+
+      // TODO: one optimization we could do is to pre-fill
+      // the queue with sentinel value that guaranteed to
+      // always compare lower than a real hit; this would
+      // save having to check queueFull on each insert
+
+      if (queueFull) {
+
+        if (numComparators == 1) {
+          // Common case
+
+          // Fastmatch: return if this hit is not competitive
+          final int cmp = reverseMul1 * comparator1.compareBottom(doc, score);
+          if (cmp < 0) {
+            // Definitely not competitive
+            return;
+          } else if (cmp == 0 && doc + currentDocBase > bottom.docID) {
+            // Definitely not competitive
+            return;
+          }
+
+          // This hit is competitive -- replace bottom
+          // element in queue & adjustTop
+          comparator1.copy(bottom.slot, doc, score);
+
+          updateBottom(doc, score);
+
+          comparator1.setBottom(bottom.slot);
+
+        } else {
+
+          // Fastmatch: return if this hit is not competitive
+          for(int i=0;;i++) {
+            final int c = reverseMul[i] * comparators[i].compareBottom(doc, score);
+            if (c < 0) {
+              // Definitely not competitive
+              return;
+            } else if (c > 0) {
+              // Definitely competitive
+              break;
+            } else if (i == numComparators-1) {
+              // This is the equals case.
+              if (doc + currentDocBase > bottom.docID) {
+                // Definitely not competitive
+                return;
+              } else {
+                break;
+              }
+            }
+          }
+
+          // This hit is competitive -- replace bottom
+          // element in queue & adjustTop
+          for (int i = 0; i < numComparators; i++) {
+            comparators[i].copy(bottom.slot, doc, score);
+          }
+
+          updateBottom(doc, score);
+
+          for(int i=0;i<numComparators;i++) {
+            comparators[i].setBottom(bottom.slot);
+          }
+        }
+      } else {
+        // Startup transient: queue hasn't gathered numHits
+        // yet
+
+        final int slot = totalHits-1;
+        // Copy hit into queue
+        if (numComparators == 1) {
+          // Common case
+          comparator1.copy(slot, doc, score);
+          add(slot, doc, score);
+          if (queueFull) {
+            comparator1.setBottom(bottom.slot);
+          }
+
+        } else {
+          for (int i = 0; i < numComparators; i++) {
+            comparators[i].copy(slot, doc, score);
+          }
+          add(slot, doc, score);
+          if (queueFull) {
+            for(int i=0;i<numComparators;i++) {
+              comparators[i].setBottom(bottom.slot);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // javadoc inherited
+  public TopDocs topDocs() {
+    ScoreDoc[] scoreDocs = new ScoreDoc[queue.size()];
+    if (fillFields) {
+      for (int i = queue.size() - 1; i >= 0; i--) {
+        scoreDocs[i] = queue.fillFields((FieldValueHitQueue.Entry) queue.pop());
+      }
+    } else {
+      Entry entry = (FieldValueHitQueue.Entry) queue.pop();
+      for (int i = queue.size() - 1; i >= 0; i--) {
+        scoreDocs[i] = new FieldDoc(entry.docID,
+                                    entry.score);
+      }
+    }
+
+    return new TopFieldDocs(totalHits, scoreDocs, queue.getFields(), maxScore);
+  }
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldCollector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldDocCollector.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldDocCollector.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldDocCollector.java (original)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/TopFieldDocCollector.java Tue Jan 27 20:15:21 2009
@@ -28,8 +28,10 @@
  * <p>This may be extended, overriding the collect method to, e.g.,
  * conditionally invoke <code>super()</code> in order to filter which
  * documents are collected.
+ *
+ * @deprecated Please use {@link TopFieldCollector} instead.
  **/
-public class TopFieldDocCollector extends TopDocCollector {
+public class TopFieldDocCollector extends TopScoreDocCollector {
 
   private FieldDoc reusableFD;
 
@@ -48,15 +50,15 @@
     if (score > 0.0f) {
       totalHits++;
       if (reusableFD == null)
-        reusableFD = new FieldDoc(doc, score);
+        reusableFD = new FieldDoc(doc + docBase, score);
       else {
-        // Whereas TopDocCollector can skip this if the
+        // Whereas TopScoreDocCollector can skip this if the
         // score is not competitive, we cannot because the
         // comparators in the FieldSortedHitQueue.lessThan
         // aren't in general congruent with "higher score
         // wins"
         reusableFD.score = score;
-        reusableFD.doc = doc;
+        reusableFD.doc = doc + docBase;
       }
       reusableFD = (FieldDoc) hq.insertWithOverflow(reusableFD);
     }

Added: lucene/java/trunk/src/java/org/apache/lucene/search/TopScoreDocCollector.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/search/TopScoreDocCollector.java?rev=738219&view=auto
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/search/TopScoreDocCollector.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/search/TopScoreDocCollector.java Tue Jan 27 20:15:21 2009
@@ -0,0 +1,101 @@
+package org.apache.lucene.search;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.util.PriorityQueue;
+
+/** A {@link MultiReaderHitCollector} implementation that
+ *  collects the top-scoring documents, returning them as a
+ *  {@link TopDocs}.  This is used by {@link IndexSearcher}
+ *  to implement {@link TopDocs}-based search.
+ *
+ *  <p>This may be extended, overriding the {@link
+ *  MultiReaderHitCollector#collect} method to, e.g.,
+ *  conditionally invoke <code>super()</code> in order to
+ *  filter which documents are collected, but sure you
+ *  either take docBase into account, or also override
+ *  {@link MultiReaderHitCollector#setNextReader} method. */
+public class TopScoreDocCollector extends MultiReaderHitCollector {
+
+  private ScoreDoc reusableSD;
+  
+  /** The total number of hits the collector encountered. */
+  protected int totalHits;
+  
+  /** The priority queue which holds the top-scoring documents. */
+  protected PriorityQueue hq;
+
+  protected int docBase = 0;
+    
+  /** Construct to collect a given number of hits.
+   * @param numHits the maximum number of hits to collect
+   */
+  public TopScoreDocCollector(int numHits) {
+    this(new HitQueue(numHits));
+  }
+
+  /** Constructor to collect the top-scoring documents by using the given PQ.
+   * @param hq the PQ to use by this instance.
+   */
+  protected TopScoreDocCollector(PriorityQueue hq) {
+    this.hq = hq;
+  }
+
+  // javadoc inherited
+  public void collect(int doc, float score) {
+    if (score > 0.0f) {
+      totalHits++;
+      if (reusableSD == null) {
+        reusableSD = new ScoreDoc(doc + docBase, score);
+      } else if (score >= reusableSD.score) {
+        // reusableSD holds the last "rejected" entry, so, if
+        // this new score is not better than that, there's no
+        // need to try inserting it
+        reusableSD.doc = doc + docBase;
+        reusableSD.score = score;
+      } else {
+        return;
+      }
+      reusableSD = (ScoreDoc) hq.insertWithOverflow(reusableSD);
+    }
+  }
+
+  /** The total number of documents that matched this query. */
+  public int getTotalHits() {
+    return totalHits;
+  }
+
+  /** The top-scoring hits. */
+  public TopDocs topDocs() {
+    ScoreDoc[] scoreDocs = new ScoreDoc[hq.size()];
+    for (int i = hq.size()-1; i >= 0; i--) {     // put docs in array
+      scoreDocs[i] = (ScoreDoc) hq.pop();
+    }
+      
+    float maxScore = (totalHits==0)
+      ? Float.NEGATIVE_INFINITY
+      : scoreDocs[0].score;
+    
+    return new TopDocs(totalHits, scoreDocs, maxScore);
+  }
+  
+  public void setNextReader(IndexReader reader, int base) {
+    docBase = base;
+  }
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/search/TopScoreDocCollector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/java/trunk/src/java/org/apache/lucene/util/SorterTemplate.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/java/org/apache/lucene/util/SorterTemplate.java?rev=738219&view=auto
==============================================================================
--- lucene/java/trunk/src/java/org/apache/lucene/util/SorterTemplate.java (added)
+++ lucene/java/trunk/src/java/org/apache/lucene/util/SorterTemplate.java Tue Jan 27 20:15:21 2009
@@ -0,0 +1,176 @@
+package org.apache.lucene.util;
+
+/*
+ * Copyright 2003 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Borrowed from Cglib. Allows custom swap so that two arrays can be sorted
+ * at the same time.
+ */
+public abstract class SorterTemplate {
+    private static final int MERGESORT_THRESHOLD = 12;
+    private static final int QUICKSORT_THRESHOLD = 7;
+
+    abstract protected void swap(int i, int j);
+    abstract protected int compare(int i, int j);
+
+    public void quickSort(int lo, int hi) {
+        quickSortHelper(lo, hi);
+        insertionSort(lo, hi);
+    }
+
+    private void quickSortHelper(int lo, int hi) {
+        for (;;) {
+            int diff = hi - lo;
+            if (diff <= QUICKSORT_THRESHOLD) {
+                break;
+            }
+            int i = (hi + lo) / 2;
+            if (compare(lo, i) > 0) {
+                swap(lo, i);
+            }
+            if (compare(lo, hi) > 0) {
+                swap(lo, hi);
+            }
+            if (compare(i, hi) > 0) {
+                swap(i, hi);
+            }
+            int j = hi - 1;
+            swap(i, j);
+            i = lo;
+            int v = j;
+            for (;;) {
+                while (compare(++i, v) < 0) {
+                    /* nothing */;
+                }
+                while (compare(--j, v) > 0) {
+                    /* nothing */;
+                }
+                if (j < i) {
+                    break;
+                }
+                swap(i, j);
+            }
+            swap(i, hi - 1);
+            if (j - lo <= hi - i + 1) {
+                quickSortHelper(lo, j);
+                lo = i + 1;
+            } else {
+                quickSortHelper(i + 1, hi);
+                hi = j;
+            }
+        }
+    }
+    
+    private void insertionSort(int lo, int hi) {
+        for (int i = lo + 1 ; i <= hi; i++) {
+            for (int j = i; j > lo; j--) {
+                if (compare(j - 1, j) > 0) {
+                    swap(j - 1, j);
+                } else {
+                    break;
+                }
+            }
+        }
+    }
+
+    protected void mergeSort(int lo, int hi) {
+        int diff = hi - lo;
+        if (diff <= MERGESORT_THRESHOLD) {
+            insertionSort(lo, hi);
+            return;
+        }
+        int mid = lo + diff / 2;
+        mergeSort(lo, mid);
+        mergeSort(mid, hi);
+        merge(lo, mid, hi, mid - lo, hi - mid);
+    }
+
+    private void merge(int lo, int pivot, int hi, int len1, int len2) {
+        if (len1 == 0 || len2 == 0) {
+            return;
+        }
+        if (len1 + len2 == 2) {
+            if (compare(pivot, lo) < 0) {
+                swap(pivot, lo);
+            }
+            return;
+        }
+        int first_cut, second_cut;
+        int len11, len22;
+        if (len1 > len2) {
+            len11 = len1 / 2;
+            first_cut = lo + len11;
+            second_cut = lower(pivot, hi, first_cut);
+            len22 = second_cut - pivot;
+        } else {
+            len22 = len2 / 2;
+            second_cut = pivot + len22;
+            first_cut = upper(lo, pivot, second_cut);
+            len11 = first_cut - lo;
+        }
+        rotate(first_cut, pivot, second_cut);
+        int new_mid = first_cut + len22;
+        merge(lo, first_cut, new_mid, len11, len22);
+        merge(new_mid, second_cut, hi, len1 - len11, len2 - len22);
+    }
+
+    private void rotate(int lo, int mid, int hi) {
+        int lot = lo;
+        int hit = mid - 1;
+        while (lot < hit) {
+            swap(lot++, hit--);
+        }
+        lot = mid; hit = hi - 1;
+        while (lot < hit) {
+            swap(lot++, hit--);
+        }
+        lot = lo; hit = hi - 1;
+        while (lot < hit) {
+            swap(lot++, hit--);
+        }
+    }
+
+    private int lower(int lo, int hi, int val) {
+        int len = hi - lo;
+        while (len > 0) {
+            int half = len / 2;
+            int mid= lo + half;
+            if (compare(mid, val) < 0) {
+                lo = mid + 1;
+                len = len - half -1;
+            } else {
+                len = half;
+            }
+        }
+        return lo;
+    }
+
+    private int upper(int lo, int hi, int val) {
+        int len = hi - lo;
+        while (len > 0) {
+            int half = len / 2;
+            int mid = lo + half;
+            if (compare(val, mid) < 0) {
+                len = half;
+            } else {
+                lo = mid + 1;
+                len = len - half -1;
+            }
+        }
+        return lo;
+    }
+}

Propchange: lucene/java/trunk/src/java/org/apache/lucene/util/SorterTemplate.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/index/TestIndexReaderReopen.java Tue Jan 27 20:15:21 2009
@@ -320,7 +320,7 @@
       assertRefCountEquals(1, reader0);
 
       assertTrue(reader0 instanceof MultiSegmentReader);
-      SegmentReader[] subReaders0 = ((MultiSegmentReader) reader0).getSubReaders();
+      IndexReader[] subReaders0 = reader0.getSequentialSubReaders();
       for (int i = 0; i < subReaders0.length; i++) {
         assertRefCountEquals(1, subReaders0[i]);
       }
@@ -332,7 +332,7 @@
       
       IndexReader reader1 = refreshReader(reader0, true).refreshedReader;
       assertTrue(reader1 instanceof MultiSegmentReader);
-      SegmentReader[] subReaders1 = ((MultiSegmentReader) reader1).getSubReaders();
+      IndexReader[] subReaders1 = reader1.getSequentialSubReaders();
       assertEquals(subReaders0.length, subReaders1.length);
       
       for (int i = 0; i < subReaders0.length; i++) {
@@ -349,7 +349,7 @@
 
       IndexReader reader2 = refreshReader(reader1, true).refreshedReader;
       assertTrue(reader2 instanceof MultiSegmentReader);
-      SegmentReader[] subReaders2 = ((MultiSegmentReader) reader2).getSubReaders();
+      IndexReader[] subReaders2 = reader2.getSequentialSubReaders();
       assertEquals(subReaders1.length, subReaders2.length);
       
       for (int i = 0; i < subReaders2.length; i++) {
@@ -373,7 +373,7 @@
       
       IndexReader reader3 = refreshReader(reader0, true).refreshedReader;
       assertTrue(reader3 instanceof MultiSegmentReader);
-      SegmentReader[] subReaders3 = ((MultiSegmentReader) reader3).getSubReaders();
+      IndexReader[] subReaders3 = reader3.getSequentialSubReaders();
       assertEquals(subReaders3.length, subReaders0.length);
       
       // try some permutations
@@ -945,14 +945,14 @@
     
     if (checkSubReaders) {
       if (reader instanceof MultiSegmentReader) {
-        SegmentReader[] subReaders = ((MultiSegmentReader) reader).getSubReaders();
+        IndexReader[] subReaders = reader.getSequentialSubReaders();
         for (int i = 0; i < subReaders.length; i++) {
           assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed);
         }
       }
       
       if (reader instanceof MultiReader) {
-        IndexReader[] subReaders = ((MultiReader) reader).getSubReaders();
+        IndexReader[] subReaders = reader.getSequentialSubReaders();
         for (int i = 0; i < subReaders.length; i++) {
           assertReaderClosed(subReaders[i], checkSubReaders, checkNormsClosed);
         }
@@ -971,7 +971,7 @@
     reader.ensureOpen();
     
     if (reader instanceof MultiSegmentReader) {
-      SegmentReader[] subReaders = ((MultiSegmentReader) reader).getSubReaders();
+      IndexReader[] subReaders = reader.getSequentialSubReaders();
       for (int i = 0; i < subReaders.length; i++) {
         assertReaderOpen(subReaders[i]);
       }

Modified: lucene/java/trunk/src/test/org/apache/lucene/index/TestOmitTf.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/index/TestOmitTf.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/index/TestOmitTf.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/index/TestOmitTf.java Tue Jan 27 20:15:21 2009
@@ -26,8 +26,8 @@
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.HitCollector;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.MultiReaderHitCollector;
 import org.apache.lucene.search.Searcher;
 import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.TermQuery;
@@ -348,16 +348,21 @@
     dir.close();
   }
      
-  public static class CountingHitCollector extends HitCollector {
+  public static class CountingHitCollector extends MultiReaderHitCollector {
     static int count=0;
     static int sum=0;
+    private int docBase = -1;
     CountingHitCollector(){count=0;sum=0;}
     public void collect(int doc, float score) {
       count++;
-      sum += doc;  // use it to avoid any possibility of being optimized away
+      sum += doc + docBase;  // use it to avoid any possibility of being optimized away
     }
 
     public static int getCount() { return count; }
     public static int getSum() { return sum; }
+    
+    public void setNextReader(IndexReader reader, int docBase) {
+      this.docBase = docBase;
+    }
   }
 }

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/CheckHits.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/CheckHits.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/CheckHits.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/CheckHits.java Tue Jan 27 20:15:21 2009
@@ -89,9 +89,14 @@
     }
     
     final Set actual = new TreeSet();
-    searcher.search(query, new HitCollector() {
+    searcher.search(query, new MultiReaderHitCollector() {
+        private int base = -1;
         public void collect(int doc, float score) {
-          actual.add(new Integer(doc));
+          actual.add(new Integer(doc + base));
+        }
+
+        public void setNextReader(IndexReader reader, int docBase) {
+          base = docBase;
         }
       });
     TestCase.assertEquals(query.toString(defaultFieldName), correct, actual);
@@ -143,7 +148,7 @@
   /** Tests that a Hits has an expected order of documents */
   public static void checkDocIds(String mes, int[] results, ScoreDoc[] hits)
   throws IOException {
-    TestCase.assertEquals(mes + " nr of hits", results.length, hits.length);
+    TestCase.assertEquals(mes + " nr of hits", hits.length, results.length);
     for (int i = 0; i < results.length; i++) {
       TestCase.assertEquals(mes + " doc nrs for hit " + i, results[i], hits[i].doc);
     }
@@ -390,7 +395,7 @@
       super.search(query,results);
     }
     public void search(Query query, Filter filter,
-                       HitCollector results) throws IOException {
+        HitCollector results) throws IOException {
       checkExplanations(query);
       super.search(query,filter, results);
     }
@@ -411,7 +416,7 @@
    *
    * @see CheckHits#verifyExplanation
    */
-  public static class ExplanationAsserter extends HitCollector {
+  public static class ExplanationAsserter extends MultiReaderHitCollector {
 
     /**
      * @deprecated
@@ -423,7 +428,9 @@
     Searcher s;
     String d;
     boolean deep;
-    
+
+    private int base = -1;
+
     /** Constructs an instance which does shallow tests on the Explanation */
     public ExplanationAsserter(Query q, String defaultFieldName, Searcher s) {
       this(q,defaultFieldName,s,false);
@@ -437,7 +444,7 @@
 
     public void collect(int doc, float score) {
       Explanation exp = null;
-      
+      doc = doc + base;
       try {
         exp = s.explain(q, doc);
       } catch (IOException e) {
@@ -449,6 +456,9 @@
                              exp);
       verifyExplanation(d,doc,score,deep,exp);
     }
+    public void setNextReader(IndexReader reader, int docBase) {
+      base = docBase;
+    }
     
   }
 

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/QueryUtils.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/QueryUtils.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/QueryUtils.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/QueryUtils.java Tue Jan 27 20:15:21 2009
@@ -8,6 +8,8 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
+import org.apache.lucene.index.IndexReader;
+
 /**
  * Copyright 2005 Apache Software Foundation
  *
@@ -151,8 +153,10 @@
 
       final int[] sdoc = new int[] {-1};
       final float maxDiff = 1e-5f;
-      s.search(q,new HitCollector() {
+      s.search(q,new MultiReaderHitCollector() {
+        private int base = -1;
         public void collect(int doc, float score) {
+          doc = doc + base;
           try {
             int op = order[(opidx[0]++)%order.length];
             //System.out.println(op==skip_op ? "skip("+(sdoc[0]+1)+")":"next()");
@@ -183,6 +187,9 @@
             throw new RuntimeException(e);
           }
         }
+        public void setNextReader(IndexReader reader, int docBase) {
+          base = docBase;
+        }
       });
       
       // make sure next call to scorer is false.
@@ -198,9 +205,11 @@
     //System.out.println("checkFirstSkipTo: "+q);
     final float maxDiff = 1e-5f;
     final int lastDoc[] = {-1};
-    s.search(q,new HitCollector() {
+    s.search(q,new MultiReaderHitCollector() {
+      private int base = -1;
       public void collect(int doc, float score) {
         //System.out.println("doc="+doc);
+        doc = doc + base;
         try {
           for (int i=lastDoc[0]+1; i<=doc; i++) {
             Weight w = q.weight(s);
@@ -216,6 +225,9 @@
           throw new RuntimeException(e);
         }
       }
+      public void setNextReader(IndexReader reader, int docBase) {
+        base = docBase;
+      }
     });
     Weight w = q.weight(s);
     Scorer scorer = w.scorer(s.getIndexReader());

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/TestDocBoost.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/TestDocBoost.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/TestDocBoost.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/TestDocBoost.java Tue Jan 27 20:15:21 2009
@@ -20,6 +20,7 @@
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.lucene.analysis.SimpleAnalyzer;
 import org.apache.lucene.document.*;
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.store.RAMDirectory;
@@ -65,9 +66,13 @@
 
     new IndexSearcher(store).search
       (new TermQuery(new Term("field", "word")),
-       new HitCollector() {
+       new MultiReaderHitCollector() {
+         private int base = -1;
          public final void collect(int doc, float score) {
-           scores[doc] = score;
+           scores[doc + base] = score;
+         }
+         public void setNextReader(IndexReader reader, int docBase) {
+           base = docBase;
          }
        });
 

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/TestMultiTermConstantScore.java Tue Jan 27 20:15:21 2009
@@ -168,9 +168,13 @@
     // must use a non score normalizing method for this.
     Query q = csrq("data", "1", "6", T, T);
     q.setBoost(100);
-    search.search(q, null, new HitCollector() {
+    search.search(q, null, new MultiReaderHitCollector() {
+      private int base = -1;
       public void collect(int doc, float score) {
-        assertEquals("score for doc " + doc + " was not correct", 1.0f, score);
+        assertEquals("score for doc " + (doc + base) + " was not correct", 1.0f, score);
+      }
+      public void setNextReader(IndexReader reader, int docBase) {
+        base = docBase;
       }
     });
 
@@ -588,7 +592,6 @@
 
     IndexReader reader = IndexReader.open(danishIndex);
     IndexSearcher search = new IndexSearcher(reader);
-    Query q = new TermQuery(new Term("body","body"));
 
     Collator c = Collator.getInstance(new Locale("da", "dk"));
 

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/TestScorerPerf.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/TestScorerPerf.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/TestScorerPerf.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/TestScorerPerf.java Tue Jan 27 20:15:21 2009
@@ -5,7 +5,6 @@
 
 import java.util.Random;
 import java.util.BitSet;
-import java.util.Set;
 import java.io.IOException;
 
 import org.apache.lucene.index.IndexReader;
@@ -51,6 +50,7 @@
     // This could possibly fail if Lucene starts checking for docid ranges...
     RAMDirectory rd = new RAMDirectory();
     IndexWriter iw = new IndexWriter(rd,new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
+    iw.addDocument(new Document());
     iw.close();
     s = new IndexSearcher(rd);
   }
@@ -96,17 +96,22 @@
     return sets;
   }
 
-  public static class CountingHitCollector extends HitCollector {
+  public static class CountingHitCollector extends MultiReaderHitCollector {
     int count=0;
     int sum=0;
+    protected int docBase = -1;
 
     public void collect(int doc, float score) {
       count++;
-      sum += doc;  // use it to avoid any possibility of being optimized away
+      sum += docBase+doc;  // use it to avoid any possibility of being optimized away
     }
 
     public int getCount() { return count; }
     public int getSum() { return sum; }
+
+    public void setNextReader(IndexReader reader, int base) {
+      docBase = base;
+    }
   }
 
 
@@ -119,8 +124,8 @@
 
     public void collect(int doc, float score) {
       pos = answer.nextSetBit(pos+1);
-      if (pos != doc) {
-        throw new RuntimeException("Expected doc " + pos + " but got " + doc);
+      if (pos != doc + docBase) {
+        throw new RuntimeException("Expected doc " + pos + " but got " + doc + docBase);
       }
       super.collect(doc,score);
     }
@@ -158,6 +163,7 @@
                                          : new CountingHitCollector();
       s.search(bq, hc);
       ret += hc.getSum();
+
       if (validate) assertEquals(result.cardinality(), hc.getCount());
       // System.out.println(hc.getCount());
     }

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/TestSetNorm.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/TestSetNorm.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/TestSetNorm.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/TestSetNorm.java Tue Jan 27 20:15:21 2009
@@ -62,9 +62,13 @@
 
     new IndexSearcher(store).search
       (new TermQuery(new Term("field", "word")),
-       new HitCollector() {
+       new MultiReaderHitCollector() {
+         private int base = -1;
          public final void collect(int doc, float score) {
-           scores[doc] = score;
+           scores[doc + base] = score;
+         }
+         public void setNextReader(IndexReader reader, int docBase) {
+           base = docBase;
          }
        });
 

Modified: lucene/java/trunk/src/test/org/apache/lucene/search/TestSimilarity.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/src/test/org/apache/lucene/search/TestSimilarity.java?rev=738219&r1=738218&r2=738219&view=diff
==============================================================================
--- lucene/java/trunk/src/test/org/apache/lucene/search/TestSimilarity.java (original)
+++ lucene/java/trunk/src/test/org/apache/lucene/search/TestSimilarity.java Tue Jan 27 20:15:21 2009
@@ -21,9 +21,9 @@
 
 import java.util.Collection;
 
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexWriter;
-import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.store.RAMDirectory;
 import org.apache.lucene.analysis.SimpleAnalyzer;
 import org.apache.lucene.document.Document;
@@ -75,10 +75,11 @@
 
     searcher.search
       (new TermQuery(b),
-       new HitCollector() {
+       new MultiReaderHitCollector() {
          public final void collect(int doc, float score) {
            assertTrue(score == 1.0f);
          }
+         public void setNextReader(IndexReader reader, int docBase) {}
        });
 
     BooleanQuery bq = new BooleanQuery();
@@ -87,10 +88,14 @@
     //System.out.println(bq.toString("field"));
     searcher.search
       (bq,
-       new HitCollector() {
+       new MultiReaderHitCollector() {
+         private int base = -1;
          public final void collect(int doc, float score) {
            //System.out.println("Doc=" + doc + " score=" + score);
-           assertTrue(score == (float)doc+1);
+           assertTrue(score == (float)doc+base+1);
+         }
+         public void setNextReader(IndexReader reader, int docBase) {
+           base = docBase;
          }
        });
 
@@ -100,22 +105,24 @@
     //System.out.println(pq.toString("field"));
     searcher.search
       (pq,
-       new HitCollector() {
+       new MultiReaderHitCollector() {
          public final void collect(int doc, float score) {
            //System.out.println("Doc=" + doc + " score=" + score);
            assertTrue(score == 1.0f);
          }
+         public void setNextReader(IndexReader reader, int docBase) {}
        });
 
     pq.setSlop(2);
     //System.out.println(pq.toString("field"));
     searcher.search
       (pq,
-       new HitCollector() {
+       new MultiReaderHitCollector() {
          public final void collect(int doc, float score) {
            //System.out.println("Doc=" + doc + " score=" + score);
            assertTrue(score == 2.0f);
          }
+         public void setNextReader(IndexReader reader, int docBase) {}
        });
   }
 }



Mime
View raw message