Index: src/java/org/apache/lucene/search/payloads/BoostingNearQuery.java
===================================================================
--- src/java/org/apache/lucene/search/payloads/BoostingNearQuery.java	(revision 0)
+++ src/java/org/apache/lucene/search/payloads/BoostingNearQuery.java	(revision 0)
@@ -0,0 +1,139 @@
+package org.apache.lucene.search.payloads;
+/**
+ * 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.TermPositions;
+import org.apache.lucene.search.Explanation;
+import org.apache.lucene.search.Scorer;
+import org.apache.lucene.search.Searcher;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.Weight;
+import org.apache.lucene.search.spans.SpanNearQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanWeight;
+import org.apache.lucene.search.spans.SpanScorer;
+import org.apache.lucene.search.spans.Spans;
+import org.apache.lucene.search.spans.TermSpans;
+import org.apache.lucene.search.spans.NearSpansOrdered;
+import org.apache.lucene.search.spans.NearSpansUnordered;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+public class BoostingNearQuery extends SpanNearQuery {
+  protected float payloadScore;
+  private int payloadsSeen;
+
+  public BoostingNearQuery(SpanQuery[] clauses, int slop, boolean inOrder) {
+    super(clauses, slop, inOrder);
+
+  }
+
+  protected Weight createWeight(Searcher searcher) throws IOException {
+    return new BoostingSpanWeight(this, searcher);
+  }
+
+  public class BoostingSpanWeight extends SpanWeight {
+    public BoostingSpanWeight(SpanQuery query, Searcher searcher) throws IOException {
+      super(query, searcher);
+    }
+
+    public Scorer scorer(IndexReader reader) throws IOException {
+      return new BoostingSpanScorer(query.getSpans(reader), this,
+              similarity,
+              reader.norms(query.getField()));
+    }
+
+    public Explanation explain(IndexReader reader, int doc)
+            throws IOException {
+      Explanation result = new Explanation();
+      Explanation nonPayloadExpl = super.explain(reader, doc);
+      result.addDetail(nonPayloadExpl);
+      Explanation payloadBoost = new Explanation();
+      result.addDetail(payloadBoost);
+      float avgPayloadScore = (payloadsSeen > 0 ? (payloadScore / payloadsSeen) : 1);
+      payloadBoost.setValue(avgPayloadScore);
+      payloadBoost.setDescription("scorePayload(...)");
+      result.setValue(nonPayloadExpl.getValue() * avgPayloadScore);
+      result.setDescription("btq, product of:");
+      return result;
+    }
+  }
+
+  public class BoostingSpanScorer extends SpanScorer {
+    //TODO: is this the best way to allocate this?
+    byte[] payload = new byte[256];
+    Spans[] subSpans = null;
+    private ArrayList termsPositions = new ArrayList();
+    Similarity similarity = getSimilarity();
+
+    protected BoostingSpanScorer(Spans spans, Weight weight, Similarity similarity, byte[] norms)
+            throws IOException {
+      super(spans, weight, similarity, norms);
+      Spans[] spansArr = new Spans[1];
+      spansArr[0] = spans;
+      getTermsPositions(spansArr, termsPositions);
+    }
+
+    // Get the TermPositions associated with all underlying subspans
+    public void getTermsPositions(Spans[] subSpans, ArrayList termsPositions) {
+      for (int i = 0; i < subSpans.length; i++) {
+        if (subSpans[i] instanceof TermSpans) {
+          termsPositions.add(((TermSpans) subSpans[i]).getPositions());
+        } else if (subSpans[i] instanceof NearSpansOrdered) {
+          getTermsPositions(((NearSpansOrdered) subSpans[i]).getSubSpans(), termsPositions);
+        } else if (subSpans[i] instanceof NearSpansUnordered) {
+          getTermsPositions(((NearSpansUnordered) subSpans[i]).getSubSpans(), termsPositions);
+        }
+      }
+
+    }
+
+    protected boolean setFreqCurrentDoc() throws IOException {
+      if (!more) {
+        return false;
+      }
+      doc = spans.doc();
+      freq = 0.0f;
+      payloadScore = 0;
+      payloadsSeen = 0;
+      while (more && doc == spans.doc()) {
+        for (Iterator it = termsPositions.iterator(); it.hasNext();) {
+          TermPositions positions = (TermPositions) it.next();
+          if (positions.isPayloadAvailable()) {
+            payload = positions.getPayload(payload, 0);
+            payloadScore += similarity.scorePayload(field, payload, 0, positions.getPayloadLength());
+            payloadsSeen++;
+          }
+        }
+        int matchLength = spans.end() - spans.start();
+        freq += getSimilarity().sloppyFreq(matchLength);
+        more = spans.next();
+      }
+      return more || (freq != 0);
+    }
+
+    public float score() throws IOException {
+      return super.score() * (payloadsSeen > 0 ? (payloadScore / payloadsSeen) : 1);
+    }
+
+  }
+
+
+}

Property changes on: src/java/org/apache/lucene/search/payloads/BoostingNearQuery.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/java/org/apache/lucene/search/spans/NearSpansOrdered.java
===================================================================
--- src/java/org/apache/lucene/search/spans/NearSpansOrdered.java	(revision 681364)
+++ src/java/org/apache/lucene/search/spans/NearSpansOrdered.java	(working copy)
@@ -41,8 +41,11 @@
  * matches twice:
  * <pre>t1 t2 .. t3      </pre>
  * <pre>      t1 .. t2 t3</pre>
+ *
+ * <p>
+ * Expert-level.  Public for use with payload package
  */
