LUCENE-1748: LUCENE-1001 introduced PayloadSpans, but this was a back compat break and caused custom SpanQuery implementations to fail at runtime in a variety of ways. This issue attempts to remedy things by causing a compile time break on custom SpanQuery implementations and removing the PayloadSpans class, with its functionality now moved to Spans.

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@800925 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Robert Miller 2009-08-04 19:10:02 +00:00
parent d8680c9fd4
commit 5af69469e2
19 changed files with 147 additions and 173 deletions

View File

@ -84,6 +84,13 @@ Changes in backwards compatibility policy
be passed upon instantiation. As a result, IndexWriter was removed be passed upon instantiation. As a result, IndexWriter was removed
as a method argument from all MergePolicy methods. (Shai Erera via as a method argument from all MergePolicy methods. (Shai Erera via
Mike McCandless) Mike McCandless)
6. LUCENE-1748: LUCENE-1001 introduced PayloadSpans, but this was a back
compat break and caused custom SpanQuery implementations to fail at runtime
in a variety of ways. This issue attempts to remedy things by causing
a compile time break on custom SpanQuery implementations and removing
the PayloadSpans class, with its functionality now moved to Spans.
(Hugh Cayless, Mark Miller)
Changes in runtime behavior Changes in runtime behavior
@ -363,6 +370,13 @@ API Changes
new QueryParser framework in Lucene 3.0, that is currently located new QueryParser framework in Lucene 3.0, that is currently located
in contrib. (see New Features 35.) in contrib. (see New Features 35.)
(Luis Alves and Adriano Campos via Michael Busch) (Luis Alves and Adriano Campos via Michael Busch)
36. LUCENE-1748: LUCENE-1001 introduced PayloadSpans, but this was a back
compat break and caused custom SpanQuery implementations to fail at runtime
in a variety of ways. This issue attempts to remedy things by causing
a compile time break on custom SpanQuery implementations and removing
the PayloadSpans class, with its functionality now moved to Spans.
(Hugh Cayless, Mark Miller)
Bug fixes Bug fixes

View File

@ -42,7 +42,7 @@
<property name="Name" value="Lucene"/> <property name="Name" value="Lucene"/>
<property name="dev.version" value="2.9-dev"/> <property name="dev.version" value="2.9-dev"/>
<property name="version" value="${dev.version}"/> <property name="version" value="${dev.version}"/>
<property name="compatibility.tag" value="lucene_2_4_back_compat_tests_20090801"/> <property name="compatibility.tag" value="lucene_2_4_back_compat_tests_20090804"/>
<property name="spec.version" value="${version}"/> <property name="spec.version" value="${version}"/>
<property name="year" value="2000-${current.year}"/> <property name="year" value="2000-${current.year}"/>
<property name="final.name" value="lucene-${name}-${version}"/> <property name="final.name" value="lucene-${name}-${version}"/>

View File

@ -27,7 +27,6 @@ import org.apache.lucene.search.spans.SpanOrQuery;
import org.apache.lucene.search.spans.SpanQuery; import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery; import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.search.spans.Spans; import org.apache.lucene.search.spans.Spans;
import org.apache.lucene.search.spans.PayloadSpans;
import org.apache.lucene.util.ToStringUtils; import org.apache.lucene.util.ToStringUtils;
import java.io.IOException; import java.io.IOException;
@ -77,10 +76,6 @@ public class SpanRegexQuery extends SpanQuery implements RegexQueryCapable {
throw new UnsupportedOperationException("Query should have been rewritten"); throw new UnsupportedOperationException("Query should have been rewritten");
} }
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException {
throw new UnsupportedOperationException("Query should have been rewritten");
}
public String getField() { public String getField() {
return term.field(); return term.field();
} }

View File

