blob: dbef6db4a1f82c417386c9a050808dfbf70ff5dd [file] [log] [blame]
Nils Diewaldf399a672013-11-18 17:55:22 +00001package de.ids_mannheim.korap.query;
2
Nils Diewaldf399a672013-11-18 17:55:22 +00003import java.io.IOException;
Nils Diewaldf399a672013-11-18 17:55:22 +00004import java.util.Map;
Nils Diewaldf399a672013-11-18 17:55:22 +00005
6import org.apache.lucene.index.AtomicReaderContext;
Nils Diewald5871e4d2014-11-07 03:48:25 +00007import org.apache.lucene.index.IndexReader;
Nils Diewaldf399a672013-11-18 17:55:22 +00008import org.apache.lucene.index.Term;
9import org.apache.lucene.index.TermContext;
Eliza Margarethaf0171c52015-01-14 17:38:16 +000010import org.apache.lucene.search.Query;
Nils Diewaldf399a672013-11-18 17:55:22 +000011import org.apache.lucene.search.spans.SpanQuery;
Nils Diewaldf399a672013-11-18 17:55:22 +000012import org.apache.lucene.search.spans.Spans;
Eliza Margarethaf0171c52015-01-14 17:38:16 +000013import org.apache.lucene.search.spans.TermSpans;
Eliza Margaretha83b95372014-01-23 09:18:07 +000014import org.apache.lucene.util.Bits;
Eliza Margaretha609fcc62014-02-13 14:10:20 +000015import org.apache.lucene.util.ToStringUtils;
Nils Diewaldf399a672013-11-18 17:55:22 +000016
17import de.ids_mannheim.korap.query.spans.NextSpans;
18
Nils Diewald44d5fa12015-01-15 21:31:52 +000019/*
20 * Based on SpanNearQuery
21 * Todo: Make one Spanarray and switch between the results of A and B.
22 */
23
Nils Diewald5871e4d2014-11-07 03:48:25 +000024/**
Eliza Margarethaf0171c52015-01-14 17:38:16 +000025 * SpanNextQuery matches two spans which are directly next to each other. It is
26 * identical to a phrase query with exactly two clauses.
27 *
28 * In the example below, the SpanNextQuery retrieves {@link NextSpans} starting
29 * from the start position of {@link TermSpans} "turn" and ending at the end
30 * position of {@link TermSpans} "off" occurring immediately after the
31 * {@link TermSpans} "turn".
32 *
33 * <pre>
34 * SpanNextQuery sq = new SpanNextQuery(
35 * new SpanTermQuery(new Term(&quot;tokens&quot;,&quot;s:turn&quot;)),
36 * new SpanTermQuery(new Term(&quot;tokens&quot;, &quot;s:off&quot;)));
37 * </pre>
38 *
Nils Diewald44d5fa12015-01-15 21:31:52 +000039 * @author diewald
40 * @author margaretha
Eliza Margarethaf0171c52015-01-14 17:38:16 +000041 *
Nils Diewaldf399a672013-11-18 17:55:22 +000042 */
Eliza Margarethaed3bb3b2014-01-14 10:53:56 +000043public class SpanNextQuery extends SimpleSpanQuery implements Cloneable {
Nils Diewaldf399a672013-11-18 17:55:22 +000044
Eliza Margarethaf0171c52015-01-14 17:38:16 +000045 /**
46 * Constructs a SpanNextQuery for the two specified {@link SpanQuery
47 * SpanQueries} whose payloads are to be collected for the resulting
48 * {@link NextSpans}. The first SpanQuery is immediately followed by the
49 * second SpanQuery.
50 *
51 * @param firstClause the first SpanQuery
52 * @param secondClause the second SpanQuery
53 */
Nils Diewald364eb642013-12-22 15:03:01 +000054 public SpanNextQuery(SpanQuery firstClause, SpanQuery secondClause) {
Eliza Margarethaf0171c52015-01-14 17:38:16 +000055 this(firstClause, secondClause, true);
Nils Diewaldf399a672013-11-18 17:55:22 +000056 };
57
Eliza Margarethaf0171c52015-01-14 17:38:16 +000058 /**
59 * Constructs a SpanNextQuery for the two specified {@link SpanQuery
60 * SpanQueries} where the first SpanQuery is immediately followed by the
61 * second SpanQuery.
62 *
63 * @param firstClause the first SpanQuery
64 * @param secondClause the second SpanQuery
65 * @param collectPayloads a boolean flag representing the value
66 * <code>true</code> if payloads are to be collected, otherwise
67 * <code>false</code>.
68 */
Eliza Margarethaed3bb3b2014-01-14 10:53:56 +000069 public SpanNextQuery(SpanQuery firstClause, SpanQuery secondClause,
Eliza Margarethaf0171c52015-01-14 17:38:16 +000070 boolean collectPayloads) {
71 super(firstClause, secondClause, collectPayloads);
Nils Diewaldf399a672013-11-18 17:55:22 +000072 };
73
Nils Diewaldf399a672013-11-18 17:55:22 +000074 @Override
Eliza Margarethaf0171c52015-01-14 17:38:16 +000075 public Spans getSpans(final AtomicReaderContext context, Bits acceptDocs,
76 Map<Term, TermContext> termContexts) throws IOException {
77 return (Spans) new NextSpans(this, context, acceptDocs, termContexts);
Nils Diewaldf399a672013-11-18 17:55:22 +000078 };
Nils Diewaldf399a672013-11-18 17:55:22 +000079
80 @Override
81 public SpanNextQuery clone() {
Eliza Margarethaf0171c52015-01-14 17:38:16 +000082 SpanNextQuery spanNextQuery = new SpanNextQuery(
83 (SpanQuery) firstClause.clone(),
84 (SpanQuery) secondClause.clone(), collectPayloads);
85 spanNextQuery.setBoost(getBoost());
86 return spanNextQuery;
Nils Diewaldf399a672013-11-18 17:55:22 +000087 };
Nils Diewald5871e4d2014-11-07 03:48:25 +000088
89 /*
90 * Rewrite query in case it includes regular expressions or wildcards
91 */
92 @Override
Eliza Margarethaf0171c52015-01-14 17:38:16 +000093 public Query rewrite(IndexReader reader) throws IOException {
94 SpanNextQuery clone = null;
Nils Diewald5871e4d2014-11-07 03:48:25 +000095
Eliza Margarethaf0171c52015-01-14 17:38:16 +000096 // Does the first clause needs a rewrite?
97 SpanQuery query = (SpanQuery) firstClause.rewrite(reader);
98 if (query != firstClause) {
99 if (clone == null)
100 clone = this.clone();
101 clone.firstClause = query;
102 }
103 ;
Nils Diewald5871e4d2014-11-07 03:48:25 +0000104
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000105 // Does the second clause needs a rewrite?
106 query = (SpanQuery) secondClause.rewrite(reader);
107 if (query != secondClause) {
108 if (clone == null)
109 clone = this.clone();
110 clone.secondClause = query;
111 }
112 ;
Nils Diewald5871e4d2014-11-07 03:48:25 +0000113
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000114 // There is a clone and it is important
115 if (clone != null)
116 return clone;
Nils Diewald5871e4d2014-11-07 03:48:25 +0000117
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000118 return this;
Nils Diewald5871e4d2014-11-07 03:48:25 +0000119 };
120
Eliza Margaretha609fcc62014-02-13 14:10:20 +0000121 @Override
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000122 public String toString(String field) {
123 StringBuilder sb = new StringBuilder();
124 sb.append("spanNext(");
125 sb.append(firstClause.toString(field));
126 sb.append(", ");
127 sb.append(secondClause.toString(field));
128 sb.append(")");
129 sb.append(ToStringUtils.boost(getBoost()));
130 return sb.toString();
Eliza Margaretha609fcc62014-02-13 14:10:20 +0000131 }
Nils Diewaldf399a672013-11-18 17:55:22 +0000132
Nils Diewaldf399a672013-11-18 17:55:22 +0000133 /** Returns true iff <code>o</code> is equal to this. */
134 @Override
135 public boolean equals(Object o) {
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000136 if (this == o)
137 return true;
138 if (!(o instanceof SpanNextQuery))
139 return false;
Nils Diewaldf399a672013-11-18 17:55:22 +0000140
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000141 final SpanNextQuery spanNextQuery = (SpanNextQuery) o;
142
143 if (collectPayloads != spanNextQuery.collectPayloads)
144 return false;
145 if (!firstClause.equals(spanNextQuery.firstClause))
146 return false;
147 if (!secondClause.equals(spanNextQuery.secondClause))
148 return false;
149
150 return getBoost() == spanNextQuery.getBoost();
Nils Diewaldf399a672013-11-18 17:55:22 +0000151 };
152
Nils Diewaldf399a672013-11-18 17:55:22 +0000153 // I don't know what I am doing here
154 @Override
155 public int hashCode() {
Eliza Margarethaf0171c52015-01-14 17:38:16 +0000156 int result;
157 result = firstClause.hashCode() + secondClause.hashCode();
158 result ^= (result << 31) | (result >>> 2); // reversible
159 result += Float.floatToRawIntBits(getBoost());
160 return result;
Nils Diewaldf399a672013-11-18 17:55:22 +0000161 };
162};