-class NearSpansOrdered implements Spans {
+public class NearSpansOrdered implements Spans {
   private final int allowedSlop;
   private boolean firstTime = true;
   private boolean more = false;
@@ -92,6 +95,11 @@
   // inherit javadocs
   public int end() { return matchEnd; }
 
+  public Spans[] getSubSpans() {
+	  return subSpans;
+  }
+
+  
   // inherit javadocs
   public boolean next() throws IOException {
     if (firstTime) {
Index: src/java/org/apache/lucene/search/spans/NearSpansUnordered.java
===================================================================
--- src/java/org/apache/lucene/search/spans/NearSpansUnordered.java	(revision 681364)
+++ src/java/org/apache/lucene/search/spans/NearSpansUnordered.java	(working copy)
@@ -25,10 +25,15 @@
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.util.PriorityQueue;
 
-class NearSpansUnordered implements Spans {
+/*
+* <p>
+* Expert-level.  Public for use with payload package
+* */
+public class NearSpansUnordered implements Spans {
   private SpanNearQuery query;
 
   private List ordered = new ArrayList();         // spans in query order
+  private Spans[] subSpans;
   private int slop;                               // from query
 
   private SpansCell first;                        // linked list of spans
@@ -111,13 +116,17 @@
 
     SpanQuery[] clauses = query.getClauses();
     queue = new CellQueue(clauses.length);
+    subSpans = new Spans[clauses.length];
     for (int i = 0; i < clauses.length; i++) {
       SpansCell cell =
         new SpansCell(clauses[i].getSpans(reader), i);
       ordered.add(cell);
+      subSpans[i] = cell.spans;
     }
   }
-
+  public Spans[] getSubSpans() {
+	  return subSpans;
+  }
   public boolean next() throws IOException {
     if (firstTime) {
       initList(true);
Index: src/java/org/apache/lucene/search/spans/SpanNearQuery.java
===================================================================
--- src/java/org/apache/lucene/search/spans/SpanNearQuery.java	(revision 681364)
+++ src/java/org/apache/lucene/search/spans/SpanNearQuery.java	(working copy)
@@ -38,7 +38,7 @@
   private int slop;
   private boolean inOrder;
 
-  private String field;
+  protected String field;
 
   /** Construct a SpanNearQuery.  Matches spans matching a span from each
    * clause, with up to <code>slop</code> total unmatched positions between
