You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by si...@apache.org on 2012/07/19 03:13:59 UTC

svn commit: r1363198 [1/2] - in /lucene/dev/branches/LUCENE-2878/lucene: core/src/java/org/apache/lucene/search/ core/src/java/org/apache/lucene/search/payloads/ core/src/java/org/apache/lucene/search/positions/ core/src/java/org/apache/lucene/search/s...

Author: simonw
Date: Thu Jul 19 01:13:58 2012
New Revision: 1363198

URL: http://svn.apache.org/viewvc?rev=1363198&view=rev
Log:
LUCENE-2878: Added Brouwerian operator, several testcases and introduced matchDistance on position iterators for filtering

Added:
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianIntervalIterator.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianQuery.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionQuery.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/TermIntervalIterator.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinOrderedFilter.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestBrouwerianQuery.java   (with props)
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestPositionFilterQueries.java   (with props)
Removed:
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/MockSpanQuery.java
Modified:
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionScorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionTermScorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ExactPhraseScorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/Scorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BlockPositionIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionPositionIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/DisjunctionPositionIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueue.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueAnd.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueOr.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/MaxLengthPositionIntervalIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionPositionIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionFilterQuery.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionIntervalIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/RangePositionsIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinPositionIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestSimplePositions.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/spans/TestNearSpansOrdered.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/spans/TestPayloadSpans.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/spans/TestSpanFirstQuery.java
    lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/spans/TestSpans.java
    lucene/dev/branches/LUCENE-2878/lucene/highlighter/src/java/org/apache/lucene/search/poshighlight/PositionIntervalArrayIterator.java
    lucene/dev/branches/LUCENE-2878/lucene/highlighter/src/test/org/apache/lucene/search/poshighlight/PosHighlighterTest.java

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionScorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionScorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionScorer.java Thu Jul 19 01:13:58 2012
@@ -17,15 +17,15 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Comparator;
+
 import org.apache.lucene.search.positions.BooleanPositionIterator;
 import org.apache.lucene.search.positions.ConjunctionPositionIterator;
 import org.apache.lucene.search.positions.PositionIntervalIterator;
 import org.apache.lucene.util.ArrayUtil;
 
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Comparator;
-
 /** Scorer for conjunctions, sets of queries, all of which are required. */
 class ConjunctionScorer extends Scorer {
   

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionTermScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionTermScorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionTermScorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ConjunctionTermScorer.java Thu Jul 19 01:13:58 2012
@@ -17,17 +17,17 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.util.Comparator;
+
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.search.TermQuery.TermDocsEnumFactory;
-import org.apache.lucene.search.TermScorer.TermPositions;
 import org.apache.lucene.search.positions.ConjunctionPositionIterator;
 import org.apache.lucene.search.positions.PositionIntervalIterator;
+import org.apache.lucene.search.positions.TermIntervalIterator;
 import org.apache.lucene.search.similarities.Similarity.ExactSimScorer;
 import org.apache.lucene.util.ArrayUtil;
 
-import java.io.IOException;
-import java.util.Comparator;
-
 
 /** Scorer for conjunctions, sets of terms, all of which are required. */
 class ConjunctionTermScorer extends Scorer {
@@ -123,10 +123,10 @@ class ConjunctionTermScorer extends Scor
 
   @Override
   public PositionIntervalIterator positions(boolean needsPayloads, boolean needsOffsets, boolean collectPositions) throws IOException {
-    TermPositions[] positionIters = new TermPositions[origDocsAndFreqs.length];
+    TermIntervalIterator[] positionIters = new TermIntervalIterator[origDocsAndFreqs.length];
     for (int i = 0; i < positionIters.length; i++) {
       DocsAndFreqs d = origDocsAndFreqs[i];
-      positionIters[i] = new TermPositions(this, d.factory.docsAndPositionsEnum(needsOffsets), needsPayloads, collectPositions);
+      positionIters[i] = new TermIntervalIterator(this, d.factory.docsAndPositionsEnum(needsOffsets), needsPayloads, collectPositions);
     }
     return new ConjunctionPositionIterator(this, collectPositions, positionIters);
   }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ExactPhraseScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ExactPhraseScorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ExactPhraseScorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/ExactPhraseScorer.java Thu Jul 19 01:13:58 2012
@@ -20,6 +20,7 @@ package org.apache.lucene.search;
 import org.apache.lucene.index.DocsAndPositionsEnum;
 import org.apache.lucene.search.positions.BlockPositionIterator;
 import org.apache.lucene.search.positions.PositionIntervalIterator;
+import org.apache.lucene.search.positions.TermIntervalIterator;
 import org.apache.lucene.search.similarities.Similarity;
 
 import java.io.IOException;
@@ -326,9 +327,9 @@ final class ExactPhraseScorer extends Sc
   
   @Override
   public PositionIntervalIterator positions(boolean needsPayloads, boolean needsOffsets, boolean collectPositions) throws IOException {
-    TermScorer.TermPositions[] posIters = new TermScorer.TermPositions[chunkStates.length];
+    TermIntervalIterator[] posIters = new TermIntervalIterator[chunkStates.length];
     for (int i = 0; i < chunkStates.length; i++) {
-      posIters[i] = new TermScorer.TermPositions(this, chunkStates[i].factory.docsAndPositionsEnum(needsOffsets), needsPayloads, collectPositions);
+      posIters[i] = new TermIntervalIterator(this, chunkStates[i].factory.docsAndPositionsEnum(needsOffsets), needsPayloads, collectPositions);
     }
     return new BlockPositionIterator(this, collectPositions, posIters);
   }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/Scorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/Scorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/Scorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/Scorer.java Thu Jul 19 01:13:58 2012
@@ -63,6 +63,7 @@ public abstract class Scorer extends Doc
     }
   }
   
