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 2015/05/20 15:47:19 UTC

svn commit: r1680569 [1/2] - in /lucene/dev/branches/branch_5x: ./ lucene/ lucene/core/ lucene/core/src/java/org/apache/lucene/search/payloads/ lucene/core/src/java/org/apache/lucene/search/spans/ lucene/core/src/test/org/apache/lucene/search/spans/ lu...

Author: romseygeek
Date: Wed May 20 13:47:18 2015
New Revision: 1680569

URL: http://svn.apache.org/r1680569
Log:
LUCENE-6466: Move SpanQuery.getSpans() and .extractTerms() to SpanWeight

Added:
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanSimilarity.java
      - copied unchanged from r1680565, lucene/dev/trunk/lucene/core/src/java/org/apache/lucene/search/spans/SpanSimilarity.java
    lucene/dev/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/search/spans/AssertingSpanWeight.java
      - copied unchanged from r1680565, lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/spans/AssertingSpanWeight.java
Modified:
    lucene/dev/branches/branch_5x/   (props changed)
    lucene/dev/branches/branch_5x/lucene/   (props changed)
    lucene/dev/branches/branch_5x/lucene/CHANGES.txt   (contents, props changed)
    lucene/dev/branches/branch_5x/lucene/core/   (props changed)
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanCollector.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanNearPayloadCheckQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanPayloadCheckQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanCollectorFactory.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
    lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanWithinQuery.java
    lucene/dev/branches/branch_5x/lucene/core/src/test/org/apache/lucene/search/spans/JustCompileSearchSpans.java
    lucene/dev/branches/branch_5x/lucene/core/src/test/org/apache/lucene/search/spans/MultiSpansWrapper.java
    lucene/dev/branches/branch_5x/lucene/core/src/test/org/apache/lucene/search/spans/TestFieldMaskingSpanQuery.java
    lucene/dev/branches/branch_5x/lucene/highlighter/   (props changed)
    lucene/dev/branches/branch_5x/lucene/highlighter/src/java/org/apache/lucene/search/highlight/WeightedSpanTermExtractor.java
    lucene/dev/branches/branch_5x/lucene/test-framework/   (props changed)
    lucene/dev/branches/branch_5x/lucene/test-framework/src/java/org/apache/lucene/search/spans/AssertingSpanQuery.java

Modified: lucene/dev/branches/branch_5x/lucene/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/CHANGES.txt?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/CHANGES.txt (original)
+++ lucene/dev/branches/branch_5x/lucene/CHANGES.txt Wed May 20 13:47:18 2015
@@ -175,6 +175,9 @@ API Changes
 * LUCENE-6484: Removed EliasFanoDocIdSet, which was unused.
   (Paul Elschot via Adrien Grand)
 
+* LUCENE-6466: Moved SpanQuery.getSpans() and .extractTerms() to SpanWeight
+  (Alan Woodward)
+
 Other
 
 * LUCENE-6413: Test runner should report the number of suites completed/ 

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadNearQuery.java Wed May 20 13:47:18 2015
@@ -24,9 +24,11 @@ import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
 import org.apache.lucene.search.similarities.Similarity;
 import org.apache.lucene.search.similarities.Similarity.SimScorer;
+import org.apache.lucene.search.spans.SpanCollectorFactory;
 import org.apache.lucene.search.spans.SpanNearQuery;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanScorer;
+import org.apache.lucene.search.spans.SpanSimilarity;
 import org.apache.lucene.search.spans.SpanWeight;
 import org.apache.lucene.search.spans.Spans;
 import org.apache.lucene.util.Bits;
@@ -34,8 +36,10 @@ import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.ToStringUtils;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -69,8 +73,13 @@ public class PayloadNearQuery extends Sp
   }
 
   @Override
-  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-    return new PayloadNearSpanWeight(this, searcher);
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    List<SpanWeight> subWeights = new ArrayList<>();
+    for (SpanQuery q : clauses) {
+      subWeights.add(q.createWeight(searcher, false, PayloadSpanCollector.FACTORY));
+    }
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, subWeights);
+    return new PayloadNearSpanWeight(subWeights, similarity);
   }
 
   @Override
@@ -127,20 +136,20 @@ public class PayloadNearQuery extends Sp
           && function.equals(other.function);
   }
 
