pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.4.0 / lucene / src / java / org / apache / lucene / search / spans / NearSpansOrdered.java
diff --git a/lucene-java-3.4.0/lucene/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java b/lucene-java-3.4.0/lucene/src/java/org/apache/lucene/search/spans/NearSpansOrdered.java
deleted file mode 100644 (file)
index 9b1ff5c..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-package org.apache.lucene.search.spans;
-
-/**
- * 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.ArrayUtil;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Collection;
-import java.util.Set;
-
-/** A Spans that is formed from the ordered subspans of a SpanNearQuery
- * where the subspans do not overlap and have a maximum slop between them.
- * <p>
- * The formed spans only contains minimum slop matches.<br>
- * The matching slop is computed from the distance(s) between
- * the non overlapping matching Spans.<br>
- * Successive matches are always formed from the successive Spans
- * of the SpanNearQuery.
- * <p>
- * The formed spans may contain overlaps when the slop is at least 1.
- * For example, when querying using
- * <pre>t1 t2 t3</pre>
- * with slop at least 1, the fragment:
- * <pre>t1 t2 t1 t3 t2 t3</pre>
- * matches twice:
- * <pre>t1 t2 .. t3      </pre>
- * <pre>      t1 .. t2 t3</pre>
- *
- *
- * Expert:
- * Only public for subclassing.  Most implementations should not need this class
- */
-public class NearSpansOrdered extends Spans {
-  private final int allowedSlop;
-  private boolean firstTime = true;
-  private boolean more = false;
-
-  /** The spans in the same order as the SpanNearQuery */
-  private final Spans[] subSpans;
-
-  /** Indicates that all subSpans have same doc() */
-  private boolean inSameDoc = false;
-
-  private int matchDoc = -1;
-  private int matchStart = -1;
-  private int matchEnd = -1;
-  private List<byte[]> matchPayload;
-
-  private final Spans[] subSpansByDoc;
-  private final Comparator<Spans> spanDocComparator = new Comparator<Spans>() {
-    public int compare(Spans o1, Spans o2) {
-      return o1.doc() - o2.doc();
-    }
-  };
-  
-  private SpanNearQuery query;
-  private boolean collectPayloads = true;
-  
-  public NearSpansOrdered(SpanNearQuery spanNearQuery, IndexReader reader) throws IOException {
-    this(spanNearQuery, reader, true);
-  }
-
-  public NearSpansOrdered(SpanNearQuery spanNearQuery, IndexReader reader, boolean collectPayloads)
-  throws IOException {
-    if (spanNearQuery.getClauses().length < 2) {
-      throw new IllegalArgumentException("Less than 2 clauses: "
-                                         + spanNearQuery);
-    }
-    this.collectPayloads = collectPayloads;
-    allowedSlop = spanNearQuery.getSlop();
-    SpanQuery[] clauses = spanNearQuery.getClauses();
-    subSpans = new Spans[clauses.length];
-    matchPayload = new LinkedList<byte[]>();
-    subSpansByDoc = new Spans[clauses.length];
-    for (int i = 0; i < clauses.length; i++) {
-      subSpans[i] = clauses[i].getSpans(reader);
-      subSpansByDoc[i] = subSpans[i]; // used in toSameDoc()
-    }
-    query = spanNearQuery; // kept for toString() only.
-  }
-
-  // inherit javadocs
-  @Override
-  public int doc() { return matchDoc; }
-
-  // inherit javadocs
-  @Override
-  public int start() { return matchStart; }
-
-  // inherit javadocs
-  @Override
-  public int end() { return matchEnd; }
-  
-  public Spans[] getSubSpans() {
-         return subSpans;
-  }  
-
-  // TODO: Remove warning after API has been finalized
-  // TODO: Would be nice to be able to lazy load payloads
-  @Override
-  public Collection<byte[]> getPayload() throws IOException {
-    return matchPayload;
-  }
-
-  // TODO: Remove warning after API has been finalized
-  @Override
-  public boolean isPayloadAvailable() {
-    return matchPayload.isEmpty() == false;
-  }
-
-  // inherit javadocs
-  @Override
-  public boolean next() throws IOException {
-    if (firstTime) {
-      firstTime = false;
-      for (int i = 0; i < subSpans.length; i++) {
-        if (! subSpans[i].next()) {
-          more = false;
-          return false;
-        }
-      }
-      more = true;
-    }
-    if(collectPayloads) {
-      matchPayload.clear();
-    }
-    return advanceAfterOrdered();
-  }
-
-  // inherit javadocs
-  @Override
-  public boolean skipTo(int target) throws IOException {
-    if (firstTime) {
-      firstTime = false;
-      for (int i = 0; i < subSpans.length; i++) {
-        if (! subSpans[i].skipTo(target)) {
-          more = false;
-          return false;
-        }
-      }
-      more = true;
-    } else if (more && (subSpans[0].doc() < target)) {
-      if (subSpans[0].skipTo(target)) {
-        inSameDoc = false;
-      } else {
-        more = false;
-        return false;
-      }
-    }
-    if(collectPayloads) {
-      matchPayload.clear();
-    }
-    return advanceAfterOrdered();
-  }
-  
-  /** Advances the subSpans to just after an ordered match with a minimum slop
-   * that is smaller than the slop allowed by the SpanNearQuery.
-   * @return true iff there is such a match.
-   */
-  private boolean advanceAfterOrdered() throws IOException {
-    while (more && (inSameDoc || toSameDoc())) {
-      if (stretchToOrder() && shrinkToAfterShortestMatch()) {
-        return true;
-      }
-    }
-    return false; // no more matches
-  }
-
-
-  /** Advance the subSpans to the same document */
-  private boolean toSameDoc() throws IOException {
-    ArrayUtil.mergeSort(subSpansByDoc, spanDocComparator);
-    int firstIndex = 0;
-    int maxDoc = subSpansByDoc[subSpansByDoc.length - 1].doc();
-    while (subSpansByDoc[firstIndex].doc() != maxDoc) {
-      if (! subSpansByDoc[firstIndex].skipTo(maxDoc)) {
-        more = false;
-        inSameDoc = false;
-        return false;
-      }
-      maxDoc = subSpansByDoc[firstIndex].doc();
-      if (++firstIndex == subSpansByDoc.length) {
-        firstIndex = 0;
-      }
-    }
-    for (int i = 0; i < subSpansByDoc.length; i++) {
-      assert (subSpansByDoc[i].doc() == maxDoc)
-             : " NearSpansOrdered.toSameDoc() spans " + subSpansByDoc[0]
-                                 + "\n at doc " + subSpansByDoc[i].doc()
-                                 + ", but should be at " + maxDoc;
-    }
-    inSameDoc = true;
-    return true;
-  }
-  
-  /** Check whether two Spans in the same document are ordered.
-   * @param spans1 
-   * @param spans2 
-   * @return true iff spans1 starts before spans2
-   *              or the spans start at the same position,
-   *              and spans1 ends before spans2.
-   */
-  static final boolean docSpansOrdered(Spans spans1, Spans spans2) {
-    assert spans1.doc() == spans2.doc() : "doc1 " + spans1.doc() + " != doc2 " + spans2.doc();
-    int start1 = spans1.start();
-    int start2 = spans2.start();
-    /* Do not call docSpansOrdered(int,int,int,int) to avoid invoking .end() : */
-    return (start1 == start2) ? (spans1.end() < spans2.end()) : (start1 < start2);
-  }
-
-  /** Like {@link #docSpansOrdered(Spans,Spans)}, but use the spans
-   * starts and ends as parameters.
-   */
-  private static final boolean docSpansOrdered(int start1, int end1, int start2, int end2) {
-    return (start1 == start2) ? (end1 < end2) : (start1 < start2);
-  }
-
-  /** Order the subSpans within the same document by advancing all later spans
-   * after the previous one.
-   */
-  private boolean stretchToOrder() throws IOException {
-    matchDoc = subSpans[0].doc();
-    for (int i = 1; inSameDoc && (i < subSpans.length); i++) {
-      while (! docSpansOrdered(subSpans[i-1], subSpans[i])) {
-        if (! subSpans[i].next()) {
-          inSameDoc = false;
-          more = false;
-          break;
-        } else if (matchDoc != subSpans[i].doc()) {
-          inSameDoc = false;
-          break;
-        }
-      }
-    }
-    return inSameDoc;
-  }
-
-  /** The subSpans are ordered in the same doc, so there is a possible match.
-   * Compute the slop while making the match as short as possible by advancing
-   * all subSpans except the last one in reverse order.
-   */
-  private boolean shrinkToAfterShortestMatch() throws IOException {
-    matchStart = subSpans[subSpans.length - 1].start();
-    matchEnd = subSpans[subSpans.length - 1].end();
-    Set<byte[]> possibleMatchPayloads = new HashSet<byte[]>();
-    if (subSpans[subSpans.length - 1].isPayloadAvailable()) {
-      possibleMatchPayloads.addAll(subSpans[subSpans.length - 1].getPayload());
-    }
-
-    Collection<byte[]> possiblePayload = null;
-    
-    int matchSlop = 0;
-    int lastStart = matchStart;
-    int lastEnd = matchEnd;
-    for (int i = subSpans.length - 2; i >= 0; i--) {
-      Spans prevSpans = subSpans[i];
-      if (collectPayloads && prevSpans.isPayloadAvailable()) {
-        Collection<byte[]> payload = prevSpans.getPayload();
-        possiblePayload = new ArrayList<byte[]>(payload.size());
-        possiblePayload.addAll(payload);
-      }
-      
-      int prevStart = prevSpans.start();
-      int prevEnd = prevSpans.end();
-      while (true) { // Advance prevSpans until after (lastStart, lastEnd)
-        if (! prevSpans.next()) {
-          inSameDoc = false;
-          more = false;
-          break; // Check remaining subSpans for final match.
-        } else if (matchDoc != prevSpans.doc()) {
-          inSameDoc = false; // The last subSpans is not advanced here.
-          break; // Check remaining subSpans for last match in this document.
-        } else {
-          int ppStart = prevSpans.start();
-          int ppEnd = prevSpans.end(); // Cannot avoid invoking .end()
-          if (! docSpansOrdered(ppStart, ppEnd, lastStart, lastEnd)) {
-            break; // Check remaining subSpans.
-          } else { // prevSpans still before (lastStart, lastEnd)
-            prevStart = ppStart;
-            prevEnd = ppEnd;
-            if (collectPayloads && prevSpans.isPayloadAvailable()) {
-              Collection<byte[]> payload = prevSpans.getPayload();
-              possiblePayload = new ArrayList<byte[]>(payload.size());
-              possiblePayload.addAll(payload);
-            }
-          }
-        }
-      }
-
-      if (collectPayloads && possiblePayload != null) {
-        possibleMatchPayloads.addAll(possiblePayload);
-      }
-      
-      assert prevStart <= matchStart;
-      if (matchStart > prevEnd) { // Only non overlapping spans add to slop.
-        matchSlop += (matchStart - prevEnd);
-      }
-
-      /* Do not break on (matchSlop > allowedSlop) here to make sure
-       * that subSpans[0] is advanced after the match, if any.
-       */
-      matchStart = prevStart;
-      lastStart = prevStart;
-      lastEnd = prevEnd;
-    }
-    
-    boolean match = matchSlop <= allowedSlop;
-    
-    if(collectPayloads && match && possibleMatchPayloads.size() > 0) {
-      matchPayload.addAll(possibleMatchPayloads);
-    }
-
-    return match; // ordered and allowed slop
-  }
-
-  @Override
-  public String toString() {
-    return getClass().getName() + "("+query.toString()+")@"+
-      (firstTime?"START":(more?(doc()+":"+start()+"-"+end()):"END"));
-  }
-}
-