blob: a728baaf273b22491b627c0e008e2355ac94f7f9 [file] [log] [blame]
package de.ids_mannheim.korap.query;
import java.io.IOException;
import java.util.Map;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermContext;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.spans.SpanQuery;
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.ToStringUtils;
import de.ids_mannheim.korap.query.spans.NextSpans;
/*
* Based on SpanNearQuery
* Todo: Make one Spanarray and switch between the results of A and B.
*/
/**
* SpanNextQuery matches two spans which are directly next to each
* other. It is identical to a phrase query with exactly two clauses.
*
* In the example below, the SpanNextQuery retrieves {@link NextSpans}
* starting from the start position of {@link TermSpans} "turn" and
* ending at the end position of {@link TermSpans} "off" occurring
* immediately after the {@link TermSpans} "turn".
*
* <pre>
* SpanNextQuery sq = new SpanNextQuery(
* new SpanTermQuery(new Term(&quot;tokens&quot;,&quot;s:turn&quot;)),
* new SpanTermQuery(new Term(&quot;tokens&quot;,
* &quot;s:off&quot;)));
* </pre>
*
* @author diewald
* @author margaretha
*
*/
public class SpanNextQuery extends SimpleSpanQuery implements Cloneable {
/**
* Constructs a SpanNextQuery for the two specified
* {@link SpanQuery
* SpanQueries} whose payloads are to be collected for the
* resulting {@link NextSpans}. The first SpanQuery is immediately
* followed by the
* second SpanQuery.
*
* @param firstClause
* the first SpanQuery
* @param secondClause
* the second SpanQuery
*/
public SpanNextQuery (SpanQuery firstClause, SpanQuery secondClause) {
this(firstClause, secondClause, true);
}
/**
* Constructs a SpanNextQuery for the two specified
* {@link SpanQuery
* SpanQueries} where the first SpanQuery is immediately followed
* by the
* second SpanQuery.
*
* @param firstClause
* the first SpanQuery
* @param secondClause
* the second SpanQuery
* @param collectPayloads
* a boolean flag representing the value
* <code>true</code> if payloads are to be collected,
* otherwise
* <code>false</code>.
*/
public SpanNextQuery (SpanQuery firstClause, SpanQuery secondClause,
boolean collectPayloads) {
super(firstClause, secondClause, collectPayloads);
}
@Override
// TODO: 5.3 removes getSpans fro SpanQuery ... oh, well ...
public Spans getSpans (final LeafReaderContext context, Bits acceptDocs,
Map<Term, TermContext> termContexts) throws IOException {
return (Spans) new NextSpans(this, context, acceptDocs, termContexts);
}
@Override
public SpanNextQuery clone () {
SpanNextQuery spanNextQuery = new SpanNextQuery(
(SpanQuery) firstClause.clone(),
(SpanQuery) secondClause.clone(), collectPayloads);
spanNextQuery.setBoost(getBoost());
return spanNextQuery;
}
/*
* Rewrite query in case it includes regular expressions or wildcards
*/
@Override
public Query rewrite (IndexReader reader) throws IOException {
SpanNextQuery clone = null;
// Does the first clause needs a rewrite?
SpanQuery query = (SpanQuery) firstClause.rewrite(reader);
if (query != firstClause) {
if (clone == null)
clone = this.clone();
clone.firstClause = query;
};
// Does the second clause needs a rewrite?
query = (SpanQuery) secondClause.rewrite(reader);
if (query != secondClause) {
if (clone == null)
clone = this.clone();
clone.secondClause = query;
};
// There is a clone and it is important
if (clone != null)
return clone;
return this;
}
@Override
public String toString (String field) {
StringBuilder sb = new StringBuilder();
sb.append("spanNext(");
sb.append(firstClause.toString(field));
sb.append(", ");
sb.append(secondClause.toString(field));
sb.append(")");
sb.append(ToStringUtils.boost(getBoost()));
return sb.toString();
}
/** Returns true iff <code>o</code> is equal to this. */
@Override
public boolean equals (Object o) {
if (this == o)
return true;
if (!(o instanceof SpanNextQuery))
return false;
final SpanNextQuery spanNextQuery = (SpanNextQuery) o;
if (collectPayloads != spanNextQuery.collectPayloads)
return false;
if (!firstClause.equals(spanNextQuery.firstClause))
return false;
if (!secondClause.equals(spanNextQuery.secondClause))
return false;
return getBoost() == spanNextQuery.getBoost();
}
@Override
public int hashCode () {
int result;
result = firstClause.hashCode() + secondClause.hashCode();
result ^= (result << 31) | (result >>> 2); // reversible
result += Float.floatToRawIntBits(getBoost());
return result;
}
}