-  public class PayloadNearSpanWeight extends SpanWeight {
+  public class PayloadNearSpanWeight extends SpanNearWeight {
 
-    public PayloadNearSpanWeight(SpanQuery query, IndexSearcher searcher)
+    public PayloadNearSpanWeight(List<SpanWeight> subWeights, SpanSimilarity similarity)
         throws IOException {
-      super(query, searcher, PayloadSpanCollector.FACTORY);
+      super(subWeights, similarity, PayloadSpanCollector.FACTORY);
     }
 
     @Override
     public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
-      PayloadSpanCollector collector = PayloadSpanCollector.FACTORY.newCollector();
-      Spans spans = query.getSpans(context, acceptDocs, termContexts, collector);
+      PayloadSpanCollector collector = (PayloadSpanCollector) collectorFactory.newCollector();
+      Spans spans = super.getSpans(context, acceptDocs, collector);
       return (spans == null)
               ? null
-              : new PayloadNearSpanScorer(spans, this, collector, similarity.simScorer(stats, context));
+              : new PayloadNearSpanScorer(spans, this, collector, similarity.simScorer(context));
     }
     
     @Override
@@ -151,7 +160,7 @@ public class PayloadNearQuery extends Sp
         if (newDoc == doc) {
           float freq = scorer.freq();
           Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
-          SimScorer docScorer = similarity.simScorer(stats, context);
+          SimScorer docScorer = similarity.simScorer(context);
           Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
           Explanation expl = Explanation.match(
               scoreExplanation.getValue(),

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanCollector.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanCollector.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanCollector.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanCollector.java Wed May 20 13:47:18 2015
@@ -34,7 +34,7 @@ import java.util.Collection;
  */
 public class PayloadSpanCollector implements SpanCollector {
 
-  public static final SpanCollectorFactory<PayloadSpanCollector> FACTORY = new SpanCollectorFactory<PayloadSpanCollector>() {
+  public static final SpanCollectorFactory FACTORY = new SpanCollectorFactory() {
     @Override
     public PayloadSpanCollector newCollector() {
       return new PayloadSpanCollector();

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadSpanUtil.java Wed May 20 13:47:18 2015
@@ -21,7 +21,6 @@ import org.apache.lucene.index.IndexRead
 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.BooleanClause;
 import org.apache.lucene.search.BooleanQuery;
 import org.apache.lucene.search.DisjunctionMaxQuery;
@@ -35,16 +34,14 @@ import org.apache.lucene.search.spans.Sp
 import org.apache.lucene.search.spans.SpanOrQuery;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanTermQuery;
+import org.apache.lucene.search.spans.SpanWeight;
 import org.apache.lucene.search.spans.Spans;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.TreeSet;
 
 /**
  * Experimental class to get set of payloads for most standard Lucene queries.
@@ -179,18 +176,15 @@ public class PayloadSpanUtil {
 
   private void getPayloads(Collection<byte []> payloads, SpanQuery query)
       throws IOException {
-    Map<Term,TermContext> termContexts = new HashMap<>();
-    TreeSet<Term> terms = new TreeSet<>();
+
     final IndexSearcher searcher = new IndexSearcher(context);
     searcher.setQueryCache(null);
-    searcher.createNormalizedWeight(query, false).extractTerms(terms);
-    for (Term term : terms) {
-      termContexts.put(term, TermContext.build(context, term));
-    }
+
+    SpanWeight w = (SpanWeight) searcher.createNormalizedWeight(query, false);
 
     PayloadSpanCollector collector = new PayloadSpanCollector();
     for (LeafReaderContext leafReaderContext : context.leaves()) {
-      final Spans spans = query.getSpans(leafReaderContext, leafReaderContext.reader().getLiveDocs(), termContexts, collector);
+      final Spans spans = w.getSpans(leafReaderContext, leafReaderContext.reader().getLiveDocs(), collector);
       if (spans != null) {
         while (spans.nextDoc() != Spans.NO_MORE_DOCS) {
           while (spans.nextStartPosition() != Spans.NO_MORE_POSITIONS) {

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/PayloadTermQuery.java Wed May 20 13:47:18 2015
@@ -20,6 +20,7 @@ package org.apache.lucene.search.payload
 import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.index.PostingsEnum;
 import org.apache.lucene.index.Term;
+import org.apache.lucene.index.TermContext;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.similarities.DefaultSimilarity;
@@ -27,13 +28,12 @@ import org.apache.lucene.search.similari
 import org.apache.lucene.search.similarities.Similarity.SimScorer;
 import org.apache.lucene.search.spans.BufferedSpanCollector;
 import org.apache.lucene.search.spans.SpanCollector;
-import org.apache.lucene.search.spans.SpanCollectorFactory;
 import org.apache.lucene.search.spans.SpanQuery;
 import org.apache.lucene.search.spans.SpanScorer;
+import org.apache.lucene.search.spans.SpanSimilarity;
 import org.apache.lucene.search.spans.SpanTermQuery;
 import org.apache.lucene.search.spans.SpanWeight;
 import org.apache.lucene.search.spans.Spans;
-import org.apache.lucene.search.spans.TermSpans;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.BytesRef;
 
@@ -70,7 +70,9 @@ public class PayloadTermQuery extends Sp
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-    return new PayloadTermWeight(this, searcher);
+    TermContext context = TermContext.build(searcher.getTopReaderContext(), term);
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, searcher.termStatistics(term, context));
+    return new PayloadTermWeight(context, similarity);
   }
 
   private static class PayloadTermCollector implements SpanCollector {
@@ -103,20 +105,20 @@ public class PayloadTermQuery extends Sp
     }
   }
 
-  private class PayloadTermWeight extends SpanWeight {
+  private class PayloadTermWeight extends SpanTermWeight {
 
-    public PayloadTermWeight(PayloadTermQuery query, IndexSearcher searcher)
+    public PayloadTermWeight(TermContext context, SpanSimilarity similarity)
         throws IOException {
-      super(query, searcher, SpanCollectorFactory.NO_OP_FACTORY);
+      super(context, similarity, PayloadSpanCollector.FACTORY);
     }
 
     @Override
     public PayloadTermSpanScorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
       PayloadTermCollector collector = new PayloadTermCollector();
-      TermSpans spans = (TermSpans) query.getSpans(context, acceptDocs, termContexts, collector);
+      Spans spans = super.getSpans(context, acceptDocs, collector);
       return (spans == null)
               ? null
-              : new PayloadTermSpanScorer(spans, this, collector, similarity.simScorer(stats, context));
+              : new PayloadTermSpanScorer(spans, this, collector, similarity.simScorer(context));
     }
 
     protected class PayloadTermSpanScorer extends SpanScorer {
@@ -125,7 +127,7 @@ public class PayloadTermQuery extends Sp
       protected int payloadsSeen;
       private final PayloadTermCollector payloadCollector;
 
-      public PayloadTermSpanScorer(TermSpans spans, SpanWeight weight, PayloadTermCollector collector,
+      public PayloadTermSpanScorer(Spans spans, SpanWeight weight, PayloadTermCollector collector,
                                    Similarity.SimScorer docScorer) throws IOException {
         super(spans, weight, docScorer);
         this.payloadCollector = collector;
@@ -206,7 +208,7 @@ public class PayloadTermQuery extends Sp
         if (newDoc == doc) {
           float freq = scorer.sloppyFreq();
           Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
-          SimScorer docScorer = similarity.simScorer(stats, context);
+          SimScorer docScorer = similarity.simScorer(context);
           Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
           Explanation expl = Explanation.match(
               scoreExplanation.getValue(),

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanNearPayloadCheckQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanNearPayloadCheckQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanNearPayloadCheckQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanNearPayloadCheckQuery.java Wed May 20 13:47:18 2015
@@ -50,7 +50,7 @@ public class SpanNearPayloadCheckQuery e
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-    return new SpanWeight(this, searcher, PayloadSpanCollector.FACTORY);
+    return createWeight(searcher, needsScores, PayloadSpanCollector.FACTORY);
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanPayloadCheckQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanPayloadCheckQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanPayloadCheckQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/payloads/SpanPayloadCheckQuery.java Wed May 20 13:47:18 2015
@@ -58,7 +58,7 @@ public class SpanPayloadCheckQuery exten
 
   @Override
   public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-    return new SpanWeight(this, searcher, PayloadSpanCollector.FACTORY);
+    return super.createWeight(searcher, needsScores, PayloadSpanCollector.FACTORY);
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/FieldMaskingSpanQuery.java Wed May 20 13:47:18 2015
@@ -18,18 +18,12 @@ package org.apache.lucene.search.spans;
  */
 
 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.IndexSearcher;
 import org.apache.lucene.search.Query;
-import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.ToStringUtils;
 
 import java.io.IOException;
-import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 
 /**
  * <p>Wrapper to allow {@link SpanQuery} objects participate in composite 
@@ -94,20 +88,10 @@ public class FieldMaskingSpanQuery exten
 
   // :NOTE: getBoost and setBoost are not proxied to the maskedQuery
   // ...this is done to be more consistent with things like SpanFirstQuery
-  
-  @Override
-  public Spans getSpans(LeafReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException {
-    return maskedQuery.getSpans(context, acceptDocs, termContexts, collector);
-  }
-
-  @Override
-  public void extractTerms(Set<Term> terms) {
-    maskedQuery.extractTerms(terms);
-  }  
 
   @Override
-  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-    return maskedQuery.createWeight(searcher, needsScores);
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    return maskedQuery.createWeight(searcher, needsScores, factory);
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanCollectorFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanCollectorFactory.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanCollectorFactory.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanCollectorFactory.java Wed May 20 13:47:18 2015
@@ -19,19 +19,18 @@ package org.apache.lucene.search.spans;
 
 /**
  * Interface defining a factory for creating new {@link SpanCollector}s
- * @param <T> the SpanCollector type
  */
-public interface SpanCollectorFactory<T extends SpanCollector> {
+public interface SpanCollectorFactory {
 
   /**
    * @return a new SpanCollector
    */
-  T newCollector();
+  SpanCollector newCollector();
 
   /**
    * Factory for creating NO_OP collectors
    */
-  public static final SpanCollectorFactory<?> NO_OP_FACTORY = new SpanCollectorFactory() {
+  public static final SpanCollectorFactory NO_OP_FACTORY = new SpanCollectorFactory() {
     @Override
     public SpanCollector newCollector() {
       return SpanCollector.NO_OP;

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainQuery.java Wed May 20 13:47:18 2015
@@ -31,6 +31,7 @@ import java.util.Objects;
 import java.util.Set;
 
 abstract class SpanContainQuery extends SpanQuery implements Cloneable {
+
   SpanQuery big;
   SpanQuery little;
 
@@ -48,26 +49,48 @@ abstract class SpanContainQuery extends
   @Override
   public String getField() { return big.getField(); }
 
-  /** Extract terms from both <code>big</code> and <code>little</code>. */
-  @Override
-  public void extractTerms(Set<Term> terms) {
-    big.extractTerms(terms);
-    little.extractTerms(terms);
-  }
+  public abstract class SpanContainWeight extends SpanWeight {
+
+    final SpanWeight bigWeight;
+    final SpanWeight littleWeight;
+
+    public SpanContainWeight(SpanSimilarity similarity, SpanCollectorFactory factory,
+                             SpanWeight bigWeight, SpanWeight littleWeight) throws IOException {
+      super(SpanContainQuery.this, similarity, factory);
+      this.bigWeight = bigWeight;
+      this.littleWeight = littleWeight;
+    }
 
-  ArrayList<Spans> prepareConjunction(final LeafReaderContext context, final Bits acceptDocs, final Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException {
-    Spans bigSpans = big.getSpans(context, acceptDocs, termContexts, collector);
-    if (bigSpans == null) {
-      return null;
+    /**
+     * Extract terms from both <code>big</code> and <code>little</code>.
+     */
+    @Override
+    public void extractTerms(Set<Term> terms) {
+      bigWeight.extractTerms(terms);
+      littleWeight.extractTerms(terms);
     }
-    Spans littleSpans = little.getSpans(context, acceptDocs, termContexts, collector);
-    if (littleSpans == null) {
-      return null;
+
+    ArrayList<Spans> prepareConjunction(final LeafReaderContext context, final Bits acceptDocs, SpanCollector collector) throws IOException {
+      Spans bigSpans = bigWeight.getSpans(context, acceptDocs, collector);
+      if (bigSpans == null) {
+        return null;
+      }
+      Spans littleSpans = littleWeight.getSpans(context, acceptDocs, collector);
+      if (littleSpans == null) {
+        return null;
+      }
+      ArrayList<Spans> bigAndLittle = new ArrayList<>();
+      bigAndLittle.add(bigSpans);
+      bigAndLittle.add(littleSpans);
+      return bigAndLittle;
     }
-    ArrayList<Spans> bigAndLittle = new ArrayList<>();
-    bigAndLittle.add(bigSpans);
-    bigAndLittle.add(littleSpans);
-    return bigAndLittle;
+
+    @Override
+    public void extractTermContexts(Map<Term, TermContext> contexts) {
+      bigWeight.extractTermContexts(contexts);
+      littleWeight.extractTermContexts(contexts);
+    }
+
   }
 
   String toString(String field, String name) {

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanContainingQuery.java Wed May 20 13:47:18 2015
@@ -18,13 +18,11 @@ package org.apache.lucene.search.spans;
  */
 
 import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.util.Bits;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Map;
 
 /** Keep matches that contain another Spans. */
 public class SpanContainingQuery extends SpanContainQuery {
@@ -48,63 +46,79 @@ public class SpanContainingQuery extends
           (SpanQuery) big.clone(),
           (SpanQuery) little.clone());
   }
-  
-  /** 
-   * Return spans from <code>big</code> that contain at least one spans from <code>little</code>.
-   * The payload is from the spans of <code>big</code>.
-   */
+
   @Override
-  public Spans getSpans(final LeafReaderContext context, final Bits acceptDocs, final Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException {
-    ArrayList<Spans> containerContained = prepareConjunction(context, acceptDocs, termContexts, collector);
-    if (containerContained == null) {
-      return null;
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    SpanWeight bigWeight = big.createWeight(searcher, false, factory);
+    SpanWeight littleWeight = little.createWeight(searcher, false, factory);
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, bigWeight, littleWeight);
+    return new SpanContainingWeight(similarity, factory, bigWeight, littleWeight);
+  }
+
+  public class SpanContainingWeight extends SpanContainWeight {
+
+    public SpanContainingWeight(SpanSimilarity similarity, SpanCollectorFactory factory,
+                                SpanWeight bigWeight, SpanWeight littleWeight) throws IOException {
+      super(similarity, factory, bigWeight, littleWeight);
     }
-    
-    Spans big = containerContained.get(0);
-    Spans little = containerContained.get(1);
-
-    return new ContainSpans(big, little, big) {
-
-      @Override
-      boolean twoPhaseCurrentDocMatches() throws IOException {
-        oneExhaustedInCurrentDoc = false;
-        assert littleSpans.startPosition() == -1;
-        while (bigSpans.nextStartPosition() != NO_MORE_POSITIONS) {
-          while (littleSpans.startPosition() < bigSpans.startPosition()) {
-            if (littleSpans.nextStartPosition() == NO_MORE_POSITIONS) {
-              oneExhaustedInCurrentDoc = true;
-              return false;
-            }
-          }
-          if (bigSpans.endPosition() >= littleSpans.endPosition()) {
-            atFirstInCurrentDoc = true;
-            return true;
-          }
-        } 
-        oneExhaustedInCurrentDoc = true;
-        return false;
+
+    /**
+     * Return spans from <code>big</code> that contain at least one spans from <code>little</code>.
+     * The payload is from the spans of <code>big</code>.
+     */
+    @Override
+    public Spans getSpans(final LeafReaderContext context, final Bits acceptDocs, SpanCollector collector) throws IOException {
+      ArrayList<Spans> containerContained = prepareConjunction(context, acceptDocs, collector);
+      if (containerContained == null) {
+        return null;
       }
 
-      @Override
-      public int nextStartPosition() throws IOException {
-        if (atFirstInCurrentDoc) {
-          atFirstInCurrentDoc = false;
-          return bigSpans.startPosition();
-        }
-        while (bigSpans.nextStartPosition() != NO_MORE_POSITIONS) {
-          while (littleSpans.startPosition() < bigSpans.startPosition()) {
-            if (littleSpans.nextStartPosition() == NO_MORE_POSITIONS) {
-              oneExhaustedInCurrentDoc = true;
-              return NO_MORE_POSITIONS;
+      Spans big = containerContained.get(0);
+      Spans little = containerContained.get(1);
+
+      return new ContainSpans(big, little, big) {
+
+        @Override
+        boolean twoPhaseCurrentDocMatches() throws IOException {
+          oneExhaustedInCurrentDoc = false;
+          assert littleSpans.startPosition() == -1;
+          while (bigSpans.nextStartPosition() != NO_MORE_POSITIONS) {
+            while (littleSpans.startPosition() < bigSpans.startPosition()) {
+              if (littleSpans.nextStartPosition() == NO_MORE_POSITIONS) {
+                oneExhaustedInCurrentDoc = true;
+                return false;
+              }
+            }
+            if (bigSpans.endPosition() >= littleSpans.endPosition()) {
+              atFirstInCurrentDoc = true;
+              return true;
             }
           }
-          if (bigSpans.endPosition() >= littleSpans.endPosition()) {
+          oneExhaustedInCurrentDoc = true;
+          return false;
+        }
+
+        @Override
+        public int nextStartPosition() throws IOException {
+          if (atFirstInCurrentDoc) {
+            atFirstInCurrentDoc = false;
             return bigSpans.startPosition();
           }
+          while (bigSpans.nextStartPosition() != NO_MORE_POSITIONS) {
+            while (littleSpans.startPosition() < bigSpans.startPosition()) {
+              if (littleSpans.nextStartPosition() == NO_MORE_POSITIONS) {
+                oneExhaustedInCurrentDoc = true;
+                return NO_MORE_POSITIONS;
+              }
+            }
+            if (bigSpans.endPosition() >= littleSpans.endPosition()) {
+              return bigSpans.startPosition();
+            }
+          }
+          oneExhaustedInCurrentDoc = true;
+          return NO_MORE_POSITIONS;
         }
-        oneExhaustedInCurrentDoc = true;
-        return NO_MORE_POSITIONS;
-      }
-    };
+      };
+    }
   }
 }
\ No newline at end of file

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanMultiTermQueryWrapper.java Wed May 20 13:47:18 2015
@@ -18,20 +18,17 @@ package org.apache.lucene.search.spans;
  */
 
 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.Occur;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.MultiTermQuery;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.ScoringRewrite;
 import org.apache.lucene.search.TopTermsRewrite;
-import org.apache.lucene.util.Bits;
 
 import java.io.IOException;
-import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 
 /**
  * Wraps any {@link MultiTermQuery} as a {@link SpanQuery}, 
@@ -75,11 +72,6 @@ public class SpanMultiTermQueryWrapper<Q
     }
   }
 
-  @Override
-  protected void extractTerms(Set<Term> terms) {
-    throw new IllegalStateException("Rewrite first");
-  }
-
   /**
    * Expert: returns the rewriteMethod
    */
@@ -97,17 +89,17 @@ public class SpanMultiTermQueryWrapper<Q
   public final void setRewriteMethod(SpanRewriteMethod rewriteMethod) {
     query.setRewriteMethod(rewriteMethod);
   }
-  
-  @Override
-  public Spans getSpans(LeafReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException {
-    throw new UnsupportedOperationException("Query should have been rewritten");
-  }
 
   @Override
   public String getField() {
     return query.getField();
   }
-  
+
+  @Override
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    throw new IllegalArgumentException("Rewrite first!");
+  }
+
   /** Returns the wrapped query */
   public Query getWrappedQuery() {
     return query;

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNearQuery.java Wed May 20 13:47:18 2015
@@ -22,6 +22,7 @@ import org.apache.lucene.index.LeafReade
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
 import org.apache.lucene.index.Terms;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.ToStringUtils;
@@ -90,13 +91,6 @@ public class SpanNearQuery extends SpanQ
   public String getField() { return field; }
 
   @Override
-  public void extractTerms(Set<Term> terms) {
-    for (final SpanQuery clause : clauses) {
-      clause.extractTerms(terms);
-    }
-  }
-
-  @Override
   public String toString(String field) {
     StringBuilder buffer = new StringBuilder();
     buffer.append("spanNear([");
@@ -118,27 +112,61 @@ public class SpanNearQuery extends SpanQ
   }
 
   @Override
-  public Spans getSpans(final LeafReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException {
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    List<SpanWeight> subWeights = new ArrayList<>();
+    for (SpanQuery q : clauses) {
+      subWeights.add(q.createWeight(searcher, false, factory));
+    }
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, subWeights);
+    return new SpanNearWeight(subWeights, similarity, factory);
+  }
+
+  public class SpanNearWeight extends SpanWeight {
 
-    Terms terms = context.reader().terms(field);
-    if (terms == null) {
-      return null; // field does not exist
+    final List<SpanWeight> subWeights;
+
+    public SpanNearWeight(List<SpanWeight> subWeights, SpanSimilarity similarity, SpanCollectorFactory factory) throws IOException {
+      super(SpanNearQuery.this, similarity, factory);
+      this.subWeights = subWeights;
     }
 
-    ArrayList<Spans> subSpans = new ArrayList<>(clauses.size());
-    SpanCollector subSpanCollector = inOrder ? collector.bufferedCollector() : collector;
-    for (SpanQuery seq : clauses) {
-      Spans subSpan = seq.getSpans(context, acceptDocs, termContexts, subSpanCollector);
-      if (subSpan != null) {
-        subSpans.add(subSpan);
-      } else {
-        return null; // all required
+    @Override
+    public void extractTermContexts(Map<Term, TermContext> contexts) {
+      for (SpanWeight w : subWeights) {
+        w.extractTermContexts(contexts);
       }
     }
 
-    
-    // all NearSpans require at least two subSpans
-    return (! inOrder) ? new NearSpansUnordered(this, subSpans) : new NearSpansOrdered(this, subSpans, collector);
+    @Override
+    public Spans getSpans(final LeafReaderContext context, Bits acceptDocs, SpanCollector collector) throws IOException {
+
+      Terms terms = context.reader().terms(field);
+      if (terms == null) {
+        return null; // field does not exist
+      }
+
+      ArrayList<Spans> subSpans = new ArrayList<>(clauses.size());
+      SpanCollector subSpanCollector = inOrder ? collector.bufferedCollector() : collector;
+      for (SpanWeight w : subWeights) {
+        Spans subSpan = w.getSpans(context, acceptDocs, subSpanCollector);
+        if (subSpan != null) {
+          subSpans.add(subSpan);
+        } else {
+          return null; // all required
+        }
+      }
+
+      // all NearSpans require at least two subSpans
+      return (!inOrder) ? new NearSpansUnordered(SpanNearQuery.this, subSpans)
+          : new NearSpansOrdered(SpanNearQuery.this, subSpans, collector);
+    }
+
+    @Override
+    public void extractTerms(Set<Term> terms) {
+      for (SpanWeight w : subWeights) {
+        w.extractTerms(terms);
+      }
+    }
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanNotQuery.java Wed May 20 13:47:18 2015
@@ -22,6 +22,7 @@ import org.apache.lucene.index.IndexRead
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
 import org.apache.lucene.search.DocIdSetIterator;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TwoPhaseIterator;
 import org.apache.lucene.util.Bits;
@@ -78,9 +79,6 @@ public class SpanNotQuery extends SpanQu
   public String getField() { return include.getField(); }
 
   @Override
-  public void extractTerms(Set<Term> terms) { include.extractTerms(terms); }
-
-  @Override
   public String toString(String field) {
     StringBuilder buffer = new StringBuilder();
     buffer.append("spanNot(");
@@ -104,70 +102,100 @@ public class SpanNotQuery extends SpanQu
     return spanNotQuery;
   }
 
-  @Override
-  public Spans getSpans(final LeafReaderContext context, final Bits acceptDocs, final Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException {
-    final Spans includeSpans = include.getSpans(context, acceptDocs, termContexts, collector);
-    if (includeSpans == null) {
-      return null;
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    SpanWeight includeWeight = include.createWeight(searcher, false, factory);
+    SpanWeight excludeWeight = exclude.createWeight(searcher, false, factory);
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, includeWeight);
+    return new SpanNotWeight(similarity, factory, includeWeight, excludeWeight);
+  }
+
+  public class SpanNotWeight extends SpanWeight {
+
+    final SpanWeight includeWeight;
+    final SpanWeight excludeWeight;
+
+    public SpanNotWeight(SpanSimilarity similarity, SpanCollectorFactory factory,
+                         SpanWeight includeWeight, SpanWeight excludeWeight) throws IOException {
+      super(SpanNotQuery.this, similarity, factory);
+      this.includeWeight = includeWeight;
+      this.excludeWeight = excludeWeight;
     }
 
-    final Spans excludeSpans = exclude.getSpans(context, acceptDocs, termContexts, collector);
-    if (excludeSpans == null) {
-      return includeSpans;
+    @Override
+    public void extractTermContexts(Map<Term, TermContext> contexts) {
+      includeWeight.extractTermContexts(contexts);
     }
-    
-    final TwoPhaseIterator excludeTwoPhase = excludeSpans.asTwoPhaseIterator();
-    final DocIdSetIterator excludeApproximation = excludeTwoPhase == null ? null : excludeTwoPhase.approximation();
-    
-    return new FilterSpans(includeSpans) {
-      // last document we have checked matches() against for the exclusion, and failed
-      // when using approximations, so we don't call it again, and pass thru all inclusions.
-      int lastApproxDoc = -1;
-      boolean lastApproxResult = false;
-      
-      @Override
-      protected AcceptStatus accept(Spans candidate) throws IOException {
-        // TODO: this logic is ugly and sneaky, can we clean it up?
-        int doc = candidate.docID();
-        if (doc > excludeSpans.docID()) {
-          // catch up 'exclude' to the current doc
-          if (excludeTwoPhase != null) {
-            if (excludeApproximation.advance(doc) == doc) {
-              lastApproxDoc = doc;
-              lastApproxResult = excludeTwoPhase.matches();
+
+    @Override
+    public Spans getSpans(final LeafReaderContext context, final Bits acceptDocs, SpanCollector collector) throws IOException {
+      final Spans includeSpans = includeWeight.getSpans(context, acceptDocs, collector);
+      if (includeSpans == null) {
+        return null;
+      }
+
+      final Spans excludeSpans = excludeWeight.getSpans(context, acceptDocs, collector);
+      if (excludeSpans == null) {
+        return includeSpans;
+      }
+
+      final TwoPhaseIterator excludeTwoPhase = excludeSpans.asTwoPhaseIterator();
+      final DocIdSetIterator excludeApproximation = excludeTwoPhase == null ? null : excludeTwoPhase.approximation();
+
+      return new FilterSpans(includeSpans) {
+        // last document we have checked matches() against for the exclusion, and failed
+        // when using approximations, so we don't call it again, and pass thru all inclusions.
+        int lastApproxDoc = -1;
+        boolean lastApproxResult = false;
+
+        @Override
+        protected AcceptStatus accept(Spans candidate) throws IOException {
+          // TODO: this logic is ugly and sneaky, can we clean it up?
+          int doc = candidate.docID();
+          if (doc > excludeSpans.docID()) {
+            // catch up 'exclude' to the current doc
+            if (excludeTwoPhase != null) {
+              if (excludeApproximation.advance(doc) == doc) {
+                lastApproxDoc = doc;
+                lastApproxResult = excludeTwoPhase.matches();
+              }
+            } else {
+              excludeSpans.advance(doc);
             }
-          } else {
-            excludeSpans.advance(doc);
+          } else if (excludeTwoPhase != null && doc == excludeSpans.docID() && doc != lastApproxDoc) {
+            // excludeSpans already sitting on our candidate doc, but matches not called yet.
+            lastApproxDoc = doc;
+            lastApproxResult = excludeTwoPhase.matches();
           }
-        } else if (excludeTwoPhase != null && doc == excludeSpans.docID() && doc != lastApproxDoc) {
-          // excludeSpans already sitting on our candidate doc, but matches not called yet.
-          lastApproxDoc = doc;
-          lastApproxResult = excludeTwoPhase.matches();
-        }
-        
-        if (doc != excludeSpans.docID() || (doc == lastApproxDoc && lastApproxResult == false)) {
-          return AcceptStatus.YES;
-        }
-        
-        if (excludeSpans.startPosition() == -1) { // init exclude start position if needed
-          excludeSpans.nextStartPosition();
-        }
-        
-        while (excludeSpans.endPosition() <= candidate.startPosition() - pre) {
-          // exclude end position is before a possible exclusion
-          if (excludeSpans.nextStartPosition() == NO_MORE_POSITIONS) {
-            return AcceptStatus.YES; // no more exclude at current doc.
+
+          if (doc != excludeSpans.docID() || (doc == lastApproxDoc && lastApproxResult == false)) {
+            return AcceptStatus.YES;
+          }
+
+          if (excludeSpans.startPosition() == -1) { // init exclude start position if needed
+            excludeSpans.nextStartPosition();
+          }
+
+          while (excludeSpans.endPosition() <= candidate.startPosition() - pre) {
+            // exclude end position is before a possible exclusion
+            if (excludeSpans.nextStartPosition() == NO_MORE_POSITIONS) {
+              return AcceptStatus.YES; // no more exclude at current doc.
+            }
+          }
+
+          // exclude end position far enough in current doc, check start position:
+          if (candidate.endPosition() + post <= excludeSpans.startPosition()) {
+            return AcceptStatus.YES;
+          } else {
+            return AcceptStatus.NO;
           }
         }
-        
-        // exclude end position far enough in current doc, check start position:
-        if (candidate.endPosition() + post <= excludeSpans.startPosition()) {
-          return AcceptStatus.YES;
-        } else {
-          return AcceptStatus.NO;
-        }
-      }
-    };
+      };
+    }
+
+    @Override
+    public void extractTerms(Set<Term> terms) {
+      includeWeight.extractTerms(terms);
+    }
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanOrQuery.java Wed May 20 13:47:18 2015
@@ -24,6 +24,7 @@ import org.apache.lucene.index.TermConte
 import org.apache.lucene.search.DisiPriorityQueue;
 import org.apache.lucene.search.DisiWrapper;
 import org.apache.lucene.search.DisjunctionDISIApproximation;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.TwoPhaseIterator;
 import org.apache.lucene.util.Bits;
@@ -72,13 +73,6 @@ public class SpanOrQuery extends SpanQue
   public String getField() { return field; }
 
   @Override
-  public void extractTerms(Set<Term> terms) {
-    for(final SpanQuery clause: clauses) {
-      clause.extractTerms(terms);
-    }
-  }
-
-  @Override
   public SpanOrQuery clone() {
     int sz = clauses.size();
     SpanQuery[] newClauses = new SpanQuery[sz];
@@ -143,190 +137,223 @@ public class SpanOrQuery extends SpanQue
     return h;
   }
 
-
   @Override
-  public Spans getSpans(final LeafReaderContext context, final Bits acceptDocs, final Map<Term,TermContext> termContexts, SpanCollector collector)
-  throws IOException {
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    List<SpanWeight> subWeights = new ArrayList<>(clauses.size());
+    for (SpanQuery q : clauses) {
+      subWeights.add(q.createWeight(searcher, false, factory));
+    }
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, subWeights);
+    return new SpanOrWeight(similarity, factory, subWeights);
+  }
 
-    final ArrayList<Spans> subSpans = new ArrayList<>(clauses.size());
+  public class SpanOrWeight extends SpanWeight {
 
-    for (SpanQuery sq : clauses) {
-      Spans spans = sq.getSpans(context, acceptDocs, termContexts, collector);
-      if (spans != null) {
-        subSpans.add(spans);
-      }
+    final List<SpanWeight> subWeights;
+
+    public SpanOrWeight(SpanSimilarity similarity, SpanCollectorFactory factory, List<SpanWeight> subWeights) throws IOException {
+      super(SpanOrQuery.this, similarity, factory);
+      this.subWeights = subWeights;
     }
 
-    if (subSpans.size() == 0) {
-      return null;
-    } else if (subSpans.size() == 1) {
-      return subSpans.get(0);
-    }
-
-    final DisiPriorityQueue<Spans> byDocQueue = new DisiPriorityQueue<>(subSpans.size());
-    for (Spans spans : subSpans) {
-      byDocQueue.add(new DisiWrapper<>(spans));
-    }
-
-    final SpanPositionQueue byPositionQueue = new SpanPositionQueue(subSpans.size()); // when empty use -1
-
-    return new Spans() {
-      Spans topPositionSpans = null;
-
-      @Override
-      public int nextDoc() throws IOException {
-        topPositionSpans = null;
-        DisiWrapper<Spans> topDocSpans = byDocQueue.top();
-        int currentDoc = topDocSpans.doc;
-        do {
-          topDocSpans.doc = topDocSpans.iterator.nextDoc();
-          topDocSpans = byDocQueue.updateTop();
-        } while (topDocSpans.doc == currentDoc);
-        return topDocSpans.doc;
+    @Override
+    public void extractTerms(Set<Term> terms) {
+      for (final SpanWeight w: subWeights) {
+        w.extractTerms(terms);
       }
+    }
 
-      @Override
-      public int advance(int target) throws IOException {
-        topPositionSpans = null;
-        DisiWrapper<Spans> topDocSpans = byDocQueue.top();
-        do {
-          topDocSpans.doc = topDocSpans.iterator.advance(target);
-          topDocSpans = byDocQueue.updateTop();
-        } while (topDocSpans.doc < target);
-        return topDocSpans.doc;
+    @Override
+    public void extractTermContexts(Map<Term, TermContext> contexts) {
+      for (SpanWeight w : subWeights) {
+        w.extractTermContexts(contexts);
       }
+    }
 
-      @Override
-      public int docID() {
-        DisiWrapper<Spans> topDocSpans = byDocQueue.top();
-        return topDocSpans.doc;
+    @Override
+    public Spans getSpans(final LeafReaderContext context, final Bits acceptDocs, SpanCollector collector)
+        throws IOException {
+
+      final ArrayList<Spans> subSpans = new ArrayList<>(clauses.size());
+
+      for (SpanWeight w : subWeights) {
+        Spans spans = w.getSpans(context, acceptDocs, collector);
+        if (spans != null) {
+          subSpans.add(spans);
+        }
       }
 
-      @Override
-      public TwoPhaseIterator asTwoPhaseIterator() {
-        boolean hasApproximation = false;
-        for (DisiWrapper<Spans> w : byDocQueue) {
-          if (w.twoPhaseView != null) {
-            hasApproximation = true;
-            break;
-          }
+      if (subSpans.size() == 0) {
+        return null;
+      } else if (subSpans.size() == 1) {
+        return subSpans.get(0);
+      }
+
+      final DisiPriorityQueue<Spans> byDocQueue = new DisiPriorityQueue<>(subSpans.size());
+      for (Spans spans : subSpans) {
+        byDocQueue.add(new DisiWrapper<>(spans));
+      }
+
+      final SpanPositionQueue byPositionQueue = new SpanPositionQueue(subSpans.size()); // when empty use -1
+
+      return new Spans() {
+        Spans topPositionSpans = null;
+
+        @Override
+        public int nextDoc() throws IOException {
+          topPositionSpans = null;
+          DisiWrapper<Spans> topDocSpans = byDocQueue.top();
+          int currentDoc = topDocSpans.doc;
+          do {
+            topDocSpans.doc = topDocSpans.iterator.nextDoc();
+            topDocSpans = byDocQueue.updateTop();
+          } while (topDocSpans.doc == currentDoc);
+          return topDocSpans.doc;
+        }
+
+        @Override
+        public int advance(int target) throws IOException {
+          topPositionSpans = null;
+          DisiWrapper<Spans> topDocSpans = byDocQueue.top();
+          do {
+            topDocSpans.doc = topDocSpans.iterator.advance(target);
+            topDocSpans = byDocQueue.updateTop();
+          } while (topDocSpans.doc < target);
+          return topDocSpans.doc;
         }
 
-        if (! hasApproximation) { // none of the sub spans supports approximations
-          return null;
+        @Override
+        public int docID() {
+          DisiWrapper<Spans> topDocSpans = byDocQueue.top();
+          return topDocSpans.doc;
         }
 
-        return new TwoPhaseIterator(new DisjunctionDISIApproximation<Spans>(byDocQueue)) {
-          @Override
-          public boolean matches() throws IOException {
-            return twoPhaseCurrentDocMatches();
+        @Override
+        public TwoPhaseIterator asTwoPhaseIterator() {
+          boolean hasApproximation = false;
+          for (DisiWrapper<Spans> w : byDocQueue) {
+            if (w.twoPhaseView != null) {
+              hasApproximation = true;
+              break;
+            }
           }
-        };
-      }
-      
-      int lastDocTwoPhaseMatched = -1;
 
-      boolean twoPhaseCurrentDocMatches() throws IOException {
-        DisiWrapper<Spans> listAtCurrentDoc = byDocQueue.topList();
-        // remove the head of the list as long as it does not match
-        final int currentDoc = listAtCurrentDoc.doc;
-        while (listAtCurrentDoc.twoPhaseView != null) {
-          if (listAtCurrentDoc.twoPhaseView.matches()) {
-            // use this spans for positions at current doc:
-            listAtCurrentDoc.lastApproxMatchDoc = currentDoc;
-            break;
+          if (!hasApproximation) { // none of the sub spans supports approximations
+            return null;
           }
-          // do not use this spans for positions at current doc:
-          listAtCurrentDoc.lastApproxNonMatchDoc = currentDoc;
-          listAtCurrentDoc = listAtCurrentDoc.next;
-          if (listAtCurrentDoc == null) {
-            return false;
+
+          return new TwoPhaseIterator(new DisjunctionDISIApproximation<Spans>(byDocQueue)) {
+            @Override
+            public boolean matches() throws IOException {
+              return twoPhaseCurrentDocMatches();
+            }
+          };
+        }
+
+        int lastDocTwoPhaseMatched = -1;
+
+        boolean twoPhaseCurrentDocMatches() throws IOException {
+          DisiWrapper<Spans> listAtCurrentDoc = byDocQueue.topList();
+          // remove the head of the list as long as it does not match
+          final int currentDoc = listAtCurrentDoc.doc;
+          while (listAtCurrentDoc.twoPhaseView != null) {
+            if (listAtCurrentDoc.twoPhaseView.matches()) {
+              // use this spans for positions at current doc:
+              listAtCurrentDoc.lastApproxMatchDoc = currentDoc;
+              break;
+            }
+            // do not use this spans for positions at current doc:
+            listAtCurrentDoc.lastApproxNonMatchDoc = currentDoc;
+            listAtCurrentDoc = listAtCurrentDoc.next;
+            if (listAtCurrentDoc == null) {
+              return false;
+            }
           }
+          lastDocTwoPhaseMatched = currentDoc;
+          topPositionSpans = null;
+          return true;
         }
-        lastDocTwoPhaseMatched = currentDoc;
-        topPositionSpans = null;
-        return true;
-      }
 
-      void fillPositionQueue() throws IOException { // called at first nextStartPosition
-        assert byPositionQueue.size() == 0;
-        // add all matching Spans at current doc to byPositionQueue
-        DisiWrapper<Spans> listAtCurrentDoc = byDocQueue.topList();
-        while (listAtCurrentDoc != null) {
-          Spans spansAtDoc = listAtCurrentDoc.iterator;
-          if (lastDocTwoPhaseMatched == listAtCurrentDoc.doc) { // matched by DisjunctionDisiApproximation
-            if (listAtCurrentDoc.twoPhaseView != null) { // matched by approximation
-              if (listAtCurrentDoc.lastApproxNonMatchDoc == listAtCurrentDoc.doc) { // matches() returned false
-                spansAtDoc = null;
-              } else {
-                if (listAtCurrentDoc.lastApproxMatchDoc != listAtCurrentDoc.doc) {
-                  if (! listAtCurrentDoc.twoPhaseView.matches()) {
-                    spansAtDoc = null;
+        void fillPositionQueue() throws IOException { // called at first nextStartPosition
+          assert byPositionQueue.size() == 0;
+          // add all matching Spans at current doc to byPositionQueue
+          DisiWrapper<Spans> listAtCurrentDoc = byDocQueue.topList();
+          while (listAtCurrentDoc != null) {
+            Spans spansAtDoc = listAtCurrentDoc.iterator;
+            if (lastDocTwoPhaseMatched == listAtCurrentDoc.doc) { // matched by DisjunctionDisiApproximation
+              if (listAtCurrentDoc.twoPhaseView != null) { // matched by approximation
+                if (listAtCurrentDoc.lastApproxNonMatchDoc == listAtCurrentDoc.doc) { // matches() returned false
+                  spansAtDoc = null;
+                } else {
+                  if (listAtCurrentDoc.lastApproxMatchDoc != listAtCurrentDoc.doc) {
+                    if (!listAtCurrentDoc.twoPhaseView.matches()) {
+                      spansAtDoc = null;
+                    }
                   }
                 }
-              } 
+              }
             }
-          }
 
-          if (spansAtDoc != null) {
-            assert spansAtDoc.docID() == listAtCurrentDoc.doc;
-            assert spansAtDoc.startPosition() == -1;
-            spansAtDoc.nextStartPosition();
-            assert spansAtDoc.startPosition() != NO_MORE_POSITIONS;
-            byPositionQueue.add(spansAtDoc);
+            if (spansAtDoc != null) {
+              assert spansAtDoc.docID() == listAtCurrentDoc.doc;
+              assert spansAtDoc.startPosition() == -1;
+              spansAtDoc.nextStartPosition();
+              assert spansAtDoc.startPosition() != NO_MORE_POSITIONS;
+              byPositionQueue.add(spansAtDoc);
+            }
+            listAtCurrentDoc = listAtCurrentDoc.next;
           }
-          listAtCurrentDoc = listAtCurrentDoc.next;
+          assert byPositionQueue.size() > 0;
         }
-        assert byPositionQueue.size() > 0;
-      }
-        
-      @Override
-      public int nextStartPosition() throws IOException {
-        if (topPositionSpans == null) {
-          byPositionQueue.clear();
-          fillPositionQueue(); // fills byPositionQueue at first position
-          topPositionSpans = byPositionQueue.top();
-        } else {
-          topPositionSpans.nextStartPosition();
-          topPositionSpans = byPositionQueue.updateTop();
+
+        @Override
+        public int nextStartPosition() throws IOException {
+          if (topPositionSpans == null) {
+            byPositionQueue.clear();
+            fillPositionQueue(); // fills byPositionQueue at first position
+            topPositionSpans = byPositionQueue.top();
+          } else {
+            topPositionSpans.nextStartPosition();
+            topPositionSpans = byPositionQueue.updateTop();
+          }
+          return topPositionSpans.startPosition();
         }
-        return topPositionSpans.startPosition();
-      }
 
-      @Override
-      public int startPosition() {
-        return topPositionSpans == null ? -1 : topPositionSpans.startPosition();
-      }
+        @Override
+        public int startPosition() {
+          return topPositionSpans == null ? -1 : topPositionSpans.startPosition();
+        }
 
-      @Override
-      public int endPosition() {
-        return topPositionSpans == null ? -1 : topPositionSpans.endPosition();
-      }
+        @Override
+        public int endPosition() {
+          return topPositionSpans == null ? -1 : topPositionSpans.endPosition();
+        }
 
-      @Override
-      public void collect(SpanCollector collector) throws IOException {
-        if (topPositionSpans != null)
-          topPositionSpans.collect(collector);
-      }
+        @Override
+        public void collect(SpanCollector collector) throws IOException {
+          if (topPositionSpans != null)
+            topPositionSpans.collect(collector);
+        }
 
-      @Override
-      public String toString() {
-        return "spanOr("+SpanOrQuery.this+")@"+docID()+": "+startPosition()+" - "+endPosition();
-      }
+        @Override
+        public String toString() {
+          return "spanOr(" + SpanOrQuery.this + ")@" + docID() + ": " + startPosition() + " - " + endPosition();
+        }
 
-      long cost = -1;
+        long cost = -1;
 
-      @Override
-      public long cost() {
-        if (cost == -1) {
-          cost = 0;
-          for (Spans spans : subSpans) {
-            cost += spans.cost();
+        @Override
+        public long cost() {
+          if (cost == -1) {
+            cost = 0;
+            for (Spans spans : subSpans) {
+              cost += spans.cost();
+            }
           }
+          return cost;
         }
-        return cost;
-      }
-    };
+      };
+    }
   }
 
 }

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanPositionCheckQuery.java Wed May 20 13:47:18 2015
@@ -21,6 +21,7 @@ import org.apache.lucene.index.LeafReade
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermContext;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.spans.FilterSpans.AcceptStatus;
 import org.apache.lucene.util.Bits;
@@ -47,18 +48,9 @@ public abstract class SpanPositionCheckQ
    * */
   public SpanQuery getMatch() { return match; }
 
-
-
   @Override
   public String getField() { return match.getField(); }
 
-
-
-  @Override
-  public void extractTerms(Set<Term> terms) {
-    match.extractTerms(terms);
-  }
-
   /**
    * Implementing classes are required to return whether the current position is a match for the passed in
    * "match" {@link SpanQuery}.
@@ -66,7 +58,6 @@ public abstract class SpanPositionCheckQ
    * This is only called if the underlying last {@link Spans#nextStartPosition()} for the
    * match indicated a valid start position.
    *
-   *
    * @param spans The {@link Spans} instance, positioned at the spot to check
    * @param collector the {@link SpanCollector} associated with the Spans
    *
@@ -78,14 +69,47 @@ public abstract class SpanPositionCheckQ
   protected abstract AcceptStatus acceptPosition(Spans spans, SpanCollector collector) throws IOException;
 
   @Override
-  public Spans getSpans(final LeafReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts, final SpanCollector collector) throws IOException {
-    Spans matchSpans = match.getSpans(context, acceptDocs, termContexts, collector);
-    return (matchSpans == null) ? null : new FilterSpans(matchSpans) {
-      @Override
-      protected AcceptStatus accept(Spans candidate) throws IOException {
-        return acceptPosition(candidate, collector);
-      }
-    };
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    SpanWeight matchWeight = match.createWeight(searcher, false, factory);
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, matchWeight);
+    return new SpanPositionCheckWeight(matchWeight, similarity, factory);
+  }
+
+  public class SpanPositionCheckWeight extends SpanWeight {
+
+    final SpanWeight matchWeight;
+
+    public SpanPositionCheckWeight(SpanWeight matchWeight, SpanSimilarity similarity,
+                                   SpanCollectorFactory collectorFactory) throws IOException {
+      super(SpanPositionCheckQuery.this, similarity, collectorFactory);
+      this.matchWeight = matchWeight;
+    }
+
+    public SpanPositionCheckWeight(SpanWeight matchWeight, SpanSimilarity similarity) throws IOException {
+      this(matchWeight, similarity, SpanCollectorFactory.NO_OP_FACTORY);
+    }
+
+    @Override
+    public void extractTerms(Set<Term> terms) {
+      matchWeight.extractTerms(terms);
+    }
+
+    @Override
+    public void extractTermContexts(Map<Term, TermContext> contexts) {
+      matchWeight.extractTermContexts(contexts);
+    }
+
+    @Override
+    public Spans getSpans(final LeafReaderContext context, Bits acceptDocs, final SpanCollector collector) throws IOException {
+      Spans matchSpans = matchWeight.getSpans(context, acceptDocs, collector);
+      return (matchSpans == null) ? null : new FilterSpans(matchSpans) {
+        @Override
+        protected AcceptStatus accept(Spans candidate) throws IOException {
+          return acceptPosition(candidate, collector);
+        }
+      };
+    }
+
   }
 
   @Override

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanQuery.java Wed May 20 13:47:18 2015
@@ -17,47 +17,33 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-import org.apache.lucene.index.LeafReaderContext;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.index.TermContext;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.Query;
 import org.apache.lucene.search.Weight;
-import org.apache.lucene.util.Bits;
 
 import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
 
 /** Base class for span-based queries. */
 public abstract class SpanQuery extends Query {
-  /** Expert: Returns the matches for this query in an index.  
-   *  Used internally to search for spans.
-   *  This may return null to indicate that the SpanQuery has no results.
-   */
-  public abstract Spans getSpans(LeafReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts, SpanCollector collector) throws IOException;
 
   /**
-   * Extract terms from these spans.
-   * @lucene.internal
-   * @see Weight#extractTerms
+   * Returns the name of the field matched by this query.
    */
-  protected abstract void extractTerms(Set<Term> terms);
+  public abstract String getField();
 
   /**
-   * Returns the name of the field matched by this query.
-   * <p>
-   * Note that this may return null if the query matches no terms.
+   * Create a SpanWeight for this query
+   * @param searcher the IndexSearcher to be searched across
+   * @param needsScores if the query needs scores
+   * @param collectorFactory a SpanCollectorFactory to use in collecting postings data
+   * @return a SpanWeight
+   * @throws IOException on error
    */
-  public abstract String getField();
+  public abstract SpanWeight createWeight(IndexSearcher searcher, boolean needsScores,
+                                          SpanCollectorFactory collectorFactory) throws IOException;
 
   @Override
-  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
-    return new SpanWeight(this, searcher, getSpanCollectorFactory());
-  }
-
-  protected SpanCollectorFactory<? extends SpanCollector> getSpanCollectorFactory() {
-    return SpanCollectorFactory.NO_OP_FACTORY;
+  public Weight createWeight(IndexSearcher searcher, boolean needsScores) throws IOException {
+    return createWeight(searcher, needsScores, SpanCollectorFactory.NO_OP_FACTORY);
   }
-
 }

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanScorer.java Wed May 20 13:47:18 2015
@@ -17,13 +17,13 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.util.Objects;
-
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.TwoPhaseIterator;
 import org.apache.lucene.search.similarities.Similarity;
 
+import java.io.IOException;
+import java.util.Objects;
+
 /**
  * Public for extension only.
  */
@@ -42,7 +42,7 @@ public class SpanScorer extends Scorer {
 
   protected SpanScorer(Spans spans, SpanWeight weight, Similarity.SimScorer docScorer) throws IOException {
     super(weight);
-    this.docScorer = Objects.requireNonNull(docScorer);
+    this.docScorer = docScorer;
     this.spans = Objects.requireNonNull(spans);
   }
 
@@ -91,6 +91,10 @@ public class SpanScorer extends Scorer {
       // assert (startPos != prevStartPos) || (endPos > prevEndPos) : "non increased endPos="+endPos;
       assert (startPos != prevStartPos) || (endPos >= prevEndPos) : "decreased endPos="+endPos;
       numMatches++;
+      if (docScorer == null) {  // scores not required, break out here
+        freq = 1;
+        return;
+      }
       int matchLength = endPos - startPos;
       freq += docScorer.computeSlopFactor(matchLength);
       prevStartPos = startPos;

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanTermQuery.java Wed May 20 13:47:18 2015
@@ -24,6 +24,7 @@ import org.apache.lucene.index.TermConte
 import org.apache.lucene.index.TermState;
 import org.apache.lucene.index.Terms;
 import org.apache.lucene.index.TermsEnum;
+import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.ToStringUtils;
 
@@ -50,8 +51,51 @@ public class SpanTermQuery extends SpanQ
   public String getField() { return term.field(); }
 
   @Override
-  public void extractTerms(Set<Term> terms) {
-    terms.add(term);
+  public SpanWeight createWeight(IndexSearcher searcher, boolean needsScores, SpanCollectorFactory factory) throws IOException {
+    TermContext context = TermContext.build(searcher.getTopReaderContext(), term);
+    SpanSimilarity similarity = SpanSimilarity.build(this, searcher, needsScores, searcher.termStatistics(term, context));
+    return new SpanTermWeight(context, similarity, factory);
+  }
+
+  public class SpanTermWeight extends SpanWeight {
+
+    final TermContext termContext;
+
+    public SpanTermWeight(TermContext termContext, SpanSimilarity similarity, SpanCollectorFactory factory) throws IOException {
+      super(SpanTermQuery.this, similarity, factory);
+      this.termContext = termContext;
+    }
+
+    @Override
+    public void extractTerms(Set<Term> terms) {
+      terms.add(term);
+    }
+
+    @Override
+    public void extractTermContexts(Map<Term, TermContext> contexts) {
+      contexts.put(term, termContext);
+    }
+
+    @Override
+    public Spans getSpans(final LeafReaderContext context, Bits acceptDocs, SpanCollector collector) throws IOException {
+
+      final TermState state = termContext.get(context.ord);
+      if (state == null) { // term is not present in that reader
+        return null;
+      }
+
+      final Terms terms = context.reader().terms(term.field());
+      if (terms == null)
+        return null;
+      if (terms.hasPositions() == false)
+        throw new IllegalStateException("field \"" + term.field() + "\" was indexed without position data; cannot run SpanTermQuery (term=" + term.text() + ")");
+
+      final TermsEnum termsEnum = terms.iterator();
+      termsEnum.seekExact(term.bytes(), state);
+
+      final PostingsEnum postings = termsEnum.postings(acceptDocs, null, collector.requiredPostings());
+      return new TermSpans(postings, term);
+    }
   }
 
   @Override
@@ -82,40 +126,4 @@ public class SpanTermQuery extends SpanQ
     return term.equals(other.term);
   }
 
-  @Override
-  public Spans getSpans(final LeafReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts, SpanCollector collector) 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 it's ugly mostly!
-      final Terms terms = context.reader().terms(term.field());
-      if (terms != null) {
-        if (terms.hasPositions() == false) {
-          throw new IllegalStateException("field \"" + term.field() + "\" was indexed without position data; cannot run SpanTermQuery (term=" + term.text() + ")");
-        }
-
-        final TermsEnum termsEnum = terms.iterator();
-        if (termsEnum.seekExact(term.bytes())) {
-          state = termsEnum.termState();
-        } else {
-          state = null;
-        }
-      } else {
-        state = null;
-      }
-    } else {
-      state = termContext.get(context.ord);
-    }
-
-    if (state == null) { // term is not present in that reader
-      return null;
-    }
-
-    final TermsEnum termsEnum = context.reader().terms(term.field()).iterator();
-    termsEnum.seekExact(term.bytes(), state);
-
-    final PostingsEnum postings = termsEnum.postings(acceptDocs, null, collector.requiredPostings());
-    return new TermSpans(postings, term);
-  }
 }

Modified: lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java?rev=1680569&r1=1680568&r2=1680569&view=diff
==============================================================================
--- lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java (original)
+++ lucene/dev/branches/branch_5x/lucene/core/src/java/org/apache/lucene/search/spans/SpanWeight.java Wed May 20 13:47:18 2015
@@ -17,97 +17,91 @@ package org.apache.lucene.search.spans;
  * limitations under the License.
  */
 
-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.index.Terms;
 import org.apache.lucene.search.Explanation;
-import org.apache.lucene.search.IndexSearcher;
 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;
 
 import java.io.IOException;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
 
 /**
  * Expert-only.  Public for use by other weight implementations
  */
-public class SpanWeight extends Weight {
-  protected final Similarity similarity;
-  protected final Map<Term,TermContext> termContexts;
-  protected final SpanQuery query;
-  protected final SpanCollectorFactory<?> collectorFactory;
-  protected Similarity.SimWeight stats;
+public abstract class SpanWeight extends Weight {
 
-  public SpanWeight(SpanQuery query, IndexSearcher searcher, SpanCollectorFactory<?> collectorFactory) throws IOException {
+  protected final SpanSimilarity similarity;
+  protected final SpanCollectorFactory collectorFactory;
+
+  /**
+   * Create a new SpanWeight
+   * @param query the parent query
+   * @param similarity a SpanSimilarity to be used for scoring
+   * @param collectorFactory a SpanCollectorFactory to be used for Span collection
+   * @throws IOException on error
+   */
+  public SpanWeight(SpanQuery query, SpanSimilarity similarity, SpanCollectorFactory collectorFactory) throws IOException {
     super(query);
-    this.similarity = searcher.getSimilarity();
-    this.query = query;
+    this.similarity = similarity;
     this.collectorFactory = collectorFactory;
-
-    termContexts = new HashMap<>();
-    TreeSet<Term> terms = new TreeSet<>();
-    query.extractTerms(terms);
-    final IndexReaderContext context = searcher.getTopReaderContext();
-    final TermStatistics termStats[] = new TermStatistics[terms.size()];
-    int i = 0;
-    for (Term term : terms) {
-      TermContext state = TermContext.build(context, term);
-      termStats[i] = searcher.termStatistics(term, state);
-      termContexts.put(term, state);
-      i++;
-    }
-    final String field = query.getField();
-    if (field != null) {
-      stats = similarity.computeWeight(query.getBoost(),
-                                       searcher.collectionStatistics(query.getField()),
-                                       termStats);
-    }
   }
 
   /**
-   * @return the SpanCollectorFactory associated with this SpanWeight
+   * Collect all TermContexts used by this Weight
+   * @param contexts a map to add the TermContexts to
    */
-  public SpanCollectorFactory<?> getSpanCollectorFactory() {
-    return collectorFactory;
-  }
+  public abstract void extractTermContexts(Map<Term, TermContext> contexts);
 
-  @Override
-  public void extractTerms(Set<Term> terms) {
-    query.extractTerms(terms);
+  /**
+   * Expert: Return a Spans object iterating over matches from this Weight
+   * @param ctx a LeafReaderContext for this Spans
+   * @param acceptDocs a bitset of documents to check
+   * @param collector a SpanCollector to use for postings data collection
+   * @return a Spans
+   * @throws IOException on error
+   */
+  public abstract Spans getSpans(LeafReaderContext ctx, Bits acceptDocs, SpanCollector collector) throws IOException;
+
+  /**
+   * Expert: Return a Spans object iterating over matches from this Weight, without
+   * collecting any postings data.
+   * @param ctx a LeafReaderContext for this Spans
+   * @param acceptDocs a bitset of documents to check
+   * @return a Spans
+   * @throws IOException on error
+   */
+  public final Spans getSpans(LeafReaderContext ctx, Bits acceptDocs) throws IOException {
+    return getSpans(ctx, acceptDocs, collectorFactory.newCollector());
   }
 
   @Override
   public float getValueForNormalization() throws IOException {
-    return stats == null ? 1.0f : stats.getValueForNormalization();
+    return similarity == null ? 1.0f : similarity.getValueForNormalization();
   }
 
   @Override
   public void normalize(float queryNorm, float topLevelBoost) {
-    if (stats != null) {
-      stats.normalize(queryNorm, topLevelBoost);
+    if (similarity != null) {
+      similarity.normalize(queryNorm, topLevelBoost);
     }
   }
 
   @Override
   public Scorer scorer(LeafReaderContext context, Bits acceptDocs) throws IOException {
-    if (stats == null) {
+    if (similarity == null) {
       return null;
     }
-    Terms terms = context.reader().terms(query.getField());
+    Terms terms = context.reader().terms(similarity.getField());
     if (terms != null && terms.hasPositions() == false) {
-      throw new IllegalStateException("field \"" + query.getField() + "\" was indexed without position data; cannot run SpanQuery (query=" + query + ")");
+      throw new IllegalStateException("field \"" + similarity.getField() + "\" was indexed without position data; cannot run SpanQuery (query=" + parentQuery + ")");
     }
-    Spans spans = query.getSpans(context, acceptDocs, termContexts, collectorFactory.newCollector());
-    return (spans == null) ? null : new SpanScorer(spans, this, similarity.simScorer(stats, context));
+    Spans spans = getSpans(context, acceptDocs, collectorFactory.newCollector());
+    return (spans == null) ? null : new SpanScorer(spans, this, similarity.simScorer(context));
   }
 
   @Override
@@ -117,7 +111,7 @@ public class SpanWeight extends Weight {
       int newDoc = scorer.advance(doc);
       if (newDoc == doc) {
         float freq = scorer.sloppyFreq();
-        SimScorer docScorer = similarity.simScorer(stats, context);
+        SimScorer docScorer = similarity.simScorer(context);
         Explanation freqExplanation = Explanation.match(freq, "phraseFreq=" + freq);
         Explanation scoreExplanation = docScorer.explain(doc, freqExplanation);
         return Explanation.match(scoreExplanation.getValue(),