pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / queryparser / src / test / org / apache / lucene / queryParser / standard / TestQueryParserWrapper.java
1 package org.apache.lucene.queryParser.standard;
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 java.io.IOException;
21 import java.io.Reader;
22 import java.text.Collator;
23 import java.text.DateFormat;
24 import java.util.Calendar;
25 import java.util.Date;
26 import java.util.GregorianCalendar;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Collections;
30
31 import org.apache.lucene.analysis.Analyzer;
32 import org.apache.lucene.analysis.KeywordAnalyzer;
33 import org.apache.lucene.analysis.LowerCaseTokenizer;
34 import org.apache.lucene.analysis.SimpleAnalyzer;
35 import org.apache.lucene.analysis.StopAnalyzer;
36 import org.apache.lucene.analysis.StopFilter;
37 import org.apache.lucene.analysis.TokenFilter;
38 import org.apache.lucene.analysis.TokenStream;
39 import org.apache.lucene.analysis.WhitespaceAnalyzer;
40 import org.apache.lucene.analysis.standard.StandardAnalyzer;
41 import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
42 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
43 import org.apache.lucene.document.DateField;
44 import org.apache.lucene.document.DateTools;
45 import org.apache.lucene.document.Document;
46 import org.apache.lucene.document.Field;
47 import org.apache.lucene.index.IndexWriter;
48 import org.apache.lucene.index.Term;
49 import org.apache.lucene.messages.MessageImpl;
50 import org.apache.lucene.queryParser.ParseException;
51 import org.apache.lucene.queryParser.core.QueryNodeException;
52 import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
53 import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
54 import org.apache.lucene.queryParser.core.nodes.QueryNode;
55 import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
56 import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
57 import org.apache.lucene.queryParser.standard.nodes.WildcardQueryNode;
58 import org.apache.lucene.queryParser.standard.processors.WildcardQueryNodeProcessor;
59 import org.apache.lucene.search.BooleanClause;
60 import org.apache.lucene.search.BooleanQuery;
61 import org.apache.lucene.search.FuzzyQuery;
62 import org.apache.lucene.search.IndexSearcher;
63 import org.apache.lucene.search.MatchAllDocsQuery;
64 import org.apache.lucene.search.MultiTermQuery;
65 import org.apache.lucene.search.PhraseQuery;
66 import org.apache.lucene.search.PrefixQuery;
67 import org.apache.lucene.search.Query;
68 import org.apache.lucene.search.ScoreDoc;
69 import org.apache.lucene.search.TermQuery;
70 import org.apache.lucene.search.TermRangeQuery;
71 import org.apache.lucene.search.WildcardQuery;
72 import org.apache.lucene.store.Directory;
73 import org.apache.lucene.util.LuceneTestCase;
74
75 /**
76  * This test case is a copy of the core Lucene query parser test, it was adapted
77  * to use new {@link QueryParserWrapper} instead of the old query parser.
78  * 
79  * Tests QueryParser.
80  * 
81  * @deprecated this entire test case tests QueryParserWrapper which is
82  *             deprecated. When QPW is gone, so will the test.
83  */
84 @Deprecated
85 public class TestQueryParserWrapper extends LuceneTestCase {
86   
87   public static Analyzer qpAnalyzer = new QPTestAnalyzer();
88
89   public static final class QPTestFilter extends TokenFilter {
90     private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
91     private final OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
92
93     /**
94      * Filter which discards the token 'stop' and which expands the token
95      * 'phrase' into 'phrase1 phrase2'
96      */
97     public QPTestFilter(TokenStream in) {
98       super(in);
99     }
100
101     boolean inPhrase = false;
102     int savedStart = 0, savedEnd = 0;
103
104     @Override
105     public boolean incrementToken() throws IOException {
106       if (inPhrase) {
107         inPhrase = false;
108         clearAttributes();
109         termAtt.setEmpty().append("phrase2");
110         offsetAtt.setOffset(savedStart, savedEnd);
111         return true;
112       } else
113         while (input.incrementToken()) {
114           if (termAtt.toString().equals("phrase")) {
115             inPhrase = true;
116             savedStart = offsetAtt.startOffset();
117             savedEnd = offsetAtt.endOffset();
118             termAtt.setEmpty().append("phrase1");
119             offsetAtt.setOffset(savedStart, savedEnd);
120             return true;
121           } else if (!termAtt.toString().equals("stop"))
122             return true;
123         }
124       return false;
125     }
126   }
127
128   public static final class QPTestAnalyzer extends Analyzer {
129
130     /** Filters LowerCaseTokenizer with StopFilter. */
131     @Override
132     public final TokenStream tokenStream(String fieldName, Reader reader) {
133       return new QPTestFilter(new LowerCaseTokenizer(TEST_VERSION_CURRENT, reader));
134     }
135   }
136
137   public static class QPTestParser extends QueryParserWrapper {
138     public QPTestParser(String f, Analyzer a) {
139       super(f, a);
140
141       QueryNodeProcessorPipeline newProcessorPipeline = new QueryNodeProcessorPipeline(
142           getQueryProcessor().getQueryConfigHandler());
143       newProcessorPipeline.add(new WildcardQueryNodeProcessor());
144       newProcessorPipeline.add(new QPTestParserQueryNodeProcessor());
145       newProcessorPipeline.add(getQueryProcessor());
146
147       setQueryProcessor(newProcessorPipeline);
148
149     }
150
151     @Override
152     protected Query getFuzzyQuery(String field, String termStr,
153         float minSimilarity) throws ParseException {
154       throw new ParseException("Fuzzy queries not allowed");
155     }
156
157     @Override
158     protected Query getWildcardQuery(String field, String termStr)
159         throws ParseException {
160       throw new ParseException("Wildcard queries not allowed");
161     }
162
163     private static class QPTestParserQueryNodeProcessor extends
164         QueryNodeProcessorImpl {
165
166       @Override
167       protected QueryNode postProcessNode(QueryNode node)
168           throws QueryNodeException {
169
170         return node;
171
172       }
173
174       @Override
175       protected QueryNode preProcessNode(QueryNode node)
176           throws QueryNodeException {
177
178         if (node instanceof WildcardQueryNode || node instanceof FuzzyQueryNode) {
179
180           throw new QueryNodeException(new MessageImpl(
181               QueryParserMessages.EMPTY_MESSAGE));
182
183         }
184
185         return node;
186
187       }
188
189       @Override
190       protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
191           throws QueryNodeException {
192
193         return children;
194
195       }
196
197     }
198
199   }
200
201   private int originalMaxClauses;
202
203   @Override
204   public void setUp() throws Exception {
205     super.setUp();
206     originalMaxClauses = BooleanQuery.getMaxClauseCount();
207   }
208
209   public QueryParserWrapper getParser(Analyzer a) throws Exception {
210     if (a == null)
211       a = new SimpleAnalyzer(TEST_VERSION_CURRENT);
212     QueryParserWrapper qp = new QueryParserWrapper("field", a);
213     qp.setDefaultOperator(QueryParserWrapper.OR_OPERATOR);
214     return qp;
215   }
216
217   public Query getQuery(String query, Analyzer a) throws Exception {
218     return getParser(a).parse(query);
219   }
220
221   public Query getQueryAllowLeadingWildcard(String query, Analyzer a) throws Exception {
222     QueryParserWrapper parser = getParser(a);
223     parser.setAllowLeadingWildcard(true);
224     return parser.parse(query);
225   }
226
227   public void assertQueryEquals(String query, Analyzer a, String result)
228       throws Exception {
229     Query q = getQuery(query, a);
230     String s = q.toString("field");
231     if (!s.equals(result)) {
232       fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
233           + "/");
234     }
235   }
236
237   public void assertQueryEqualsAllowLeadingWildcard(String query, Analyzer a, String result)
238       throws Exception {
239     Query q = getQueryAllowLeadingWildcard(query, a);
240     String s = q.toString("field");
241     if (!s.equals(result)) {
242       fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
243           + "/");
244     }
245   }
246   public void assertQueryEquals(QueryParserWrapper qp, String field,
247       String query, String result) throws Exception {
248     Query q = qp.parse(query);
249     String s = q.toString(field);
250     if (!s.equals(result)) {
251       fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
252           + "/");
253     }
254   }
255
256   public void assertEscapedQueryEquals(String query, Analyzer a, String result)
257       throws Exception {
258     String escapedQuery = QueryParserWrapper.escape(query);
259     if (!escapedQuery.equals(result)) {
260       fail("Query /" + query + "/ yielded /" + escapedQuery + "/, expecting /"
261           + result + "/");
262     }
263   }
264
265   public void assertWildcardQueryEquals(String query, boolean lowercase,
266       String result, boolean allowLeadingWildcard) throws Exception {
267     QueryParserWrapper qp = getParser(null);
268     qp.setLowercaseExpandedTerms(lowercase);
269     qp.setAllowLeadingWildcard(allowLeadingWildcard);
270     Query q = qp.parse(query);
271     String s = q.toString("field");
272     if (!s.equals(result)) {
273       fail("WildcardQuery /" + query + "/ yielded /" + s + "/, expecting /"
274           + result + "/");
275     }
276   }
277
278   public void assertWildcardQueryEquals(String query, boolean lowercase,
279       String result) throws Exception {
280     assertWildcardQueryEquals(query, lowercase, result, false);
281   }
282
283   public void assertWildcardQueryEquals(String query, String result)
284       throws Exception {
285     QueryParserWrapper qp = getParser(null);
286     Query q = qp.parse(query);
287     String s = q.toString("field");
288     if (!s.equals(result)) {
289       fail("WildcardQuery /" + query + "/ yielded /" + s + "/, expecting /"
290           + result + "/");
291     }
292   }
293
294   public Query getQueryDOA(String query, Analyzer a) throws Exception {
295     if (a == null)
296       a = new SimpleAnalyzer(TEST_VERSION_CURRENT);
297     QueryParserWrapper qp = new QueryParserWrapper("field", a);
298     qp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
299     return qp.parse(query);
300   }
301
302   public void assertQueryEqualsDOA(String query, Analyzer a, String result)
303       throws Exception {
304     Query q = getQueryDOA(query, a);
305     String s = q.toString("field");
306     if (!s.equals(result)) {
307       fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
308           + "/");
309     }
310   }
311
312   public void testCJK() throws Exception {
313     // Test Ideographic Space - As wide as a CJK character cell (fullwidth)
314     // used google to translate the word "term" to japanese -> ??
315     assertQueryEquals("term\u3000term\u3000term", null,
316         "term\u0020term\u0020term");
317     assertQueryEqualsAllowLeadingWildcard("??\u3000??\u3000??", null, "??\u0020??\u0020??");
318   }
319   
320   public void testCJKTerm() throws Exception {
321     // individual CJK chars as terms
322     StandardAnalyzer analyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
323     
324     BooleanQuery expected = new BooleanQuery();
325     expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.SHOULD);
326     expected.add(new TermQuery(new Term("field", "国")), BooleanClause.Occur.SHOULD);
327     
328     assertEquals(expected, getQuery("中国", analyzer));
329   }
330   
331   public void testCJKBoostedTerm() throws Exception {
332     // individual CJK chars as terms
333     StandardAnalyzer analyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
334     
335     BooleanQuery expected = new BooleanQuery();
336     expected.setBoost(0.5f);
337     expected.add(new TermQuery(new Term("field", "中")), BooleanClause.Occur.SHOULD);
338     expected.add(new TermQuery(new Term("field", "国")), BooleanClause.Occur.SHOULD);
339     
340     assertEquals(expected, getQuery("中国^0.5", analyzer));
341   }
342   
343   public void testCJKPhrase() throws Exception {
344     // individual CJK chars as terms
345     StandardAnalyzer analyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
346     
347     PhraseQuery expected = new PhraseQuery();
348     expected.add(new Term("field", "中"));
349     expected.add(new Term("field", "国"));
350     
351     assertEquals(expected, getQuery("\"中国\"", analyzer));
352   }
353   
354   public void testCJKBoostedPhrase() throws Exception {
355     // individual CJK chars as terms
356     StandardAnalyzer analyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
357     
358     PhraseQuery expected = new PhraseQuery();
359     expected.setBoost(0.5f);
360     expected.add(new Term("field", "中"));
361     expected.add(new Term("field", "国"));
362     
363     assertEquals(expected, getQuery("\"中国\"^0.5", analyzer));
364   }
365   
366   public void testCJKSloppyPhrase() throws Exception {
367     // individual CJK chars as terms
368     StandardAnalyzer analyzer = new StandardAnalyzer(TEST_VERSION_CURRENT);
369     
370     PhraseQuery expected = new PhraseQuery();
371     expected.setSlop(3);
372     expected.add(new Term("field", "中"));
373     expected.add(new Term("field", "国"));
374     
375     assertEquals(expected, getQuery("\"中国\"~3", analyzer));
376   }
377   
378   public void testSimple() throws Exception {
379     assertQueryEquals("\"term germ\"~2", null, "\"term germ\"~2");
380     assertQueryEquals("term term term", null, "term term term");
381     assertQueryEquals("t�rm term term", new WhitespaceAnalyzer(TEST_VERSION_CURRENT),
382         "t�rm term term");
383     assertQueryEquals("�mlaut", new WhitespaceAnalyzer(TEST_VERSION_CURRENT), "�mlaut");
384
385     assertQueryEquals("\"\"", new KeywordAnalyzer(), "");
386     assertQueryEquals("foo:\"\"", new KeywordAnalyzer(), "foo:");
387
388     assertQueryEquals("a AND b", null, "+a +b");
389     assertQueryEquals("(a AND b)", null, "+a +b");
390     assertQueryEquals("c OR (a AND b)", null, "c (+a +b)");
391
392     assertQueryEquals("a AND NOT b", null, "+a -b");
393
394     assertQueryEquals("a AND -b", null, "+a -b");
395
396     assertQueryEquals("a AND !b", null, "+a -b");
397
398     assertQueryEquals("a && b", null, "+a +b");
399
400     assertQueryEquals("a && ! b", null, "+a -b");
401
402     assertQueryEquals("a OR b", null, "a b");
403     assertQueryEquals("a || b", null, "a b");
404
405     assertQueryEquals("a OR !b", null, "a -b");
406
407     assertQueryEquals("a OR ! b", null, "a -b");
408
409     assertQueryEquals("a OR -b", null, "a -b");
410
411     assertQueryEquals("+term -term term", null, "+term -term term");
412     assertQueryEquals("foo:term AND field:anotherTerm", null,
413         "+foo:term +anotherterm");
414     assertQueryEquals("term AND \"phrase phrase\"", null,
415         "+term +\"phrase phrase\"");
416     assertQueryEquals("\"hello there\"", null, "\"hello there\"");
417     assertTrue(getQuery("a AND b", null) instanceof BooleanQuery);
418     assertTrue(getQuery("hello", null) instanceof TermQuery);
419     assertTrue(getQuery("\"hello there\"", null) instanceof PhraseQuery);
420
421     assertQueryEquals("germ term^2.0", null, "germ term^2.0");
422     assertQueryEquals("(term)^2.0", null, "term^2.0");
423     assertQueryEquals("(germ term)^2.0", null, "(germ term)^2.0");
424     assertQueryEquals("term^2.0", null, "term^2.0");
425     assertQueryEquals("term^2", null, "term^2.0");
426     assertQueryEquals("\"germ term\"^2.0", null, "\"germ term\"^2.0");
427     assertQueryEquals("\"term germ\"^2", null, "\"term germ\"^2.0");
428
429     assertQueryEquals("(foo OR bar) AND (baz OR boo)", null,
430         "+(foo bar) +(baz boo)");
431     assertQueryEquals("((a OR b) AND NOT c) OR d", null, "(+(a b) -c) d");
432     assertQueryEquals("+(apple \"steve jobs\") -(foo bar baz)", null,
433         "+(apple \"steve jobs\") -(foo bar baz)");
434     assertQueryEquals("+title:(dog OR cat) -author:\"bob dole\"", null,
435         "+(title:dog title:cat) -author:\"bob dole\"");
436
437     QueryParserWrapper qp = new QueryParserWrapper("field",
438         new StandardAnalyzer(TEST_VERSION_CURRENT));
439     // make sure OR is the default:
440     assertEquals(QueryParserWrapper.OR_OPERATOR, qp.getDefaultOperator());
441     qp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
442     assertEquals(QueryParserWrapper.AND_OPERATOR, qp.getDefaultOperator());
443     qp.setDefaultOperator(QueryParserWrapper.OR_OPERATOR);
444     assertEquals(QueryParserWrapper.OR_OPERATOR, qp.getDefaultOperator());
445   }
446
447   public void testPunct() throws Exception {
448     Analyzer a = new WhitespaceAnalyzer(TEST_VERSION_CURRENT);
449     assertQueryEquals("a&b", a, "a&b");
450     assertQueryEquals("a&&b", a, "a&&b");
451     assertQueryEquals(".NET", a, ".NET");
452   }
453
454   public void testSlop() throws Exception {
455
456     assertQueryEquals("\"term germ\"~2", null, "\"term germ\"~2");
457     assertQueryEquals("\"term germ\"~2 flork", null, "\"term germ\"~2 flork");
458     assertQueryEquals("\"term\"~2", null, "term");
459     assertQueryEquals("\" \"~2 germ", null, "germ");
460     assertQueryEquals("\"term germ\"~2^2", null, "\"term germ\"~2^2.0");
461   }
462
463   public void testNumber() throws Exception {
464     // The numbers go away because SimpleAnalzyer ignores them
465     assertQueryEquals("3", null, "");
466     assertQueryEquals("term 1.0 1 2", null, "term");
467     assertQueryEquals("term term1 term2", null, "term term term");
468
469     Analyzer a = new StandardAnalyzer(TEST_VERSION_CURRENT);
470     assertQueryEquals("3", a, "3");
471     assertQueryEquals("term 1.0 1 2", a, "term 1.0 1 2");
472     assertQueryEquals("term term1 term2", a, "term term1 term2");
473   }
474
475   public void testWildcard() throws Exception {
476     assertQueryEquals("term*", null, "term*");
477     assertQueryEquals("term*^2", null, "term*^2.0");
478     assertQueryEquals("term~", null, "term~0.5");
479     assertQueryEquals("term~0.7", null, "term~0.7");
480
481     assertQueryEquals("term~^2", null, "term~0.5^2.0");
482
483     assertQueryEquals("term^2~", null, "term~0.5^2.0");
484     assertQueryEquals("term*germ", null, "term*germ");
485     assertQueryEquals("term*germ^3", null, "term*germ^3.0");
486
487     assertTrue(getQuery("term*", null) instanceof PrefixQuery);
488     assertTrue(getQuery("term*^2", null) instanceof PrefixQuery);
489     assertTrue(getQuery("term~", null) instanceof FuzzyQuery);
490     assertTrue(getQuery("term~0.7", null) instanceof FuzzyQuery);
491     FuzzyQuery fq = (FuzzyQuery) getQuery("term~0.7", null);
492     assertEquals(0.7f, fq.getMinSimilarity(), 0.1f);
493     assertEquals(FuzzyQuery.defaultPrefixLength, fq.getPrefixLength());
494     fq = (FuzzyQuery) getQuery("term~", null);
495     assertEquals(0.5f, fq.getMinSimilarity(), 0.1f);
496     assertEquals(FuzzyQuery.defaultPrefixLength, fq.getPrefixLength());
497
498     assertParseException("term~1.1"); // value > 1, throws exception
499
500     assertTrue(getQuery("term*germ", null) instanceof WildcardQuery);
501
502     /*
503      * Tests to see that wild card terms are (or are not) properly lower-cased
504      * with propery parser configuration
505      */
506     // First prefix queries:
507     // by default, convert to lowercase:
508     assertWildcardQueryEquals("Term*", true, "term*");
509     // explicitly set lowercase:
510     assertWildcardQueryEquals("term*", true, "term*");
511     assertWildcardQueryEquals("Term*", true, "term*");
512     assertWildcardQueryEquals("TERM*", true, "term*");
513     // explicitly disable lowercase conversion:
514     assertWildcardQueryEquals("term*", false, "term*");
515     assertWildcardQueryEquals("Term*", false, "Term*");
516     assertWildcardQueryEquals("TERM*", false, "TERM*");
517     // Then 'full' wildcard queries:
518     // by default, convert to lowercase:
519     assertWildcardQueryEquals("Te?m", "te?m");
520     // explicitly set lowercase:
521     assertWildcardQueryEquals("te?m", true, "te?m");
522     assertWildcardQueryEquals("Te?m", true, "te?m");
523     assertWildcardQueryEquals("TE?M", true, "te?m");
524     assertWildcardQueryEquals("Te?m*gerM", true, "te?m*germ");
525     // explicitly disable lowercase conversion:
526     assertWildcardQueryEquals("te?m", false, "te?m");
527     assertWildcardQueryEquals("Te?m", false, "Te?m");
528     assertWildcardQueryEquals("TE?M", false, "TE?M");
529     assertWildcardQueryEquals("Te?m*gerM", false, "Te?m*gerM");
530     // Fuzzy queries:
531     assertWildcardQueryEquals("Term~", "term~0.5");
532     assertWildcardQueryEquals("Term~", true, "term~0.5");
533     assertWildcardQueryEquals("Term~", false, "Term~0.5");
534     // Range queries:
535
536     // TODO: implement this on QueryParser
537     // Q0002E_INVALID_SYNTAX_CANNOT_PARSE: Syntax Error, cannot parse '[A TO
538     // C]': Lexical error at line 1, column 1. Encountered: "[" (91), after : ""
539     assertWildcardQueryEquals("[A TO C]", "[a TO c]");
540     assertWildcardQueryEquals("[A TO C]", true, "[a TO c]");
541     assertWildcardQueryEquals("[A TO C]", false, "[A TO C]");
542     // Test suffix queries: first disallow
543     try {
544       assertWildcardQueryEquals("*Term", true, "*term");
545       fail();
546     } catch (ParseException pe) {
547       // expected exception
548     }
549     try {
550       assertWildcardQueryEquals("?Term", true, "?term");
551       fail();
552     } catch (ParseException pe) {
553       // expected exception
554     }
555     // Test suffix queries: then allow
556     assertWildcardQueryEquals("*Term", true, "*term", true);
557     assertWildcardQueryEquals("?Term", true, "?term", true);
558   }
559
560   public void testLeadingWildcardType() throws Exception {
561     QueryParserWrapper qp = getParser(null);
562     qp.setAllowLeadingWildcard(true);
563     assertEquals(WildcardQuery.class, qp.parse("t*erm*").getClass());
564     assertEquals(WildcardQuery.class, qp.parse("?term*").getClass());
565     assertEquals(WildcardQuery.class, qp.parse("*term*").getClass());
566   }
567
568   public void testQPA() throws Exception {
569     assertQueryEquals("term term^3.0 term", qpAnalyzer, "term term^3.0 term");
570     assertQueryEquals("term stop^3.0 term", qpAnalyzer, "term term");
571
572     assertQueryEquals("term term term", qpAnalyzer, "term term term");
573     assertQueryEquals("term +stop term", qpAnalyzer, "term term");
574     assertQueryEquals("term -stop term", qpAnalyzer, "term term");
575
576     assertQueryEquals("drop AND (stop) AND roll", qpAnalyzer, "+drop +roll");
577     assertQueryEquals("term +(stop) term", qpAnalyzer, "term term");
578     assertQueryEquals("term -(stop) term", qpAnalyzer, "term term");
579
580     assertQueryEquals("drop AND stop AND roll", qpAnalyzer, "+drop +roll");
581     assertQueryEquals("term phrase term", qpAnalyzer,
582         "term (phrase1 phrase2) term");
583
584     assertQueryEquals("term AND NOT phrase term", qpAnalyzer,
585         "+term -(phrase1 phrase2) term");
586
587     assertQueryEquals("stop^3", qpAnalyzer, "");
588     assertQueryEquals("stop", qpAnalyzer, "");
589     assertQueryEquals("(stop)^3", qpAnalyzer, "");
590     assertQueryEquals("((stop))^3", qpAnalyzer, "");
591     assertQueryEquals("(stop^3)", qpAnalyzer, "");
592     assertQueryEquals("((stop)^3)", qpAnalyzer, "");
593     assertQueryEquals("(stop)", qpAnalyzer, "");
594     assertQueryEquals("((stop))", qpAnalyzer, "");
595     assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery);
596     assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery);
597   }
598
599   public void testRange() throws Exception {
600     assertQueryEquals("[ a TO z]", null, "[a TO z]");
601     assertEquals(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT, ((TermRangeQuery)getQuery("[ a TO z]", null)).getRewriteMethod());
602
603     QueryParserWrapper qp = new QueryParserWrapper("field",
604         new SimpleAnalyzer(TEST_VERSION_CURRENT));
605     
606     qp.setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
607     assertEquals(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE,((TermRangeQuery)qp.parse("[ a TO z]")).getRewriteMethod());
608
609     assertQueryEquals("[ a TO z ]", null, "[a TO z]");
610     assertQueryEquals("{ a TO z}", null, "{a TO z}");
611     assertQueryEquals("{ a TO z }", null, "{a TO z}");
612     assertQueryEquals("{ a TO z }^2.0", null, "{a TO z}^2.0");
613     assertQueryEquals("[ a TO z] OR bar", null, "[a TO z] bar");
614     assertQueryEquals("[ a TO z] AND bar", null, "+[a TO z] +bar");
615     assertQueryEquals("( bar blar { a TO z}) ", null, "bar blar {a TO z}");
616     assertQueryEquals("gack ( bar blar { a TO z}) ", null,
617         "gack (bar blar {a TO z})");
618   }
619
620   public void testFarsiRangeCollating() throws Exception {
621
622     Directory ramDir = newDirectory();
623     IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(TEST_VERSION_CURRENT), true,
624         IndexWriter.MaxFieldLength.LIMITED);
625     Document doc = new Document();
626     doc.add(newField("content", "\u0633\u0627\u0628", Field.Store.YES,
627         Field.Index.NOT_ANALYZED));
628     iw.addDocument(doc);
629     iw.close();
630     IndexSearcher is = new IndexSearcher(ramDir, true);
631
632     QueryParserWrapper qp = new QueryParserWrapper("content",
633         new WhitespaceAnalyzer(TEST_VERSION_CURRENT));
634
635     // Neither Java 1.4.2 nor 1.5.0 has Farsi Locale collation available in
636     // RuleBasedCollator. However, the Arabic Locale seems to order the Farsi
637     // characters properly.
638     Collator c = Collator.getInstance(new Locale("ar"));
639     qp.setRangeCollator(c);
640
641     // Unicode order would include U+0633 in [ U+062F - U+0698 ], but Farsi
642     // orders the U+0698 character before the U+0633 character, so the single
643     // index Term below should NOT be returned by a ConstantScoreRangeQuery
644     // with a Farsi Collator (or an Arabic one for the case when Farsi is not
645     // supported).
646
647     // Test ConstantScoreRangeQuery
648     qp.setMultiTermRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
649     ScoreDoc[] result = is.search(qp.parse("[ \u062F TO \u0698 ]"), null, 1000).scoreDocs;
650     assertEquals("The index Term should not be included.", 0, result.length);
651
652     result = is.search(qp.parse("[ \u0633 TO \u0638 ]"), null, 1000).scoreDocs;
653     assertEquals("The index Term should be included.", 1, result.length);
654
655     // Test RangeQuery
656     qp.setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
657     result = is.search(qp.parse("[ \u062F TO \u0698 ]"), null, 1000).scoreDocs;
658     assertEquals("The index Term should not be included.", 0, result.length);
659
660     result = is.search(qp.parse("[ \u0633 TO \u0638 ]"), null, 1000).scoreDocs;
661     assertEquals("The index Term should be included.", 1, result.length);
662
663     is.close();
664     ramDir.close();
665   }
666   
667   private String escapeDateString(String s) {
668     if (s.contains(" ")) {
669       return "\"" + s + "\"";
670     } else {
671       return s;
672     }
673   }
674
675   /** for testing legacy DateField support */
676   private String getLegacyDate(String s) throws Exception {
677     DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
678     return DateField.dateToString(df.parse(s));
679   }
680
681   /** for testing DateTools support */
682   private String getDate(String s, DateTools.Resolution resolution)
683       throws Exception {
684     DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
685     return getDate(df.parse(s), resolution);
686   }
687
688   /** for testing DateTools support */
689   private String getDate(Date d, DateTools.Resolution resolution)
690       throws Exception {
691     if (resolution == null) {
692       return DateField.dateToString(d);
693     } else {
694       return DateTools.dateToString(d, resolution);
695     }
696   }
697
698   private String getLocalizedDate(int year, int month, int day) {
699     DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
700     Calendar calendar = new GregorianCalendar();
701     calendar.clear();
702     calendar.set(year, month, day);
703     calendar.set(Calendar.HOUR_OF_DAY, 23);
704     calendar.set(Calendar.MINUTE, 59);
705     calendar.set(Calendar.SECOND, 59);
706     calendar.set(Calendar.MILLISECOND, 999);
707     return df.format(calendar.getTime());
708   }
709
710   /** for testing legacy DateField support */
711   public void testLegacyDateRange() throws Exception {
712     String startDate = getLocalizedDate(2002, 1, 1);
713     String endDate = getLocalizedDate(2002, 1, 4);
714     Calendar endDateExpected = new GregorianCalendar();
715     endDateExpected.clear();
716     endDateExpected.set(2002, 1, 4, 23, 59, 59);
717     endDateExpected.set(Calendar.MILLISECOND, 999);
718     assertQueryEquals("[ " + escapeDateString(startDate) + " TO " + escapeDateString(endDate) + "]", null, "["
719         + getLegacyDate(startDate) + " TO "
720         + DateField.dateToString(endDateExpected.getTime()) + "]");
721     assertQueryEquals("{  " + escapeDateString(startDate) + "    " + escapeDateString(endDate) + "   }", null, "{"
722         + getLegacyDate(startDate) + " TO " + getLegacyDate(endDate) + "}");
723   }
724
725   public void testDateRange() throws Exception {
726     String startDate = getLocalizedDate(2002, 1, 1);
727     String endDate = getLocalizedDate(2002, 1, 4);
728     Calendar endDateExpected = new GregorianCalendar();
729     endDateExpected.clear();
730     endDateExpected.set(2002, 1, 4, 23, 59, 59);
731     endDateExpected.set(Calendar.MILLISECOND, 999);
732     final String defaultField = "default";
733     final String monthField = "month";
734     final String hourField = "hour";
735     QueryParserWrapper qp = new QueryParserWrapper("field",
736         new SimpleAnalyzer(TEST_VERSION_CURRENT));
737
738     // Don't set any date resolution and verify if DateField is used
739     assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
740         endDateExpected.getTime(), null);
741
742     // set a field specific date resolution
743     qp.setDateResolution(monthField, DateTools.Resolution.MONTH);
744
745     // DateField should still be used for defaultField
746     assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
747         endDateExpected.getTime(), null);
748
749     // set default date resolution to MILLISECOND
750     qp.setDateResolution(DateTools.Resolution.MILLISECOND);
751
752     // set second field specific date resolution
753     qp.setDateResolution(hourField, DateTools.Resolution.HOUR);
754
755     // for this field no field specific date resolution has been set,
756     // so verify if the default resolution is used
757     assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
758         endDateExpected.getTime(), DateTools.Resolution.MILLISECOND);
759
760     // verify if field specific date resolutions are used for these two fields
761     assertDateRangeQueryEquals(qp, monthField, startDate, endDate,
762         endDateExpected.getTime(), DateTools.Resolution.MONTH);
763
764     assertDateRangeQueryEquals(qp, hourField, startDate, endDate,
765         endDateExpected.getTime(), DateTools.Resolution.HOUR);
766   }
767
768   public void assertDateRangeQueryEquals(QueryParserWrapper qp, String field,
769       String startDate, String endDate, Date endDateInclusive,
770       DateTools.Resolution resolution) throws Exception {
771     assertQueryEquals(qp, field, field + ":[" + escapeDateString(startDate) + " TO " + escapeDateString(endDate)
772         + "]", "[" + getDate(startDate, resolution) + " TO "
773         + getDate(endDateInclusive, resolution) + "]");
774     assertQueryEquals(qp, field, field + ":{" + escapeDateString(startDate) + " TO " + escapeDateString(endDate)
775         + "}", "{" + getDate(startDate, resolution) + " TO "
776         + getDate(endDate, resolution) + "}");
777   }
778
779   public void testEscaped() throws Exception {
780     Analyzer a = new WhitespaceAnalyzer(TEST_VERSION_CURRENT);
781
782     /*
783      * assertQueryEquals("\\[brackets", a, "\\[brackets");
784      * assertQueryEquals("\\[brackets", null, "brackets");
785      * assertQueryEquals("\\\\", a, "\\\\"); assertQueryEquals("\\+blah", a,
786      * "\\+blah"); assertQueryEquals("\\(blah", a, "\\(blah");
787      * 
788      * assertQueryEquals("\\-blah", a, "\\-blah"); assertQueryEquals("\\!blah",
789      * a, "\\!blah"); assertQueryEquals("\\{blah", a, "\\{blah");
790      * assertQueryEquals("\\}blah", a, "\\}blah"); assertQueryEquals("\\:blah",
791      * a, "\\:blah"); assertQueryEquals("\\^blah", a, "\\^blah");
792      * assertQueryEquals("\\[blah", a, "\\[blah"); assertQueryEquals("\\]blah",
793      * a, "\\]blah"); assertQueryEquals("\\\"blah", a, "\\\"blah");
794      * assertQueryEquals("\\(blah", a, "\\(blah"); assertQueryEquals("\\)blah",
795      * a, "\\)blah"); assertQueryEquals("\\~blah", a, "\\~blah");
796      * assertQueryEquals("\\*blah", a, "\\*blah"); assertQueryEquals("\\?blah",
797      * a, "\\?blah"); //assertQueryEquals("foo \\&\\& bar", a,
798      * "foo \\&\\& bar"); //assertQueryEquals("foo \\|| bar", a,
799      * "foo \\|| bar"); //assertQueryEquals("foo \\AND bar", a,
800      * "foo \\AND bar");
801      */
802
803     assertQueryEquals("\\a", a, "a");
804
805     assertQueryEquals("a\\-b:c", a, "a-b:c");
806     assertQueryEquals("a\\+b:c", a, "a+b:c");
807     assertQueryEquals("a\\:b:c", a, "a:b:c");
808     assertQueryEquals("a\\\\b:c", a, "a\\b:c");
809
810     assertQueryEquals("a:b\\-c", a, "a:b-c");
811     assertQueryEquals("a:b\\+c", a, "a:b+c");
812     assertQueryEquals("a:b\\:c", a, "a:b:c");
813     assertQueryEquals("a:b\\\\c", a, "a:b\\c");
814
815     assertQueryEquals("a:b\\-c*", a, "a:b-c*");
816     assertQueryEquals("a:b\\+c*", a, "a:b+c*");
817     assertQueryEquals("a:b\\:c*", a, "a:b:c*");
818
819     assertQueryEquals("a:b\\\\c*", a, "a:b\\c*");
820
821     assertQueryEquals("a:b\\-?c", a, "a:b-?c");
822     assertQueryEquals("a:b\\+?c", a, "a:b+?c");
823     assertQueryEquals("a:b\\:?c", a, "a:b:?c");
824
825     assertQueryEquals("a:b\\\\?c", a, "a:b\\?c");
826
827     assertQueryEquals("a:b\\-c~", a, "a:b-c~0.5");
828     assertQueryEquals("a:b\\+c~", a, "a:b+c~0.5");
829     assertQueryEquals("a:b\\:c~", a, "a:b:c~0.5");
830     assertQueryEquals("a:b\\\\c~", a, "a:b\\c~0.5");
831
832     // TODO: implement Range queries on QueryParser
833     assertQueryEquals("[ a\\- TO a\\+ ]", null, "[a- TO a+]");
834     assertQueryEquals("[ a\\: TO a\\~ ]", null, "[a: TO a~]");
835     assertQueryEquals("[ a\\\\ TO a\\* ]", null, "[a\\ TO a*]");
836
837     assertQueryEquals(
838         "[\"c\\:\\\\temp\\\\\\~foo0.txt\" TO \"c\\:\\\\temp\\\\\\~foo9.txt\"]",
839         a, "[c:\\temp\\~foo0.txt TO c:\\temp\\~foo9.txt]");
840
841     assertQueryEquals("a\\\\\\+b", a, "a\\+b");
842
843     assertQueryEquals("a \\\"b c\\\" d", a, "a \"b c\" d");
844     assertQueryEquals("\"a \\\"b c\\\" d\"", a, "\"a \"b c\" d\"");
845     assertQueryEquals("\"a \\+b c d\"", a, "\"a +b c d\"");
846
847     assertQueryEquals("c\\:\\\\temp\\\\\\~foo.txt", a, "c:\\temp\\~foo.txt");
848
849     assertParseException("XY\\"); // there must be a character after the escape
850                                   // char
851
852     // test unicode escaping
853     assertQueryEquals("a\\u0062c", a, "abc");
854     assertQueryEquals("XY\\u005a", a, "XYZ");
855     assertQueryEquals("XY\\u005A", a, "XYZ");
856     assertQueryEquals("\"a \\\\\\u0028\\u0062\\\" c\"", a, "\"a \\(b\" c\"");
857
858     assertParseException("XY\\u005G"); // test non-hex character in escaped
859                                        // unicode sequence
860     assertParseException("XY\\u005"); // test incomplete escaped unicode
861                                       // sequence
862
863     // Tests bug LUCENE-800
864     assertQueryEquals("(item:\\\\ item:ABCD\\\\)", a, "item:\\ item:ABCD\\");
865     assertParseException("(item:\\\\ item:ABCD\\\\))"); // unmatched closing
866                                                         // paranthesis
867     assertQueryEquals("\\*", a, "*");
868     assertQueryEquals("\\\\", a, "\\"); // escaped backslash
869
870     assertParseException("\\"); // a backslash must always be escaped
871
872     // LUCENE-1189
873     assertQueryEquals("(\"a\\\\\") or (\"b\")", a, "a\\ or b");
874   }
875
876   public void testQueryStringEscaping() throws Exception {
877     Analyzer a = new WhitespaceAnalyzer(TEST_VERSION_CURRENT);
878
879     assertEscapedQueryEquals("a-b:c", a, "a\\-b\\:c");
880     assertEscapedQueryEquals("a+b:c", a, "a\\+b\\:c");
881     assertEscapedQueryEquals("a:b:c", a, "a\\:b\\:c");
882     assertEscapedQueryEquals("a\\b:c", a, "a\\\\b\\:c");
883
884     assertEscapedQueryEquals("a:b-c", a, "a\\:b\\-c");
885     assertEscapedQueryEquals("a:b+c", a, "a\\:b\\+c");
886     assertEscapedQueryEquals("a:b:c", a, "a\\:b\\:c");
887     assertEscapedQueryEquals("a:b\\c", a, "a\\:b\\\\c");
888
889     assertEscapedQueryEquals("a:b-c*", a, "a\\:b\\-c\\*");
890     assertEscapedQueryEquals("a:b+c*", a, "a\\:b\\+c\\*");
891     assertEscapedQueryEquals("a:b:c*", a, "a\\:b\\:c\\*");
892
893     assertEscapedQueryEquals("a:b\\\\c*", a, "a\\:b\\\\\\\\c\\*");
894
895     assertEscapedQueryEquals("a:b-?c", a, "a\\:b\\-\\?c");
896     assertEscapedQueryEquals("a:b+?c", a, "a\\:b\\+\\?c");
897     assertEscapedQueryEquals("a:b:?c", a, "a\\:b\\:\\?c");
898
899     assertEscapedQueryEquals("a:b?c", a, "a\\:b\\?c");
900
901     assertEscapedQueryEquals("a:b-c~", a, "a\\:b\\-c\\~");
902     assertEscapedQueryEquals("a:b+c~", a, "a\\:b\\+c\\~");
903     assertEscapedQueryEquals("a:b:c~", a, "a\\:b\\:c\\~");
904     assertEscapedQueryEquals("a:b\\c~", a, "a\\:b\\\\c\\~");
905
906     assertEscapedQueryEquals("[ a - TO a+ ]", null, "\\[ a \\- TO a\\+ \\]");
907     assertEscapedQueryEquals("[ a : TO a~ ]", null, "\\[ a \\: TO a\\~ \\]");
908     assertEscapedQueryEquals("[ a\\ TO a* ]", null, "\\[ a\\\\ TO a\\* \\]");
909
910     // LUCENE-881
911     assertEscapedQueryEquals("|| abc ||", a, "\\|\\| abc \\|\\|");
912     assertEscapedQueryEquals("&& abc &&", a, "\\&\\& abc \\&\\&");
913   }
914
915   public void testTabNewlineCarriageReturn() throws Exception {
916     assertQueryEqualsDOA("+weltbank +worlbank", null, "+weltbank +worlbank");
917
918     assertQueryEqualsDOA("+weltbank\n+worlbank", null, "+weltbank +worlbank");
919     assertQueryEqualsDOA("weltbank \n+worlbank", null, "+weltbank +worlbank");
920     assertQueryEqualsDOA("weltbank \n +worlbank", null, "+weltbank +worlbank");
921
922     assertQueryEqualsDOA("+weltbank\r+worlbank", null, "+weltbank +worlbank");
923     assertQueryEqualsDOA("weltbank \r+worlbank", null, "+weltbank +worlbank");
924     assertQueryEqualsDOA("weltbank \r +worlbank", null, "+weltbank +worlbank");
925
926     assertQueryEqualsDOA("+weltbank\r\n+worlbank", null, "+weltbank +worlbank");
927     assertQueryEqualsDOA("weltbank \r\n+worlbank", null, "+weltbank +worlbank");
928     assertQueryEqualsDOA("weltbank \r\n +worlbank", null, "+weltbank +worlbank");
929     assertQueryEqualsDOA("weltbank \r \n +worlbank", null,
930         "+weltbank +worlbank");
931
932     assertQueryEqualsDOA("+weltbank\t+worlbank", null, "+weltbank +worlbank");
933     assertQueryEqualsDOA("weltbank \t+worlbank", null, "+weltbank +worlbank");
934     assertQueryEqualsDOA("weltbank \t +worlbank", null, "+weltbank +worlbank");
935   }
936
937   public void testSimpleDAO() throws Exception {
938     assertQueryEqualsDOA("term term term", null, "+term +term +term");
939     assertQueryEqualsDOA("term +term term", null, "+term +term +term");
940     assertQueryEqualsDOA("term term +term", null, "+term +term +term");
941     assertQueryEqualsDOA("term +term +term", null, "+term +term +term");
942     assertQueryEqualsDOA("-term term term", null, "-term +term +term");
943   }
944
945   public void testBoost() throws Exception {
946     StandardAnalyzer oneStopAnalyzer = new StandardAnalyzer(TEST_VERSION_CURRENT, Collections.singleton("on"));
947     QueryParserWrapper qp = new QueryParserWrapper("field", oneStopAnalyzer);
948     Query q = qp.parse("on^1.0");
949     assertNotNull(q);
950     q = qp.parse("\"hello\"^2.0");
951     assertNotNull(q);
952     assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
953     q = qp.parse("hello^2.0");
954     assertNotNull(q);
955     assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
956     q = qp.parse("\"on\"^1.0");
957     assertNotNull(q);
958
959     QueryParserWrapper qp2 = new QueryParserWrapper("field",
960         new StandardAnalyzer(TEST_VERSION_CURRENT));
961     q = qp2.parse("the^3");
962     // "the" is a stop word so the result is an empty query:
963     assertNotNull(q);
964     assertEquals("", q.toString());
965     assertEquals(1.0f, q.getBoost(), 0.01f);
966   }
967
968   public void assertParseException(String queryString) throws Exception {
969     try {
970       getQuery(queryString, null);
971     } catch (ParseException expected) {
972       return;
973     }
974     fail("ParseException expected, not thrown");
975   }
976
977   public void testException() throws Exception {
978     assertParseException("\"some phrase");
979     assertParseException("(foo bar");
980     assertParseException("foo bar))");
981     assertParseException("field:term:with:colon some more terms");
982     assertParseException("(sub query)^5.0^2.0 plus more");
983     assertParseException("secret AND illegal) AND access:confidential");
984   }
985
986   public void testCustomQueryParserWildcard() {
987     try {
988       new QPTestParser("contents", new WhitespaceAnalyzer(TEST_VERSION_CURRENT)).parse("a?t");
989       fail("Wildcard queries should not be allowed");
990     } catch (ParseException expected) {
991       // expected exception
992     }
993   }
994
995   public void testCustomQueryParserFuzzy() throws Exception {
996     try {
997       new QPTestParser("contents", new WhitespaceAnalyzer(TEST_VERSION_CURRENT)).parse("xunit~");
998       fail("Fuzzy queries should not be allowed");
999     } catch (ParseException expected) {
1000       // expected exception
1001     }
1002   }
1003
1004   public void testBooleanQuery() throws Exception {
1005     BooleanQuery.setMaxClauseCount(2);
1006     try {
1007       QueryParserWrapper qp = new QueryParserWrapper("field",
1008           new WhitespaceAnalyzer(TEST_VERSION_CURRENT));
1009       qp.parse("one two three");
1010       fail("ParseException expected due to too many boolean clauses");
1011     } catch (ParseException expected) {
1012       // too many boolean clauses, so ParseException is expected
1013     }
1014   }
1015
1016   /**
1017    * This test differs from TestPrecedenceQueryParser
1018    */
1019   public void testPrecedence() throws Exception {
1020     QueryParserWrapper qp = new QueryParserWrapper("field",
1021         new WhitespaceAnalyzer(TEST_VERSION_CURRENT));
1022     Query query1 = qp.parse("A AND B OR C AND D");
1023     Query query2 = qp.parse("+A +B +C +D");
1024
1025     assertEquals(query1, query2);
1026   }
1027
1028   public void testLocalDateFormat() throws IOException, ParseException {
1029
1030     Directory ramDir = newDirectory();
1031     IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(TEST_VERSION_CURRENT), true,
1032         IndexWriter.MaxFieldLength.LIMITED);
1033     addDateDoc("a", 2005, 12, 2, 10, 15, 33, iw);
1034     addDateDoc("b", 2005, 12, 4, 22, 15, 00, iw);
1035     iw.close();
1036     IndexSearcher is = new IndexSearcher(ramDir, true);
1037     assertHits(1, "[12/1/2005 TO 12/3/2005]", is);
1038     assertHits(2, "[12/1/2005 TO 12/4/2005]", is);
1039     assertHits(1, "[12/3/2005 TO 12/4/2005]", is);
1040     assertHits(1, "{12/1/2005 TO 12/3/2005}", is);
1041     assertHits(1, "{12/1/2005 TO 12/4/2005}", is);
1042     assertHits(0, "{12/3/2005 TO 12/4/2005}", is);
1043     is.close();
1044     ramDir.close();
1045   }
1046
1047   public void testStarParsing() throws Exception {
1048     // final int[] type = new int[1];
1049     // QueryParser qp = new QueryParserWrapper("field", new
1050     // WhitespaceAnalyzer()) {
1051     // protected Query getWildcardQuery(String field, String termStr) throws
1052     // ParseException {
1053     // // override error checking of superclass
1054     // type[0]=1;
1055     // return new TermQuery(new Term(field,termStr));
1056     // }
1057     // protected Query getPrefixQuery(String field, String termStr) throws
1058     // ParseException {
1059     // // override error checking of superclass
1060     // type[0]=2;
1061     // return new TermQuery(new Term(field,termStr));
1062     // }
1063     //
1064     // protected Query getFieldQuery(String field, String queryText) throws
1065     // ParseException {
1066     // type[0]=3;
1067     // return super.getFieldQuery(field, queryText);
1068     // }
1069     // };
1070     //
1071     // TermQuery tq;
1072     //
1073     // tq = (TermQuery)qp.parse("foo:zoo*");
1074     // assertEquals("zoo",tq.getTerm().text());
1075     // assertEquals(2,type[0]);
1076     //
1077     // tq = (TermQuery)qp.parse("foo:zoo*^2");
1078     // assertEquals("zoo",tq.getTerm().text());
1079     // assertEquals(2,type[0]);
1080     // assertEquals(tq.getBoost(),2,0);
1081     //
1082     // tq = (TermQuery)qp.parse("foo:*");
1083     // assertEquals("*",tq.getTerm().text());
1084     // assertEquals(1,type[0]); // could be a valid prefix query in the future
1085     // too
1086     //
1087     // tq = (TermQuery)qp.parse("foo:*^2");
1088     // assertEquals("*",tq.getTerm().text());
1089     // assertEquals(1,type[0]);
1090     // assertEquals(tq.getBoost(),2,0);
1091     //
1092     // tq = (TermQuery)qp.parse("*:foo");
1093     // assertEquals("*",tq.getTerm().field());
1094     // assertEquals("foo",tq.getTerm().text());
1095     // assertEquals(3,type[0]);
1096     //
1097     // tq = (TermQuery)qp.parse("*:*");
1098     // assertEquals("*",tq.getTerm().field());
1099     // assertEquals("*",tq.getTerm().text());
1100     // assertEquals(1,type[0]); // could be handled as a prefix query in the
1101     // future
1102     //
1103     // tq = (TermQuery)qp.parse("(*:*)");
1104     // assertEquals("*",tq.getTerm().field());
1105     // assertEquals("*",tq.getTerm().text());
1106     // assertEquals(1,type[0]);
1107
1108   }
1109
1110   public void testStopwords() throws Exception {
1111     QueryParserWrapper qp = new QueryParserWrapper("a", new StopAnalyzer(TEST_VERSION_CURRENT, StopFilter.makeStopSet(TEST_VERSION_CURRENT, "the", "foo")));
1112     Query result = qp.parse("a:the OR a:foo");
1113     assertNotNull("result is null and it shouldn't be", result);
1114     assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery);
1115     assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: "
1116         + 0, ((BooleanQuery) result).clauses().size() == 0);
1117     result = qp.parse("a:woo OR a:the");
1118     assertNotNull("result is null and it shouldn't be", result);
1119     assertTrue("result is not a TermQuery", result instanceof TermQuery);
1120     result = qp
1121         .parse("(fieldX:xxxxx OR fieldy:xxxxxxxx)^2 AND (fieldx:the OR fieldy:foo)");
1122     assertNotNull("result is null and it shouldn't be", result);
1123     assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery);
1124     if (VERBOSE) System.out.println("Result: " + result);
1125     assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: "
1126         + 2, ((BooleanQuery) result).clauses().size() == 2);
1127   }
1128
1129   public void testPositionIncrement() throws Exception {
1130     QueryParserWrapper qp = new QueryParserWrapper("a", new StopAnalyzer(TEST_VERSION_CURRENT, StopFilter.makeStopSet(TEST_VERSION_CURRENT, "the", "in", "are", "this")));
1131     qp.setEnablePositionIncrements(true);
1132     String qtxt = "\"the words in poisitions pos02578 are stopped in this phrasequery\"";
1133     // 0 2 5 7 8
1134     int expectedPositions[] = { 1, 3, 4, 6, 9 };
1135     PhraseQuery pq = (PhraseQuery) qp.parse(qtxt);
1136     // System.out.println("Query text: "+qtxt);
1137     // System.out.println("Result: "+pq);
1138     Term t[] = pq.getTerms();
1139     int pos[] = pq.getPositions();
1140     for (int i = 0; i < t.length; i++) {
1141       // System.out.println(i+". "+t[i]+"  pos: "+pos[i]);
1142       assertEquals("term " + i + " = " + t[i] + " has wrong term-position!",
1143           expectedPositions[i], pos[i]);
1144     }
1145   }
1146
1147   public void testMatchAllDocs() throws Exception {
1148     QueryParserWrapper qp = new QueryParserWrapper("field",
1149         new WhitespaceAnalyzer(TEST_VERSION_CURRENT));
1150     assertEquals(new MatchAllDocsQuery(), qp.parse("*:*"));
1151     assertEquals(new MatchAllDocsQuery(), qp.parse("(*:*)"));
1152     BooleanQuery bq = (BooleanQuery) qp.parse("+*:* -*:*");
1153     assertTrue(bq.getClauses()[0].getQuery() instanceof MatchAllDocsQuery);
1154     assertTrue(bq.getClauses()[1].getQuery() instanceof MatchAllDocsQuery);
1155   }
1156
1157   private void assertHits(int expected, String query, IndexSearcher is)
1158       throws ParseException, IOException {
1159     QueryParserWrapper qp = new QueryParserWrapper("date",
1160         new WhitespaceAnalyzer(TEST_VERSION_CURRENT));
1161     qp.setLocale(Locale.ENGLISH);
1162     Query q = qp.parse(query);
1163     ScoreDoc[] hits = is.search(q, null, 1000).scoreDocs;
1164     assertEquals(expected, hits.length);
1165   }
1166
1167   private void addDateDoc(String content, int year, int month, int day,
1168       int hour, int minute, int second, IndexWriter iw) throws IOException {
1169     Document d = new Document();
1170     d.add(newField("f", content, Field.Store.YES, Field.Index.ANALYZED));
1171     Calendar cal = Calendar.getInstance(Locale.ENGLISH);
1172     cal.set(year, month - 1, day, hour, minute, second);
1173     d.add(newField("date", DateField.dateToString(cal.getTime()),
1174         Field.Store.YES, Field.Index.NOT_ANALYZED));
1175     iw.addDocument(d);
1176   }
1177
1178   @Override
1179   public void tearDown() throws Exception {
1180     BooleanQuery.setMaxClauseCount(originalMaxClauses);
1181     super.tearDown();
1182   }
1183
1184 }