+  //nocommit javadocs
   public abstract PositionIntervalIterator positions(boolean needsPayloads, boolean needsOffsets, boolean collectPositions) throws IOException;
 
   /**

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseScorer.java Thu Jul 19 01:13:58 2012
@@ -33,6 +33,7 @@ import org.apache.lucene.index.Term;
 import org.apache.lucene.search.positions.ConjunctionPositionIterator;
 import org.apache.lucene.search.positions.MaxLengthPositionIntervalIterator;
 import org.apache.lucene.search.positions.PositionIntervalIterator;
+import org.apache.lucene.search.positions.TermIntervalIterator;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.OpenBitSet;
 
@@ -559,7 +560,7 @@ final class SloppyPhraseScorer extends P
       if (!map.containsKey(term)) {
         DocsAndPositionsEnum docsAndPosEnum = postings[i].factory
             .docsAndPositionsEnum(needsOffsets);
-        iterAndOffset = new IterAndOffsets(new TermScorer.TermPositions(this, docsAndPosEnum, needsPayloads,
+        iterAndOffset = new IterAndOffsets(new TermIntervalIterator(this, docsAndPosEnum, needsPayloads,
             collectPositions));
         map.put(term, iterAndOffset);
       } else {

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java Thu Jul 19 01:13:58 2012
@@ -23,6 +23,7 @@ import org.apache.lucene.index.DocsAndPo
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.search.TermQuery.TermDocsEnumFactory;
 import org.apache.lucene.search.positions.PositionIntervalIterator;
+import org.apache.lucene.search.positions.TermIntervalIterator;
 import org.apache.lucene.search.positions.PositionIntervalIterator.PositionInterval;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.BytesRef;
@@ -98,100 +99,6 @@ final class TermScorer extends Scorer {
   
   @Override
   public PositionIntervalIterator positions(boolean needsPayloads, boolean needsOffsets, boolean collectPositions) throws IOException {
-    return new TermPositions(this, factory.docsAndPositionsEnum(needsOffsets), needsPayloads, collectPositions);
-  }
-
- static final class TermPositions extends PositionIntervalIterator {
-    private final PositionInterval interval;
-    int positionsPending;
-    private final DocsAndPositionsEnum docsAndPos;
-    private int docID = -1;
-
-    public TermPositions(Scorer scorer, DocsAndPositionsEnum docsAndPos, boolean doPayloads,  boolean collectPositions) {
-      super(scorer, collectPositions);
-      this.docsAndPos = docsAndPos;
-      this.interval = doPayloads ? new PayloadPosInterval(docsAndPos, this)
-          : new PositionInterval();
-    }
-
-    @Override
-    public PositionInterval next() throws IOException {
-      if (--positionsPending >= 0) {
-        interval.begin = interval.end = docsAndPos.nextPosition();
-        interval.offsetBegin = docsAndPos.startOffset();
-        interval.offsetEnd = docsAndPos.endOffset();
-        return interval;
-      }
-      positionsPending = 0;
-      return null;
-    }
-
-    @Override
-    public int docID() {
-      return docID;
-    }
-
-    @Override
-    public PositionIntervalIterator[] subs(boolean inOrder) {
-      return EMPTY;
-    }
-
-    @Override
-    public void collect(PositionCollector collector) {
-      collector.collectLeafPosition(scorer, interval, docID);
-    }
-
-    @Override
-    public int advanceTo(int docId) throws IOException {
-      int advance = docsAndPos.advance(docId);
-      if (advance != NO_MORE_DOCS) {
-        positionsPending = docsAndPos.freq();
-      }
-      interval.reset();
-      return docID = docsAndPos.docID();
-    }
-    
-    @Override
-    public String toString() {
-      return "TermPositions [interval=" + interval + ", positionsPending="
-          + positionsPending + ", docID=" + docID + "]";
-    }
-  }
-
-  private static final class PayloadPosInterval extends PositionInterval {
-    private int pos = -1;
-    private final DocsAndPositionsEnum payloads;
-    private final TermPositions termPos;
-
-    public PayloadPosInterval(DocsAndPositionsEnum payloads, TermPositions pos) {
-      this.payloads = payloads;
-      this.termPos = pos;
-    }
-
-    @Override
-    public boolean payloadAvailable() {
-      return payloads.hasPayload();
-    }
-
-    @Override
-    public boolean nextPayload(BytesRef ref) throws IOException {
-      if (pos == termPos.positionsPending) {
-        return false;
-      } else {
-        pos = termPos.positionsPending;
-        final BytesRef payload = payloads.getPayload();
-        ref.bytes = payload.bytes;
-        ref.length = payload.length;
-        ref.offset = payload.offset;
-        return true;
-      }
-    }
-
-    @Override
-    public void reset() {
-      super.reset();
-      pos = -1;
-    }
-
+    return new TermIntervalIterator(this, factory.docsAndPositionsEnum(needsOffsets), needsPayloads, collectPositions);
   }
 }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java Thu Jul 19 01:13:58 2012
@@ -19,15 +19,19 @@ package org.apache.lucene.search.payload
 
 import org.apache.lucene.index.AtomicReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.*;
-import org.apache.lucene.search.positions.PositionIntervalIterator.PositionInterval;
+import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.ComplexExplanation;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.search.similarities.Similarity.SloppySimScorer;
-import org.apache.lucene.search.spans.SpanScorer;
+import org.apache.lucene.search.spans.TermSpans;
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.search.spans.SpanWeight;
-import org.apache.lucene.search.spans.SpansScorerWrapper;
+import org.apache.lucene.search.spans.SpanScorer;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 
@@ -76,17 +80,17 @@ public class PayloadTermQuery extends Sp
     @Override
     public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder,
         boolean topScorer, Bits acceptDocs) throws IOException {
-      return new PayloadTermSpanScorer((SpansScorerWrapper) query.getSpans(context, acceptDocs, termContexts),
+      return new PayloadTermSpanScorer((TermSpans) query.getSpans(context, acceptDocs, termContexts),
           this, similarity.sloppySimScorer(stats, context));
     }
 
     protected class PayloadTermSpanScorer extends SpanScorer {
-      protected BytesRef payload = new BytesRef();
+      protected BytesRef payload;
       protected float payloadScore;
       protected int payloadsSeen;
-      private final SpansScorerWrapper termSpans;
+      private final TermSpans termSpans;
 
-      public PayloadTermSpanScorer(SpansScorerWrapper spans, Weight weight, Similarity.SloppySimScorer docScorer) throws IOException {
+      public PayloadTermSpanScorer(TermSpans spans, Weight weight, Similarity.SloppySimScorer docScorer) throws IOException {
         super(spans, weight, docScorer);
         termSpans = spans;
       }
@@ -113,19 +117,19 @@ public class PayloadTermQuery extends Sp
       }
 
       protected void processPayload(Similarity similarity) throws IOException {
-        if (termSpans.isPayloadAvailable()) {
-          
-          final PositionInterval current = termSpans.current();
-          if (current.nextPayload(payload) && payload.length != 0) {
+        final DocsAndPositionsEnum postings = termSpans.getPostings();
+        if (postings.hasPayload()) {
+          payload = postings.getPayload();
+          if (payload != null) {
             payloadScore = function.currentScore(doc, term.field(),
-                spans.start(), spans.end(), payloadsSeen, payloadScore,
-                docScorer.computePayloadFactor(doc, spans.start(), spans.end(), payload));
+                                                 spans.start(), spans.end(), payloadsSeen, payloadScore,
+                                                 docScorer.computePayloadFactor(doc, spans.start(), spans.end(), payload));
           } else {
             payloadScore = function.currentScore(doc, term.field(),
-                spans.start(), spans.end(), payloadsSeen, payloadScore, 1F);
+                                                 spans.start(), spans.end(), payloadsSeen, payloadScore, 1F);
           }
           payloadsSeen++;
-          
+
         } else {
           // zero out the payload?
         }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BlockPositionIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BlockPositionIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BlockPositionIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BlockPositionIterator.java Thu Jul 19 01:13:58 2012
@@ -16,12 +16,11 @@ package org.apache.lucene.search.positio
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.positions.PositionIntervalIterator.PositionCollector;
-
 import java.io.IOException;
 import java.util.Arrays;
 
+import org.apache.lucene.search.Scorer;
+
 /**
  * 
  * @lucene.experimental
@@ -153,4 +152,9 @@ public final class BlockPositionIterator
     Arrays.fill(intervals, INFINITE_INTERVAL);
     return currentDoc = docId;
   }
+
+  @Override
+  public int matchDistance() {
+    return intervals[lastIter].begin - intervals[0].end;
+  }
 }

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianIntervalIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianIntervalIterator.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianIntervalIterator.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianIntervalIterator.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,81 @@
+package org.apache.lucene.search.positions;
+
+import java.io.IOException;
+
+import org.apache.lucene.search.Scorer;
+
+/*
+ * 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.
+ */
+
+public class BrouwerianIntervalIterator extends PositionIntervalIterator {
+  
+  private final PositionIntervalIterator minuted;
+  private final PositionIntervalIterator subtracted;
+  private PositionInterval subtractedInterval = new PositionInterval();
+  private PositionInterval currentInterval = new PositionInterval();
+  private int secondDoc = -1;
+
+  public BrouwerianIntervalIterator(Scorer scorer, boolean collectPositions, PositionIntervalIterator minuted, PositionIntervalIterator subtracted) {
+    super(scorer, collectPositions);
+    this.minuted = minuted;
+    this.subtracted = subtracted;
+  }
+  
+
+  @Override
+  public int advanceTo(int docId) throws IOException {
+    currentDoc = minuted.advanceTo(docId);
+    secondDoc  = subtracted.advanceTo(docId);
+    subtractedInterval.reset();
+    return currentDoc;
+  }
+  
+  @Override
+  public PositionInterval next() throws IOException {
+    if (secondDoc != currentDoc) {
+      return currentInterval = minuted.next();
+    }
+    while ((currentInterval = minuted.next()) != null) {
+      while(subtractedInterval.lessThan(currentInterval) && (subtractedInterval = subtracted.next()) != null) {
+      }
+      if (subtractedInterval == null || subtractedInterval.greaterThan(currentInterval)) {
+        return currentInterval;
+      }
+    }
+    return currentInterval;
+  }
+  
+  @Override
+  public void collect(PositionCollector collector) {
+    assert collectPositions;
+    collector.collectComposite(scorer, currentInterval, currentDoc);
+    minuted.collect(collector);
+    
+  }
+  
+  @Override
+  public PositionIntervalIterator[] subs(boolean inOrder) {
+    return new PositionIntervalIterator[] {minuted, subtracted};
+  }
+
+
+  @Override
+  public int matchDistance() {
+    return minuted.matchDistance();
+  }
+  
+}

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianQuery.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianQuery.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/BrouwerianQuery.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,215 @@
+package org.apache.lucene.search.positions;
+
+/*
+ * 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 java.util.Set;
+
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.util.Bits;
+
+/**
+ *
+ * @lucene.experimental
+ */ // nocommit - javadoc
+public final class BrouwerianQuery extends Query implements Cloneable {
+  
+  private Query minuted;
+  private Query subtracted;
+
+
+  public BrouwerianQuery(Query minuted, Query subtracted) {
+    this.minuted = minuted;
+    this.subtracted = subtracted;
+  }
+
+  @Override
+  public void extractTerms(Set<Term> terms) {
+    minuted.extractTerms(terms);
+    subtracted.extractTerms(terms);
+  }
+
+  @Override
+  public Query rewrite(IndexReader reader) throws IOException {
+    BrouwerianQuery clone = null;
+
+    Query rewritten =  minuted.rewrite(reader);
+    Query subRewritten =  subtracted.rewrite(reader);
+    if (rewritten != minuted || subRewritten != subtracted) {
+      clone = (BrouwerianQuery) this.clone();
+      clone.minuted = rewritten;
+      clone.subtracted = subRewritten;
+    }
+
+    if (clone != null) {
+      return clone; // some clauses rewrote
+    } else {
+      return this; // no clauses rewrote
+    }
+  }
+
+  @Override
+  public Weight createWeight(IndexSearcher searcher) throws IOException {
+    return new BrouwerianQueryWeight(minuted.createWeight(searcher), subtracted.createWeight(searcher));
+  }
+
+  class BrouwerianQueryWeight extends Weight {
+
+    private final Weight minuted;
+    private final Weight subtracted;
+
+    public BrouwerianQueryWeight(Weight minuted, Weight subtracted) {
+      this.minuted = minuted;
+      this.subtracted = subtracted;
+    }
+
+    @Override
+    public Explanation explain(AtomicReaderContext context, int doc)
+        throws IOException {
+      return minuted.explain(context, doc);
+    }
+
+    @Override
+    public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder,
+        boolean topScorer, Bits acceptDocs) throws IOException {
+      final Scorer scorer = minuted.scorer(context, scoreDocsInOrder, topScorer, acceptDocs);
+      final Scorer subScorer = subtracted.scorer(context, scoreDocsInOrder, topScorer, acceptDocs);
+      if (subScorer == null) {
+        return scorer;
+      }
+      return scorer == null ? null : new PositionFilterScorer(this, scorer, subScorer);
+    }
+
+    @Override
+    public Query getQuery() {
+      return BrouwerianQuery.this;
+    }
+    
+    @Override
+    public float getValueForNormalization() throws IOException {
+      return minuted.getValueForNormalization();
+    }
+
+    @Override
+    public void normalize(float norm, float topLevelBoost) {
+      minuted.normalize(norm, topLevelBoost);
+    }
+  }
+
+  class PositionFilterScorer extends Scorer {
+
+    private final Scorer other;
+    private PositionIntervalIterator filter;
+    private final Scorer substracted;
+
+    public PositionFilterScorer(Weight weight, Scorer other, Scorer substacted) throws IOException {
+      super(weight);
+      this.other = other;
+      this.substracted = substacted;
+      this.filter = new BrouwerianIntervalIterator(other, false, other.positions(false, false, false), substacted.positions(false, false, false));
+    }
+
+    @Override
+    public float score() throws IOException {
+      return other.score();
+    }
+
+    @Override
+    public PositionIntervalIterator positions(boolean needsPayloads, boolean needsOffsets, boolean collectPositions) throws IOException {
+      return new BrouwerianIntervalIterator(other, collectPositions, other.positions(needsPayloads, needsOffsets, collectPositions), substracted.positions(needsPayloads, needsOffsets, collectPositions));
+    }
+
+    @Override
+    public int docID() {
+      return other.docID();
+    }
+
+    @Override
+    public int nextDoc() throws IOException {
+      int docId = -1;
+      while ((docId = other.nextDoc()) != Scorer.NO_MORE_DOCS) {
+        filter.advanceTo(docId);
+        if (filter.next() != null) { // just check if there is a position that matches!
+          return other.docID();
+        }
+      }
+      return Scorer.NO_MORE_DOCS;
+    }
+
+    @Override
+    public int advance(int target) throws IOException {
+      int docId = other.advance(target);
+      if (docId == Scorer.NO_MORE_DOCS) {
+        return NO_MORE_DOCS;
+      }
+      do {
+        filter.advanceTo(docId);
+        if (filter.next() != null) {
+          return other.docID();
+        }
+      } while ((docId = other.nextDoc()) != Scorer.NO_MORE_DOCS);
+      return NO_MORE_DOCS;
+    }
+
+  }
+
+  @Override
+  public String toString(String field) {
+    //nocommit TODO
+    return minuted.toString();
+  }
+
+  /* 
+   *
+   */
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = super.hashCode();
+    result = prime * result + ((minuted == null) ? 0 : minuted.hashCode());
+    result = prime * result
+        + ((subtracted == null) ? 0 : subtracted.hashCode());
+    return result;
+  }
+
+  /* 
+   *
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) return true;
+    if (!super.equals(obj)) return false;
+    if (getClass() != obj.getClass()) return false;
+    BrouwerianQuery other = (BrouwerianQuery) obj;
+    if (minuted == null) {
+      if (other.minuted != null) return false;
+    } else if (!minuted.equals(other.minuted)) return false;
+    if (subtracted == null) {
+      if (other.subtracted != null) return false;
+    } else if (!subtracted.equals(other.subtracted)) return false;
+    return true;
+  }
+
+}
\ No newline at end of file

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionPositionIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionPositionIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionPositionIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/ConjunctionPositionIterator.java Thu Jul 19 01:13:58 2012
@@ -38,6 +38,8 @@ public final class ConjunctionPositionIt
   private final IntervalQueueAnd queue;
   private final int nrMustMatch;
   private SnapshotPositionCollector snapshot;
+  private int rightExtremeBegin;
+  
 
   public ConjunctionPositionIterator(Scorer scorer, boolean collectPositions,
       PositionIntervalIterator... iterators) throws IOException {
@@ -58,7 +60,7 @@ public final class ConjunctionPositionIt
     PositionInterval interval = null;
     if ((interval = iterators[top.index].next()) != null) {
       top.interval = interval;
-      queue.updateRightExtreme(interval);
+      queue.updateRightExtreme(top);
       queue.updateTop();
     } else {
       queue.pop();
@@ -86,7 +88,7 @@ public final class ConjunctionPositionIt
           && queue.currentCandidate.end == top.end) {
         return queue.currentCandidate;
       }
-     
+      rightExtremeBegin = queue.rightExtremeBegin;
       advance();
       if (queue.size() < nrMustMatch) {
         break;
@@ -97,21 +99,31 @@ public final class ConjunctionPositionIt
   
   
   @Override
-  public int advanceTo(int docId) throws IOException {
-    queue.reset();
-    int advancedTo = -1;
-    for (int i = 0; i < iterators.length; i++) {
-      currentDoc = iterators[i].advanceTo(docId);
-      assert advancedTo == -1 || advancedTo == currentDoc;
-      
-      final PositionInterval interval = iterators[i].next();
-      if (interval != null) {
-        IntervalRef intervalRef = new IntervalRef(interval, i); // TODO maybe reuse?
-        queue.updateRightExtreme(intervalRef.interval);
-        queue.add(intervalRef);
+  public int advanceTo(final int docId) throws IOException {
+    int advancedTo = docId;
+    while (true) {
+      queue.reset();
+      for (int i = 0; i < iterators.length; i++) {
+        currentDoc = iterators[i].advanceTo(advancedTo);
+        if (currentDoc == NO_MORE_DOCS) {
+          return NO_MORE_DOCS;
+        }
+        
+        if (i != 0 && currentDoc != advancedTo) {
+          advancedTo = currentDoc;
+          continue;
+        }
+        advancedTo = currentDoc;
+        final PositionInterval interval = iterators[i].next();
+        if (interval != null) {
+          IntervalRef intervalRef = new IntervalRef(interval, i); // TODO maybe
+                                                                  // reuse?
+          queue.updateRightExtreme(intervalRef);
+          queue.add(intervalRef);
+        }
       }
+      return currentDoc;
     }
-    return currentDoc;
   }
   
   
@@ -227,4 +239,9 @@ public final class ConjunctionPositionIt
     }
     
   }
+
+  @Override
+  public int matchDistance() {
+    return (rightExtremeBegin) - (queue.currentTopEnd) -1; // align the match if pos are adjacent
+  }
 }
\ No newline at end of file

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/DisjunctionPositionIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/DisjunctionPositionIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/DisjunctionPositionIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/DisjunctionPositionIterator.java Thu Jul 19 01:13:58 2012
@@ -20,7 +20,6 @@ import java.io.IOException;
 
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.positions.IntervalQueue.IntervalRef;
-import org.apache.lucene.search.positions.PositionIntervalIterator.PositionCollector;
 
 /**
  * DisjunctionPositionIterator based on minimal interval semantics for OR
@@ -53,7 +52,7 @@ public final class DisjunctionPositionIt
 
   @Override
   public PositionInterval next() throws IOException {
-    while (queue.size() > 0 && queue.topContainsQueueInterval()) {
+    while (queue.size() > 0 && queue.top().interval.begin <= queue.currentCandidate.begin) {
       advance();
     }
     if (queue.size() == 0) {
@@ -77,7 +76,7 @@ public final class DisjunctionPositionIt
 
   @Override
   public int advanceTo(int docId) throws IOException {
-    queue.clear();
+    queue.reset();
     int minAdvance = NO_MORE_DOCS;
     for (int i = 0; i < iterators.length; i++) {
       if (iterators[i].docID() < docId) {
@@ -97,4 +96,9 @@ public final class DisjunctionPositionIt
     return currentDoc = minAdvance;
   }
 
+  @Override
+  public int matchDistance() {
+    return iterators[queue.top().index].matchDistance();
+  }
+
 }
\ No newline at end of file

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueue.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueue.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueue.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueue.java Thu Jul 19 01:13:58 2012
@@ -31,6 +31,10 @@ abstract class IntervalQueue extends Pri
 
   public void reset() {
     clear();
+    currentCandidate.begin = Integer.MIN_VALUE;
+    currentCandidate.end = Integer.MIN_VALUE;
+    currentCandidate.offsetBegin = -1;
+    currentCandidate.offsetEnd = -1;
   }
 
   abstract public boolean topContainsQueueInterval();
@@ -43,7 +47,6 @@ abstract class IntervalQueue extends Pri
 
   final static class IntervalRef {
     PositionInterval interval;
-    int ord;
     int index;
 
     IntervalRef(PositionInterval interval, int index) {

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueAnd.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueAnd.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueAnd.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueAnd.java Thu Jul 19 01:13:58 2012
@@ -25,6 +25,9 @@ final class IntervalQueueAnd extends Int
 
   int rightExtreme = Integer.MIN_VALUE;
   int rightExtremeOffset = Integer.MIN_VALUE;
+  int rightExtremeBegin;  
+  int currentTopEnd;
+  
   
   public IntervalQueueAnd(int size) {
     super(size);
@@ -32,15 +35,17 @@ final class IntervalQueueAnd extends Int
 
   public void reset () {
     super.reset();
-    currentCandidate.begin = Integer.MIN_VALUE;
-    currentCandidate.end = Integer.MIN_VALUE;
     rightExtreme = Integer.MIN_VALUE;
     rightExtremeOffset = Integer.MIN_VALUE;
   }
 
-  public void updateRightExtreme(PositionInterval interval) {
-    rightExtreme = Math.max(rightExtreme, interval.end);
-    rightExtremeOffset = Math.max(rightExtremeOffset, interval.offsetEnd);
+  public void updateRightExtreme(IntervalRef intervalRef) {
+    final PositionInterval interval = intervalRef.interval;
+    if (rightExtreme <= interval.end) {
+      rightExtreme = interval.end;
+      rightExtremeOffset = interval.offsetEnd;
+      rightExtremeBegin = interval.begin;
+    }
   }
   
   public boolean topContainsQueueInterval() {
@@ -50,11 +55,14 @@ final class IntervalQueueAnd extends Int
   }
  
   public void updateCurrentCandidate() {
-    PositionInterval interval = top().interval;
+    final IntervalRef top = top();
+    PositionInterval interval = top.interval;
     currentCandidate.begin = interval.begin;
     currentCandidate.offsetBegin = interval.offsetBegin;
     currentCandidate.end = rightExtreme;
     currentCandidate.offsetEnd = rightExtremeOffset;
+    currentTopEnd = interval.end;
+        
   }
   
   @Override
@@ -63,4 +71,5 @@ final class IntervalQueueAnd extends Int
     final PositionInterval b = right.interval;
     return a.begin < b.begin || (a.begin == b.begin && a.end > b.end) || a.offsetBegin < b.offsetBegin;
   }
+  
 }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueOr.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueOr.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueOr.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/IntervalQueueOr.java Thu Jul 19 01:13:58 2012
@@ -26,10 +26,6 @@ final class IntervalQueueOr extends Inte
     super(size);
   }
   
-  public void reset() {
-    clear();
-  }
-  
   public boolean topContainsQueueInterval() {
     PositionInterval interval = top().interval;
     return interval.begin <= currentCandidate.begin
@@ -44,7 +40,7 @@ final class IntervalQueueOr extends Inte
   protected boolean lessThan(IntervalRef left, IntervalRef right) {
     final PositionInterval a = left.interval;
     final PositionInterval b = right.interval;
-    return a.end < b.end|| (a.end == b.end && a.begin >= b.begin);
+    return a.end < b.end || (a.end == b.end && a.begin >= b.begin);
   }
 
 }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/MaxLengthPositionIntervalIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/MaxLengthPositionIntervalIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/MaxLengthPositionIntervalIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/MaxLengthPositionIntervalIterator.java Thu Jul 19 01:13:58 2012
@@ -19,13 +19,12 @@ package org.apache.lucene.search.positio
 import java.io.IOException;
 
 import org.apache.lucene.search.Scorer;
-import org.apache.lucene.search.positions.IntervalQueue.IntervalRef;
 
 /**
  * An interval iterator that has the semantics of sloppy phrase query.
  */
 public class MaxLengthPositionIntervalIterator extends PositionIntervalIterator {
-  
+  //TODO rename to sloppy iter?
   private final int maxLen;
   private int matchDistance;
   private final PositionIntervalIterator iterator;
@@ -60,7 +59,7 @@ public class MaxLengthPositionIntervalIt
     return currentDoc = iterator.advanceTo(docId);
   }
   