@ -1,6 +1,5 @@
package org.apache.lucene.search.payloads; package org.apache.lucene.search.payloads;
import org.apache.lucene.search.BooleanClause;
/** /**
* Licensed to the Apache Software Foundation (ASF) under one or more * Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with * contributor license agreements. See the NOTICE file distributed with
@ -26,6 +25,7 @@ import java.util.List;
import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.DisjunctionMaxQuery; import org.apache.lucene.search.DisjunctionMaxQuery;
import org.apache.lucene.search.FilteredQuery; import org.apache.lucene.search.FilteredQuery;
@ -33,11 +33,11 @@ import org.apache.lucene.search.MultiPhraseQuery;
import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.spans.PayloadSpans;
import org.apache.lucene.search.spans.SpanNearQuery; import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanOrQuery; import org.apache.lucene.search.spans.SpanOrQuery;
import org.apache.lucene.search.spans.SpanQuery; import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery; import org.apache.lucene.search.spans.SpanTermQuery;
import org.apache.lucene.search.spans.Spans;
/** /**
* Experimental class to get set of payloads for most standard Lucene queries. * Experimental class to get set of payloads for most standard Lucene queries.
@ -173,7 +173,7 @@ public class PayloadSpanUtil {
private void getPayloads(Collection payloads, SpanQuery query) private void getPayloads(Collection payloads, SpanQuery query)
throws IOException { throws IOException {
PayloadSpans spans = query.getPayloadSpans(reader); Spans spans = query.getSpans(reader);
while (spans.next() == true) { while (spans.next() == true) {
if (spans.isPayloadAvailable()) { if (spans.isPayloadAvailable()) {

View File

@ -93,9 +93,6 @@ public class FieldMaskingSpanQuery extends SpanQuery {
public Spans getSpans(IndexReader reader) throws IOException { public Spans getSpans(IndexReader reader) throws IOException {
return maskedQuery.getSpans(reader); return maskedQuery.getSpans(reader);
} }
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException {
return maskedQuery.getPayloadSpans(reader);
}
/** @deprecated use {@link #extractTerms(Set)} instead. */ /** @deprecated use {@link #extractTerms(Set)} instead. */
public Collection getTerms() { public Collection getTerms() {

View File

@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Collection; import java.util.Collection;
@ -48,13 +47,13 @@ import java.util.Set;
* <pre>t1 t2 .. t3 </pre> * <pre>t1 t2 .. t3 </pre>
* <pre> t1 .. t2 t3</pre> * <pre> t1 .. t2 t3</pre>
*/ */
class NearSpansOrdered implements PayloadSpans { class NearSpansOrdered implements Spans {
private final int allowedSlop; private final int allowedSlop;
private boolean firstTime = true; private boolean firstTime = true;
private boolean more = false; private boolean more = false;
/** The spans in the same order as the SpanNearQuery */ /** The spans in the same order as the SpanNearQuery */
private final PayloadSpans[] subSpans; private final Spans[] subSpans;
/** Indicates that all subSpans have same doc() */ /** Indicates that all subSpans have same doc() */
private boolean inSameDoc = false; private boolean inSameDoc = false;
@ -64,7 +63,7 @@ class NearSpansOrdered implements PayloadSpans {
private int matchEnd = -1; private int matchEnd = -1;
private List/*<byte[]>*/ matchPayload; private List/*<byte[]>*/ matchPayload;
private final PayloadSpans[] subSpansByDoc; private final Spans[] subSpansByDoc;
private final Comparator spanDocComparator = new Comparator() { private final Comparator spanDocComparator = new Comparator() {
public int compare(Object o1, Object o2) { public int compare(Object o1, Object o2) {
return ((Spans)o1).doc() - ((Spans)o2).doc(); return ((Spans)o1).doc() - ((Spans)o2).doc();
@ -87,11 +86,11 @@ class NearSpansOrdered implements PayloadSpans {
this.collectPayloads = collectPayloads; this.collectPayloads = collectPayloads;
allowedSlop = spanNearQuery.getSlop(); allowedSlop = spanNearQuery.getSlop();
SpanQuery[] clauses = spanNearQuery.getClauses(); SpanQuery[] clauses = spanNearQuery.getClauses();
subSpans = new PayloadSpans[clauses.length]; subSpans = new Spans[clauses.length];
matchPayload = new LinkedList(); matchPayload = new LinkedList();
subSpansByDoc = new PayloadSpans[clauses.length]; subSpansByDoc = new Spans[clauses.length];
for (int i = 0; i < clauses.length; i++) { for (int i = 0; i < clauses.length; i++) {
subSpans[i] = clauses[i].getPayloadSpans(reader); subSpans[i] = clauses[i].getSpans(reader);
subSpansByDoc[i] = subSpans[i]; // used in toSameDoc() subSpansByDoc[i] = subSpans[i]; // used in toSameDoc()
} }
query = spanNearQuery; // kept for toString() only. query = spanNearQuery; // kept for toString() only.
@ -260,7 +259,7 @@ class NearSpansOrdered implements PayloadSpans {
int lastStart = matchStart; int lastStart = matchStart;
int lastEnd = matchEnd; int lastEnd = matchEnd;
for (int i = subSpans.length - 2; i >= 0; i--) { for (int i = subSpans.length - 2; i >= 0; i--) {
PayloadSpans prevSpans = subSpans[i]; Spans prevSpans = subSpans[i];
if (collectPayloads && prevSpans.isPayloadAvailable()) { if (collectPayloads && prevSpans.isPayloadAvailable()) {
Collection payload = prevSpans.getPayload(); Collection payload = prevSpans.getPayload();
possiblePayload = new ArrayList(payload.size()); possiblePayload = new ArrayList(payload.size());

View File

@ -27,7 +27,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.HashSet; import java.util.HashSet;
class NearSpansUnordered implements PayloadSpans { class NearSpansUnordered implements Spans {
private SpanNearQuery query; private SpanNearQuery query;
private List ordered = new ArrayList(); // spans in query order private List ordered = new ArrayList(); // spans in query order
@ -62,13 +62,13 @@ class NearSpansUnordered implements PayloadSpans {
/** Wraps a Spans, and can be used to form a linked list. */ /** Wraps a Spans, and can be used to form a linked list. */
private class SpansCell implements PayloadSpans { private class SpansCell implements Spans {
private PayloadSpans spans; private Spans spans;
private SpansCell next; private SpansCell next;
private int length = -1; private int length = -1;
private int index; private int index;
public SpansCell(PayloadSpans spans, int index) { public SpansCell(Spans spans, int index) {
this.spans = spans; this.spans = spans;
this.index = index; this.index = index;
} }
@ -124,7 +124,7 @@ class NearSpansUnordered implements PayloadSpans {
queue = new CellQueue(clauses.length); queue = new CellQueue(clauses.length);
for (int i = 0; i < clauses.length; i++) { for (int i = 0; i < clauses.length; i++) {
SpansCell cell = SpansCell cell =
new SpansCell(clauses[i].getPayloadSpans(reader), i); new SpansCell(clauses[i].getSpans(reader), i);
ordered.add(cell); ordered.add(cell);
} }
} }

View File

@ -1,71 +0,0 @@
package org.apache.lucene.search.spans;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.util.Collection;
import java.io.IOException;
/**
* <font color="#FF0000">
* WARNING: The status of the <b>Payloads</b> feature is experimental.
* The APIs introduced here might change in the future and will not be
* supported anymore in such a case.</font>
*
**/
public interface PayloadSpans extends Spans{
/**
* Returns the payload data for the current span.
* This is invalid until {@link #next()} is called for
* the first time.
* This method must not be called more than once after each call
* of {@link #next()}. However, most SpanQuerys load payloads lazily,
* so if the payload data for the current position is not needed,
* this method may not be called at all for performance reasons.
* The ordered case of SpanNearQuery does not load lazily and has
* an option to turn off payload loading.<br>
* <br>
* Note that the return type is a collection, thus the ordering should not be relied upon.
* <br/>
* <p><font color="#FF0000">
* WARNING: The status of the <b>Payloads</b> feature is experimental.
* The APIs introduced here might change in the future and will not be
* supported anymore in such a case.</font>
*
* @return a List of byte arrays containing the data of this payload, otherwise null if isPayloadAvailable is false
* @throws java.io.IOException
*/
// TODO: Remove warning after API has been finalized
Collection/*<byte[]>*/ getPayload() throws IOException;
/**
* Checks if a payload can be loaded at this position.
* <p/>
* Payloads can only be loaded once per call to
* {@link #next()}.
* <p/>
* <p><font color="#FF0000">
* WARNING: The status of the <b>Payloads</b> feature is experimental.
* The APIs introduced here might change in the future and will not be
* supported anymore in such a case.</font>
*
* @return true if there is a payload available at this position that can be loaded
*/
// TODO: Remove warning after API has been finalized
public boolean isPayloadAvailable();
}

View File

@ -74,13 +74,9 @@ public class SpanFirstQuery extends SpanQuery implements Cloneable {
match.extractTerms(terms); match.extractTerms(terms);
} }
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException {
return (PayloadSpans) getSpans(reader);
}
public Spans getSpans(final IndexReader reader) throws IOException { public Spans getSpans(final IndexReader reader) throws IOException {
return new PayloadSpans() { return new Spans() {
private PayloadSpans spans = match.getPayloadSpans(reader); private Spans spans = match.getSpans(reader);
public boolean next() throws IOException { public boolean next() throws IOException {
while (spans.next()) { // scan to next match while (spans.next()) { // scan to next match

View File

@ -125,18 +125,14 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
public Spans getSpans(final IndexReader reader) throws IOException { public Spans getSpans(final IndexReader reader) throws IOException {
if (clauses.size() == 0) // optimize 0-clause case if (clauses.size() == 0) // optimize 0-clause case
return new SpanOrQuery(getClauses()).getPayloadSpans(reader); return new SpanOrQuery(getClauses()).getSpans(reader);
if (clauses.size() == 1) // optimize 1-clause case if (clauses.size() == 1) // optimize 1-clause case
return ((SpanQuery)clauses.get(0)).getPayloadSpans(reader); return ((SpanQuery)clauses.get(0)).getSpans(reader);
return inOrder return inOrder
? (PayloadSpans) new NearSpansOrdered(this, reader, collectPayloads) ? (Spans) new NearSpansOrdered(this, reader, collectPayloads)
: (PayloadSpans) new NearSpansUnordered(this, reader); : (Spans) new NearSpansUnordered(this, reader);
}
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException {
return (PayloadSpans) getSpans(reader);
} }
public Query rewrite(IndexReader reader) throws IOException { public Query rewrite(IndexReader reader) throws IOException {

View File

@ -75,8 +75,8 @@ public class SpanNotQuery extends SpanQuery implements Cloneable {
} }
public Spans getSpans(final IndexReader reader) throws IOException { public Spans getSpans(final IndexReader reader) throws IOException {
return new PayloadSpans() { return new Spans() {
private PayloadSpans includeSpans = include.getPayloadSpans(reader); private Spans includeSpans = include.getSpans(reader);
private boolean moreInclude = true; private boolean moreInclude = true;
private Spans excludeSpans = exclude.getSpans(reader); private Spans excludeSpans = exclude.getSpans(reader);
@ -157,10 +157,6 @@ public class SpanNotQuery extends SpanQuery implements Cloneable {
}; };
} }
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException {
return (PayloadSpans) getSpans(reader);
}
public Query rewrite(IndexReader reader) throws IOException { public Query rewrite(IndexReader reader) throws IOException {
SpanNotQuery clone = null; SpanNotQuery clone = null;

View File

@ -167,22 +167,18 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
} }
} }
public PayloadSpans getPayloadSpans(final IndexReader reader) throws IOException {
return (PayloadSpans)getSpans(reader);
}
public Spans getSpans(final IndexReader reader) throws IOException { public Spans getSpans(final IndexReader reader) throws IOException {
if (clauses.size() == 1) // optimize 1-clause case if (clauses.size() == 1) // optimize 1-clause case
return ((SpanQuery)clauses.get(0)).getPayloadSpans(reader); return ((SpanQuery)clauses.get(0)).getSpans(reader);
return new PayloadSpans() { return new Spans() {
private SpanQueue queue = null; private SpanQueue queue = null;
private boolean initSpanQueue(int target) throws IOException { private boolean initSpanQueue(int target) throws IOException {
queue = new SpanQueue(clauses.size()); queue = new SpanQueue(clauses.size());
Iterator i = clauses.iterator(); Iterator i = clauses.iterator();
while (i.hasNext()) { while (i.hasNext()) {
PayloadSpans spans = ((SpanQuery)i.next()).getPayloadSpans(reader); Spans spans = ((SpanQuery)i.next()).getSpans(reader);
if ( ((target == -1) && spans.next()) if ( ((target == -1) && spans.next())
|| ((target != -1) && spans.skipTo(target))) { || ((target != -1) && spans.skipTo(target))) {
queue.put(spans); queue.put(spans);
@ -209,7 +205,7 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
return queue.size() != 0; return queue.size() != 0;
} }
private PayloadSpans top() { return (PayloadSpans)queue.top(); } private Spans top() { return (Spans)queue.top(); }
public boolean skipTo(int target) throws IOException { public boolean skipTo(int target) throws IOException {
if (queue == null) { if (queue == null) {
@ -239,7 +235,7 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
// TODO: Remove warning after API has been finalized // TODO: Remove warning after API has been finalized
public Collection/*<byte[]>*/ getPayload() throws IOException { public Collection/*<byte[]>*/ getPayload() throws IOException {
ArrayList result = null; ArrayList result = null;
PayloadSpans theTop = top(); Spans theTop = top();
if (theTop != null && theTop.isPayloadAvailable()) { if (theTop != null && theTop.isPayloadAvailable()) {
result = new ArrayList(theTop.getPayload()); result = new ArrayList(theTop.getPayload());
} }
@ -248,7 +244,7 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
// TODO: Remove warning after API has been finalized // TODO: Remove warning after API has been finalized
public boolean isPayloadAvailable() { public boolean isPayloadAvailable() {
PayloadSpans top = top(); Spans top = top();
return top != null && top.isPayloadAvailable(); return top != null && top.isPayloadAvailable();
} }

View File

@ -32,22 +32,6 @@ public abstract class SpanQuery extends Query {
* to search for spans. */ * to search for spans. */
public abstract Spans getSpans(IndexReader reader) throws IOException; public abstract Spans getSpans(IndexReader reader) throws IOException;
/**
* Returns the matches for this query in an index, including access to any {@link org.apache.lucene.index.Payload}s at those
* positions. Implementing classes that want access to the payloads will need to implement this.
* @param reader The {@link org.apache.lucene.index.IndexReader} to use to get spans/payloads
* @return null
* @throws IOException if there is an error accessing the payload
*
* <font color="#FF0000">
* WARNING: The status of the <b>Payloads</b> feature is experimental.
* The APIs introduced here might change in the future and will not be
* supported anymore in such a case.</font>
*/
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException{
return null;
}
/** Returns the name of the field matched by this query.*/ /** Returns the name of the field matched by this query.*/
public abstract String getField(); public abstract String getField();

View File

@ -79,9 +79,4 @@ public class SpanTermQuery extends SpanQuery {
return new TermSpans(reader.termPositions(term), term); return new TermSpans(reader.termPositions(term), term);
} }
public PayloadSpans getPayloadSpans(IndexReader reader) throws IOException {
return (PayloadSpans) getSpans(reader);
}
} }

View File

@ -18,6 +18,7 @@ package org.apache.lucene.search.spans;
*/ */
import java.io.IOException; import java.io.IOException;
import java.util.Collection;
/** Expert: an enumeration of span matches. Used to implement span searching. /** Expert: an enumeration of span matches. Used to implement span searching.
* Each span represents a range of term positions within a document. Matches * Each span represents a range of term positions within a document. Matches
@ -50,5 +51,46 @@ public interface Spans {
/** Returns the end position of the current match. Initially invalid. */ /** Returns the end position of the current match. Initially invalid. */
int end(); int end();
/**
* Returns the payload data for the current span.
* This is invalid until {@link #next()} is called for
* the first time.
* This method must not be called more than once after each call
* of {@link #next()}. However, most payloads are loaded lazily,
* so if the payload data for the current position is not needed,
* this method may not be called at all for performance reasons. An ordered
* SpanQuery does not lazy load, so if you have payloads in your index and
* you do not want ordered SpanNearQuerys to collect payloads, you can
* disable collection with a constructor option.<br>
* <br>
* Note that the return type is a collection, thus the ordering should not be relied upon.
* <br/>
* <p><font color="#FF0000">
* WARNING: The status of the <b>Payloads</b> feature is experimental.
* The APIs introduced here might change in the future and will not be
* supported anymore in such a case.</font>
*
* @return a List of byte arrays containing the data of this payload, otherwise null if isPayloadAvailable is false
* @throws java.io.IOException
*/
// TODO: Remove warning after API has been finalized
Collection/*<byte[]>*/ getPayload() throws IOException;
/**
* Checks if a payload can be loaded at this position.
* <p/>
* Payloads can only be loaded once per call to
* {@link #next()}.
* <p/>
* <p><font color="#FF0000">
* WARNING: The status of the <b>Payloads</b> feature is experimental.
* The APIs introduced here might change in the future and will not be
* supported anymore in such a case.</font>
*
* @return true if there is a payload available at this position that can be loaded
*/
// TODO: Remove warning after API has been finalized
public boolean isPayloadAvailable();
} }

View File

@ -27,7 +27,7 @@ import java.util.Collection;
* Expert: * Expert:
* Public for extension only * Public for extension only
*/ */
public class TermSpans implements PayloadSpans { public class TermSpans implements Spans {
protected TermPositions positions; protected TermPositions positions;
protected Term term; protected Term term;
protected int doc; protected int doc;

View File

@ -45,7 +45,6 @@ import org.apache.lucene.analysis.LowerCaseTokenizer;
import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.index.Payload; import org.apache.lucene.index.Payload;
import org.apache.lucene.search.payloads.PayloadSpanUtil; import org.apache.lucene.search.payloads.PayloadSpanUtil;
import org.apache.lucene.search.spans.PayloadSpans;
import org.apache.lucene.search.spans.SpanNearQuery; import org.apache.lucene.search.spans.SpanNearQuery;
import org.apache.lucene.search.spans.SpanQuery; import org.apache.lucene.search.spans.SpanQuery;
import org.apache.lucene.search.spans.SpanTermQuery; import org.apache.lucene.search.spans.SpanTermQuery;
@ -279,7 +278,7 @@ public class TestPositionIncrement extends LuceneTestCase {
count = 0; count = 0;
boolean sawZero = false; boolean sawZero = false;
//System.out.println("\ngetPayloadSpans test"); //System.out.println("\ngetPayloadSpans test");
PayloadSpans pspans = snq.getPayloadSpans(is.getIndexReader()); Spans pspans = snq.getSpans(is.getIndexReader());
while (pspans.next()) { while (pspans.next()) {
//System.out.println(pspans.doc() + " - " + pspans.start() + " - "+ pspans.end()); //System.out.println(pspans.doc() + " - " + pspans.start() + " - "+ pspans.end());
Collection payloads = pspans.getPayload(); Collection payloads = pspans.getPayload();

View File

@ -57,6 +57,14 @@ final class JustCompileSearchSpans {
public int start() { public int start() {
throw new UnsupportedOperationException(UNSUPPORTED_MSG); throw new UnsupportedOperationException(UNSUPPORTED_MSG);
} }
public Collection getPayload() throws IOException {
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
}
public boolean isPayloadAvailable() {
throw new UnsupportedOperationException(UNSUPPORTED_MSG);
}
} }
@ -81,7 +89,7 @@ final class JustCompileSearchSpans {
} }
static final class JustCompilePayloadSpans implements PayloadSpans { static final class JustCompilePayloadSpans implements Spans {
public Collection getPayload() throws IOException { public Collection getPayload() throws IOException {
throw new UnsupportedOperationException(UNSUPPORTED_MSG); throw new UnsupportedOperationException(UNSUPPORTED_MSG);

View File

@ -26,7 +26,6 @@ import java.util.Set;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.LowerCaseTokenizer; import org.apache.lucene.analysis.LowerCaseTokenizer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenFilter;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.PayloadAttribute; import org.apache.lucene.analysis.tokenattributes.PayloadAttribute;
@ -51,7 +50,7 @@ import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase;
public class TestPayloadSpans extends LuceneTestCase { public class TestPayloadSpans extends LuceneTestCase {
private final static boolean DEBUG = false; private final static boolean DEBUG = true;
private IndexSearcher searcher; private IndexSearcher searcher;
private Similarity similarity = new DefaultSimilarity(); private Similarity similarity = new DefaultSimilarity();
protected IndexReader indexReader; protected IndexReader indexReader;
@ -73,14 +72,14 @@ public class TestPayloadSpans extends LuceneTestCase {
public void testSpanTermQuery() throws Exception { public void testSpanTermQuery() throws Exception {
SpanTermQuery stq; SpanTermQuery stq;
PayloadSpans spans; Spans spans;
stq = new SpanTermQuery(new Term(PayloadHelper.FIELD, "seventy")); stq = new SpanTermQuery(new Term(PayloadHelper.FIELD, "seventy"));
spans = stq.getPayloadSpans(indexReader); spans = stq.getSpans(indexReader);
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 100, 1, 1, 1); checkSpans(spans, 100, 1, 1, 1);
stq = new SpanTermQuery(new Term(PayloadHelper.NO_PAYLOAD_FIELD, "seventy")); stq = new SpanTermQuery(new Term(PayloadHelper.NO_PAYLOAD_FIELD, "seventy"));
spans = stq.getPayloadSpans(indexReader); spans = stq.getSpans(indexReader);
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 100, 0, 0, 0); checkSpans(spans, 100, 0, 0, 0);
} }
@ -91,7 +90,7 @@ public class TestPayloadSpans extends LuceneTestCase {
SpanFirstQuery sfq; SpanFirstQuery sfq;
match = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one")); match = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one"));
sfq = new SpanFirstQuery(match, 2); sfq = new SpanFirstQuery(match, 2);
PayloadSpans spans = sfq.getPayloadSpans(indexReader); Spans spans = sfq.getSpans(indexReader);
checkSpans(spans, 109, 1, 1, 1); checkSpans(spans, 109, 1, 1, 1);
//Test more complicated subclause //Test more complicated subclause
SpanQuery[] clauses = new SpanQuery[2]; SpanQuery[] clauses = new SpanQuery[2];
@ -99,20 +98,49 @@ public class TestPayloadSpans extends LuceneTestCase {
clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "hundred")); clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "hundred"));
match = new SpanNearQuery(clauses, 0, true); match = new SpanNearQuery(clauses, 0, true);
sfq = new SpanFirstQuery(match, 2); sfq = new SpanFirstQuery(match, 2);
checkSpans(sfq.getPayloadSpans(indexReader), 100, 2, 1, 1); checkSpans(sfq.getSpans(indexReader), 100, 2, 1, 1);
match = new SpanNearQuery(clauses, 0, false); match = new SpanNearQuery(clauses, 0, false);
sfq = new SpanFirstQuery(match, 2); sfq = new SpanFirstQuery(match, 2);
checkSpans(sfq.getPayloadSpans(indexReader), 100, 2, 1, 1); checkSpans(sfq.getSpans(indexReader), 100, 2, 1, 1);
} }
public void testSpanNot() throws Exception {
SpanQuery[] clauses = new SpanQuery[2];
clauses[0] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "one"));
clauses[1] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "three"));
SpanQuery spq = new SpanNearQuery(clauses, 5, true);
SpanNotQuery snq = new SpanNotQuery(spq, new SpanTermQuery(new Term(PayloadHelper.FIELD, "two")));
checkSpans(snq.getSpans(getSpanNotSearcher().getIndexReader()), 1,new int[]{2});
}
public IndexSearcher getSpanNotSearcher()
throws IOException {
RAMDirectory directory = new RAMDirectory();
PayloadAnalyzer analyzer = new PayloadAnalyzer();
IndexWriter writer = new IndexWriter(directory, analyzer, true);
writer.setSimilarity(similarity);
Document doc = new Document();
doc.add(new Field(PayloadHelper.FIELD, "one two three one four three",
Field.Store.YES, Field.Index.ANALYZED));
writer.addDocument(doc);
writer.close();
IndexSearcher searcher = new IndexSearcher(directory);
searcher.setSimilarity(similarity);
return searcher;
}
public void testNestedSpans() throws Exception { public void testNestedSpans() throws Exception {
SpanTermQuery stq; SpanTermQuery stq;
PayloadSpans spans; Spans spans;
IndexSearcher searcher = getSearcher(); IndexSearcher searcher = getSearcher();
stq = new SpanTermQuery(new Term(PayloadHelper.FIELD, "mark")); stq = new SpanTermQuery(new Term(PayloadHelper.FIELD, "mark"));
spans = stq.getPayloadSpans(searcher.getIndexReader()); spans = stq.getSpans(searcher.getIndexReader());
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 0, null); checkSpans(spans, 0, null);
@ -123,7 +151,7 @@ public class TestPayloadSpans extends LuceneTestCase {
clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "xx")); clauses[2] = new SpanTermQuery(new Term(PayloadHelper.FIELD, "xx"));
SpanNearQuery spanNearQuery = new SpanNearQuery(clauses, 12, false); SpanNearQuery spanNearQuery = new SpanNearQuery(clauses, 12, false);
spans = spanNearQuery.getPayloadSpans(searcher.getIndexReader()); spans = spanNearQuery.getSpans(searcher.getIndexReader());
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 2, new int[]{3,3}); checkSpans(spans, 2, new int[]{3,3});
@ -135,7 +163,7 @@ public class TestPayloadSpans extends LuceneTestCase {
spanNearQuery = new SpanNearQuery(clauses, 6, true); spanNearQuery = new SpanNearQuery(clauses, 6, true);
spans = spanNearQuery.getPayloadSpans(searcher.getIndexReader()); spans = spanNearQuery.getSpans(searcher.getIndexReader());
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 1, new int[]{3}); checkSpans(spans, 1, new int[]{3});
@ -157,13 +185,13 @@ public class TestPayloadSpans extends LuceneTestCase {
// yy within 6 of xx within 6 of rr // yy within 6 of xx within 6 of rr
spans = nestedSpanNearQuery.getPayloadSpans(searcher.getIndexReader()); spans = nestedSpanNearQuery.getSpans(searcher.getIndexReader());
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 2, new int[]{3,3}); checkSpans(spans, 2, new int[]{3,3});
} }
public void testFirstClauseWithoutPayload() throws Exception { public void testFirstClauseWithoutPayload() throws Exception {
PayloadSpans spans; Spans spans;
IndexSearcher searcher = getSearcher(); IndexSearcher searcher = getSearcher();
SpanQuery[] clauses = new SpanQuery[3]; SpanQuery[] clauses = new SpanQuery[3];
@ -187,13 +215,13 @@ public class TestPayloadSpans extends LuceneTestCase {
SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses3, 6, false); SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses3, 6, false);
spans = nestedSpanNearQuery.getPayloadSpans(searcher.getIndexReader()); spans = nestedSpanNearQuery.getSpans(searcher.getIndexReader());
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 1, new int[]{3}); checkSpans(spans, 1, new int[]{3});
} }
public void testHeavilyNestedSpanQuery() throws Exception { public void testHeavilyNestedSpanQuery() throws Exception {
PayloadSpans spans; Spans spans;
IndexSearcher searcher = getSearcher(); IndexSearcher searcher = getSearcher();
SpanQuery[] clauses = new SpanQuery[3]; SpanQuery[] clauses = new SpanQuery[3];
@ -222,7 +250,7 @@ public class TestPayloadSpans extends LuceneTestCase {
SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses3, 6, false); SpanNearQuery nestedSpanNearQuery = new SpanNearQuery(clauses3, 6, false);
spans = nestedSpanNearQuery.getPayloadSpans(searcher.getIndexReader()); spans = nestedSpanNearQuery.getSpans(searcher.getIndexReader());
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
checkSpans(spans, 2, new int[]{8, 8}); checkSpans(spans, 2, new int[]{8, 8});
} }
@ -243,7 +271,7 @@ public class TestPayloadSpans extends LuceneTestCase {
SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k")); SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
SpanQuery[] sqs = { stq1, stq2 }; SpanQuery[] sqs = { stq1, stq2 };
SpanNearQuery snq = new SpanNearQuery(sqs, 1, true); SpanNearQuery snq = new SpanNearQuery(sqs, 1, true);
PayloadSpans spans = snq.getPayloadSpans(is.getIndexReader()); Spans spans = snq.getSpans(is.getIndexReader());
TopDocs topDocs = is.search(snq, 1); TopDocs topDocs = is.search(snq, 1);
Set payloadSet = new HashSet(); Set payloadSet = new HashSet();
@ -277,7 +305,7 @@ public class TestPayloadSpans extends LuceneTestCase {
SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k")); SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
SpanQuery[] sqs = { stq1, stq2 }; SpanQuery[] sqs = { stq1, stq2 };
SpanNearQuery snq = new SpanNearQuery(sqs, 0, true); SpanNearQuery snq = new SpanNearQuery(sqs, 0, true);
PayloadSpans spans = snq.getPayloadSpans(is.getIndexReader()); Spans spans = snq.getSpans(is.getIndexReader());
TopDocs topDocs = is.search(snq, 1); TopDocs topDocs = is.search(snq, 1);
Set payloadSet = new HashSet(); Set payloadSet = new HashSet();
@ -311,7 +339,7 @@ public class TestPayloadSpans extends LuceneTestCase {
SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k")); SpanTermQuery stq2 = new SpanTermQuery(new Term("content", "k"));
SpanQuery[] sqs = { stq1, stq2 }; SpanQuery[] sqs = { stq1, stq2 };
SpanNearQuery snq = new SpanNearQuery(sqs, 0, true); SpanNearQuery snq = new SpanNearQuery(sqs, 0, true);
PayloadSpans spans = snq.getPayloadSpans(is.getIndexReader()); Spans spans = snq.getSpans(is.getIndexReader());
TopDocs topDocs = is.search(snq, 1); TopDocs topDocs = is.search(snq, 1);
Set payloadSet = new HashSet(); Set payloadSet = new HashSet();
@ -364,7 +392,7 @@ public class TestPayloadSpans extends LuceneTestCase {
} }
private void checkSpans(PayloadSpans spans, int expectedNumSpans, int expectedNumPayloads, private void checkSpans(Spans spans, int expectedNumSpans, int expectedNumPayloads,
int expectedPayloadLength, int expectedFirstByte) throws IOException { int expectedPayloadLength, int expectedFirstByte) throws IOException {
assertTrue("spans is null and it shouldn't be", spans != null); assertTrue("spans is null and it shouldn't be", spans != null);
//each position match should have a span associated with it, since there is just one underlying term query, there should //each position match should have a span associated with it, since there is just one underlying term query, there should
@ -420,7 +448,7 @@ public class TestPayloadSpans extends LuceneTestCase {
return searcher; return searcher;
} }
private void checkSpans(PayloadSpans spans, int numSpans, int[] numPayloads) throws IOException { private void checkSpans(Spans spans, int numSpans, int[] numPayloads) throws IOException {
int cnt = 0; int cnt = 0;
while (spans.next() == true) { while (spans.next() == true) {