add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / contrib / queryparser / src / test / org / apache / lucene / queryParser / spans / TestSpanQueryParser.java
1 package org.apache.lucene.queryParser.spans;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import org.apache.lucene.queryParser.core.QueryNodeException;
21 import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
22 import org.apache.lucene.queryParser.core.nodes.QueryNode;
23 import org.apache.lucene.queryParser.core.parser.SyntaxParser;
24 import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
25 import org.apache.lucene.queryParser.standard.parser.StandardSyntaxParser;
26 import org.apache.lucene.queryParser.standard.processors.WildcardQueryNodeProcessor;
27 import org.apache.lucene.search.spans.SpanOrQuery;
28 import org.apache.lucene.search.spans.SpanQuery;
29 import org.apache.lucene.search.spans.SpanTermQuery;
30 import org.apache.lucene.search.Query;
31 import org.apache.lucene.util.LuceneTestCase;
32
33 /**
34  * This test case demonstrates how the new query parser can be used.<br/>
35  * <br/>
36  * 
37  * It tests queries likes "term", "field:term" "term1 term2" "term1 OR term2",
38  * which are all already supported by the current syntax parser (
39  * {@link StandardSyntaxParser}).<br/>
40  * <br/>
41  * 
42  * The goals is to create a new query parser that supports only the pair
43  * "field:term" or a list of pairs separated or not by an OR operator, and from
44  * this query generate {@link SpanQuery} objects instead of the regular
45  * {@link Query} objects. Basically, every pair will be converted to a
46  * {@link SpanTermQuery} object and if there are more than one pair they will be
47  * grouped by an {@link OrQueryNode}.<br/>
48  * <br/>
49  * 
50  * Another functionality that will be added is the ability to convert every
51  * field defined in the query to an unique specific field.<br/>
52  * <br/>
53  * 
54  * The query generation is divided in three different steps: parsing (syntax),
55  * processing (semantic) and building.<br/>
56  * <br/>
57  * 
58  * The parsing phase, as already mentioned will be performed by the current
59  * query parser: {@link StandardSyntaxParser}.<br/>
60  * <br/>
61  * 
62  * The processing phase will be performed by a processor pipeline which is
63  * compound by 2 processors: {@link SpansValidatorQueryNodeProcessor} and
64  * {@link UniqueFieldQueryNodeProcessor}.
65  * 
66  * <pre>
67  * 
68  *   {@link SpansValidatorQueryNodeProcessor}: as it's going to use the current 
69  *   query parser to parse the syntax, it will support more features than we want,
70  *   this processor basically validates the query node tree generated by the parser
71  *   and just let got through the elements we want, all the other elements as 
72  *   wildcards, range queries, etc...if found, an exception is thrown.
73  *   
74  *   {@link UniqueFieldQueryNodeProcessor}: this processor will take care of reading
75  *   what is the &quot;unique field&quot; from the configuration and convert every field defined
76  *   in every pair to this &quot;unique field&quot;. For that, a {@link SpansQueryConfigHandler} is
77  *   used, which has the {@link UniqueFieldAttribute} defined in it.
78  * </pre>
79  * 
80  * The building phase is performed by the {@link SpansQueryTreeBuilder}, which
81  * basically contains a map that defines which builder will be used to generate
82  * {@link SpanQuery} objects from {@link QueryNode} objects.<br/>
83  * <br/>
84  * 
85  * @see SpansQueryConfigHandler
86  * @see SpansQueryTreeBuilder
87  * @see SpansValidatorQueryNodeProcessor
88  * @see SpanOrQueryNodeBuilder
89  * @see SpanTermQueryNodeBuilder
90  * @see StandardSyntaxParser
91  * @see UniqueFieldQueryNodeProcessor
92  * @see UniqueFieldAttribute
93  */
94 public class TestSpanQueryParser extends LuceneTestCase {
95
96   private QueryNodeProcessorPipeline spanProcessorPipeline;
97
98   private SpansQueryConfigHandler spanQueryConfigHandler;
99
100   private SpansQueryTreeBuilder spansQueryTreeBuilder;
101
102   private SyntaxParser queryParser = new StandardSyntaxParser();
103
104   public TestSpanQueryParser() {
105     // empty constructor
106   }
107
108   @Override
109   public void setUp() throws Exception {
110     super.setUp();
111
112     this.spanProcessorPipeline = new QueryNodeProcessorPipeline();
113     this.spanQueryConfigHandler = new SpansQueryConfigHandler();
114     this.spansQueryTreeBuilder = new SpansQueryTreeBuilder();
115
116     // set up the processor pipeline
117     this.spanProcessorPipeline
118         .setQueryConfigHandler(this.spanQueryConfigHandler);
119
120     this.spanProcessorPipeline.add(new WildcardQueryNodeProcessor());
121     this.spanProcessorPipeline.add(new SpansValidatorQueryNodeProcessor());
122     this.spanProcessorPipeline.add(new UniqueFieldQueryNodeProcessor());
123
124   }
125
126   public SpanQuery getSpanQuery(CharSequence query) throws QueryNodeException {
127     return getSpanQuery("", query);
128   }
129
130   public SpanQuery getSpanQuery(String uniqueField, CharSequence query)
131       throws QueryNodeException {
132     
133     this.spanQueryConfigHandler.set(SpansQueryConfigHandler.UNIQUE_FIELD, uniqueField);
134
135     QueryNode queryTree = this.queryParser.parse(query, "defaultField");
136     queryTree = this.spanProcessorPipeline.process(queryTree);
137
138     return this.spansQueryTreeBuilder.build(queryTree);
139
140   }
141
142   public void testTermSpans() throws Exception {
143     assertEquals(getSpanQuery("field:term").toString(), "term");
144     assertEquals(getSpanQuery("term").toString(), "term");
145
146     assertTrue(getSpanQuery("field:term") instanceof SpanTermQuery);
147     assertTrue(getSpanQuery("term") instanceof SpanTermQuery);
148
149   }
150
151   public void testUniqueField() throws Exception {
152     assertEquals(getSpanQuery("field", "term").toString(), "field:term");
153     assertEquals(getSpanQuery("field", "field:term").toString(), "field:term");
154     assertEquals(getSpanQuery("field", "anotherField:term").toString(),
155         "field:term");
156
157   }
158
159   public void testOrSpans() throws Exception {
160     assertEquals(getSpanQuery("term1 term2").toString(),
161         "spanOr([term1, term2])");
162     assertEquals(getSpanQuery("term1 OR term2").toString(),
163         "spanOr([term1, term2])");
164
165     assertTrue(getSpanQuery("term1 term2") instanceof SpanOrQuery);
166     assertTrue(getSpanQuery("term1 term2") instanceof SpanOrQuery);
167
168   }
169
170   public void testQueryValidator() throws QueryNodeException {
171
172     try {
173       getSpanQuery("term*");
174       fail("QueryNodeException was expected, wildcard queries should not be supported");
175
176     } catch (QueryNodeException ex) {
177       // expected exception
178     }
179
180     try {
181       getSpanQuery("[a TO z]");
182       fail("QueryNodeException was expected, range queries should not be supported");
183
184     } catch (QueryNodeException ex) {
185       // expected exception
186     }
187
188     try {
189       getSpanQuery("a~0.5");
190       fail("QueryNodeException was expected, boost queries should not be supported");
191
192     } catch (QueryNodeException ex) {
193       // expected exception
194     }
195
196     try {
197       getSpanQuery("a^0.5");
198       fail("QueryNodeException was expected, fuzzy queries should not be supported");
199
200     } catch (QueryNodeException ex) {
201       // expected exception
202     }
203
204     try {
205       getSpanQuery("\"a b\"");
206       fail("QueryNodeException was expected, quoted queries should not be supported");
207
208     } catch (QueryNodeException ex) {
209       // expected exception
210     }
211
212     try {
213       getSpanQuery("(a b)");
214       fail("QueryNodeException was expected, parenthesized queries should not be supported");
215
216     } catch (QueryNodeException ex) {
217       // expected exception
218     }
219
220     try {
221       getSpanQuery("a AND b");
222       fail("QueryNodeException was expected, and queries should not be supported");
223
224     } catch (QueryNodeException ex) {
225       // expected exception
226     }
227
228   }
229
230 }