-  public int matchLength() {
+  public int matchDistance() {
     return matchDistance;
   }
   
@@ -114,6 +113,11 @@ public class MaxLengthPositionIntervalIt
     public PositionIntervalIterator[] subs(boolean inOrder) {
       return null;
     }
+
+    @Override
+    public int matchDistance() {
+      return sloppyInterval.end - sloppyInterval.begin;
+    }
     
   }
   
@@ -201,6 +205,11 @@ public class MaxLengthPositionIntervalIt
     public PositionIntervalIterator[] subs(boolean inOrder) {
       return new PositionIntervalIterator[] {groupIterator};
     }
+
+    @Override
+    public int matchDistance() {
+      return sloppyGroupInterval.end - sloppyGroupInterval.begin;
+    }
     
   }
   

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionPositionIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionPositionIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionPositionIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionPositionIterator.java Thu Jul 19 01:13:58 2012
@@ -34,7 +34,10 @@ public final class OrderedConjunctionPos
   private final PositionInterval interval = new PositionInterval(
       Integer.MAX_VALUE, Integer.MAX_VALUE, -1, -1);
   private int index = 1;
-
+  private int lastTopEnd;
+  private int lastEndBegin;
+  
+  
   public OrderedConjunctionPositionIterator(boolean collectPositions, PositionIntervalIterator other) {
     super(other.scorer, collectPositions);
     assert other.subs(true) != null;
@@ -85,6 +88,8 @@ public final class OrderedConjunctionPos
       interval.end = intervals[lastIter].end;
       interval.offsetBegin = intervals[0].offsetBegin;
       interval.offsetEnd = intervals[lastIter].offsetEnd;
+      lastTopEnd = intervals[0].end;
+      lastEndBegin = intervals[lastIter].begin;
       b = intervals[lastIter].begin;
       index = 1;
       intervals[0] = iterators[0].next();
@@ -124,4 +129,9 @@ public final class OrderedConjunctionPos
     return currentDoc = docId;
   }
 
