/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.lucene.queryparser.flexible.standard; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.MockAnalyzer; import org.apache.lucene.analysis.MockTokenizer; import org.apache.lucene.document.DateTools.Resolution; import org.apache.lucene.index.Term; import org.apache.lucene.queryparser.flexible.core.QueryNodeException; import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler; import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler.Operator; import org.apache.lucene.queryparser.util.QueryParserTestBase; import org.apache.lucene.search.BooleanClause; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermQuery; import org.apache.lucene.search.WildcardQuery; /** * Tests QueryParser. */ public class TestStandardQP extends QueryParserTestBase { public StandardQueryParser getParser(Analyzer a) throws Exception { if (a == null) a = new MockAnalyzer(random(), MockTokenizer.SIMPLE, true); StandardQueryParser qp = new StandardQueryParser(a); qp.setDefaultOperator(Operator.OR); return qp; } public Query parse(String query, StandardQueryParser qp) throws Exception { return qp.parse(query, getDefaultField()); } @Override public CommonQueryParserConfiguration getParserConfig(Analyzer a) throws Exception { return getParser(a); } @Override public Query getQuery(String query, CommonQueryParserConfiguration cqpC) throws Exception { assert cqpC != null : "Parameter must not be null"; assert (cqpC instanceof StandardQueryParser) : "Parameter must be instance of StandardQueryParser"; StandardQueryParser qp = (StandardQueryParser) cqpC; return parse(query, qp); } @Override public Query getQuery(String query, Analyzer a) throws Exception { return parse(query, getParser(a)); } @Override public boolean isQueryParserException(Exception exception) { return exception instanceof QueryNodeException; } @Override public void setDefaultOperatorOR(CommonQueryParserConfiguration cqpC) { assert (cqpC instanceof StandardQueryParser); StandardQueryParser qp = (StandardQueryParser) cqpC; qp.setDefaultOperator(Operator.OR); } @Override public void setDefaultOperatorAND(CommonQueryParserConfiguration cqpC) { assert (cqpC instanceof StandardQueryParser); StandardQueryParser qp = (StandardQueryParser) cqpC; qp.setDefaultOperator(Operator.AND); } @Override public void setAutoGeneratePhraseQueries(CommonQueryParserConfiguration cqpC, boolean value) { throw new UnsupportedOperationException(); } @Override public void setDateResolution(CommonQueryParserConfiguration cqpC, CharSequence field, Resolution value) { assert (cqpC instanceof StandardQueryParser); StandardQueryParser qp = (StandardQueryParser) cqpC; qp.getDateResolutionMap().put(field, value); } @Override public void testOperatorVsWhitespace() throws Exception { // LUCENE-2566 is not implemented for StandardQueryParser // TODO implement LUCENE-2566 and remove this (override)method Analyzer a = new Analyzer() { @Override public TokenStreamComponents createComponents(String fieldName) { return new TokenStreamComponents(new MockTokenizer(MockTokenizer.WHITESPACE, false)); } }; assertQueryEquals("a - b", a, "a -b"); assertQueryEquals("a + b", a, "a +b"); assertQueryEquals("a ! b", a, "a -b"); } @Override public void testRangeWithPhrase() throws Exception { // StandardSyntaxParser does not differentiate between a term and a // one-term-phrase in a range query. // Is this an issue? Should StandardSyntaxParser mark the text as // wasEscaped=true ? assertQueryEquals("[\\* TO \"*\"]", null, "[\\* TO *]"); } @Override public void testEscapedVsQuestionMarkAsWildcard() throws Exception { Analyzer a = new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false); assertQueryEquals("a:b\\-?c", a, "a:b-?c"); assertQueryEquals("a:b\\+?c", a, "a:b+?c"); assertQueryEquals("a:b\\:?c", a, "a:b:?c"); assertQueryEquals("a:b\\\\?c", a, "a:b\\?c"); } @Override public void testEscapedWildcard() throws Exception { CommonQueryParserConfiguration qp = getParserConfig( new MockAnalyzer(random(), MockTokenizer.WHITESPACE, false)); WildcardQuery q = new WildcardQuery(new Term("field", "foo?ba?r"));//TODO not correct!! assertEquals(q, getQuery("foo\\?ba?r", qp)); } @Override public void testAutoGeneratePhraseQueriesOn() throws Exception { expectThrows(UnsupportedOperationException.class, () -> { setAutoGeneratePhraseQueries(getParser(null), true); super.testAutoGeneratePhraseQueriesOn(); }); } @Override public void testStarParsing() throws Exception { } @Override public void testDefaultOperator() throws Exception { StandardQueryParser qp = getParser(new MockAnalyzer(random())); // make sure OR is the default: assertEquals(StandardQueryConfigHandler.Operator.OR, qp.getDefaultOperator()); setDefaultOperatorAND(qp); assertEquals(StandardQueryConfigHandler.Operator.AND, qp.getDefaultOperator()); setDefaultOperatorOR(qp); assertEquals(StandardQueryConfigHandler.Operator.OR, qp.getDefaultOperator()); } @Override public void testNewFieldQuery() throws Exception { /** ordinary behavior, synonyms form uncoordinated boolean query */ StandardQueryParser dumb = getParser(new Analyzer1()); BooleanQuery.Builder expanded = new BooleanQuery.Builder(); expanded.add(new TermQuery(new Term("field", "dogs")), BooleanClause.Occur.SHOULD); expanded.add(new TermQuery(new Term("field", "dog")), BooleanClause.Occur.SHOULD); assertEquals(expanded.build(), dumb.parse("\"dogs\"","field")); /** even with the phrase operator the behavior is the same */ assertEquals(expanded.build(), dumb.parse("dogs","field")); /** * custom behavior, the synonyms are expanded, unless you use quote operator */ //TODO test something like "SmartQueryParser()" } // TODO: Remove this specialization once the flexible standard parser gets multi-word synonym support @Override public void testQPA() throws Exception { super.testQPA(); assertQueryEquals("term phrase term", qpAnalyzer, "term (phrase1 phrase2) term"); CommonQueryParserConfiguration cqpc = getParserConfig(qpAnalyzer); setDefaultOperatorAND(cqpc); assertQueryEquals(cqpc, "field", "term phrase term", "+term +(+phrase1 +phrase2) +term"); } }