You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ro...@apache.org on 2014/11/12 15:56:24 UTC

svn commit: r1638805 [4/8] - in /lucene/dev/lucene2878: dev-tools/idea/lucene/highlighter/ lucene/analysis/common/src/test/org/apache/lucene/analysis/sinks/ lucene/analysis/common/src/test/org/apache/lucene/analysis/standard/ lucene/codecs/src/java/org...

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermQuery.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermQuery.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermQuery.java Wed Nov 12 14:56:17 2014
@@ -17,71 +17,75 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.util.Set;
-
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.DocsEnum;
-import org.apache.lucene.index.LeafReader;
 import org.apache.lucene.index.IndexReaderContext;
+import org.apache.lucene.index.LeafReader;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.ReaderUtil;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.TermsEnum;
-import org.apache.lucene.search.similarities.Similarity.SimScorer;
 import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.search.similarities.Similarity.SimScorer;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.ToStringUtils;
 
-/** A Query that matches documents containing a term.
-  This may be combined with other terms with a {@link BooleanQuery}.
-  */
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * A Query that matches documents containing a term. This may be combined with
+ * other terms with a {@link BooleanQuery}.
+ */
 public class TermQuery extends Query {
   private final Term term;
   private final int docFreq;
   private final TermContext perReaderTermState;
-
+  
   final class TermWeight extends Weight {
     private final Similarity similarity;
     private final Similarity.SimWeight stats;
     private final TermContext termStates;
-
+    
     public TermWeight(IndexSearcher searcher, TermContext termStates)
-      throws IOException {
+        throws IOException {
       assert termStates != null : "TermContext must not be null";
       this.termStates = termStates;
       this.similarity = searcher.getSimilarity();
-      this.stats = similarity.computeWeight(
-          getBoost(), 
-          searcher.collectionStatistics(term.field()), 
+      this.stats = similarity.computeWeight(getBoost(),
+          searcher.collectionStatistics(term.field()),
           searcher.termStatistics(term, termStates));
     }
-
+    
     @Override
-    public String toString() { return "weight(" + TermQuery.this + ")"; }
-
+    public String toString() {
+      return "weight(" + TermQuery.this + ")";
+    }
+    
     @Override
-    public Query getQuery() { return TermQuery.this; }
-
+    public Query getQuery() {
+      return TermQuery.this;
+    }
+    
     @Override
     public float getValueForNormalization() {
       return stats.getValueForNormalization();
     }
-
+    
     @Override
     public void normalize(float queryNorm, float topLevelBoost) {
       stats.normalize(queryNorm, topLevelBoost);
     }
-
+    
     @Override
-    public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
+    public Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException {
       assert termStates.topReaderContext == ReaderUtil.getTopLevelContext(context) : "The top-reader used to create Weight (" + termStates.topReaderContext + ") is not the same as the current reader's top-reader (" + ReaderUtil.getTopLevelContext(context);
       final TermsEnum termsEnum = getTermsEnum(context);
       if (termsEnum == null) {
         return null;
       }
-      DocsEnum docs = termsEnum.docs(acceptDocs, null);
+      DocsEnum docs = termsEnum.docs(acceptDocs, null, flags);
       assert docs != null;
       return new TermScorer(this, docs, similarity.simScorer(stats, context));
     }
@@ -96,90 +100,100 @@ public class TermQuery extends Query {
         assert termNotInReader(context.reader(), term) : "no termstate found but term exists in reader term=" + term;
         return null;
       }
-      //System.out.println("LD=" + reader.getLiveDocs() + " set?=" + (reader.getLiveDocs() != null ? reader.getLiveDocs().get(0) : "null"));
-      final TermsEnum termsEnum = context.reader().terms(term.field()).iterator(null);
+      // System.out.println("LD=" + reader.getLiveDocs() + " set?=" +
+      // (reader.getLiveDocs() != null ? reader.getLiveDocs().get(0) : "null"));
+      final TermsEnum termsEnum = context.reader().terms(term.field())
+          .iterator(null);
       termsEnum.seekExact(term.bytes(), state);
       return termsEnum;
     }
     
     private boolean termNotInReader(LeafReader reader, Term term) throws IOException {
       // only called from assert
-      //System.out.println("TQ.termNotInReader reader=" + reader + " term=" + field + ":" + bytes.utf8ToString());
+      // System.out.println("TQ.termNotInReader reader=" + reader + " term=" +
+      // field + ":" + bytes.utf8ToString());
       return reader.docFreq(term) == 0;
     }
     
     @Override
     public Explanation explain(LeafReaderContext context, int doc) throws IOException {
-      Scorer scorer = scorer(context, context.reader().getLiveDocs());
+      Scorer scorer = scorer(context, DocsEnum.FLAG_FREQS, context.reader().getLiveDocs());
       if (scorer != null) {
         int newDoc = scorer.advance(doc);
         if (newDoc == doc) {
           float freq = scorer.freq();
           SimScorer docScorer = similarity.simScorer(stats, context);
           ComplexExplanation result = new ComplexExplanation();
-          result.setDescription("weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:");
-          Explanation scoreExplanation = docScorer.explain(doc, new Explanation(freq, "termFreq=" + freq));
+          result.setDescription("weight(" + getQuery() + " in " + doc + ") ["
+              + similarity.getClass().getSimpleName() + "], result of:");
+          Explanation scoreExplanation = docScorer.explain(doc,
+              new Explanation(freq, "termFreq=" + freq));
           result.addDetail(scoreExplanation);
           result.setValue(scoreExplanation.getValue());
           result.setMatch(true);
           return result;
         }
       }
-      return new ComplexExplanation(false, 0.0f, "no matching term");      
+      return new ComplexExplanation(false, 0.0f, "no matching term");
     }
   }
-
+  
   /** Constructs a query for the term <code>t</code>. */
   public TermQuery(Term t) {
     this(t, -1);
   }
-
-  /** Expert: constructs a TermQuery that will use the
-   *  provided docFreq instead of looking up the docFreq
-   *  against the searcher. */
+  
+  /**
+   * Expert: constructs a TermQuery that will use the provided docFreq instead
+   * of looking up the docFreq against the searcher.
+   */
   public TermQuery(Term t, int docFreq) {
     term = t;
     this.docFreq = docFreq;
     perReaderTermState = null;
   }
   
-  /** Expert: constructs a TermQuery that will use the
-   *  provided docFreq instead of looking up the docFreq
-   *  against the searcher. */
+  /**
+   * Expert: constructs a TermQuery that will use the provided docFreq instead
+   * of looking up the docFreq against the searcher.
+   */
   public TermQuery(Term t, TermContext states) {
     assert states != null;
     term = t;
     docFreq = states.docFreq();
     perReaderTermState = states;
   }
-
+  
   /** Returns the term of this query. */
-  public Term getTerm() { return term; }
-
+  public Term getTerm() {
+    return term;
+  }
+  
   @Override
   public Weight createWeight(IndexSearcher searcher) throws IOException {
     final IndexReaderContext context = searcher.getTopReaderContext();
     final TermContext termState;
-    if (perReaderTermState == null || perReaderTermState.topReaderContext != context) {
-      // make TermQuery single-pass if we don't have a PRTS or if the context differs!
+    if (perReaderTermState == null
+        || perReaderTermState.topReaderContext != context) {
+      // make TermQuery single-pass if we don't have a PRTS or if the context
+      // differs!
       termState = TermContext.build(context, term);
     } else {
-     // PRTS was pre-build for this IS
-     termState = this.perReaderTermState;
+      // PRTS was pre-build for this IS
+      termState = this.perReaderTermState;
     }
-
+    
     // we must not ignore the given docFreq - if set use the given value (lie)
-    if (docFreq != -1)
-      termState.setDocFreq(docFreq);
+    if (docFreq != -1) termState.setDocFreq(docFreq);
     
     return new TermWeight(searcher, termState);
   }
-
+  
   @Override
   public void extractTerms(Set<Term> terms) {
     terms.add(getTerm());
   }
-
+  
   /** Prints a user-readable version of this query. */
   @Override
   public String toString(String field) {
@@ -192,21 +206,20 @@ public class TermQuery extends Query {
     buffer.append(ToStringUtils.boost(getBoost()));
     return buffer.toString();
   }
-
+  
   /** Returns true iff <code>o</code> is equal to this. */
   @Override
   public boolean equals(Object o) {
-    if (!(o instanceof TermQuery))
-      return false;
-    TermQuery other = (TermQuery)o;
+    if (!(o instanceof TermQuery)) return false;
+    TermQuery other = (TermQuery) o;
     return (this.getBoost() == other.getBoost())
-      && this.term.equals(other.term);
+        && this.term.equals(other.term);
   }
-
-  /** Returns a hash code value for this object.*/
+  
+  /** Returns a hash code value for this object. */
   @Override
   public int hashCode() {
     return Float.floatToIntBits(getBoost()) ^ term.hashCode();
   }
-
+  
 }

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TermScorer.java Wed Nov 12 14:56:17 2014
@@ -17,10 +17,11 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
-import java.io.IOException;
-
 import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.util.BytesRef;
+
+import java.io.IOException;
 
 /** Expert: A <code>Scorer</code> for documents matching a <code>Term</code>.
  */
@@ -64,6 +65,36 @@ final class TermScorer extends Scorer {
   public int nextDoc() throws IOException {
     return docsEnum.nextDoc();
   }
+
+  @Override
+  public int nextPosition() throws IOException {
+    return docsEnum.nextPosition();
+  }
+
+  @Override
+  public int startPosition() throws IOException {
+    return docsEnum.startPosition();
+  }
+
+  @Override
+  public int endPosition() throws IOException {
+    return docsEnum.endPosition();
+  }
+
+  @Override
+  public int startOffset() throws IOException {
+    return docsEnum.startOffset();
+  }
+
+  @Override
+  public int endOffset() throws IOException {
+    return docsEnum.endOffset();
+  }
+
+  @Override
+  public BytesRef getPayload() throws IOException {
+    return docsEnum.getPayload();
+  }
   
   @Override
   public float score() throws IOException {
@@ -92,5 +123,16 @@ final class TermScorer extends Scorer {
 
   /** Returns a string representation of this <code>TermScorer</code>. */
   @Override
-  public String toString() { return "scorer(" + weight + ")"; }
+  public String toString() {
+    return "scorer(" + weight + ")[" + super.toString() + "]";
+  }
+  
+  // TODO: benchmark if the specialized conjunction really benefits
+  // from this, or if instead its from sorting by docFreq, or both
+
+  DocsEnum getDocsEnum() {
+    return docsEnum;
+  }
+
+
 }

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TimeLimitingCollector.java Wed Nov 12 14:56:17 2014
@@ -156,7 +156,12 @@ public class TimeLimitingCollector imple
       
     };
   }
-  
+
+  @Override
+  public int postingFeatures() {
+    return collector.postingFeatures();
+  }
+
   /**
    * This is so the same timer can be used with a multi-phase search process such as grouping. 
    * We don't want to create a new TimeLimitingCollector for each phase because that would 

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/TotalHitCountCollector.java Wed Nov 12 14:56:17 2014
@@ -17,6 +17,7 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
+import org.apache.lucene.index.DocsEnum;
 
 /**
  * Just counts the total number of hits.
@@ -36,6 +37,12 @@ public class TotalHitCountCollector exte
   }
 
   @Override
+  public int postingFeatures() {
+    // we don't need frequencies here
+    return DocsEnum.FLAG_NONE;
+  }
+
+  @Override
   public boolean acceptsDocsOutOfOrder() {
     return true;
   }

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/Weight.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/Weight.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/Weight.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/Weight.java Wed Nov 12 14:56:17 2014
@@ -17,13 +17,13 @@ package org.apache.lucene.search;
  * limitations under the License.
  */
 
-import java.io.IOException;
-
+import org.apache.lucene.index.IndexReaderContext;
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.IndexReaderContext; // javadocs
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.util.Bits;
 
+import java.io.IOException;
+
 /**
  * Expert: Calculate query weights and build query scorers.
  * <p>
@@ -34,7 +34,7 @@ import org.apache.lucene.util.Bits;
  * {@link org.apache.lucene.index.LeafReader} dependent state should reside in the {@link Scorer}.
  * <p>
  * Since {@link Weight} creates {@link Scorer} instances for a given
- * {@link org.apache.lucene.index.LeafReaderContext} ({@link #scorer(org.apache.lucene.index.LeafReaderContext, Bits)})
+ * {@link org.apache.lucene.index.LeafReaderContext} ({@link #scorer(org.apache.lucene.index.LeafReaderContext, int, Bits)})
  * callers must maintain the relationship between the searcher's top-level
  * {@link IndexReaderContext} and the context used to create a {@link Scorer}. 
  * <p>
@@ -49,7 +49,7 @@ import org.apache.lucene.util.Bits;
  * <li>The query normalization factor is passed to {@link #normalize(float, float)}. At
  * this point the weighting is complete.
  * <li>A <code>Scorer</code> is constructed by
- * {@link #scorer(org.apache.lucene.index.LeafReaderContext, Bits)}.
+ * {@link #scorer(org.apache.lucene.index.LeafReaderContext, int, Bits)}.
  * </ol>
  * 
  * @since 2.9
@@ -96,7 +96,7 @@ public abstract class Weight {
    * @return a {@link Scorer} which scores documents in/out-of order.
    * @throws IOException if there is a low-level I/O error
    */
-  public abstract Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException;
+  public abstract Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException;
 
   /**
    * Optional method, to return a {@link BulkScorer} to
@@ -125,9 +125,9 @@ public abstract class Weight {
    * passes them to a collector.
    * @throws IOException if there is a low-level I/O error
    */
-  public BulkScorer bulkScorer(LeafReaderContext context, boolean scoreDocsInOrder, Bits acceptDocs) throws IOException {
+  public BulkScorer bulkScorer(LeafReaderContext context, boolean scoreDocsInOrder, int flags, Bits acceptDocs) throws IOException {
 
-    Scorer scorer = scorer(context, acceptDocs);
+    Scorer scorer = scorer(context, flags, acceptDocs);
     if (scorer == null) {
       // No docs match
       return null;
@@ -198,14 +198,13 @@ public abstract class Weight {
    * Returns true iff this implementation scores docs only out of order. This
    * method is used in conjunction with {@link Collector}'s
    * {@link LeafCollector#acceptsDocsOutOfOrder() acceptsDocsOutOfOrder} and
-   * {@link #bulkScorer(org.apache.lucene.index.LeafReaderContext, boolean, Bits)} to
+   * {@link #bulkScorer(org.apache.lucene.index.LeafReaderContext, boolean, int, Bits)} to
    * create a matching {@link Scorer} instance for a given {@link Collector}, or
    * vice versa.
    * <p>
    * <b>NOTE:</b> the default implementation returns <code>false</code>, i.e.
    * the <code>Scorer</code> scores documents in-order.
    */
-  public boolean scoresDocsOutOfOrder() {
-    return false;
-  }
+  public boolean scoresDocsOutOfOrder() { return false; }
+
 }

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/package.html?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/package.html (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/package.html Wed Nov 12 14:56:17 2014
@@ -436,15 +436,15 @@ on the built-in available scoring models
                 that scores via a {@link org.apache.lucene.search.similarities.Similarity Similarity} will just defer to the Similarity's implementation:
                 {@link org.apache.lucene.search.similarities.Similarity.SimWeight#normalize SimWeight#normalize(float,float)}.</li>
             <li>
-                {@link org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.LeafReaderContext, org.apache.lucene.util.Bits)
-                  scorer(LeafReaderContext context, Bits acceptDocs)} &mdash;
+                {@link org.apache.lucene.search.Weight#scorer(org.apache.lucene.index.LeafReaderContext, int, org.apache.lucene.util.Bits)
+                  scorer(LeafReaderContext context, int flags, Bits acceptDocs)} &mdash;
                 Construct a new {@link org.apache.lucene.search.Scorer Scorer} for this Weight. See <a href="#scorerClass">The Scorer Class</a>
                 below for help defining a Scorer. As the name implies, the Scorer is responsible for doing the actual scoring of documents 
                 given the Query.
             </li>
             <li>
-                {@link org.apache.lucene.search.Weight#bulkScorer(org.apache.lucene.index.LeafReaderContext, boolean, org.apache.lucene.util.Bits)
-                  scorer(LeafReaderContext context, boolean scoreDocsInOrder, Bits acceptDocs)} &mdash;
+                {@link org.apache.lucene.search.Weight#bulkScorer(org.apache.lucene.index.LeafReaderContext, boolean, int, org.apache.lucene.util.Bits)
+                  scorer(LeafReaderContext context, boolean scoreDocsInOrder, int flags, Bits acceptDocs)} &mdash;
                 Construct a new {@link org.apache.lucene.search.BulkScorer BulkScorer} for this Weight. See <a href="#bulkScorerClass">The BulkScorer Class</a>
                 below for help defining a BulkScorer. This is an optional method, and most queries do not implement it.
             </li>

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java Wed Nov 12 14:56:17 2014
@@ -17,11 +17,12 @@ package org.apache.lucene.search.payload
  * limitations under the License.
  */
 
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.ComplexExplanation;
 import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
@@ -148,14 +149,14 @@ public class PayloadNearQuery extends Sp
     }
 
     @Override
-    public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
+    public Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException {
       return new PayloadNearSpanScorer(query.getSpans(context, acceptDocs, termContexts), this,
           similarity, similarity.simScorer(stats, context));
     }
     
     @Override
     public Explanation explain(LeafReaderContext context, int doc) throws IOException {
-      PayloadNearSpanScorer scorer = (PayloadNearSpanScorer) scorer(context, context.reader().getLiveDocs());
+      PayloadNearSpanScorer scorer = (PayloadNearSpanScorer) scorer(context, DocsEnum.FLAG_PAYLOADS, context.reader().getLiveDocs());
       if (scorer != null) {
         int newDoc = scorer.advance(doc);
         if (newDoc == doc) {

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java Wed Nov 12 14:56:17 2014
@@ -19,7 +19,7 @@ package org.apache.lucene.search.payload
 
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.Weight;
@@ -79,7 +79,7 @@ public class PayloadTermQuery extends Sp
     }
 
     @Override
-    public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
+    public Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException {
       return new PayloadTermSpanScorer((TermSpans) query.getSpans(context, acceptDocs, termContexts),
           this, similarity.simScorer(stats, context));
     }
@@ -120,7 +120,7 @@ public class PayloadTermQuery extends Sp
 
       protected void processPayload(Similarity similarity) throws IOException {
         if (termSpans.isPayloadAvailable()) {
-          final DocsAndPositionsEnum postings = termSpans.getPostings();
+          final DocsEnum postings = termSpans.getPostings();
           payload = postings.getPayload();
           if (payload != null) {
             payloadScore = function.currentScore(doc, term.field(),
@@ -176,7 +176,7 @@ public class PayloadTermQuery extends Sp
     
     @Override
     public Explanation explain(LeafReaderContext context, int doc) throws IOException {
-      PayloadTermSpanScorer scorer = (PayloadTermSpanScorer) scorer(context, context.reader().getLiveDocs());
+      PayloadTermSpanScorer scorer = (PayloadTermSpanScorer) scorer(context, DocsEnum.FLAG_POSITIONS, context.reader().getLiveDocs());
       if (scorer != null) {
         int newDoc = scorer.advance(doc);
         if (newDoc == doc) {

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/BlockPhraseScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/BlockPhraseScorer.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/BlockPhraseScorer.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/BlockPhraseScorer.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,70 @@
+package org.apache.lucene.search.posfilter;
+
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.similarities.Similarity;
+
+import java.io.IOException;
+
+/*
+ * 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 BlockPhraseScorer extends PositionFilteredScorer {
+
+  private final Interval[] subIntervals;
+
+  public BlockPhraseScorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+    super(filteredScorer, simScorer);
+    subIntervals = new Interval[subScorers.length];
+    for (int i = 0; i < subScorers.length; i++) {
+      subIntervals[i] = new Interval();
+    }
+  }
+
+  @Override
+  public void reset(int doc) throws IOException {
+    super.reset(doc);
+    for (int i = 0; i < subScorers.length; i++) {
+      subIntervals[i].reset();
+    }
+  }
+
+  @Override
+  protected int doNextPosition() throws IOException {
+    if (subScorers[0].nextPosition() == NO_MORE_POSITIONS)
+      return NO_MORE_POSITIONS;
+    subIntervals[0].update(subScorers[0]);
+    int i = 1;
+    while (i < subScorers.length) {
+      while (subIntervals[i].begin <= subIntervals[i - 1].end) {
+        if (subScorers[i].nextPosition() == NO_MORE_POSITIONS)
+          return NO_MORE_POSITIONS;
+        subIntervals[i].update(subScorers[i]);
+      }
+      if (subIntervals[i].begin == subIntervals[i - 1].end + 1) {
+        i++;
+      }
+      else {
+        if (subScorers[0].nextPosition() == NO_MORE_POSITIONS)
+          return NO_MORE_POSITIONS;
+        subIntervals[0].update(subScorers[0]);
+        i = 1;
+      }
+    }
+    current.update(subIntervals[0], subIntervals[subScorers.length - 1]);
+    return subScorers[0].startPosition();
+  }
+}

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/Interval.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/Interval.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/Interval.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/Interval.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,200 @@
+package org.apache.lucene.search.posfilter;
+/*
+ * 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.DocsEnum;
+
+import java.io.IOException;
+
+/**
+ * Represents a section of a document that matches a query
+ */
+public class Interval implements Cloneable {
+
+  /** The position of the start of this Interval */
+  public int begin;
+
+  /** The position of the end of this Interval */
+  public int end;
+
+  /** The offset of the start of this Interval */
+  public int offsetBegin;
+
+  /** The offset of the end of this Interval */
+  public int offsetEnd;
+
+  /** An interval that will always compare as less than any other interval */
+  public static final Interval INFINITE_INTERVAL = new Interval();
+
+   /**
+   * Constructs a new Interval
+   * @param begin the start position
+   * @param end the end position
+   * @param offsetBegin the start offset
+   * @param offsetEnd the end offset
+   */
+  public Interval(int begin, int end, int offsetBegin, int offsetEnd) {
+    this.begin = begin;
+    this.end = end;
+    this.offsetBegin = offsetBegin;
+    this.offsetEnd = offsetEnd;
+  }
+
+  /**
+   * Constructs a new Interval with no initial values.  This
+   * will always compare as less than any other Interval.
+   */
+  public Interval() {
+    this(Integer.MIN_VALUE, Integer.MIN_VALUE, -1, -1);
+  }
+
+  public Interval(DocsEnum docsEnum) throws IOException {
+    this.begin = docsEnum.startPosition();
+    this.end = docsEnum.endPosition();
+    this.offsetBegin = docsEnum.startOffset();
+    this.offsetEnd = docsEnum.endOffset();
+  }
+
+  /**
+   * Update to span the range defined by two other Intervals.
+   * @param start the first Interval
+   * @param end the second Interval
+   */
+  public void update(Interval start, Interval end) {
+    this.begin = start.begin;
+    this.offsetBegin = start.offsetBegin;
+    this.end = end.end;
+    this.offsetEnd = end.offsetEnd;
+  }
+
+  /**
+   * Compare with another Interval.
+   * @param other the comparator
+   * @return true if both start and end positions are less than
+   *              the comparator.
+   */
+  public boolean lessThanExclusive(Interval other) {
+    return begin < other.begin && end < other.end;
+  }
+
+  /**
+   * Compare with another Interval.
+   * @param other the comparator
+   * @return true if both start and end positions are less than
+   *              or equal to the comparator's.
+   */
+  public boolean lessThan(Interval other) {
+    return begin <= other.begin && end <= other.end;
+  }
+
+  /**
+   * Compare with another Interval
+   * @param other the comparator
+   * @return true if both start and end positions are greater then
+   *              the comparator's.
+   */
+  public boolean greaterThanExclusive(Interval other) {
+    return begin > other.begin && end > other.end;
+  }
+
+  /**
+   * Compare with another Interval
+   * @param other the comparator
+   * @return true if both start and end positions are greater then
+   *              of equal to the comparator's.
+   */
+  public boolean greaterThan(Interval other) {
+    return begin >= other.begin && end >= other.end;
+  }
+
+  /**
+   * Compare with another Interval
+   * @param other the comparator
+   * @return true if this Interval contains the comparator
+   */
+  public boolean contains(Interval other) {
+    return begin <= other.begin && other.end <= end;
+  }
+
+  /**
+   * Compare with another Interval to find overlaps
+   * @param other
+   * @return true if the two intervals overlap
+   */
+  public boolean overlaps(Interval other) {
+    return this.contains(other) || other.contains(this);
+  }
+
+  /**
+   * Set all values of this Interval to be equal to another's
+   * @param other the Interval to copy
+   */
+  public void copy(Interval other) {
+    begin = other.begin;
+    end = other.end;
+    offsetBegin = other.offsetBegin;
+    offsetEnd = other.offsetEnd;
+  }
+
+  /**
+   * Set to a state that will always compare as less than any
+   * other Interval.
+   */
+  public void reset() {
+    offsetBegin = offsetEnd = -1;
+    begin = end = Integer.MIN_VALUE;
+  }
+
+  /**
+   * Set to a state that will always compare as more than any
+   * other Interval.
+   */
+  public void setMaximum() {
+    offsetBegin = offsetEnd = -1;
+    begin = end = Integer.MAX_VALUE;
+  }
+  
+  @Override
+  public Object clone() {
+    try {
+      return super.clone();
+    } catch (CloneNotSupportedException e) {
+      throw new RuntimeException(); // should not happen
+    }
+  }
+  
+  @Override
+  public String toString() {
+    return "Interval [begin=" + begin + "(" + offsetBegin + "), end="
+        + end + "(" + offsetEnd + ")]";
+  }
+
+  public void update(DocsEnum docsEnum) throws IOException {
+    offsetBegin = docsEnum.startOffset();
+    offsetEnd = docsEnum.endOffset();
+    begin = docsEnum.startPosition();
+    end = docsEnum.endPosition();
+  }
+
+  public void update(Interval interval) {
+    this.begin = interval.begin;
+    this.end = interval.end;
+    this.offsetBegin = interval.offsetBegin;
+    this.offsetEnd = interval.offsetEnd;
+  }
+
+}
\ No newline at end of file

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/NonOverlappingQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/NonOverlappingQuery.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/NonOverlappingQuery.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/NonOverlappingQuery.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,204 @@
+package org.apache.lucene.search.posfilter;
+
+/*
+ * 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.index.LeafReaderContext;
+import org.apache.lucene.index.Term;
+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.search.similarities.Similarity;
+import org.apache.lucene.util.Bits;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * A Query that matches documents containing an interval (the minuend) that
+ * does not contain another interval (the subtrahend).
+ *
+ * As an example, given the following {@link org.apache.lucene.search.BooleanQuery}:
+ * <pre>
+ *   BooleanQuery bq = new BooleanQuery();
+ *   bq.add(new TermQuery(new Term(field, "quick")), BooleanQuery.Occur.MUST);
+ *   bq.add(new TermQuery(new Term(field, "fox")), BooleanQuery.Occur.MUST);
+ * </pre>
+ *
+ * The document "the quick brown fox" will be matched by this query.  But
+ * create a NonOverlappingQuery using this query as a minuend:
+ * <pre>
+ *   NonOverlappingQuery brq = new NonOverlappingQuery(bq, new TermQuery(new Term(field, "brown")));
+ * </pre>
+ *
+ * This query will not match "the quick brown fox", because "brown" is found
+ * within the interval of the boolean query for "quick" and "fox.  The query
+ * will match "the quick fox is brown", because here "brown" is outside
+ * the minuend's interval.
+ *
+ * N.B. Positions must be included in the index for this query to work
+ *
+ * Implements the Brouwerian operator as defined in <a href=
+ * "http://vigna.dsi.unimi.it/ftp/papers/EfficientAlgorithmsMinimalIntervalSemantics"
+ * >"Efficient Optimally Lazy Algorithms for Minimal-Interval Semantics"</a>
+ *
+ * @lucene.experimental
+ */
+public final class NonOverlappingQuery extends PositionFilterQuery {
+
+  private Query subtrahend;
+
+  /**
+   * Constructs a Query that matches documents containing intervals of the minuend
+   * that are not subtended by the subtrahend
+   * @param minuend the minuend Query
+   * @param subtrahend the subtrahend Query
+   */
+  public NonOverlappingQuery(Query minuend, Query subtrahend) {
+    super(minuend, new BrouwerianScorerFactory(subtrahend));
+    this.subtrahend = subtrahend;
+  }
+
+  @Override
+  public void extractTerms(Set<Term> terms) {
+    super.extractTerms(terms);
+    subtrahend.extractTerms(terms);
+  }
+
+  @Override
+  public Query rewrite(IndexReader reader) throws IOException {
+    Query rewrittenMinuend = innerQuery.rewrite(reader);
+    Query rewrittenSubtrahend = subtrahend.rewrite(reader);
+    if (rewrittenMinuend != innerQuery || rewrittenSubtrahend != subtrahend) {
+      return new NonOverlappingQuery(rewrittenMinuend, rewrittenSubtrahend);
+    }
+    return this;
+  }
+
+  private static class BrouwerianScorerFactory implements ScorerFilterFactory {
+
+    private final Query subtrahend;
+
+    BrouwerianScorerFactory(Query subtrahend) {
+      this.subtrahend = subtrahend;
+    }
+
+    @Override
+    public Scorer scorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String getName() {
+      return "NonOverlapping[" + subtrahend.toString() + "]/";
+    }
+  }
+
+  @Override
+  public Weight createWeight(IndexSearcher searcher) throws IOException {
+    return new BrouwerianWeight(innerQuery.createWeight(searcher),
+                                subtrahend.createWeight(searcher), searcher);
+  }
+
+  class BrouwerianWeight extends ScorerFilterWeight {
+
+    private final Weight subtrahendWeight;
+
+    public BrouwerianWeight(Weight minuendWeight, Weight subtrahendWeight, IndexSearcher searcher)
+        throws IOException {
+      super(minuendWeight, searcher);
+      this.subtrahendWeight = subtrahendWeight;
+    }
+
+    @Override
+    public Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException {
+      return new BrouwerianScorer(innerWeight.scorer(context, flags, acceptDocs),
+                                  subtrahendWeight.scorer(context, flags, acceptDocs),
+                                  similarity.simScorer(stats, context));
+    }
+  }
+
+  static class BrouwerianScorer extends PositionFilteredScorer {
+
+    private final Scorer subtrahend;
+    private Interval subtInterval = new Interval();
+    private int subtPosition = -1;
+
+    BrouwerianScorer(Scorer minuend, Scorer subtrahend, Similarity.SimScorer simScorer) {
+      super(minuend, simScorer);
+      this.subtrahend = subtrahend;
+    }
+
+    @Override
+    protected void reset(int doc) throws IOException {
+      super.reset(doc);
+      if (this.subtrahend == null || this.subtrahend.advance(doc) != doc)
+        subtPosition = NO_MORE_POSITIONS;
+      else
+        subtPosition = -1;
+      this.subtInterval.reset();
+    }
+
+    @Override
+    protected int doNextPosition() throws IOException {
+      if (subtPosition == NO_MORE_POSITIONS) {
+        int pos = child.nextPosition();
+        if (pos != NO_MORE_POSITIONS)
+          current.update(child);
+        return pos;
+      }
+      while (child.nextPosition() != NO_MORE_POSITIONS) {
+        current.update(child);
+        while (subtInterval.lessThanExclusive(current) &&
+                  (subtPosition = subtrahend.nextPosition()) != NO_MORE_POSITIONS) {
+          subtInterval.update(subtrahend);
+        }
+        if (subtPosition == NO_MORE_POSITIONS || !current.overlaps(subtInterval))
+          return current.begin;
+      }
+      return NO_MORE_POSITIONS;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = super.hashCode();
+    result = prime * result + ((innerQuery == null) ? 0 : innerQuery.hashCode());
+    result = prime * result
+        + ((subtrahend == null) ? 0 : subtrahend.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;
+    NonOverlappingQuery other = (NonOverlappingQuery) obj;
+    if (innerQuery == null) {
+      if (other.innerQuery != null) return false;
+    } else if (!innerQuery.equals(other.innerQuery)) return false;
+    if (subtrahend == null) {
+      if (other.subtrahend != null) return false;
+    } else if (!subtrahend.equals(other.subtrahend)) return false;
+    return true;
+  }
+
+}
\ No newline at end of file

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/OrderedNearQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/OrderedNearQuery.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/OrderedNearQuery.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/OrderedNearQuery.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,139 @@
+package org.apache.lucene.search.posfilter;
+
+/*
+ * 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.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.similarities.Similarity;
+
+import java.io.IOException;
+
+/**
+ * A query that matches if a set of subqueries also match, and are within
+ * a given distance of each other within the document.  The subqueries
+ * must appear in the document in order.
+ *
+ * N.B. Positions must be included in the index for this query to work
+ *
+ * Implements the AND&lt; operator as defined in <a href=
+ * "http://vigna.dsi.unimi.it/ftp/papers/EfficientAlgorithmsMinimalIntervalSemantics"
+ * >"Efficient Optimally Lazy Algorithms for Minimal-Interval Semantics"</a>
+ *
+ * @lucene.experimental
+ */
+
+public class OrderedNearQuery extends PositionFilterQuery {
+
+  /**
+   * Constructs an OrderedNearQuery
+   * @param slop the maximum distance between the subquery matches
+   * @param subqueries the subqueries to match.
+   */
+  public OrderedNearQuery(int slop, Query... subqueries) {
+    super(buildBooleanQuery(subqueries), new OrderedNearScorerFactory(slop));
+  }
+
+  private static class OrderedNearScorerFactory implements ScorerFilterFactory {
+
+    private final int slop;
+
+    public OrderedNearScorerFactory(int slop) {
+      this.slop = slop;
+    }
+
+    @Override
+    public Scorer scorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      return new WithinFilteredScorer(new OrderedNearScorer(filteredScorer, simScorer), slop, simScorer);
+    }
+
+    @Override
+    public String getName() {
+      return "OrderedNear/" + slop;
+    }
+  }
+
+  private static class OrderedNearScorer extends PositionFilteredScorer {
+
+    private final int lastiter;
+
+    private int index = 1;
+    private Interval[] intervals;
+
+    public OrderedNearScorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      super(filteredScorer, simScorer);
+      intervals = new Interval[subScorers.length];
+      for (int i = 0; i < subScorers.length; i++) {
+        intervals[i] = new Interval();
+      }
+      lastiter = intervals.length - 1;
+    }
+
+    @Override
+    public int freq() throws IOException {
+      return 1; // nocommit
+    }
+
+    @Override
+    protected void reset(int doc) throws IOException {
+      for (int i = 0; i < subScorers.length; i++) {
+        assert subScorers[i].docID() == doc;
+        intervals[i].update(Interval.INFINITE_INTERVAL);
+      }
+      if (subScorers[0].nextPosition() == NO_MORE_POSITIONS)
+        intervals[0].setMaximum();
+      else
+        intervals[0].update(subScorers[0]);
+      index = 1;
+    }
+
+    @Override
+    protected int doNextPosition() throws IOException {
+      if (intervals[0].begin == NO_MORE_POSITIONS)
+        return NO_MORE_POSITIONS;
+      current.setMaximum();
+      int b = Integer.MAX_VALUE;
+      while (true) {
+        while (true) {
+          final Interval previous = intervals[index - 1];
+          if (previous.end >= b) {
+            return current.begin;
+          }
+          if (index == intervals.length || intervals[index].begin > previous.end)
+            break;
+          Interval scratch = intervals[index];
+          do {
+            if (scratch.end >= b || subScorers[index].nextPosition() == NO_MORE_POSITIONS)
+              return current.begin;
+            intervals[index].update(subScorers[index]);
+            scratch = intervals[index];
+          } while (scratch.begin <= previous.end);
+          index++;
+        }
+        current.update(intervals[0], intervals[lastiter]);
+        matchDistance = (intervals[lastiter].begin - lastiter) - intervals[0].end;
+        b = intervals[lastiter].begin;
+        index = 1;
+        if (subScorers[0].nextPosition() == NO_MORE_POSITIONS) {
+          intervals[0].setMaximum();
+          return current.begin;
+        }
+        intervals[0].update(subScorers[0]);
+      }
+    }
+  }
+}

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilterQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilterQuery.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilterQuery.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilterQuery.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,164 @@
+package org.apache.lucene.search.posfilter;
+
+/*
+ * 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.DocsEnum;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermContext;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.ComplexExplanation;
+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.TermStatistics;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.similarities.Similarity;
+import org.apache.lucene.util.Bits;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class PositionFilterQuery extends Query {
+
+  protected final Query innerQuery;
+  protected final ScorerFilterFactory scorerFilterFactory;
+
+  public PositionFilterQuery(Query innerQuery, ScorerFilterFactory scorerFilterFactory) {
+    this.innerQuery = innerQuery;
+    this.scorerFilterFactory = scorerFilterFactory;
+  }
+
+  protected static BooleanQuery buildBooleanQuery(Query... queries) {
+    BooleanQuery bq = new BooleanQuery();
+    for (Query q : queries) {
+      bq.add(q, BooleanClause.Occur.MUST);
+    }
+    return bq;
+  }
+
+  @Override
+  public void extractTerms(Set<Term> terms) {
+    innerQuery.extractTerms(terms);
+  }
+
+  @Override
+  public Query rewrite(IndexReader reader) throws IOException {
+    Query rewritten =  innerQuery.rewrite(reader);
+    if (rewritten != innerQuery) {
+      return new PositionFilterQuery(rewritten, scorerFilterFactory);
+    }
+    return this;
+  }
+
+  @Override
+  public Weight createWeight(IndexSearcher searcher) throws IOException {
+    return new ScorerFilterWeight(innerQuery.createWeight(searcher), searcher);
+  }
+
+  @Override
+  public String toString(String field) {
+    return scorerFilterFactory.getName() + "[" + innerQuery.toString() + "]";
+  }
+
+  public class ScorerFilterWeight extends Weight {
+
+    protected final Weight innerWeight;
+    protected final Similarity similarity;
+    protected final Similarity.SimWeight stats;
+
+    public ScorerFilterWeight(Weight innerWeight, IndexSearcher searcher) throws IOException {
+      this.innerWeight = innerWeight;
+      this.similarity = searcher.getSimilarity();
+      this.stats = getSimWeight(innerWeight.getQuery(), searcher);
+    }
+
+    private Similarity.SimWeight getSimWeight(Query query, IndexSearcher searcher)  throws IOException {
+      TreeSet<Term> terms = new TreeSet<Term>();
+      query.extractTerms(terms);
+      if (terms.size() == 0)
+        return null;
+      int i = 0;
+      TermStatistics[] termStats = new TermStatistics[terms.size()];
+      for (Term term : terms) {
+        TermContext state = TermContext.build(searcher.getTopReaderContext(), term);
+        termStats[i] = searcher.termStatistics(term, state);
+        i++;
+      }
+      final String field = terms.first().field(); // nocommit - should we be checking all filtered terms
+      // are on the same field?
+      return similarity.computeWeight(query.getBoost(), searcher.collectionStatistics(field), termStats);
+    }
+
+    @Override
+    public Explanation explain(LeafReaderContext context, int doc) throws IOException {
+      Scorer scorer = scorer(context, DocsEnum.FLAG_POSITIONS, context.reader().getLiveDocs());
+      if (scorer != null) {
+        int newDoc = scorer.advance(doc);
+        if (newDoc == doc) {
+          float freq = scorer.freq();
+          Similarity.SimScorer docScorer = similarity.simScorer(stats, context);
+          ComplexExplanation result = new ComplexExplanation();
+          result.setDescription("weight("+getQuery()+" in "+doc+") [" + similarity.getClass().getSimpleName() + "], result of:");
+          Explanation scoreExplanation = docScorer.explain(doc, new Explanation(freq, "phraseFreq=" + freq));
+          result.addDetail(scoreExplanation);
+          result.setValue(scoreExplanation.getValue());
+          result.setMatch(true);
+          return result;
+        }
+      }
+      return new ComplexExplanation(false, 0.0f,
+          "No matching term within position filter");
+    }
+
+    @Override
+    public Query getQuery() {
+      return PositionFilterQuery.this;
+    }
+
+    @Override
+    public float getValueForNormalization() throws IOException {
+      return stats == null ? 1.0f : stats.getValueForNormalization();
+    }
+
+    @Override
+    public void normalize(float norm, float topLevelBoost) {
+      if (stats != null)
+        stats.normalize(norm, topLevelBoost);
+    }
+
+    @Override
+    public Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException {
+      Scorer filteredScorer = innerWeight.scorer(context, flags | DocsEnum.FLAG_POSITIONS, acceptDocs);
+      return filteredScorer == null ? null
+                : scorerFilterFactory.scorer(filteredScorer, similarity.simScorer(stats, context));
+    }
+  }
+
+  public static interface ScorerFilterFactory {
+
+    public Scorer scorer(Scorer filteredScorer, Similarity.SimScorer simScorer);
+
+    public String getName();
+
+  }
+}

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilteredScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilteredScorer.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilteredScorer.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/PositionFilteredScorer.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,137 @@
+package org.apache.lucene.search.posfilter;
+
+/*
+ * 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.Scorer;
+import org.apache.lucene.search.similarities.Similarity;
+
+import java.io.IOException;
+
+public abstract class PositionFilteredScorer extends Scorer {
+
+  protected final Scorer[] subScorers;
+  protected final Scorer child;
+  protected final Interval current = new Interval();
+  protected final Similarity.SimScorer simScorer;
+  protected int matchDistance;
+
+  private boolean buffered;
+
+  public PositionFilteredScorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+    super(filteredScorer.getWeight());
+    this.simScorer = simScorer;
+    child = filteredScorer;
+    subScorers = new Scorer[filteredScorer.getChildren().size()];
+    int i = 0;
+    for (ChildScorer subScorer : filteredScorer.getChildren()) {
+      subScorers[i++] = subScorer.child;
+    }
+  }
+
+  @Override
+  public float score() throws IOException {
+    return this.simScorer.score(docID(), freq());
+  }
+
+  @Override
+  public int docID() {
+    return child.docID();
+  }
+
+  @Override
+  public int freq() throws IOException {
+    int freq = 0;
+    while (nextPosition() != NO_MORE_POSITIONS) {
+      freq++;
+    }
+    return freq;
+  }
+
+  @Override
+  public int nextDoc() throws IOException {
+    while (child.nextDoc() != NO_MORE_DOCS) {
+      reset(child.docID());
+      if (nextPosition() != NO_MORE_POSITIONS) {
+        buffered = true;
+        return child.docID();
+      }
+    }
+    return NO_MORE_DOCS;
+  }
+
+  @Override
+  public int advance(int target) throws IOException {
+    if (child.advance(target) == NO_MORE_DOCS)
+      return NO_MORE_DOCS;
+    do {
+      reset(child.docID());
+      if (nextPosition() != NO_MORE_POSITIONS) {
+        buffered = true;
+        return child.docID();
+      }
+    } while (child.nextDoc() != NO_MORE_DOCS);
+    return NO_MORE_DOCS;
+  }
+
+  @Override
+  public int nextPosition() throws IOException {
+    if (buffered) {
+      //System.out.println(this.hashCode() + ": returning buffered nextPos");
+      buffered = false;
+      return current.begin;
+    }
+    //System.out.println(this.hashCode() + ": returning unbuffered nextPos");
+    return doNextPosition();
+  }
+
+  protected abstract int doNextPosition() throws IOException;
+
+  protected void reset(int doc) throws IOException {
+    buffered = false;
+  };
+
+  public int getMatchDistance() {
+    return matchDistance;
+  }
+
+  @Override
+  public int startPosition() throws IOException {
+    return current.begin;
+  }
+
+  @Override
+  public int endPosition() throws IOException {
+    return current.end;
+  }
+
+  @Override
+  public int startOffset() throws IOException {
+    return current.offsetBegin;
+  }
+
+  @Override
+  public int endOffset() throws IOException {
+    return current.offsetEnd;
+  }
+
+  @Override
+  public long cost() {
+    return child.cost();
+  }
+// nocommit Payloads - need to add these to Interval?
+}

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/RangeFilterQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/RangeFilterQuery.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/RangeFilterQuery.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/RangeFilterQuery.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,82 @@
+package org.apache.lucene.search.posfilter;
+
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.similarities.Similarity;
+
+import java.io.IOException;
+
+/**
+ * Copyright (c) 2012 Lemur Consulting Ltd.
+ * <p/>
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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 RangeFilterQuery extends PositionFilterQuery {
+
+  public RangeFilterQuery(int start, int end, Query innerQuery) {
+    super(innerQuery, new RangeFilterScorerFactory(start, end));
+  }
+
+  public RangeFilterQuery(int end, Query innerQuery) {
+    this(0, end, innerQuery);
+  }
+
+  private static class RangeFilterScorerFactory implements ScorerFilterFactory {
+
+    private final int start;
+    private final int end;
+
+    public RangeFilterScorerFactory(int start, int end) {
+      this.start = start;
+      this.end = end;
+    }
+
+    @Override
+    public Scorer scorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      return new RangeFilterScorer(start, end, filteredScorer, simScorer);
+    }
+
+    @Override
+    public String getName() {
+      return "RangeFilter(" + start + "," + end + ")";
+    }
+  }
+
+  private static class RangeFilterScorer extends PositionFilteredScorer {
+
+    private final int start;
+    private final int end;
+
+    public RangeFilterScorer(int start, int end, Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      super(filteredScorer, simScorer);
+      this.start = start;
+      this.end = end;
+    }
+
+    @Override
+    protected int doNextPosition() throws IOException {
+      int position;
+      while ((position = child.nextPosition()) != NO_MORE_POSITIONS) {
+        if (position > end)
+          return NO_MORE_POSITIONS;
+        if (position >= start) {
+          current.update(child);
+          return position;
+        }
+      }
+      return NO_MORE_POSITIONS;
+    }
+  }
+
+}

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/UnorderedNearQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/UnorderedNearQuery.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/UnorderedNearQuery.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/UnorderedNearQuery.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,187 @@
+package org.apache.lucene.search.posfilter;
+
+/**
+ * Copyright (c) 2012 Lemur Consulting Ltd.
+ * <p/>
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.DocsEnum;
+import org.apache.lucene.search.PositionQueue;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.similarities.Similarity;
+
+import java.io.IOException;
+
+/**
+ * A query that matches if a set of subqueries also match, and are within
+ * a given distance of each other within the document.  The subqueries
+ * may appear in the document in any order.
+ *
+ * N.B. Positions must be included in the index for this query to work
+ *
+ * Implements the LOWPASS<sub>k</sub> operator as defined in <a href=
+ * "http://vigna.dsi.unimi.it/ftp/papers/EfficientAlgorithmsMinimalIntervalSemantics"
+ * >"Efficient Optimally Lazy Algorithms for Minimal-Interval Semantics"</a>
+ *
+ * @lucene.experimental
+ */
+
+public class UnorderedNearQuery extends PositionFilterQuery {
+
+  /**
+   * Constructs an OrderedNearQuery
+   * @param slop the maximum distance between the subquery matches
+   * @param subqueries the subqueries to match.
+   */
+  public UnorderedNearQuery(int slop, Query... subqueries) {
+    super(buildBooleanQuery(subqueries), new UnorderedNearScorerFactory(slop));
+  }
+
+  private static class UnorderedNearScorerFactory implements ScorerFilterFactory {
+
+    private final int slop;
+
+    UnorderedNearScorerFactory(int slop) {
+      this.slop = slop;
+    }
+
+    @Override
+    public Scorer scorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      return new WithinFilteredScorer(new UnorderedNearScorer(filteredScorer, simScorer), slop, simScorer);
+    }
+
+    @Override
+    public String getName() {
+      return "UnorderedNear/" + slop;
+    }
+  }
+
+  private static class UnorderedNearScorer extends PositionFilteredScorer {
+
+    SpanningPositionQueue posQueue;
+
+    public UnorderedNearScorer(Scorer filteredScorer, Similarity.SimScorer simScorer) {
+      super(filteredScorer, simScorer);
+      posQueue = new SpanningPositionQueue(subScorers);
+    }
+
+    @Override
+    protected int doNextPosition() throws IOException {
+      while (posQueue.isFull() && posQueue.span.begin == current.begin) {
+        posQueue.nextPosition();
+      }
+      if (!posQueue.isFull())
+        return NO_MORE_POSITIONS;
+      do {
+        //current.update(posQueue.top().interval, posQueue.span);
+        posQueue.updateCurrent(current);
+        if (current.equals(posQueue.top().interval))
+          return current.begin;
+        matchDistance = posQueue.getMatchDistance();
+        posQueue.nextPosition();
+      } while (posQueue.isFull() && current.end == posQueue.span.end);
+      return current.begin;
+    }
+
+    @Override
+    protected void reset(int doc) throws IOException {
+      super.reset(doc);
+      current.reset();
+      posQueue.advanceTo(doc);
+    }
+
+  }
+
+  private static class SpanningPositionQueue extends PositionQueue {
+
+    Interval span = new Interval();
+    int scorerCount;
+    int firstIntervalEnd;
+    int lastIntervalBegin;
+
+    public SpanningPositionQueue(Scorer[] subScorers) {
+      super(subScorers);
+      scorerCount = subScorers.length;
+    }
+
+    public int getMatchDistance() {
+      return lastIntervalBegin - firstIntervalEnd - scorerCount + 1;
+    }
+
+    public boolean isFull() {
+      return queuesize == scorerCount;
+    }
+
+    public void updateCurrent(Interval current) {
+      final Interval top = this.top().interval;
+      current.update(top, span);
+      this.firstIntervalEnd = top.end;
+    }
+
+    private void updateRightExtreme(Interval newRight) {
+      if (span.end <= newRight.end) {
+        span.update(span, newRight);
+        this.lastIntervalBegin = newRight.begin;
+      }
+    }
+
+    protected void updateInternalIntervals() {
+      updateRightExtreme(top().interval);
+    }
+
+    @Override
+    public int nextPosition() throws IOException {
+      int position;
+      if ((position = super.nextPosition()) == DocsEnum.NO_MORE_POSITIONS) {
+        return DocsEnum.NO_MORE_POSITIONS;
+      }
+      span.update(top().interval, span);
+      return position;
+    }
+
+    @Override
+    protected void init() throws IOException {
+      super.init();
+      for (Object docsEnumRef : getHeapArray()) {
+        if (docsEnumRef != null) {
+          final Interval i = ((DocsEnumRef) docsEnumRef).interval;
+          updateRightExtreme(i);
+        }
+      }
+    }
+
+    @Override
+    public void advanceTo(int doc) {
+      super.advanceTo(doc);
+      span.reset();
+      firstIntervalEnd = lastIntervalBegin = span.begin;
+    }
+
+    @Override
+    protected boolean lessThan(DocsEnumRef left, DocsEnumRef right) {
+      final Interval a = left.interval;
+      final Interval b = right.interval;
+      return a.begin < b.begin || (a.begin == b.begin && a.end > b.end);
+    }
+
+    @Override
+    public String toString() {
+      return top().interval.toString();
+    }
+  }
+
+
+}
+

Added: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/WithinFilteredScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/WithinFilteredScorer.java?rev=1638805&view=auto
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/WithinFilteredScorer.java (added)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/posfilter/WithinFilteredScorer.java Wed Nov 12 14:56:17 2014
@@ -0,0 +1,47 @@
+package org.apache.lucene.search.posfilter;
+
+/*
+ * 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.similarities.Similarity;
+
+import java.io.IOException;
+
+public class WithinFilteredScorer extends PositionFilteredScorer {
+
+  private final int slop;
+  private final PositionFilteredScorer wrappedScorer;
+
+  public WithinFilteredScorer(PositionFilteredScorer wrappedScorer, int slop, Similarity.SimScorer simScorer) {
+    super(wrappedScorer, simScorer);
+    this.slop = slop;
+    this.wrappedScorer = wrappedScorer;
+  }
+
+  @Override
+  protected int doNextPosition() throws IOException {
+    int position;
+    while ((position = wrappedScorer.nextPosition()) != NO_MORE_POSITIONS) {
+      if (wrappedScorer.getMatchDistance() <= slop) {
+        current.update(wrappedScorer);
+        return position;
+      }
+    }
+    return NO_MORE_POSITIONS;
+  }
+
+}

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/similarities/Similarity.java Wed Nov 12 14:56:17 2014
@@ -17,10 +17,8 @@ package org.apache.lucene.search.similar
  * limitations under the License.
  */
 
-import java.io.IOException;
-
-import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.CollectionStatistics;
 import org.apache.lucene.search.Explanation;
@@ -28,9 +26,11 @@ import org.apache.lucene.search.IndexSea
 import org.apache.lucene.search.PhraseQuery;
 import org.apache.lucene.search.TermQuery;
 import org.apache.lucene.search.TermStatistics;
-import org.apache.lucene.search.spans.SpanQuery; // javadoc
+import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.util.BytesRef;
-import org.apache.lucene.util.SmallFloat; // javadoc
+import org.apache.lucene.util.SmallFloat;
+
+import java.io.IOException;
 
 /** 
  * Similarity defines the components of Lucene scoring.

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java Wed Nov 12 14:56:17 2014
@@ -17,12 +17,12 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-import java.io.IOException;
-
-import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.similarities.Similarity;
 
+import java.io.IOException;
+
 /**
  * Public for extension only.
  */
@@ -96,16 +96,22 @@ public class SpanScorer extends Scorer {
   public int freq() throws IOException {
     return numMatches;
   }
-  
+
+  @Override
+  public int nextPosition() throws IOException {
+    return -1; // nocommit maybe I can coerce this into working?
+  }
+
   /** Returns the intermediate "sloppy freq" adjusted for edit distance 
    *  @lucene.internal */
   // only public so .payloads can see it.
   public float sloppyFreq() throws IOException {
     return freq;
   }
-  
+
   @Override
   public long cost() {
     return spans.cost();
   }
+
 }

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java Wed Nov 12 14:56:17 2014
@@ -20,7 +20,7 @@ package org.apache.lucene.search.spans;
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.TermContext;
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
@@ -120,7 +120,7 @@ public class SpanTermQuery extends SpanQ
     final TermsEnum termsEnum = context.reader().terms(term.field()).iterator(null);
     termsEnum.seekExact(term.bytes(), state);
     
-    final DocsAndPositionsEnum postings = termsEnum.docsAndPositions(acceptDocs, null, DocsAndPositionsEnum.FLAG_PAYLOADS);
+    final DocsEnum postings = termsEnum.docsAndPositions(acceptDocs, null, DocsEnum.FLAG_PAYLOADS);
 
     if (postings != null) {
       return new TermSpans(postings, term);

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java Wed Nov 12 14:56:17 2014
@@ -17,11 +17,18 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.IndexReaderContext;
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
-import org.apache.lucene.search.*;
+import org.apache.lucene.search.ComplexExplanation;
+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.TermStatistics;
+import org.apache.lucene.search.Weight;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.search.similarities.Similarity.SimScorer;
 import org.apache.lucene.util.Bits;
@@ -81,7 +88,7 @@ public class SpanWeight extends Weight {
   }
 
   @Override
-  public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
+  public Scorer scorer(LeafReaderContext context, int flags, Bits acceptDocs) throws IOException {
     if (stats == null) {
       return null;
     } else {
@@ -91,7 +98,7 @@ public class SpanWeight extends Weight {
 
   @Override
   public Explanation explain(LeafReaderContext context, int doc) throws IOException {
-    SpanScorer scorer = (SpanScorer) scorer(context, context.reader().getLiveDocs());
+    SpanScorer scorer = (SpanScorer) scorer(context, DocsEnum.FLAG_POSITIONS, context.reader().getLiveDocs());
     if (scorer != null) {
       int newDoc = scorer.advance(doc);
       if (newDoc == doc) {

Modified: lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/java/org/apache/lucene/search/spans/TermSpans.java Wed Nov 12 14:56:17 2014
@@ -17,7 +17,7 @@ package org.apache.lucene.search.spans;
 
 
 import org.apache.lucene.index.Term;
-import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.util.BytesRef;
 
@@ -30,7 +30,7 @@ import java.util.Collection;
  * Public for extension only
  */
 public class TermSpans extends Spans {
-  protected final DocsAndPositionsEnum postings;
+  protected final DocsEnum postings;
   protected final Term term;
   protected int doc;
   protected int freq;
@@ -38,7 +38,7 @@ public class TermSpans extends Spans {
   protected int position;
   protected boolean readPayload;
 
-  public TermSpans(DocsAndPositionsEnum postings, Term term) {
+  public TermSpans(DocsEnum postings, Term term) {
     this.postings = postings;
     this.term = term;
     doc = -1;
@@ -132,7 +132,7 @@ public class TermSpans extends Spans {
             (doc == -1 ? "START" : (doc == Integer.MAX_VALUE) ? "END" : doc + "-" + position);
   }
 
-  public DocsAndPositionsEnum getPostings() {
+  public DocsEnum getPostings() {
     return postings;
   }
 

Modified: lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestCachingTokenFilter.java Wed Nov 12 14:56:17 2014
@@ -26,7 +26,7 @@ import org.apache.lucene.document.Docume
 import org.apache.lucene.document.TextField;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.MultiFields;
-import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.search.DocIdSetIterator;
 import org.apache.lucene.store.Directory;
@@ -72,7 +72,7 @@ public class TestCachingTokenFilter exte
     writer.addDocument(doc);
     
     IndexReader reader = writer.getReader();
-    DocsAndPositionsEnum termPositions = MultiFields.getTermPositionsEnum(reader,
+    DocsEnum termPositions = MultiFields.getTermPositionsEnum(reader,
                                                                           MultiFields.getLiveDocs(reader),
                                                                           "preanalyzed",
                                                                           new BytesRef("term1"));

Modified: lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestMockAnalyzer.java
URL: http://svn.apache.org/viewvc/lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestMockAnalyzer.java?rev=1638805&r1=1638804&r2=1638805&view=diff
==============================================================================
--- lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestMockAnalyzer.java (original)
+++ lucene/dev/lucene2878/lucene/core/src/test/org/apache/lucene/analysis/TestMockAnalyzer.java Wed Nov 12 14:56:17 2014
@@ -17,15 +17,10 @@ package org.apache.lucene.analysis;
  * limitations under the License.
  */
 
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.Arrays;
-import java.util.Random;
-
 import org.apache.lucene.document.Document;
 import org.apache.lucene.document.Field;
 import org.apache.lucene.document.FieldType;
-import org.apache.lucene.index.DocsAndPositionsEnum;
+import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.Fields;
 import org.apache.lucene.index.IndexOptions;
 import org.apache.lucene.index.LeafReader;
@@ -40,6 +35,11 @@ import org.apache.lucene.util.automaton.
 import org.apache.lucene.util.automaton.Operations;
 import org.apache.lucene.util.automaton.RegExp;
 
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Random;
+
 import static org.apache.lucene.util.automaton.Operations.DEFAULT_MAX_DETERMINIZED_STATES;
 
 public class TestMockAnalyzer extends BaseTokenStreamTestCase {
@@ -321,7 +321,7 @@ public class TestMockAnalyzer extends Ba
     final Terms terms = fields.terms("f");
     final TermsEnum te = terms.iterator(null);
     assertEquals(new BytesRef("a"), te.next());
-    final DocsAndPositionsEnum dpe = te.docsAndPositions(null, null);
+    final DocsEnum dpe = te.docsAndPositions(null, null);
     assertEquals(0, dpe.nextDoc());
     assertEquals(2, dpe.freq());
     assertEquals(0, dpe.nextPosition());