+  @Override
+  public int matchDistance() {
+    return (lastEndBegin-lastIter) - lastTopEnd;
+  }
+
 }

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionQuery.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionQuery.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/OrderedConjunctionQuery.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,38 @@
+package org.apache.lucene.search.positions;
+
+/*
+ * 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.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+
+public class OrderedConjunctionQuery extends PositionFilterQuery {
+
+  public OrderedConjunctionQuery(int slop, Query... queries) {
+    super(buildBooleanQuery(queries), new WithinOrderedFilter(slop + queries.length - 1));
+  }
+
+  private static BooleanQuery buildBooleanQuery(Query... queries) {
+    BooleanQuery bq = new BooleanQuery();
+    for (Query q : queries) {
+      bq.add(q, BooleanClause.Occur.MUST);
+    }
+    return bq;
+  }
+
+}

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionFilterQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionFilterQuery.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionFilterQuery.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionFilterQuery.java Thu Jul 19 01:13:58 2012
@@ -80,7 +80,16 @@ public class PositionFilterQuery extends
     @Override
     public Explanation explain(AtomicReaderContext context, int doc)
         throws IOException {
-      return other.explain(context, doc);
+      Scorer scorer = scorer(context, true, false, context.reader()
+          .getLiveDocs());
+      if (scorer != null) {
+        int newDoc = scorer.advance(doc);
+        if (newDoc == doc) {
+          return other.explain(context, doc);
+        }
+      }
+      return new ComplexExplanation(false, 0.0f,
+          "No matching term within position filter");
     }
 
     @Override
@@ -110,7 +119,6 @@ public class PositionFilterQuery extends
 
     private final Scorer other;
     private PositionIntervalIterator filter;
-    private final FilteredPositions filtered;
 
     public PositionFilterScorer(Weight weight, Scorer other) throws IOException {
       super(weight);
@@ -119,7 +127,6 @@ public class PositionFilterQuery extends
       this.filter = PositionFilterQuery.this.filter != null
           ? PositionFilterQuery.this.filter.filter(other.positions(false, false, false))
           : other.positions(false, false, false);
-      filtered = new FilteredPositions(this, filter);
     }
 
     @Override
@@ -143,7 +150,7 @@ public class PositionFilterQuery extends
       int docId = -1;
       while ((docId = other.nextDoc()) != Scorer.NO_MORE_DOCS) {
         filter.advanceTo(docId);
-        if ((filtered.interval = filter.next()) != null) { // just check if there is a position that matches!
+        if (filter.next() != null) { // just check if there is a position that matches!
           return other.docID();
         }
       }
@@ -158,7 +165,7 @@ public class PositionFilterQuery extends
       }
       do {
         filter.advanceTo(docId);
-        if ((filtered.interval = filter.next()) != null) {
+        if (filter.next() != null) {
           return other.docID();
         }
       } while ((docId = other.nextDoc()) != Scorer.NO_MORE_DOCS);
@@ -169,42 +176,9 @@ public class PositionFilterQuery extends
 
   @Override
   public String toString(String field) {
-    return inner.toString();
+    return filter.toString() + "(" + inner.toString() + ")";
   }
   
-  private final class FilteredPositions extends PositionIntervalIterator {
-    public FilteredPositions(Scorer scorer, PositionIntervalIterator other) {
-      super(scorer, other.collectPositions);
-      this.other = other;
-    }
-
-    private final PositionIntervalIterator other;
-    PositionInterval interval;
-    @Override
-    public int advanceTo(int docId) throws IOException {
-      return currentDoc = other.docID();
-    }
-
-    @Override
-    public PositionInterval next() throws IOException {
-      PositionInterval current = this.interval;
-      this.interval = null;
-      return current;
-    }
-
-    @Override
-    public void collect(PositionCollector collector) {
-      assert this.collectPositions;
-      other.collect(collector);
-      
-    }
-    @Override
-    public PositionIntervalIterator[] subs(boolean inOrder) {
-      return EMPTY;
-    }
-
-  }
-
   @Override
   public int hashCode() {
     final int prime = 31;

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionIntervalIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionIntervalIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionIntervalIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/PositionIntervalIterator.java Thu Jul 19 01:13:58 2012
@@ -24,30 +24,34 @@ import java.io.IOException;
 /**
  * 
  * @lucene.experimental
- */ // nocommit - javadoc
+ */
+// nocommit - javadoc
 public abstract class PositionIntervalIterator {
-
+  
   public static final PositionIntervalIterator[] EMPTY = new PositionIntervalIterator[0];
   public static final PositionIntervalIterator NO_MORE_POSITIONS = new NoPositionsIntervalIterator();
   public static final int NO_MORE_DOCS = Integer.MAX_VALUE;
-
+  
   protected int currentDoc = -1;
   protected final Scorer scorer;
   protected final boolean collectPositions;
-
+  
   public PositionIntervalIterator(Scorer scorer, boolean collectPositions) {
     this.scorer = scorer;
     this.collectPositions = collectPositions;
   }
-
+  
   public abstract int advanceTo(int docId) throws IOException;
-
+  
   public abstract PositionInterval next() throws IOException;
-
+  
   public abstract void collect(PositionCollector collector);
-
+  
   public abstract PositionIntervalIterator[] subs(boolean inOrder);
   
+  
+  public abstract int matchDistance();
+  
   public int docID() {
     return currentDoc;
   }
@@ -55,28 +59,48 @@ public abstract class PositionIntervalIt
   public Scorer getScorer() {
     return scorer;
   }
-
+  
   public static interface PositionIntervalFilter {
     public abstract PositionIntervalIterator filter(
         PositionIntervalIterator iter);
   }
-
+  
   public static class PositionInterval implements Cloneable {
-
+    
     public int begin;
     public int end;
     public int offsetBegin;
     public int offsetEnd;
-
+    
     public PositionInterval(int begin, int end, int offsetBegin, int offsetEnd) {
       this.begin = begin;
       this.end = end;
       this.offsetBegin = offsetBegin;
       this.offsetEnd = offsetEnd;
     }
-
+    
     public PositionInterval() {
-      this(0, 0, -1, -1);
+      this(Integer.MIN_VALUE, Integer.MIN_VALUE, -1, -1);
+    }
+    
+    public boolean lessThanExclusive(PositionInterval other) {
+      return begin < other.begin && end < other.end;
+    }
+    
+    public boolean lessThan(PositionInterval other) {
+      return begin <= other.begin && end <= other.end;
+    }
+    
+    public boolean greaterThanExclusive(PositionInterval other) {
+      return begin > other.begin && end > other.end;
+    }
+    
+    public boolean greaterThan(PositionInterval other) {
+      return begin >= other.begin && end >= other.end;
+    }
+    
+    public boolean contains(PositionInterval other) {
+      return begin <= other.begin && other.end <= end;
     }
     
     public void copy(PositionInterval other) {
@@ -85,19 +109,20 @@ public abstract class PositionIntervalIt
       offsetBegin = other.offsetBegin;
       offsetEnd = other.offsetEnd;
     }
-
+    
     public boolean nextPayload(BytesRef ref) throws IOException {
       return false;
     }
-
+    
     public boolean payloadAvailable() {
       return false;
     }
-
+    
     public void reset() {
-      offsetBegin = offsetEnd = begin = end = -1;
+      offsetBegin = offsetEnd = -1;
+      begin = end = Integer.MIN_VALUE;
     }
-
+    
     @Override
     public Object clone() {
       try {
@@ -106,45 +131,54 @@ public abstract class PositionIntervalIt
         throw new RuntimeException(); // should not happen
       }
     }
-
+    
     @Override
     public String toString() {
-      return "PositionInterval [begin=" + begin + "(" + offsetBegin + "), end=" + end + "(" + offsetEnd + ")]";
+      return "PositionInterval [begin=" + begin + "(" + offsetBegin + "), end="
+          + end + "(" + offsetEnd + ")]";
     }
-
+    
   }
-
+  
   public static interface PositionCollector {
-    public void collectLeafPosition(Scorer scorer, PositionInterval interval, int docID);
-    public void collectComposite(Scorer scorer, PositionInterval interval, int docID);
-
+    public void collectLeafPosition(Scorer scorer, PositionInterval interval,
+        int docID);
+    
+    public void collectComposite(Scorer scorer, PositionInterval interval,
+        int docID);
+    
   }
   
   private static final class NoPositionsIntervalIterator extends
-  PositionIntervalIterator {
-
+      PositionIntervalIterator {
+    
     public NoPositionsIntervalIterator() {
       super(null, false);
     }
-
+    
     @Override
     public int advanceTo(int docId) throws IOException {
       return PositionIntervalIterator.NO_MORE_DOCS;
     }
-
+    
     @Override
     public PositionInterval next() throws IOException {
       return null;
     }
-
+    
     @Override
     public void collect(PositionCollector collectoc) {}
-
+    
     @Override
     public PositionIntervalIterator[] subs(boolean inOrder) {
       return EMPTY;
     }
+
+    @Override
+    public int matchDistance() {
+      return Integer.MAX_VALUE;
+    }
     
   }
-
+  
 }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/RangePositionsIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/RangePositionsIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/RangePositionsIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/RangePositionsIterator.java Thu Jul 19 01:13:58 2012
@@ -18,7 +18,6 @@ package org.apache.lucene.search.positio
 
 import java.io.IOException;
 
-import org.apache.lucene.search.positions.PositionIntervalIterator.PositionCollector;
 import org.apache.lucene.search.positions.PositionIntervalIterator.PositionIntervalFilter;
 
 /**
@@ -76,6 +75,11 @@ public class RangePositionsIterator exte
   public int advanceTo(int docId) throws IOException {
     return currentDoc = iterator.advanceTo(docId);
   }
+
+  @Override
+  public int matchDistance() {
+    return iterator.matchDistance();
+  }
   
   
 

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/TermIntervalIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/TermIntervalIterator.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/TermIntervalIterator.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/TermIntervalIterator.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,127 @@
+package org.apache.lucene.search.positions;
+/*
+ * 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.DocsAndPositionsEnum;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.util.BytesRef;
+
+
+/**
+ * 
+ */
+//nocommmit javadocs
+public final class TermIntervalIterator extends PositionIntervalIterator {
+  private final PositionInterval interval;
+  int positionsPending;
+  private final DocsAndPositionsEnum docsAndPos;
+  private int docID = -1;
+
+  public TermIntervalIterator(Scorer scorer, DocsAndPositionsEnum docsAndPos, boolean doPayloads,  boolean collectPositions) {
+    super(scorer, collectPositions);
+    this.docsAndPos = docsAndPos;
+    this.interval = doPayloads ? new PayloadPosInterval(docsAndPos, this)
+        : new PositionInterval();
+  }
+
+  @Override
+  public PositionInterval next() throws IOException {
+    if (--positionsPending >= 0) {
+      interval.begin = interval.end = docsAndPos.nextPosition();
+      interval.offsetBegin = docsAndPos.startOffset();
+      interval.offsetEnd = docsAndPos.endOffset();
+      return interval;
+    }
+    positionsPending = 0;
+    return null;
+  }
+
+  @Override
+  public int docID() {
+    return docID;
+  }
+
+  @Override
+  public PositionIntervalIterator[] subs(boolean inOrder) {
+    return EMPTY;
+  }
+
+  @Override
+  public void collect(PositionCollector collector) {
+    collector.collectLeafPosition(scorer, interval, docID);
+  }
+
+  @Override
+  public int advanceTo(int docId) throws IOException {
+    int advance = docsAndPos.advance(docId);
+    if (advance != NO_MORE_DOCS) {
+      positionsPending = docsAndPos.freq();
+    }
+    interval.reset();
+    return docID = docsAndPos.docID();
+  }
+  
+  @Override
+  public String toString() {
+    return "TermPositions [interval=" + interval + ", positionsPending="
+        + positionsPending + ", docID=" + docID + "]";
+  }
+
+  @Override
+  public int matchDistance() {
+    return 0;
+  }
+  
+  private static final class PayloadPosInterval extends PositionInterval {
+    private int pos = -1;
+    private final DocsAndPositionsEnum payloads;
+    private final TermIntervalIterator termPos;
+
+    public PayloadPosInterval(DocsAndPositionsEnum payloads, TermIntervalIterator pos) {
+      this.payloads = payloads;
+      this.termPos = pos;
+    }
+
+    @Override
+    public boolean payloadAvailable() {
+      return payloads.hasPayload();
+    }
+
+    @Override
+    public boolean nextPayload(BytesRef ref) throws IOException {
+      if (pos == termPos.positionsPending) {
+        return false;
+      } else {
+        pos = termPos.positionsPending;
+        final BytesRef payload = payloads.getPayload();
+        ref.bytes = payload.bytes;
+        ref.length = payload.length;
+        ref.offset = payload.offset;
+        return true;
+      }
+    }
+
+    @Override
+    public void reset() {
+      super.reset();
+      pos = -1;
+    }
+
+  }
+}
\ No newline at end of file

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinOrderedFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinOrderedFilter.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinOrderedFilter.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinOrderedFilter.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,39 @@
+package org.apache.lucene.search.positions;
+
+/*
+ * 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.
+ */
+
+public class WithinOrderedFilter implements PositionIntervalIterator.PositionIntervalFilter {
+
+  private int slop;
+
+  public WithinOrderedFilter(int slop) {
+    this.slop = slop;
+  }
+
+  @Override
+  public PositionIntervalIterator filter(PositionIntervalIterator iter) {
+    return new WithinPositionIterator(slop,
+        new OrderedConjunctionPositionIterator(false, iter));
+  }
+
+  @Override
+  public String toString() {
+    return "WithinOrderedFilter[" + slop + "]";
+  }
+
+}

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinPositionIterator.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinPositionIterator.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinPositionIterator.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/positions/WithinPositionIterator.java Thu Jul 19 01:13:58 2012
@@ -17,7 +17,6 @@ package org.apache.lucene.search.positio
  */
 import java.io.IOException;
 
-import org.apache.lucene.search.positions.PositionIntervalIterator.PositionCollector;
 import org.apache.lucene.search.positions.PositionIntervalIterator.PositionIntervalFilter;
 
 
@@ -41,7 +40,7 @@ public class WithinPositionIterator exte
   @Override
   public PositionInterval next() throws IOException {
     while ((interval = iterator.next()) != null) {
-      if((interval.end - interval.begin) <= howMany){
+      if((iterator.matchDistance()) <= howMany){
         return interval;
       }
     }
@@ -69,4 +68,9 @@ public class WithinPositionIterator exte
     return currentDoc = iterator.advanceTo(docId);
   }
 
+  @Override
+  public int matchDistance() {
+    return iterator.matchDistance();
+  }
+
 }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java Thu Jul 19 01:13:58 2012
@@ -17,13 +17,13 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-import org.apache.lucene.search.Scorer;
+import java.io.IOException;
+
 import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.positions.PositionIntervalIterator;
 import org.apache.lucene.search.similarities.Similarity;
 
-import java.io.IOException;
-
 /**
  * Public for extension only.
  */
@@ -100,7 +100,8 @@ public class SpanScorer extends Scorer {
   }
 
   @Override
-  public PositionIntervalIterator positions(boolean needsPayloads, boolean needsOffsets, boolean collectPositions) throws IOException {
+  public PositionIntervalIterator positions(boolean needsPayloads,
+      boolean needsOffsets, boolean collectPositions) throws IOException {
     return null;
   }
 }

Modified: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java?rev=1363198&r1=1363197&r2=1363198&view=diff
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java (original)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java Thu Jul 19 01:13:58 2012
@@ -1,6 +1,6 @@
 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.
@@ -17,40 +17,51 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-import java.util.Set;
-
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.TermContext;
+import org.apache.lucene.index.TermState;
+import org.apache.lucene.index.Terms;
+import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.ToStringUtils;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
 
 /** Matches spans containing a term. */
-public class SpanTermQuery extends MockSpanQuery {
+public class SpanTermQuery extends SpanQuery {
   protected Term term;
 
   /** Construct a SpanTermQuery matching the named term's spans. */
-  public SpanTermQuery(Term term) {
-    this(term, true);
-  }
-
-  public SpanTermQuery(Term term, boolean needsPayloads) {
-    this(term, new TermQuery(term), needsPayloads);
-  }
-
-  private SpanTermQuery(Term term, TermQuery query, boolean needsPayloads) {
-    super(query, needsPayloads, term.field(), null);
-    this.term = term;
-  }
+  public SpanTermQuery(Term term) { this.term = term; }
 
   /** Return the term whose spans are matched. */
-  public Term getTerm() {
-    return term;
-  }
+  public Term getTerm() { return term; }
 
   @Override
+  public String getField() { return term.field(); }
+  
+  @Override
   public void extractTerms(Set<Term> terms) {
     terms.add(term);
   }
 
   @Override
+  public String toString(String field) {
+    StringBuilder buffer = new StringBuilder();
+    if (term.field().equals(field))
+      buffer.append(term.text());
+    else
+      buffer.append(term.toString());
+    buffer.append(ToStringUtils.boost(getBoost()));
+    return buffer.toString();
+  }
+
+  @Override
   public int hashCode() {
     final int prime = 31;
     int result = super.hashCode();
@@ -60,14 +71,62 @@ public class SpanTermQuery extends MockS
 
   @Override
   public boolean equals(Object obj) {
-    if (this == obj) return true;
-    if (!super.equals(obj)) return false;
-    if (getClass() != obj.getClass()) return false;
+    if (this == obj)
+      return true;
+    if (!super.equals(obj))
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
     SpanTermQuery other = (SpanTermQuery) obj;
     if (term == null) {
-      if (other.term != null) return false;
-    } else if (!term.equals(other.term)) return false;
+      if (other.term != null)
+        return false;
+    } else if (!term.equals(other.term))
+      return false;
     return true;
   }
 
+  @Override
+  public Spans getSpans(final AtomicReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts) throws IOException {
+    TermContext termContext = termContexts.get(term);
+    final TermState state;
+    if (termContext == null) {
+      // this happens with span-not query, as it doesn't include the NOT side in extractTerms()
+      // so we seek to the term now in this segment..., this sucks because its ugly mostly!
+      final Fields fields = context.reader().fields();
+      if (fields != null) {
+        final Terms terms = fields.terms(term.field());
+        if (terms != null) {
+          final TermsEnum termsEnum = terms.iterator(null);
+          if (termsEnum.seekExact(term.bytes(), true)) { 
+            state = termsEnum.termState();
+          } else {
+            state = null;
+          }
+        } else {
+          state = null;
+        }
+      } else {
+        state = null;
+      }
+    } else {
+      state = termContext.get(context.ord);
+    }
+    
+    if (state == null) { // term is not present in that reader
+      return TermSpans.EMPTY_TERM_SPANS;
+    }
+    
+    final TermsEnum termsEnum = context.reader().terms(term.field()).iterator(null);
+    termsEnum.seekExact(term.bytes(), state);
+    
+    final DocsAndPositionsEnum postings = termsEnum.docsAndPositions(acceptDocs, null, false);
+
+    if (postings != null) {
+      return new TermSpans(postings, term);
+    } else {
+      // term does exist, but has no positions
+      throw new IllegalStateException("field \"" + term.field() + "\" was indexed without position data; cannot run SpanTermQuery (term=" + term.text() + ")");
+    }
+  }
 }

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,169 @@
+package org.apache.lucene.search.spans;
+/**
+ * Copyright 2005 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.
+ */
+
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.util.BytesRef;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Collection;
+
+/**
+ * Expert:
+ * Public for extension only
+ */
+public class TermSpans extends Spans {
+  protected final DocsAndPositionsEnum postings;
+  protected final Term term;
+  protected int doc;
+  protected int freq;
+  protected int count;
+  protected int position;
+
+  public TermSpans(DocsAndPositionsEnum postings, Term term) {
+    this.postings = postings;
+    this.term = term;
+    doc = -1;
+  }
+
+  // only for EmptyTermSpans (below)
+  TermSpans() {
+    term = null;
+    postings = null;
+  }
+
+  @Override
+  public boolean next() throws IOException {
+    if (count == freq) {
+      if (postings == null) {
+        return false;
+      }
+      doc = postings.nextDoc();
+      if (doc == DocIdSetIterator.NO_MORE_DOCS) {
+        return false;
+      }
+      freq = postings.freq();
+      count = 0;
+    }
+    position = postings.nextPosition();
+    count++;
+    return true;
+  }
+
+  @Override
+  public boolean skipTo(int target) throws IOException {
+    doc = postings.advance(target);
+    if (doc == DocIdSetIterator.NO_MORE_DOCS) {
+      return false;
+    }
+
+    freq = postings.freq();
+    count = 0;
+    position = postings.nextPosition();
+    count++;
+
+    return true;
+  }
+
+  @Override
+  public int doc() {
+    return doc;
+  }
+
+  @Override
+  public int start() {
+    return position;
+  }
+
+  @Override
+  public int end() {
+    return position + 1;
+  }
+
+  // TODO: Remove warning after API has been finalized
+  @Override
+  public Collection<byte[]> getPayload() throws IOException {
+    final BytesRef payload = postings.getPayload();
+    final byte[] bytes;
+    if (payload != null) {
+      bytes = new byte[payload.length];
+      System.arraycopy(payload.bytes, payload.offset, bytes, 0, payload.length);
+    } else {
+      bytes = null;
+    }
+    return Collections.singletonList(bytes);
+  }
+
+  // TODO: Remove warning after API has been finalized
+  @Override
+  public boolean isPayloadAvailable() {
+    return postings.hasPayload();
+  }
+
+  @Override
+  public String toString() {
+    return "spans(" + term.toString() + ")@" +
+            (doc == -1 ? "START" : (doc == Integer.MAX_VALUE) ? "END" : doc + "-" + position);
+  }
+
+  public DocsAndPositionsEnum getPostings() {
+    return postings;
+  }
+
+  private static final class EmptyTermSpans extends TermSpans {
+
+    @Override
+    public boolean next() {
+      return false;
+    }
+
+    @Override
+    public boolean skipTo(int target) {
+      return false;
+    }
+
+    @Override
+    public int doc() {
+      return DocIdSetIterator.NO_MORE_DOCS;
+    }
+    
+    @Override
+    public int start() {
+      return -1;
+    }
+
+    @Override
+    public int end() {
+      return -1;
+    }
+
+    @Override
+    public Collection<byte[]> getPayload() {
+      return null;
+    }
+
+    @Override
+    public boolean isPayloadAvailable() {
+      return false;
+    }
+  }
+
+  public static final TermSpans EMPTY_TERM_SPANS = new EmptyTermSpans();
+}

Added: lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestBrouwerianQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestBrouwerianQuery.java?rev=1363198&view=auto
==============================================================================
--- lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestBrouwerianQuery.java (added)
+++ lucene/dev/branches/LUCENE-2878/lucene/core/src/test/org/apache/lucene/search/positions/TestBrouwerianQuery.java Thu Jul 19 01:13:58 2012
@@ -0,0 +1,159 @@
+package org.apache.lucene.search.positions;
+/**
+ * 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 java.util.List;
+
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.TextField;
+import org.apache.lucene.index.AtomicReaderContext;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexReaderContext;
+import org.apache.lucene.index.RandomIndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TopDocs;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.positions.PositionIntervalIterator.PositionInterval;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+
+public class TestBrouwerianQuery extends LuceneTestCase {
+  
+  private static final void addDocs(RandomIndexWriter writer) throws CorruptIndexException, IOException {
+    {
+      Document doc = new Document();
+      doc.add(newField(
+          "field",
+          "The quick brown fox jumps over the lazy dog",
+              TextField.TYPE_STORED));
+      writer.addDocument(doc);
+    }
+    
+    {
+      Document doc = new Document();
+      doc.add(newField(
+          "field",
+          "The quick brown duck jumps over the lazy dog with the quick brown fox",
+              TextField.TYPE_STORED));
+      writer.addDocument(doc);
+    }
+  }
+  
+  public void testBrouwerianBooleanQuery() throws IOException {
+    Directory directory = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
+        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())));
+    addDocs(writer);
+    
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = new IndexSearcher(reader);
+    writer.close();
+    BooleanQuery query = new BooleanQuery();
+    query.add(new BooleanClause(new TermQuery(new Term("field", "the")), Occur.MUST));
+    query.add(new BooleanClause(new TermQuery(new Term("field", "quick")), Occur.MUST));
+    query.add(new BooleanClause(new TermQuery(new Term("field", "jumps")), Occur.MUST));
+    BooleanQuery sub = new BooleanQuery();
+    sub.add(new BooleanClause(new TermQuery(new Term("field", "fox")), Occur.MUST));
+    BrouwerianQuery q = new BrouwerianQuery(query, sub);
+    TopDocs search = searcher.search(q, 10);
+    ScoreDoc[] scoreDocs = search.scoreDocs;
+    assertEquals(1, search.totalHits);
+    assertEquals(1, scoreDocs[0].doc);
+    
+    reader.close();
+    directory.close();
+  }
+  
+  public void testBrouwerianBooleanQueryExcludedDoesNotExist() throws IOException {
+    Directory directory = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
+        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())));
+    addDocs(writer);
+    
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = new IndexSearcher(reader);
+    writer.close();
+    BooleanQuery query = new BooleanQuery();
+    query.add(new BooleanClause(new TermQuery(new Term("field", "the")), Occur.MUST));
+    query.add(new BooleanClause(new TermQuery(new Term("field", "quick")), Occur.MUST));
+    query.add(new BooleanClause(new TermQuery(new Term("field", "jumps")), Occur.MUST));
+    BooleanQuery sub = new BooleanQuery();
+    sub.add(new BooleanClause(new TermQuery(new Term("field", "blox")), Occur.MUST));
+    BrouwerianQuery q = new BrouwerianQuery(query, sub);
+    TopDocs search = searcher.search(q, 10);
+    ScoreDoc[] scoreDocs = search.scoreDocs;
+    assertEquals(2, search.totalHits);
+    assertEquals(0, scoreDocs[0].doc);
+    assertEquals(1, scoreDocs[1].doc);
+
+    
+    reader.close();
+    directory.close();
+  }
+  
+  public void testPositions() throws IOException {
+    Directory directory = newDirectory();
+    RandomIndexWriter writer = new RandomIndexWriter(random(), directory,
+        newIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random())));
+    addDocs(writer);
+    
+    IndexReader reader = writer.getReader();
+    IndexSearcher searcher = new IndexSearcher(reader);
+    writer.close();
+    BooleanQuery query = new BooleanQuery();
+    query.add(new BooleanClause(new TermQuery(new Term("field", "the")), Occur.MUST));
+    query.add(new BooleanClause(new TermQuery(new Term("field", "quick")), Occur.MUST));
+    query.add(new BooleanClause(new TermQuery(new Term("field", "jumps")), Occur.MUST));
+    BooleanQuery sub = new BooleanQuery();
+    sub.add(new BooleanClause(new TermQuery(new Term("field", "fox")), Occur.MUST));
+    BrouwerianQuery q = new BrouwerianQuery(query, sub);
+    Weight weight = q.createWeight(searcher);
+    IndexReaderContext topReaderContext = searcher.getTopReaderContext();
+    List<AtomicReaderContext> leaves = topReaderContext.leaves();
+    assertEquals(1, leaves.size());
+    for (AtomicReaderContext atomicReaderContext : leaves) {
+      Scorer scorer = weight.scorer(atomicReaderContext, true, true, atomicReaderContext.reader().getLiveDocs());
+        int nextDoc = scorer.nextDoc();
+        assertEquals(1, nextDoc);
+        PositionIntervalIterator positions = scorer.positions(false, false, false);
+        assertEquals(1, positions.advanceTo(nextDoc));
+        PositionInterval interval = null;
+        int[] start = new int[] {0, 1, 4};
+        int[] end = new int[] {4, 6, 11};
+        for (int j = 0; j < end.length; j++) {
+          interval = positions.next();
+          assertNotNull("" + j, interval);
+          assertEquals(start[j], interval.begin);
+          assertEquals(end[j], interval.end);
+        }
+        assertNull(positions.next());
+        assertEquals(Scorer.NO_MORE_DOCS, scorer.nextDoc());
+    reader.close();
+    directory.close();
+  }
+  
+  }
+}