001: package org.apache.lucene.search;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import org.apache.lucene.search.spans.*;
021: import org.apache.lucene.store.RAMDirectory;
022:
023: import org.apache.lucene.index.IndexWriter;
024: import org.apache.lucene.index.IndexReader;
025: import org.apache.lucene.index.Term;
026:
027: import org.apache.lucene.analysis.WhitespaceAnalyzer;
028:
029: import org.apache.lucene.document.Document;
030: import org.apache.lucene.document.Field;
031:
032: import org.apache.lucene.queryParser.QueryParser;
033: import org.apache.lucene.queryParser.ParseException;
034:
035: import org.apache.lucene.util.LuceneTestCase;
036:
037: import java.util.Random;
038: import java.util.BitSet;
039:
040: /**
041: * Tests primative queries (ie: that rewrite to themselves) to
042: * insure they match the expected set of docs, and that the score of each
043: * match is equal to the value of the scores explanation.
044: *
045: * <p>
046: * The assumption is that if all of the "primative" queries work well,
047: * then anythingthat rewrites to a primative will work well also.
048: * </p>
049: *
050: * @see "Subclasses for actual tests"
051: */
052: public class TestExplanations extends LuceneTestCase {
053: protected IndexSearcher searcher;
054:
055: public static final String FIELD = "field";
056: public static final QueryParser qp = new QueryParser(FIELD,
057: new WhitespaceAnalyzer());
058:
059: public void tearDown() throws Exception {
060: super .tearDown();
061: searcher.close();
062: }
063:
064: public void setUp() throws Exception {
065: super .setUp();
066: RAMDirectory directory = new RAMDirectory();
067: IndexWriter writer = new IndexWriter(directory,
068: new WhitespaceAnalyzer(), true);
069: for (int i = 0; i < docFields.length; i++) {
070: Document doc = new Document();
071: doc.add(new Field(FIELD, docFields[i], Field.Store.NO,
072: Field.Index.TOKENIZED));
073: writer.addDocument(doc);
074: }
075: writer.close();
076: searcher = new IndexSearcher(directory);
077: }
078:
079: protected String[] docFields = { "w1 w2 w3 w4 w5",
080: "w1 w3 w2 w3 zz", "w1 xx w2 yy w3", "w1 w3 xx w2 yy w3 zz" };
081:
082: public Query makeQuery(String queryText) throws ParseException {
083: return qp.parse(queryText);
084: }
085:
086: /** check the expDocNrs first, then check the query (and the explanations) */
087: public void qtest(String queryText, int[] expDocNrs)
088: throws Exception {
089: qtest(makeQuery(queryText), expDocNrs);
090: }
091:
092: /** check the expDocNrs first, then check the query (and the explanations) */
093: public void qtest(Query q, int[] expDocNrs) throws Exception {
094: CheckHits.checkHitCollector(q, FIELD, searcher, expDocNrs);
095: }
096:
097: /**
098: * Tests a query using qtest after wrapping it with both optB and reqB
099: * @see #qtest
100: * @see #reqB
101: * @see #optB
102: */
103: public void bqtest(Query q, int[] expDocNrs) throws Exception {
104: qtest(reqB(q), expDocNrs);
105: qtest(optB(q), expDocNrs);
106: }
107:
108: /**
109: * Tests a query using qtest after wrapping it with both optB and reqB
110: * @see #qtest
111: * @see #reqB
112: * @see #optB
113: */
114: public void bqtest(String queryText, int[] expDocNrs)
115: throws Exception {
116: bqtest(makeQuery(queryText), expDocNrs);
117: }
118:
119: /** A filter that only lets the specified document numbers pass */
120: public static class ItemizedFilter extends Filter {
121: int[] docs;
122:
123: public ItemizedFilter(int[] docs) {
124: this .docs = docs;
125: }
126:
127: public BitSet bits(IndexReader r) {
128: BitSet b = new BitSet(r.maxDoc());
129: for (int i = 0; i < docs.length; i++) {
130: b.set(docs[i]);
131: }
132: return b;
133: }
134: }
135:
136: /** helper for generating MultiPhraseQueries */
137: public static Term[] ta(String[] s) {
138: Term[] t = new Term[s.length];
139: for (int i = 0; i < s.length; i++) {
140: t[i] = new Term(FIELD, s[i]);
141: }
142: return t;
143: }
144:
145: /** MACRO for SpanTermQuery */
146: public SpanTermQuery st(String s) {
147: return new SpanTermQuery(new Term(FIELD, s));
148: }
149:
150: /** MACRO for SpanNotQuery */
151: public SpanNotQuery snot(SpanQuery i, SpanQuery e) {
152: return new SpanNotQuery(i, e);
153: }
154:
155: /** MACRO for SpanOrQuery containing two SpanTerm queries */
156: public SpanOrQuery sor(String s, String e) {
157: return sor(st(s), st(e));
158: }
159:
160: /** MACRO for SpanOrQuery containing two SpanQueries */
161: public SpanOrQuery sor(SpanQuery s, SpanQuery e) {
162: return new SpanOrQuery(new SpanQuery[] { s, e });
163: }
164:
165: /** MACRO for SpanOrQuery containing three SpanTerm queries */
166: public SpanOrQuery sor(String s, String m, String e) {
167: return sor(st(s), st(m), st(e));
168: }
169:
170: /** MACRO for SpanOrQuery containing two SpanQueries */
171: public SpanOrQuery sor(SpanQuery s, SpanQuery m, SpanQuery e) {
172: return new SpanOrQuery(new SpanQuery[] { s, m, e });
173: }
174:
175: /** MACRO for SpanNearQuery containing two SpanTerm queries */
176: public SpanNearQuery snear(String s, String e, int slop,
177: boolean inOrder) {
178: return snear(st(s), st(e), slop, inOrder);
179: }
180:
181: /** MACRO for SpanNearQuery containing two SpanQueries */
182: public SpanNearQuery snear(SpanQuery s, SpanQuery e, int slop,
183: boolean inOrder) {
184: return new SpanNearQuery(new SpanQuery[] { s, e }, slop,
185: inOrder);
186: }
187:
188: /** MACRO for SpanNearQuery containing three SpanTerm queries */
189: public SpanNearQuery snear(String s, String m, String e, int slop,
190: boolean inOrder) {
191: return snear(st(s), st(m), st(e), slop, inOrder);
192: }
193:
194: /** MACRO for SpanNearQuery containing three SpanQueries */
195: public SpanNearQuery snear(SpanQuery s, SpanQuery m, SpanQuery e,
196: int slop, boolean inOrder) {
197: return new SpanNearQuery(new SpanQuery[] { s, m, e }, slop,
198: inOrder);
199: }
200:
201: /** MACRO for SpanFirst(SpanTermQuery) */
202: public SpanFirstQuery sf(String s, int b) {
203: return new SpanFirstQuery(st(s), b);
204: }
205:
206: /**
207: * MACRO: Wraps a Query in a BooleanQuery so that it is optional, along
208: * with a second prohibited clause which will never match anything
209: */
210: public Query optB(String q) throws Exception {
211: return optB(makeQuery(q));
212: }
213:
214: /**
215: * MACRO: Wraps a Query in a BooleanQuery so that it is optional, along
216: * with a second prohibited clause which will never match anything
217: */
218: public Query optB(Query q) throws Exception {
219: BooleanQuery bq = new BooleanQuery(true);
220: bq.add(q, BooleanClause.Occur.SHOULD);
221: bq.add(new TermQuery(new Term("NEVER", "MATCH")),
222: BooleanClause.Occur.MUST_NOT);
223: return bq;
224: }
225:
226: /**
227: * MACRO: Wraps a Query in a BooleanQuery so that it is required, along
228: * with a second optional clause which will match everything
229: */
230: public Query reqB(String q) throws Exception {
231: return reqB(makeQuery(q));
232: }
233:
234: /**
235: * MACRO: Wraps a Query in a BooleanQuery so that it is required, along
236: * with a second optional clause which will match everything
237: */
238: public Query reqB(Query q) throws Exception {
239: BooleanQuery bq = new BooleanQuery(true);
240: bq.add(q, BooleanClause.Occur.MUST);
241: bq.add(new TermQuery(new Term(FIELD, "w1")),
242: BooleanClause.Occur.SHOULD);
243: return bq;
244: }
245:
246: /**
247: * Placeholder: JUnit freaks if you don't have one test ... making
248: * class abstract doesn't help
249: */
250: public void testNoop() {
251: /* NOOP */
252: }
253: }
|