| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 1 | package de.ids_mannheim.korap.query; |
| 2 | |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 3 | import java.io.IOException; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 4 | import java.util.Map; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 5 | |
| 6 | import org.apache.lucene.index.AtomicReaderContext; |
| Nils Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 7 | import org.apache.lucene.index.IndexReader; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 8 | import org.apache.lucene.index.Term; |
| 9 | import org.apache.lucene.index.TermContext; |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 10 | import org.apache.lucene.search.Query; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 11 | import org.apache.lucene.search.spans.SpanQuery; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 12 | import org.apache.lucene.search.spans.Spans; |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 13 | import org.apache.lucene.search.spans.TermSpans; |
| Eliza Margaretha | 83b9537 | 2014-01-23 09:18:07 +0000 | [diff] [blame] | 14 | import org.apache.lucene.util.Bits; |
| Eliza Margaretha | 609fcc6 | 2014-02-13 14:10:20 +0000 | [diff] [blame] | 15 | import org.apache.lucene.util.ToStringUtils; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 16 | |
| 17 | import de.ids_mannheim.korap.query.spans.NextSpans; |
| 18 | |
| Nils Diewald | 44d5fa1 | 2015-01-15 21:31:52 +0000 | [diff] [blame] | 19 | /* |
| 20 | * Based on SpanNearQuery |
| 21 | * Todo: Make one Spanarray and switch between the results of A and B. |
| 22 | */ |
| 23 | |
| Nils Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 24 | /** |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 25 | * 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("tokens","s:turn")), |
| 36 | * new SpanTermQuery(new Term("tokens", "s:off"))); |
| 37 | * </pre> |
| 38 | * |
| Nils Diewald | 44d5fa1 | 2015-01-15 21:31:52 +0000 | [diff] [blame] | 39 | * @author diewald |
| 40 | * @author margaretha |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 41 | * |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 42 | */ |
| Eliza Margaretha | ed3bb3b | 2014-01-14 10:53:56 +0000 | [diff] [blame] | 43 | public class SpanNextQuery extends SimpleSpanQuery implements Cloneable { |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 44 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 45 | /** |
| 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 Diewald | 364eb64 | 2013-12-22 15:03:01 +0000 | [diff] [blame] | 54 | public SpanNextQuery(SpanQuery firstClause, SpanQuery secondClause) { |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 55 | this(firstClause, secondClause, true); |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 56 | }; |
| 57 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 58 | /** |
| 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 Margaretha | ed3bb3b | 2014-01-14 10:53:56 +0000 | [diff] [blame] | 69 | public SpanNextQuery(SpanQuery firstClause, SpanQuery secondClause, |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 70 | boolean collectPayloads) { |
| 71 | super(firstClause, secondClause, collectPayloads); |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 72 | }; |
| 73 | |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 74 | @Override |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 75 | 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 Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 78 | }; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 79 | |
| 80 | @Override |
| 81 | public SpanNextQuery clone() { |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 82 | SpanNextQuery spanNextQuery = new SpanNextQuery( |
| 83 | (SpanQuery) firstClause.clone(), |
| 84 | (SpanQuery) secondClause.clone(), collectPayloads); |
| 85 | spanNextQuery.setBoost(getBoost()); |
| 86 | return spanNextQuery; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 87 | }; |
| Nils Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 88 | |
| 89 | /* |
| 90 | * Rewrite query in case it includes regular expressions or wildcards |
| 91 | */ |
| 92 | @Override |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 93 | public Query rewrite(IndexReader reader) throws IOException { |
| 94 | SpanNextQuery clone = null; |
| Nils Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 95 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 96 | // 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 Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 104 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 105 | // 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 Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 113 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 114 | // There is a clone and it is important |
| 115 | if (clone != null) |
| 116 | return clone; |
| Nils Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 117 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 118 | return this; |
| Nils Diewald | 5871e4d | 2014-11-07 03:48:25 +0000 | [diff] [blame] | 119 | }; |
| 120 | |
| Eliza Margaretha | 609fcc6 | 2014-02-13 14:10:20 +0000 | [diff] [blame] | 121 | @Override |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 122 | 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 Margaretha | 609fcc6 | 2014-02-13 14:10:20 +0000 | [diff] [blame] | 131 | } |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 132 | |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 133 | /** Returns true iff <code>o</code> is equal to this. */ |
| 134 | @Override |
| 135 | public boolean equals(Object o) { |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 136 | if (this == o) |
| 137 | return true; |
| 138 | if (!(o instanceof SpanNextQuery)) |
| 139 | return false; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 140 | |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 141 | 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 Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 151 | }; |
| 152 | |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 153 | // I don't know what I am doing here |
| 154 | @Override |
| 155 | public int hashCode() { |
| Eliza Margaretha | f0171c5 | 2015-01-14 17:38:16 +0000 | [diff] [blame] | 156 | int result; |
| 157 | result = firstClause.hashCode() + secondClause.hashCode(); |
| 158 | result ^= (result << 31) | (result >>> 2); // reversible |
| 159 | result += Float.floatToRawIntBits(getBoost()); |
| 160 | return result; |
| Nils Diewald | f399a67 | 2013-11-18 17:55:22 +0000 | [diff] [blame] | 161 | }; |
| 162 | }; |