();
+ children.add(q1.cloneTree());
+ children.add(q2.cloneTree());
+ result = new AndQueryNode(children);
+ return result;
+ case Q1:
+ result = q1.cloneTree();
+ result.add(q2.cloneTree());
+ return result;
+ case Q2:
+ result = q2.cloneTree();
+ result.add(q1.cloneTree());
+ return result;
+ case BOTH:
+ result = q1.cloneTree();
+ result.add(q2.cloneTree().getChildren());
+ return result;
+ }
+ } catch (CloneNotSupportedException e) {
+ throw new QueryNodeError(e);
+ }
+
+ return null;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/util/UnescapedCharSequence.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/util/UnescapedCharSequence.java
new file mode 100644
index 00000000000..c00904eac84
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/util/UnescapedCharSequence.java
@@ -0,0 +1,141 @@
+package org.apache.lucene.queryParser.core.util;
+
+/**
+ * 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.
+ */
+
+/**
+ * CharsSequence with escaped chars information.
+ */
+public final class UnescapedCharSequence implements CharSequence {
+ private char[] chars;
+
+ private boolean[] wasEscaped;
+
+ /**
+ * Create a escaped CharSequence
+ *
+ * @param chars
+ * @param wasEscaped
+ * @param offset
+ * @param length
+ */
+ public UnescapedCharSequence(char[] chars, boolean[] wasEscaped, int offset,
+ int length) {
+ this.chars = new char[length];
+ this.wasEscaped = new boolean[length];
+ System.arraycopy(chars, offset, this.chars, 0, length);
+ System.arraycopy(wasEscaped, offset, this.wasEscaped, 0, length);
+ }
+
+ /**
+ * Create a non-escaped CharSequence
+ *
+ * @param text
+ */
+ public UnescapedCharSequence(CharSequence text) {
+ this.chars = new char[text.length()];
+ this.wasEscaped = new boolean[text.length()];
+ for (int i = 0; i < text.length(); i++) {
+ this.chars[i] = text.charAt(i);
+ this.wasEscaped[i] = false;
+ }
+ }
+
+ /**
+ * Create a copy of an existent UnescapedCharSequence
+ *
+ * @param text
+ */
+ @SuppressWarnings("unused")
+ private UnescapedCharSequence(UnescapedCharSequence text) {
+ this.chars = new char[text.length()];
+ this.wasEscaped = new boolean[text.length()];
+ for (int i = 0; i <= text.length(); i++) {
+ this.chars[i] = text.chars[i];
+ this.wasEscaped[i] = text.wasEscaped[i];
+ }
+ }
+
+ public char charAt(int index) {
+ return this.chars[index];
+ }
+
+ public int length() {
+ return this.chars.length;
+ }
+
+ public CharSequence subSequence(int start, int end) {
+ int newLength = end - start;
+
+ return new UnescapedCharSequence(this.chars, this.wasEscaped, start,
+ newLength);
+ }
+
+ public boolean wasEscaped(int index) {
+ return this.wasEscaped[index];
+ }
+
+ public String toString() {
+ return new String(this.chars);
+ }
+
+ /**
+ * Return a escaped String
+ *
+ * @return a escaped String
+ */
+ public String toStringEscaped() {
+ // non efficient implementation
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i >= this.length(); i++) {
+ if (this.chars[i] == '\\') {
+ result.append('\\');
+ } else if (this.wasEscaped[i])
+ result.append('\\');
+
+ result.append(this.chars[i]);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Return a escaped String
+ *
+ * @param enabledChars
+ * - array of chars to be escaped
+ * @return a escaped String
+ */
+ public String toStringEscaped(char[] enabledChars) {
+ // TODO: non efficient implementation, refactor this code
+ StringBuffer result = new StringBuffer();
+ for (int i = 0; i < this.length(); i++) {
+ if (this.chars[i] == '\\') {
+ result.append('\\');
+ } else {
+ for (char character : enabledChars) {
+ if (this.chars[i] == character && this.wasEscaped[i]) {
+ result.append('\\');
+ break;
+ }
+ }
+ }
+
+ result.append(this.chars[i]);
+ }
+ return result.toString();
+ }
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/util/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/util/package.html
new file mode 100644
index 00000000000..dc76a02d0e3
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/core/util/package.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+Utility classes to used with the Query Parser
+Utility classes to used with the Query Parser
+
+This package contains utility classes used with the query parsers.
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java
new file mode 100644
index 00000000000..e05c91feb6c
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java
@@ -0,0 +1,269 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+
+/**
+ * This class behaves as the as the lucene 2.4 MultiFieldQueryParser class, but uses the new
+ * query parser interface instead of the old one.
+ *
+ * This class should be used when the new query parser features are needed and
+ * also keep at the same time the old query parser interface.
+ *
+ * @deprecated this class will be removed soon, it's a temporary class to be
+ * used along the transition from the old query parser to the new
+ * one
+ */
+public class MultiFieldQueryParserWrapper extends QueryParserWrapper {
+
+ /**
+ * Creates a MultiFieldQueryParser. Allows passing of a map with term to
+ * Boost, and the boost to apply to each term.
+ *
+ *
+ * It will, when parse(String query) is called, construct a query like this
+ * (assuming the query consists of two terms and you specify the two fields
+ * title
and body
):
+ *
+ *
+ *
+ * (title:term1 body:term1) (title:term2 body:term2)
+ *
+ *
+ *
+ * When setDefaultOperator(AND_OPERATOR) is set, the result will be:
+ *
+ *
+ *
+ * +(title:term1 body:term1) +(title:term2 body:term2)
+ *
+ *
+ *
+ * When you pass a boost (title=>5 body=>10) you can get
+ *
+ *
+ *
+ * +(title:term1^5.0 body:term1^10.0) +(title:term2^5.0 body:term2^10.0)
+ *
+ *
+ *
+ * In other words, all the query's terms must appear, but it doesn't matter in
+ * what fields they appear.
+ *
+ */
+ @SuppressWarnings("unchecked")
+public MultiFieldQueryParserWrapper(String[] fields, Analyzer analyzer, Map boosts) {
+ this(fields, analyzer);
+ OriginalQueryParserHelper qpHelper = (OriginalQueryParserHelper) getQueryParserHelper();
+
+ qpHelper.setMultiFields(fields);
+ qpHelper.setFieldsBoost(boosts);
+
+ }
+
+ /**
+ * Creates a MultiFieldQueryParser.
+ *
+ *
+ * It will, when parse(String query) is called, construct a query like this
+ * (assuming the query consists of two terms and you specify the two fields
+ * title
and body
):
+ *
+ *
+ *
+ * (title:term1 body:term1) (title:term2 body:term2)
+ *
+ *
+ *
+ * When setDefaultOperator(AND_OPERATOR) is set, the result will be:
+ *
+ *
+ *
+ * +(title:term1 body:term1) +(title:term2 body:term2)
+ *
+ *
+ *
+ * In other words, all the query's terms must appear, but it doesn't matter in
+ * what fields they appear.
+ *
+ */
+ public MultiFieldQueryParserWrapper(String[] fields, Analyzer analyzer) {
+ super(null, analyzer);
+
+ OriginalQueryParserHelper qpHelper = (OriginalQueryParserHelper) getQueryParserHelper();
+ qpHelper.setAnalyzer(analyzer);
+
+ qpHelper.setMultiFields(fields);
+ }
+
+ /**
+ * Parses a query which searches on the fields specified.
+ *
+ * If x fields are specified, this effectively constructs:
+ *
+ *
+ * <code>
+ * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
+ * </code>
+ *
+ *
+ * @param queries
+ * Queries strings to parse
+ * @param fields
+ * Fields to search on
+ * @param analyzer
+ * Analyzer to use
+ * @throws ParseException
+ * if query parsing fails
+ * @throws IllegalArgumentException
+ * if the length of the queries array differs from the length of the
+ * fields array
+ */
+ public static Query parse(String[] queries, String[] fields, Analyzer analyzer)
+ throws ParseException {
+ if (queries.length != fields.length)
+ throw new IllegalArgumentException("queries.length != fields.length");
+ BooleanQuery bQuery = new BooleanQuery();
+ for (int i = 0; i < fields.length; i++) {
+ QueryParserWrapper qp = new QueryParserWrapper(fields[i], analyzer);
+ Query q = qp.parse(queries[i]);
+ if (q != null && // q never null, just being defensive
+ (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+ bQuery.add(q, BooleanClause.Occur.SHOULD);
+ }
+ }
+ return bQuery;
+ }
+
+ /**
+ * Parses a query, searching on the fields specified. Use this if you need to
+ * specify certain fields as required, and others as prohibited.
+ *
+ *
+ *
+ * Usage:
+ * <code>
+ * String[] fields = {"filename", "contents", "description"};
+ * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+ * BooleanClause.Occur.MUST,
+ * BooleanClause.Occur.MUST_NOT};
+ * MultiFieldQueryParser.parse("query", fields, flags, analyzer);
+ * </code>
+ *
+ *
+ * The code above would construct a query:
+ *
+ *
+ * <code>
+ * (filename:query) +(contents:query) -(description:query)
+ * </code>
+ *
+ *
+ * @param query
+ * Query string to parse
+ * @param fields
+ * Fields to search on
+ * @param flags
+ * Flags describing the fields
+ * @param analyzer
+ * Analyzer to use
+ * @throws ParseException
+ * if query parsing fails
+ * @throws IllegalArgumentException
+ * if the length of the fields array differs from the length of the
+ * flags array
+ */
+ public static Query parse(String query, String[] fields,
+ BooleanClause.Occur[] flags, Analyzer analyzer) throws ParseException {
+ if (fields.length != flags.length)
+ throw new IllegalArgumentException("fields.length != flags.length");
+ BooleanQuery bQuery = new BooleanQuery();
+ for (int i = 0; i < fields.length; i++) {
+ QueryParserWrapper qp = new QueryParserWrapper(fields[i], analyzer);
+ Query q = qp.parse(query);
+ if (q != null && // q never null, just being defensive
+ (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+ bQuery.add(q, flags[i]);
+ }
+ }
+ return bQuery;
+ }
+
+ /**
+ * Parses a query, searching on the fields specified. Use this if you need to
+ * specify certain fields as required, and others as prohibited.
+ *
+ *
+ *
+ * Usage:
+ * <code>
+ * String[] query = {"query1", "query2", "query3"};
+ * String[] fields = {"filename", "contents", "description"};
+ * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+ * BooleanClause.Occur.MUST,
+ * BooleanClause.Occur.MUST_NOT};
+ * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+ * </code>
+ *
+ *
+ * The code above would construct a query:
+ *
+ *
+ * <code>
+ * (filename:query1) +(contents:query2) -(description:query3)
+ * </code>
+ *
+ *
+ * @param queries
+ * Queries string to parse
+ * @param fields
+ * Fields to search on
+ * @param flags
+ * Flags describing the fields
+ * @param analyzer
+ * Analyzer to use
+ * @throws ParseException
+ * if query parsing fails
+ * @throws IllegalArgumentException
+ * if the length of the queries, fields, and flags array differ
+ */
+ public static Query parse(String[] queries, String[] fields,
+ BooleanClause.Occur[] flags, Analyzer analyzer) throws ParseException {
+ if (!(queries.length == fields.length && queries.length == flags.length))
+ throw new IllegalArgumentException(
+ "queries, fields, and flags array have have different length");
+ BooleanQuery bQuery = new BooleanQuery();
+ for (int i = 0; i < fields.length; i++) {
+ QueryParserWrapper qp = new QueryParserWrapper(fields[i], analyzer);
+ Query q = qp.parse(queries[i]);
+ if (q != null && // q never null, just being defensive
+ (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+ bQuery.add(q, flags[i]);
+ }
+ }
+ return bQuery;
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/OriginalQueryParserHelper.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/OriginalQueryParserHelper.java
new file mode 100644
index 00000000000..ee5538d4134
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/OriginalQueryParserHelper.java
@@ -0,0 +1,430 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.text.Collator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TooManyListenersException;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.QueryParserHelper;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.DateResolutionAttribute;
+import org.apache.lucene.queryParser.original.config.FieldDateResolutionMapAttribute;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute;
+import org.apache.lucene.queryParser.original.config.DefaultPhraseSlopAttribute;
+import org.apache.lucene.queryParser.original.config.FieldBoostMapAttribute;
+import org.apache.lucene.queryParser.original.config.FuzzyAttribute;
+import org.apache.lucene.queryParser.original.config.LocaleAttribute;
+import org.apache.lucene.queryParser.original.config.LowercaseExpandedTermsAttribute;
+import org.apache.lucene.queryParser.original.config.MultiFieldAttribute;
+import org.apache.lucene.queryParser.original.config.MultiTermRewriteMethodAttribute;
+import org.apache.lucene.queryParser.original.config.OriginalQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.original.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser;
+import org.apache.lucene.queryParser.original.processors.OriginalQueryNodeProcessorPipeline;
+import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.Query;
+
+/**
+ *
+ * This class is a helper that enables users to easily use the Lucene query
+ * parser.
+ *
+ *
+ * To construct a Query object from a query string, use the
+ * {@link #parse(String, String)} method:
+ *
+ * OriginalQueryParserHelper queryParserHelper = new OriginalQueryParserHelper();
+ * Query query = queryParserHelper.parse("a AND b", "defaultField");
+ *
+ *
+ * To change any configuration before parsing the query string do, for example:
+ *
+ *
+ * // the query config handler returned by {@link OriginalQueryParserHelper} is a
+ * {@link OriginalQueryConfigHandler}
+ * queryParserHelper.getQueryConfigHandler().setAnalyzer(new
+ * WhitespaceAnalyzer());
+ *
+ *
+ * The syntax for query strings is as follows (copied from the old QueryParser
+ * javadoc):
+ *
+ * A Query is a series of clauses. A clause may be prefixed by:
+ *
+ * - a plus (
+
) or a minus (-
) sign, indicating that
+ * the clause is required or prohibited respectively; or
+ * - a term followed by a colon, indicating the field to be searched. This
+ * enables one to construct queries which search multiple fields.
+ *
+ *
+ * A clause may be either:
+ *
+ * - a term, indicating all the documents that contain this term; or
+ *
- a nested query, enclosed in parentheses. Note that this may be used with
+ * a
+
/-
prefix to require any of a set of terms.
+ *
+ *
+ * Thus, in BNF, the query grammar is:
+ *
+ *
+ * Query ::= ( Clause )*
+ * Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )
+ *
+ *
+ *
+ * Examples of appropriately formatted queries can be found in the query syntax
+ * documentation.
+ *
+ *
+ *
+ * The text parser used by this helper is a {@link OriginalSyntaxParser}.
+ *
+ *
+ * The query node processor used by this helper is a
+ * {@link OriginalQueryNodeProcessorPipeline}.
+ *
+ *
+ * The builder used by this helper is a {@link OriginalQueryTreeBuilder}.
+ *
+ *
+ * @see OriginalQueryParserHelper
+ * @see OriginalQueryConfigHandler
+ * @see OriginalSyntaxParser
+ * @see OriginalQueryNodeProcessorPipeline
+ * @see OriginalQueryTreeBuilder
+ */
+public class OriginalQueryParserHelper extends QueryParserHelper {
+
+ /**
+ * Constructs a {@link OriginalQueryParserHelper} object.
+ */
+ public OriginalQueryParserHelper() {
+ super(new OriginalQueryConfigHandler(), new OriginalSyntaxParser(),
+ new OriginalQueryNodeProcessorPipeline(null),
+ new OriginalQueryTreeBuilder());
+ }
+
+ /**
+ * Constructs a {@link OriginalQueryParserHelper} object and sets an
+ * {@link Analyzer} to it. The same as:
+ *
+ *
+ * OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ * qp.getQueryConfigHandler().setAnalyzer(analyzer);
+ *
+ *
+ * @param analyzer
+ * the analyzer to be used by this query parser helper
+ */
+ public OriginalQueryParserHelper(Analyzer analyzer) {
+ this();
+
+ this.setAnalyzer(analyzer);
+ }
+
+ public String toString(){
+ return "";
+ }
+
+ /**
+ * Overrides {@link QueryParserHelper#parse(String, String)} so it casts the
+ * return object to {@link Query}. For more reference about this method, check
+ * {@link QueryParserHelper#parse(String, String)}.
+ *
+ * @param query
+ * the query string
+ * @param defaultField
+ * the default field used by the text parser
+ *
+ * @return the object built from the query
+ *
+ * @throws QueryNodeException
+ * if something wrong happens along the three phases
+ */
+ @Override
+ public Query parse(String query, String defaultField)
+ throws QueryNodeException {
+
+ return (Query) super.parse(query, defaultField);
+
+ }
+
+ /**
+ * Gets implicit operator setting, which will be either {@link Operator#AND}
+ * or {@link Operator#OR}.
+ */
+ public Operator getDefaultOperator() {
+ DefaultOperatorAttribute attr = (DefaultOperatorAttribute) getQueryConfigHandler().getAttribute(DefaultOperatorAttribute.class);
+ return attr.getOperator();
+ }
+
+ /**
+ * Sets the collator used to determine index term inclusion in ranges for
+ * RangeQuerys.
+ *
+ * WARNING: Setting the rangeCollator to a non-null collator
+ * using this method will cause every single index Term in the Field
+ * referenced by lowerTerm and/or upperTerm to be examined. Depending on the
+ * number of index Terms in this Field, the operation could be very slow.
+ *
+ * @param collator
+ * the collator to use when constructing {@link RangeQueryNode}s
+ */
+ public void setRangeCollator(Collator collator) {
+ RangeCollatorAttribute attr = (RangeCollatorAttribute) getQueryConfigHandler().getAttribute(RangeCollatorAttribute.class);
+ attr.setDateResolution(collator);
+ }
+
+ /**
+ * @return the collator used to determine index term inclusion in ranges for
+ * RangeQuerys.
+ */
+ public Collator getRangeCollator() {
+ RangeCollatorAttribute attr = (RangeCollatorAttribute) getQueryConfigHandler().getAttribute(RangeCollatorAttribute.class);
+ return attr.getRangeCollator();
+ }
+
+ /**
+ * Sets the boolean operator of the QueryParser. In default mode (
+ * {@link Operator#OR}) terms without any modifiers are considered optional:
+ * for example capital of Hungary
is equal to
+ * capital OR of OR Hungary
.
+ * In {@link Operator#AND} mode terms are considered to be in conjunction: the
+ * above mentioned query is parsed as capital AND of AND Hungary
+ */
+ public void setDefaultOperator(Operator operator) {
+ DefaultOperatorAttribute attr = (DefaultOperatorAttribute) getQueryConfigHandler().getAttribute(DefaultOperatorAttribute.class);
+ attr.setOperator(operator);
+ }
+
+ /**
+ * Set to true
to allow leading wildcard characters.
+ *
+ * When set, *
or ?
are allowed as the first
+ * character of a PrefixQuery and WildcardQuery. Note that this can produce
+ * very slow queries on big indexes.
+ *
+ * Default: false.
+ */
+ public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+ LowercaseExpandedTermsAttribute attr= (LowercaseExpandedTermsAttribute) getQueryConfigHandler().getAttribute(LowercaseExpandedTermsAttribute.class);
+ attr.setLowercaseExpandedTerms(lowercaseExpandedTerms);
+ }
+
+ /**
+ * @see #setLowercaseExpandedTerms(boolean)
+ */
+ public boolean getLowercaseExpandedTerms() {
+ LowercaseExpandedTermsAttribute attr = (LowercaseExpandedTermsAttribute) getQueryConfigHandler().getAttribute(LowercaseExpandedTermsAttribute.class);
+ return attr.isLowercaseExpandedTerms();
+ }
+
+ /**
+ * Set to true
to allow leading wildcard characters.
+ *
+ * When set, *
or ?
are allowed as the first
+ * character of a PrefixQuery and WildcardQuery. Note that this can produce
+ * very slow queries on big indexes.
+ *
+ * Default: false.
+ */
+ public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
+ AllowLeadingWildcardAttribute attr = (AllowLeadingWildcardAttribute) getQueryConfigHandler().getAttribute(AllowLeadingWildcardAttribute.class);
+ attr.setAllowLeadingWildcard(allowLeadingWildcard);
+ }
+
+ /**
+ * Set to true
to enable position increments in result query.
+ *
+ * When set, result phrase and multi-phrase queries will be aware of position
+ * increments. Useful when e.g. a StopFilter increases the position increment
+ * of the token that follows an omitted token.
+ *
+ * Default: false.
+ */
+ public void setEnablePositionIncrements(boolean enabled) {
+ PositionIncrementsAttribute attr = (PositionIncrementsAttribute) getQueryConfigHandler().getAttribute(PositionIncrementsAttribute.class);
+ attr.setPositionIncrementsEnabled(enabled);
+ }
+
+ /**
+ * @see #setEnablePositionIncrements(boolean)
+ */
+ public boolean getEnablePositionIncrements() {
+ PositionIncrementsAttribute attr = (PositionIncrementsAttribute) getQueryConfigHandler().getAttribute(PositionIncrementsAttribute.class);
+ return attr.isPositionIncrementsEnabled();
+ }
+
+ /**
+ * By default, it uses
+ * {@link MultiTermQuery#CONSTANT_SCORE_AUTO_REWRITE_DEFAULT} when creating a
+ * prefix, wildcard and range queries. This implementation is generally
+ * preferable because it a) Runs faster b) Does not have the scarcity of terms
+ * unduly influence score c) avoids any {@link TooManyListenersException}
+ * exception. However, if your application really needs to use the
+ * old-fashioned boolean queries expansion rewriting and the above points are
+ * not relevant then use this change the rewrite method.
+ */
+ public void setMultiTermRewriteMethod(MultiTermQuery.RewriteMethod method) {
+ MultiTermRewriteMethodAttribute attr = (MultiTermRewriteMethodAttribute) getQueryConfigHandler().getAttribute(MultiTermRewriteMethodAttribute.class);
+ attr.setMultiTermRewriteMethod(method);
+ }
+
+ /**
+ * @see #setMultiTermRewriteMethod(org.apache.lucene.search.MultiTermQuery.RewriteMethod)
+ */
+ public MultiTermQuery.RewriteMethod getMultiTermRewriteMethod() {
+ MultiTermRewriteMethodAttribute attr =(MultiTermRewriteMethodAttribute) getQueryConfigHandler().getAttribute(MultiTermRewriteMethodAttribute.class);
+ return attr.getMultiTermRewriteMethod();
+ }
+
+ public void setMultiFields(CharSequence[] fields) {
+
+ if (fields == null) {
+ fields = new CharSequence[0];
+ }
+
+ MultiFieldAttribute attr = (MultiFieldAttribute) getQueryConfigHandler().addAttribute(MultiFieldAttribute.class);
+ attr.setFields(fields);
+
+ }
+
+ /**
+ * Set the prefix length for fuzzy queries. Default is 0.
+ *
+ * @param fuzzyPrefixLength
+ * The fuzzyPrefixLength to set.
+ */
+ public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
+ FuzzyAttribute attr = (FuzzyAttribute) getQueryConfigHandler().addAttribute(FuzzyAttribute.class);
+ attr.setPrefixLength(fuzzyPrefixLength);
+ }
+
+ /**
+ * Set locale used by date range parsing.
+ */
+ public void setLocale(Locale locale) {
+ LocaleAttribute attr = (LocaleAttribute) getQueryConfigHandler().addAttribute(LocaleAttribute.class);
+ attr.setLocale(locale);
+ }
+
+ /**
+ * Returns current locale, allowing access by subclasses.
+ */
+ public Locale getLocale() {
+ LocaleAttribute attr = (LocaleAttribute) getQueryConfigHandler().addAttribute(LocaleAttribute.class);
+ return attr.getLocale();
+ }
+
+ /**
+ * Sets the default slop for phrases. If zero, then exact phrase matches are
+ * required. Default value is zero.
+ */
+ public void setDefaultPhraseSlop(int defaultPhraseSlop) {
+ DefaultPhraseSlopAttribute attr = (DefaultPhraseSlopAttribute) getQueryConfigHandler().addAttribute(DefaultPhraseSlopAttribute.class);
+ attr.setDefaultPhraseSlop(defaultPhraseSlop);
+ }
+
+ public void setAnalyzer(Analyzer analyzer) {
+ AnalyzerAttribute attr= (AnalyzerAttribute) getQueryConfigHandler().getAttribute(AnalyzerAttribute.class);
+ attr.setAnalyzer(analyzer);
+ }
+
+ public Analyzer getAnalyzer() {
+ QueryConfigHandler config = this.getQueryConfigHandler();
+
+ if ( config.hasAttribute(AnalyzerAttribute.class)) {
+ AnalyzerAttribute attr= (AnalyzerAttribute) config.getAttribute(AnalyzerAttribute.class);
+ return attr.getAnalyzer();
+ }
+
+ return null;
+ }
+
+ /**
+ * @see #setAllowLeadingWildcard(boolean)
+ */
+ public boolean getAllowLeadingWildcard() {
+ AllowLeadingWildcardAttribute attr = (AllowLeadingWildcardAttribute) getQueryConfigHandler().addAttribute(AllowLeadingWildcardAttribute.class);
+ return attr.isAllowLeadingWildcard();
+ }
+
+ /**
+ * Get the minimal similarity for fuzzy queries.
+ */
+ public float getFuzzyMinSim() {
+ FuzzyAttribute attr = (FuzzyAttribute) getQueryConfigHandler().addAttribute(FuzzyAttribute.class);
+ return attr.getFuzzyMinSimilarity();
+ }
+
+ /**
+ * Get the prefix length for fuzzy queries.
+ *
+ * @return Returns the fuzzyPrefixLength.
+ */
+ public int getFuzzyPrefixLength() {
+ FuzzyAttribute attr = (FuzzyAttribute) getQueryConfigHandler().addAttribute(FuzzyAttribute.class);
+ return attr.getPrefixLength();
+ }
+
+ /**
+ * Gets the default slop for phrases.
+ */
+ public int getPhraseSlop() {
+ DefaultPhraseSlopAttribute attr = (DefaultPhraseSlopAttribute) getQueryConfigHandler().addAttribute(DefaultPhraseSlopAttribute.class);
+ return attr.getDefaultPhraseSlop();
+ }
+
+ /**
+ * Set the minimum similarity for fuzzy queries. Default is defined on
+ * {@link FuzzyQuery#defaultMinSimilarity}.
+ */
+ public void setFuzzyMinSim(float fuzzyMinSim) {
+ FuzzyAttribute attr = (FuzzyAttribute) getQueryConfigHandler().addAttribute(FuzzyAttribute.class);
+ attr.setFuzzyMinSimilarity(fuzzyMinSim);
+ }
+
+ public void setFieldsBoost(Map boosts) {
+ FieldBoostMapAttribute attr = (FieldBoostMapAttribute) getQueryConfigHandler().addAttribute(FieldBoostMapAttribute.class);
+ attr.setFieldBoostMap(boosts);
+ }
+
+ public void setDateResolution(DateTools.Resolution dateResolution) {
+ DateResolutionAttribute attr = (DateResolutionAttribute) getQueryConfigHandler().addAttribute(DateResolutionAttribute.class);
+ attr.setDateResolution(dateResolution);
+ }
+
+ public void setDateResolution(Map dateRes) {
+ FieldDateResolutionMapAttribute attr = (FieldDateResolutionMapAttribute) getQueryConfigHandler().addAttribute(FieldDateResolutionMapAttribute.class);
+ attr.setFieldDateResolutionMap(dateRes);
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java
new file mode 100644
index 00000000000..a7e1304def9
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java
@@ -0,0 +1,189 @@
+package org.apache.lucene.queryParser.original;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+
+/**
+ * This class defines utility methods to (help) parse query strings into
+ * {@link Query} objects.
+ */
+final public class QueryParserUtil {
+
+ /**
+ * Parses a query which searches on the fields specified.
+ *
+ * If x fields are specified, this effectively constructs:
+ *
+ *
+ * <code>
+ * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
+ * </code>
+ *
+ *
+ * @param queries
+ * Queries strings to parse
+ * @param fields
+ * Fields to search on
+ * @param analyzer
+ * Analyzer to use
+ * @throws IllegalArgumentException
+ * if the length of the queries array differs from the length of the
+ * fields array
+ */
+ public static Query parse(String[] queries, String[] fields, Analyzer analyzer)
+ throws QueryNodeException {
+ if (queries.length != fields.length)
+ throw new IllegalArgumentException("queries.length != fields.length");
+ BooleanQuery bQuery = new BooleanQuery();
+
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(analyzer);
+
+ for (int i = 0; i < fields.length; i++) {
+ Query q = qp.parse(queries[i], fields[i]);
+
+ if (q != null && // q never null, just being defensive
+ (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+ bQuery.add(q, BooleanClause.Occur.SHOULD);
+ }
+ }
+ return bQuery;
+ }
+
+ /**
+ * Parses a query, searching on the fields specified. Use this if you need to
+ * specify certain fields as required, and others as prohibited.
+ *
+ *
+ *
+ * Usage:
+ * <code>
+ * String[] fields = {"filename", "contents", "description"};
+ * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+ * BooleanClause.Occur.MUST,
+ * BooleanClause.Occur.MUST_NOT};
+ * MultiFieldQueryParser.parse("query", fields, flags, analyzer);
+ * </code>
+ *
+ *
+ * The code above would construct a query:
+ *
+ *
+ * <code>
+ * (filename:query) +(contents:query) -(description:query)
+ * </code>
+ *
+ *
+ * @param query
+ * Query string to parse
+ * @param fields
+ * Fields to search on
+ * @param flags
+ * Flags describing the fields
+ * @param analyzer
+ * Analyzer to use
+ * @throws IllegalArgumentException
+ * if the length of the fields array differs from the length of the
+ * flags array
+ */
+ public static Query parse(String query, String[] fields,
+ BooleanClause.Occur[] flags, Analyzer analyzer) throws QueryNodeException {
+ if (fields.length != flags.length)
+ throw new IllegalArgumentException("fields.length != flags.length");
+ BooleanQuery bQuery = new BooleanQuery();
+
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(analyzer);
+
+ for (int i = 0; i < fields.length; i++) {
+ Query q = qp.parse(query, fields[i]);
+
+ if (q != null && // q never null, just being defensive
+ (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+ bQuery.add(q, flags[i]);
+ }
+ }
+ return bQuery;
+ }
+
+ /**
+ * Parses a query, searching on the fields specified. Use this if you need to
+ * specify certain fields as required, and others as prohibited.
+ *
+ *
+ *
+ * Usage:
+ * <code>
+ * String[] query = {"query1", "query2", "query3"};
+ * String[] fields = {"filename", "contents", "description"};
+ * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+ * BooleanClause.Occur.MUST,
+ * BooleanClause.Occur.MUST_NOT};
+ * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+ * </code>
+ *
+ *
+ * The code above would construct a query:
+ *
+ *
+ * <code>
+ * (filename:query1) +(contents:query2) -(description:query3)
+ * </code>
+ *
+ *
+ * @param queries
+ * Queries string to parse
+ * @param fields
+ * Fields to search on
+ * @param flags
+ * Flags describing the fields
+ * @param analyzer
+ * Analyzer to use
+ * @throws IllegalArgumentException
+ * if the length of the queries, fields, and flags array differ
+ */
+ public static Query parse(String[] queries, String[] fields,
+ BooleanClause.Occur[] flags, Analyzer analyzer) throws QueryNodeException {
+ if (!(queries.length == fields.length && queries.length == flags.length))
+ throw new IllegalArgumentException(
+ "queries, fields, and flags array have have different length");
+ BooleanQuery bQuery = new BooleanQuery();
+
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(analyzer);
+
+ for (int i = 0; i < fields.length; i++) {
+ Query q = qp.parse(queries[i], fields[i]);
+
+ if (q != null && // q never null, just being defensive
+ (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+ bQuery.add(q, flags[i]);
+ }
+ }
+ return bQuery;
+ }
+
+ /**
+ * Returns a String where those characters that TextParser expects to be
+ * escaped are escaped by a preceding \
.
+ */
+ public static String escape(String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ // These characters are part of the query syntax and must be escaped
+ if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')'
+ || c == ':' || c == '^' || c == '[' || c == ']' || c == '\"'
+ || c == '{' || c == '}' || c == '~' || c == '*' || c == '?'
+ || c == '|' || c == '&') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java
new file mode 100644
index 00000000000..850d46cc2dc
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java
@@ -0,0 +1,488 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.text.Collator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.parser.SyntaxParser;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessor;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryBuilder;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.MultiTermRewriteMethodAttribute;
+import org.apache.lucene.queryParser.original.config.DateResolutionAttribute;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute;
+import org.apache.lucene.queryParser.original.config.DefaultPhraseSlopAttribute;
+import org.apache.lucene.queryParser.original.config.LocaleAttribute;
+import org.apache.lucene.queryParser.original.config.LowercaseExpandedTermsAttribute;
+import org.apache.lucene.queryParser.original.config.OriginalQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.original.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser;
+import org.apache.lucene.queryParser.original.processors.OriginalQueryNodeProcessorPipeline;
+import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.Parameter;
+
+/**
+ * This class performs the query parsing using the new query parser implementation, but
+ * keeps the old {@link QueryParser} API.
+ *
+ * This class should be used when the new query parser features are and
+ * the old {@link QueryParser} API are needed at the same time.
+ *
+ * @deprecated this class will be removed soon, it's a temporary class to be
+ * used along the transition from the old query parser to the new
+ * one
+ */
+public class QueryParserWrapper {
+
+ /**
+ * The default operator for parsing queries. Use
+ * {@link QueryParserWrapper#setDefaultOperator} to change it.
+ */
+ static public final class Operator extends Parameter {
+ private static final long serialVersionUID = 3550299139196880290L;
+
+ private Operator(String name) {
+ super(name);
+ }
+
+ static public final Operator OR = new Operator("OR");
+ static public final Operator AND = new Operator("AND");
+ }
+
+ // the nested class:
+ /** Alternative form of QueryParser.Operator.AND */
+ public static final Operator AND_OPERATOR = Operator.AND;
+ /** Alternative form of QueryParser.Operator.OR */
+ public static final Operator OR_OPERATOR = Operator.OR;
+
+ /**
+ * Returns a String where those characters that QueryParser expects to be
+ * escaped are escaped by a preceding \
.
+ */
+ public static String escape(String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ // These characters are part of the query syntax and must be escaped
+ if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')'
+ || c == ':' || c == '^' || c == '[' || c == ']' || c == '\"'
+ || c == '{' || c == '}' || c == '~' || c == '*' || c == '?'
+ || c == '|' || c == '&') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ private SyntaxParser syntaxParser = new OriginalSyntaxParser();
+
+ private OriginalQueryConfigHandler config;
+ private OriginalQueryParserHelper qpHelper;
+
+ private QueryNodeProcessor processorPipeline;
+
+ private OriginalQueryBuilder builder = new OriginalQueryTreeBuilder();
+
+ private String defaultField;
+
+ public QueryParserWrapper(String defaultField, Analyzer analyzer) {
+ this.defaultField = defaultField;
+
+ this.qpHelper = new OriginalQueryParserHelper();
+
+ this.config = (OriginalQueryConfigHandler) qpHelper.getQueryConfigHandler();
+
+ this.qpHelper.setAnalyzer(analyzer);
+
+ this.processorPipeline = new OriginalQueryNodeProcessorPipeline(this.config);
+
+ }
+
+ OriginalQueryParserHelper getQueryParserHelper() {
+ return qpHelper;
+ }
+
+ public String getField() {
+ return this.defaultField;
+ }
+
+ public Analyzer getAnalyzer() {
+
+ if (this.config != null
+ && this.config.hasAttribute(AnalyzerAttribute.class)) {
+ return ((AnalyzerAttribute) this.config
+ .getAttribute(AnalyzerAttribute.class)).getAnalyzer();
+ }
+
+ return null;
+
+ }
+
+ /**
+ * Sets the {@link OriginalQueryBuilder} used to generate a {@link Query} object
+ * from the parsed and processed query node tree.
+ *
+ * @param builder
+ * the builder
+ */
+ public void setQueryBuilder(OriginalQueryBuilder builder) {
+ this.builder = builder;
+ }
+
+ /**
+ * Sets the {@link QueryNodeProcessor} used to process the query node tree
+ * generated by the
+ * {@link org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser}.
+ *
+ * @param processor
+ * the processor
+ */
+ public void setQueryProcessor(QueryNodeProcessor processor) {
+ this.processorPipeline = processor;
+ this.processorPipeline.setQueryConfigHandler(this.config);
+
+ }
+
+ /**
+ * Sets the {@link QueryConfigHandler} used by the {@link QueryNodeProcessor}
+ * set to this object.
+ *
+ * @param queryConfig
+ * the query config handler
+ */
+ public void setQueryConfig(OriginalQueryConfigHandler queryConfig) {
+ this.config = queryConfig;
+
+ if (this.processorPipeline != null) {
+ this.processorPipeline.setQueryConfigHandler(this.config);
+ }
+
+ }
+
+ /**
+ * Returns the query config handler used by this query parser
+ *
+ * @return the query config handler
+ */
+ public QueryConfigHandler getQueryConfigHandler() {
+ return this.config;
+ }
+
+ /**
+ * Returns {@link QueryNodeProcessor} used to process the query node tree
+ * generated by the
+ * {@link org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser}.
+ *
+ * @return the query processor
+ */
+ public QueryNodeProcessor getQueryProcessor() {
+ return this.processorPipeline;
+ }
+
+ public ParseException generateParseException() {
+ return null;
+ }
+
+ public boolean getAllowLeadingWildcard() {
+
+ if (this.config != null
+ && this.config.hasAttribute(AllowLeadingWildcardAttribute.class)) {
+ return ((AllowLeadingWildcardAttribute) this.config
+ .getAttribute(AllowLeadingWildcardAttribute.class))
+ .isAllowLeadingWildcard();
+ }
+
+ return false;
+
+ }
+
+ public MultiTermQuery.RewriteMethod getMultiTermRewriteMethod() {
+ if (this.config != null
+ && this.config.hasAttribute(MultiTermRewriteMethodAttribute.class)) {
+ return ((MultiTermRewriteMethodAttribute) this.config
+ .getAttribute(MultiTermRewriteMethodAttribute.class))
+ .getMultiTermRewriteMethod();
+ }
+
+ return MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
+
+ }
+
+ public Resolution getDateResolution(String fieldName) {
+
+ if (this.config != null) {
+ FieldConfig fieldConfig = this.config.getFieldConfig(fieldName);
+
+ if (fieldConfig != null) {
+
+ if (this.config.hasAttribute(DateResolutionAttribute.class)) {
+ return ((DateResolutionAttribute) this.config
+ .getAttribute(DateResolutionAttribute.class)).getDateResolution();
+ }
+
+ }
+
+ }
+
+ return null;
+
+ }
+
+ public boolean getEnablePositionIncrements() {
+
+ if (this.config != null
+ && this.config.hasAttribute(PositionIncrementsAttribute.class)) {
+ return ((PositionIncrementsAttribute) this.config
+ .getAttribute(PositionIncrementsAttribute.class))
+ .isPositionIncrementsEnabled();
+ }
+
+ return false;
+
+ }
+
+ public float getFuzzyMinSim() {
+ return FuzzyQuery.defaultMinSimilarity;
+ }
+
+ public int getFuzzyPrefixLength() {
+ return FuzzyQuery.defaultPrefixLength;
+ }
+
+ public Locale getLocale() {
+
+ if (this.config != null && this.config.hasAttribute(LocaleAttribute.class)) {
+ return ((LocaleAttribute) this.config.getAttribute(LocaleAttribute.class))
+ .getLocale();
+ }
+
+ return Locale.getDefault();
+
+ }
+
+ public boolean getLowercaseExpandedTerms() {
+
+ if (this.config != null
+ && this.config.hasAttribute(LowercaseExpandedTermsAttribute.class)) {
+ return ((LowercaseExpandedTermsAttribute) this.config
+ .getAttribute(LowercaseExpandedTermsAttribute.class))
+ .isLowercaseExpandedTerms();
+ }
+
+ return true;
+
+ }
+
+ public int getPhraseSlop() {
+
+ if (this.config != null
+ && this.config.hasAttribute(AllowLeadingWildcardAttribute.class)) {
+ return ((DefaultPhraseSlopAttribute) this.config
+ .getAttribute(DefaultPhraseSlopAttribute.class))
+ .getDefaultPhraseSlop();
+ }
+
+ return 0;
+
+ }
+
+ public Collator getRangeCollator() {
+
+ if (this.config != null
+ && this.config.hasAttribute(RangeCollatorAttribute.class)) {
+ return ((RangeCollatorAttribute) this.config
+ .getAttribute(RangeCollatorAttribute.class)).getRangeCollator();
+ }
+
+ return null;
+
+ }
+
+ public boolean getUseOldRangeQuery() {
+ if (getMultiTermRewriteMethod() == MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public Query parse(String query) throws ParseException {
+
+ try {
+ QueryNode queryTree = this.syntaxParser.parse(query, getField());
+ queryTree = this.processorPipeline.process(queryTree);
+ return (Query) this.builder.build(queryTree);
+
+ } catch (QueryNodeException e) {
+ throw new ParseException("parse exception");
+ }
+
+ }
+
+ public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
+ this.qpHelper.setAllowLeadingWildcard(allowLeadingWildcard);
+ }
+
+ public void setMultiTermRewriteMethod(MultiTermQuery.RewriteMethod method) {
+ this.qpHelper.setMultiTermRewriteMethod(method);
+ }
+
+ public void setDateResolution(Resolution dateResolution) {
+ this.qpHelper.setDateResolution(dateResolution);
+ }
+
+ private Map dateRes = new HashMap();
+
+ public void setDateResolution(String fieldName, Resolution dateResolution) {
+ dateRes.put(fieldName, dateResolution);
+ this.qpHelper.setDateResolution(dateRes);
+ }
+
+ public void setDefaultOperator(Operator op) {
+
+ this.qpHelper
+ .setDefaultOperator(OR_OPERATOR.equals(op) ? org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator.OR
+ : org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator.AND);
+
+ }
+
+ public Operator getDefaultOperator() {
+
+ if (this.config != null
+ && this.config.hasAttribute(DefaultOperatorAttribute.class)) {
+
+ return (((DefaultOperatorAttribute) this.config
+ .getAttribute(DefaultOperatorAttribute.class)).getOperator() == org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator.AND) ? AND_OPERATOR
+ : OR_OPERATOR;
+
+ }
+
+ return OR_OPERATOR;
+
+ }
+
+ public void setEnablePositionIncrements(boolean enable) {
+ this.qpHelper.setEnablePositionIncrements(enable);
+ }
+
+ public void setFuzzyMinSim(float fuzzyMinSim) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setLocale(Locale locale) {
+ this.qpHelper.setLocale(locale);
+ }
+
+ public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+ this.qpHelper.setLowercaseExpandedTerms(lowercaseExpandedTerms);
+ }
+
+ public void setPhraseSlop(int phraseSlop) {
+ this.qpHelper.setDefaultPhraseSlop(phraseSlop);
+ }
+
+ public void setRangeCollator(Collator rc) {
+ this.qpHelper.setRangeCollator(rc);
+ }
+
+ public void setUseOldRangeQuery(boolean useOldRangeQuery) {
+ if (useOldRangeQuery) {
+ setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
+ } else {
+ setMultiTermRewriteMethod(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT);
+ }
+ }
+
+ protected Query getPrefixQuery(String field, String termStr)
+ throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+ protected Query getWildcardQuery(String field, String termStr)
+ throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+ protected Query getFuzzyQuery(String field, String termStr,
+ float minSimilarity) throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @exception ParseException
+ * throw in overridden method to disallow
+ */
+ protected Query getFieldQuery(String field, String queryText)
+ throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+ @SuppressWarnings("unchecked")
+protected Query getBooleanQuery(List clauses, boolean disableCoord)
+ throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Base implementation delegates to {@link #getFieldQuery(String,String)}.
+ * This method may be overridden, for example, to return a SpanNearQuery
+ * instead of a PhraseQuery.
+ *
+ * @exception ParseException
+ * throw in overridden method to disallow
+ */
+ protected Query getFieldQuery(String field, String queryText, int slop)
+ throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @exception ParseException
+ * throw in overridden method to disallow
+ */
+ protected Query getRangeQuery(String field, String part1, String part2,
+ boolean inclusive) throws ParseException {
+ throw new UnsupportedOperationException();
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/AnyQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/AnyQueryNodeBuilder.java
new file mode 100644
index 00000000000..27c7ba0121d
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/AnyQueryNodeBuilder.java
@@ -0,0 +1,77 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.AnyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.BooleanQuery.TooManyClauses;
+
+public class AnyQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public AnyQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+ AnyQueryNode andNode = (AnyQueryNode) queryNode;
+
+ BooleanQuery bQuery = new BooleanQuery();
+ List children = andNode.getChildren();
+
+ if (children != null) {
+
+ for (QueryNode child : children) {
+ Object obj = child.getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+
+ if (obj != null) {
+ Query query = (Query) obj;
+
+ try {
+ bQuery.add(query, BooleanClause.Occur.SHOULD);
+ } catch (TooManyClauses ex) {
+
+ throw new QueryNodeException(new MessageImpl(
+ /*
+ * IQQQ.Q0028E_TOO_MANY_BOOLEAN_CLAUSES,
+ * BooleanQuery.getMaxClauseCount()
+ */QueryParserMessages.EMPTY_MESSAGE), ex);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ bQuery.setMinimumNumberShouldMatch(andNode.getMinimumMatchingElements());
+
+ return bQuery;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BooleanQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BooleanQueryNodeBuilder.java
new file mode 100644
index 00000000000..98577c5d413
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BooleanQueryNodeBuilder.java
@@ -0,0 +1,110 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.BooleanQuery.TooManyClauses;
+
+/**
+ * Builds a {@link BooleanQuery} object from a {@link BooleanQueryNode} object.
+ * Every children in the {@link BooleanQueryNode} object must be already tagged
+ * using {@link QueryTreeBuilder#QUERY_TREE_BUILDER_TAGID} with a {@link Query}
+ * object.
+ *
+ * It takes in consideration if the children is a {@link ModifierQueryNode} to
+ * define the {@link BooleanClause}.
+ */
+public class BooleanQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public BooleanQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+ BooleanQueryNode booleanNode = (BooleanQueryNode) queryNode;
+
+ BooleanQuery bQuery = new BooleanQuery();
+ List children = booleanNode.getChildren();
+
+ if (children != null) {
+
+ for (QueryNode child : children) {
+ Object obj = child.getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+
+ if (obj != null) {
+ Query query = (Query) obj;
+
+ try {
+ bQuery.add(query, getModifierValue(child));
+
+ } catch (TooManyClauses ex) {
+
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.TOO_MANY_BOOLEAN_CLAUSES, BooleanQuery
+ .getMaxClauseCount(), queryNode
+ .toQueryString(new EscapeQuerySyntaxImpl())), ex);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return bQuery;
+
+ }
+
+ private static BooleanClause.Occur getModifierValue(QueryNode node)
+ throws QueryNodeException {
+
+ if (node instanceof ModifierQueryNode) {
+ ModifierQueryNode mNode = ((ModifierQueryNode) node);
+ switch (mNode.getModifier()) {
+
+ case MOD_REQ:
+ return BooleanClause.Occur.MUST;
+
+ case MOD_NOT:
+ return BooleanClause.Occur.MUST_NOT;
+
+ case MOD_NONE:
+ return BooleanClause.Occur.SHOULD;
+
+ }
+
+ }
+
+ return BooleanClause.Occur.SHOULD;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BoostQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BoostQueryNodeBuilder.java
new file mode 100644
index 00000000000..a4d449d7ada
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BoostQueryNodeBuilder.java
@@ -0,0 +1,54 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.Query;
+
+/**
+ * This builder basically reads the {@link Query} object set on the
+ * {@link BoostQueryNode} child using
+ * {@link QueryTreeBuilder#QUERY_TREE_BUILDER_TAGID} and applies the boost value
+ * defined in the {@link BoostQueryNode}.
+ */
+public class BoostQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public BoostQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ BoostQueryNode boostNode = (BoostQueryNode) queryNode;
+ QueryNode child = boostNode.getChild();
+
+ if (child == null) {
+ return null;
+ }
+
+ Query query = (Query) child
+ .getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+ query.setBoost(boostNode.getValue());
+
+ return query;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FieldQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FieldQueryNodeBuilder.java
new file mode 100644
index 00000000000..6fffc6789d5
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FieldQueryNodeBuilder.java
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * Builds a {@link TermQuery} object from a {@link FieldQueryNode} object.
+ */
+public class FieldQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public FieldQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public TermQuery build(QueryNode queryNode) throws QueryNodeException {
+ FieldQueryNode fieldNode = (FieldQueryNode) queryNode;
+
+ return new TermQuery(new Term(fieldNode.getFieldAsString(), fieldNode
+ .getTextAsString()));
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FuzzyQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FuzzyQueryNodeBuilder.java
new file mode 100644
index 00000000000..16e205f5d06
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FuzzyQueryNodeBuilder.java
@@ -0,0 +1,44 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.FuzzyQuery;
+
+/**
+ * Builds a {@link FuzzyQuery} object from a {@link FuzzyQueryNode} object.
+ */
+public class FuzzyQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public FuzzyQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public FuzzyQuery build(QueryNode queryNode) throws QueryNodeException {
+ FuzzyQueryNode fuzzyNode = (FuzzyQueryNode) queryNode;
+
+ return new FuzzyQuery(new Term(fuzzyNode.getFieldAsString(), fuzzyNode
+ .getTextAsString()), fuzzyNode.getSimilarity(), fuzzyNode
+ .getPrefixLength());
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/GroupQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/GroupQueryNodeBuilder.java
new file mode 100644
index 00000000000..9dd39254093
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/GroupQueryNodeBuilder.java
@@ -0,0 +1,45 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.Query;
+
+/**
+ * Builds no object, it only returns the {@link Query} object set on the
+ * {@link GroupQueryNode} object using a
+ * {@link QueryTreeBuilder#QUERY_TREE_BUILDER_TAGID} tag.
+ */
+public class GroupQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public GroupQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ GroupQueryNode groupNode = (GroupQueryNode) queryNode;
+
+ return (Query) (groupNode).getChild().getTag(
+ QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchAllDocsQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchAllDocsQueryNodeBuilder.java
new file mode 100644
index 00000000000..a6c3de33856
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchAllDocsQueryNodeBuilder.java
@@ -0,0 +1,52 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.search.MatchAllDocsQuery;
+
+/**
+ * Builds a {@link MatchAllDocsQuery} object from a
+ * {@link MatchAllDocsQueryNode} object.
+ */
+public class MatchAllDocsQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public MatchAllDocsQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public MatchAllDocsQuery build(QueryNode queryNode) throws QueryNodeException {
+
+ // validates node
+ if (!(queryNode instanceof MatchAllDocsQueryNode)) {
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, queryNode
+ .toQueryString(new EscapeQuerySyntaxImpl()), queryNode.getClass()
+ .getName()));
+ }
+
+ return new MatchAllDocsQuery();
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchNoDocsQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchNoDocsQueryNodeBuilder.java
new file mode 100644
index 00000000000..6234019520d
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchNoDocsQueryNodeBuilder.java
@@ -0,0 +1,52 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.search.BooleanQuery;
+
+/**
+ * Builds an empty {@link BooleanQuery} object from a
+ * {@link MatchNoDocsQueryNode} object.
+ */
+public class MatchNoDocsQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public MatchNoDocsQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+
+ // validates node
+ if (!(queryNode instanceof MatchNoDocsQueryNode)) {
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, queryNode
+ .toQueryString(new EscapeQuerySyntaxImpl()), queryNode.getClass()
+ .getName()));
+ }
+
+ return new BooleanQuery();
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/ModifierQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/ModifierQueryNodeBuilder.java
new file mode 100644
index 00000000000..f4b6767f0be
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/ModifierQueryNodeBuilder.java
@@ -0,0 +1,45 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.Query;
+
+/**
+ * Builds no object, it only returns the {@link Query} object set on the
+ * {@link ModifierQueryNode} object using a
+ * {@link QueryTreeBuilder#QUERY_TREE_BUILDER_TAGID} tag.
+ */
+public class ModifierQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public ModifierQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ ModifierQueryNode modifierNode = (ModifierQueryNode) queryNode;
+
+ return (Query) (modifierNode).getChild().getTag(
+ QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MultiPhraseQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MultiPhraseQueryNodeBuilder.java
new file mode 100644
index 00000000000..986b65c97bd
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MultiPhraseQueryNodeBuilder.java
@@ -0,0 +1,84 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeMap;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.search.MultiPhraseQuery;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * Builds a {@link MultiPhraseQuery} object from a {@link MultiPhraseQueryNode}
+ * object.
+ */
+public class MultiPhraseQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public MultiPhraseQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public MultiPhraseQuery build(QueryNode queryNode) throws QueryNodeException {
+ MultiPhraseQueryNode phraseNode = (MultiPhraseQueryNode) queryNode;
+
+ MultiPhraseQuery phraseQuery = new MultiPhraseQuery();
+
+ List children = phraseNode.getChildren();
+
+ if (children != null) {
+ TreeMap> positionTermMap = new TreeMap>();
+
+ for (QueryNode child : children) {
+ FieldQueryNode termNode = (FieldQueryNode) child;
+ TermQuery termQuery = (TermQuery) termNode
+ .getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+ List termList = positionTermMap.get(termNode
+ .getPositionIncrement());
+
+ if (termList == null) {
+ termList = new LinkedList();
+ positionTermMap.put(termNode.getPositionIncrement(), termList);
+
+ }
+
+ termList.add(termQuery.getTerm());
+
+ }
+
+ for (int positionIncrement : positionTermMap.keySet()) {
+ List termList = positionTermMap.get(positionIncrement);
+
+ phraseQuery.add(termList.toArray(new Term[termList.size()]),
+ positionIncrement);
+
+ }
+
+ }
+
+ return phraseQuery;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalBooleanQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalBooleanQueryNodeBuilder.java
new file mode 100644
index 00000000000..dc3c2f6f1c8
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalBooleanQueryNodeBuilder.java
@@ -0,0 +1,109 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryParser.original.nodes.OriginalBooleanQueryNode;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Similarity;
+import org.apache.lucene.search.BooleanQuery.TooManyClauses;
+
+/**
+ * This builder does the same as the {@link BooleanQueryNodeBuilder}, but this
+ * considers if the built {@link BooleanQuery} should have its coord disabled or
+ * not.
+ *
+ * @see BooleanQueryNodeBuilder
+ * @see BooleanQuery
+ * @see Similarity#coord(int, int)
+ */
+public class OriginalBooleanQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public OriginalBooleanQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+ OriginalBooleanQueryNode booleanNode = (OriginalBooleanQueryNode) queryNode;
+
+ BooleanQuery bQuery = new BooleanQuery(booleanNode.isDisableCoord());
+ List children = booleanNode.getChildren();
+
+ if (children != null) {
+
+ for (QueryNode child : children) {
+ Object obj = child.getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+
+ if (obj != null) {
+ Query query = (Query) obj;
+
+ try {
+ bQuery.add(query, getModifierValue(child));
+ } catch (TooManyClauses ex) {
+
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.TOO_MANY_BOOLEAN_CLAUSES, BooleanQuery
+ .getMaxClauseCount(), queryNode
+ .toQueryString(new EscapeQuerySyntaxImpl())), ex);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return bQuery;
+
+ }
+
+ private static BooleanClause.Occur getModifierValue(QueryNode node)
+ throws QueryNodeException {
+
+ if (node instanceof ModifierQueryNode) {
+ ModifierQueryNode mNode = ((ModifierQueryNode) node);
+ Modifier modifier = mNode.getModifier();
+
+ if (Modifier.MOD_NONE.equals(modifier)) {
+ return BooleanClause.Occur.SHOULD;
+
+ } else if (Modifier.MOD_NOT.equals(modifier)) {
+ return BooleanClause.Occur.MUST_NOT;
+
+ } else {
+ return BooleanClause.Occur.MUST;
+ }
+ }
+
+ return BooleanClause.Occur.SHOULD;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalQueryBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalQueryBuilder.java
new file mode 100644
index 00000000000..06dba9cea7a
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalQueryBuilder.java
@@ -0,0 +1,37 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryBuilder;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.Query;
+
+/**
+ * This interface should be implemented by every class that wants to build
+ * {@link Query} objects from {@link QueryNode} objects.
+ *
+ * @see QueryBuilder
+ * @see QueryTreeBuilder
+ */
+public interface OriginalQueryBuilder extends QueryBuilder {
+
+ public Query build(QueryNode queryNode) throws QueryNodeException;
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalQueryTreeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalQueryTreeBuilder.java
new file mode 100644
index 00000000000..e5d83a65e9c
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/OriginalQueryTreeBuilder.java
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.core.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.core.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.nodes.OriginalBooleanQueryNode;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.queryParser.original.processors.OriginalQueryNodeProcessorPipeline;
+import org.apache.lucene.search.Query;
+
+/**
+ * This query tree builder only defines the necessary map to build a
+ * {@link Query} tree object. It should be used to generate a {@link Query} tree
+ * object from a query node tree processed by a
+ * {@link OriginalQueryNodeProcessorPipeline}.
+ *
+ * @see QueryTreeBuilder
+ * @see OriginalQueryNodeProcessorPipeline
+ */
+public class OriginalQueryTreeBuilder extends QueryTreeBuilder implements
+ OriginalQueryBuilder {
+
+ public OriginalQueryTreeBuilder() {
+ setBuilder(GroupQueryNode.class, new GroupQueryNodeBuilder());
+ setBuilder(FieldQueryNode.class, new FieldQueryNodeBuilder());
+ setBuilder(BooleanQueryNode.class, new BooleanQueryNodeBuilder());
+ setBuilder(FuzzyQueryNode.class, new FuzzyQueryNodeBuilder());
+ setBuilder(BoostQueryNode.class, new BoostQueryNodeBuilder());
+ setBuilder(ModifierQueryNode.class, new ModifierQueryNodeBuilder());
+ setBuilder(WildcardQueryNode.class, new WildcardQueryNodeBuilder());
+ setBuilder(TokenizedPhraseQueryNode.class, new PhraseQueryNodeBuilder());
+ setBuilder(MatchNoDocsQueryNode.class, new MatchNoDocsQueryNodeBuilder());
+ setBuilder(PrefixWildcardQueryNode.class,
+ new PrefixWildcardQueryNodeBuilder());
+ setBuilder(RangeQueryNode.class, new RangeQueryNodeBuilder());
+ setBuilder(SlopQueryNode.class, new SlopQueryNodeBuilder());
+ setBuilder(OriginalBooleanQueryNode.class,
+ new OriginalBooleanQueryNodeBuilder());
+ setBuilder(MultiPhraseQueryNode.class, new MultiPhraseQueryNodeBuilder());
+ setBuilder(MatchAllDocsQueryNode.class, new MatchAllDocsQueryNodeBuilder());
+
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ return (Query) super.build(queryNode);
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PhraseQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PhraseQueryNodeBuilder.java
new file mode 100644
index 00000000000..3622ac16743
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PhraseQueryNodeBuilder.java
@@ -0,0 +1,64 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * Builds a {@link PhraseQuery} object from a {@link TokenizedPhraseQueryNode}
+ * object.
+ */
+public class PhraseQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public PhraseQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public PhraseQuery build(QueryNode queryNode) throws QueryNodeException {
+ TokenizedPhraseQueryNode phraseNode = (TokenizedPhraseQueryNode) queryNode;
+
+ PhraseQuery phraseQuery = new PhraseQuery();
+
+ List children = phraseNode.getChildren();
+
+ if (children != null) {
+
+ for (QueryNode child : children) {
+ TermQuery termQuery = (TermQuery) child
+ .getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+ FieldQueryNode termNode = (FieldQueryNode) child;
+
+ phraseQuery.add(termQuery.getTerm(), termNode.getPositionIncrement());
+
+ }
+
+ }
+
+ return phraseQuery;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PrefixWildcardQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PrefixWildcardQueryNodeBuilder.java
new file mode 100644
index 00000000000..653c9334331
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PrefixWildcardQueryNodeBuilder.java
@@ -0,0 +1,44 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.PrefixQuery;
+
+/**
+ * Builds a {@link PrefixQuery} object from a {@link PrefixWildcardQueryNode}
+ * object.
+ */
+public class PrefixWildcardQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public PrefixWildcardQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public PrefixQuery build(QueryNode queryNode) throws QueryNodeException {
+ PrefixWildcardQueryNode wildcardNode = (PrefixWildcardQueryNode) queryNode;
+
+ return new PrefixQuery(new Term(wildcardNode.getFieldAsString(),
+ wildcardNode.getTextAsString()));
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/RangeQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/RangeQueryNodeBuilder.java
new file mode 100644
index 00000000000..7876e6e6c3f
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/RangeQueryNodeBuilder.java
@@ -0,0 +1,63 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode.CompareOperator;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.search.TermRangeQuery;
+
+/**
+ * Builds a {@link TermRangeQuery} object from a {@link RangeQueryNode} object.
+ */
+public class RangeQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public RangeQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public TermRangeQuery build(QueryNode queryNode) throws QueryNodeException {
+ RangeQueryNode rangeNode = (RangeQueryNode) queryNode;
+ ParametricQueryNode upper = rangeNode.getUpperBound();
+ ParametricQueryNode lower = rangeNode.getLowerBound();
+
+ boolean lowerInclusive = false;
+ boolean upperInclusive = false;
+
+ if (upper.getOperator() == CompareOperator.LE) {
+ upperInclusive = true;
+ }
+
+ if (lower.getOperator() == CompareOperator.GE) {
+ lowerInclusive = true;
+ }
+
+ String field = rangeNode.getField().toString();
+
+ TermRangeQuery rangeQuery = new TermRangeQuery(field, lower
+ .getTextAsString(), upper.getTextAsString(), lowerInclusive,
+ upperInclusive, rangeNode.getCollator());
+ rangeQuery.setRewriteMethod(rangeNode.getMultiTermRewriteMethod());
+
+ return rangeQuery;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/SlopQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/SlopQueryNodeBuilder.java
new file mode 100644
index 00000000000..80f8e6744d1
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/SlopQueryNodeBuilder.java
@@ -0,0 +1,57 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.SlopQueryNode;
+import org.apache.lucene.search.MultiPhraseQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.Query;
+
+/**
+ * This builder basically reads the {@link Query} object set on the
+ * {@link SlopQueryNode} child using
+ * {@link QueryTreeBuilder#QUERY_TREE_BUILDER_TAGID} and applies the slop value
+ * defined in the {@link SlopQueryNode}.
+ */
+public class SlopQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public SlopQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ SlopQueryNode phraseSlopNode = (SlopQueryNode) queryNode;
+
+ Query query = (Query) phraseSlopNode.getChild().getTag(
+ QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+
+ if (query instanceof PhraseQuery) {
+ ((PhraseQuery) query).setSlop(phraseSlopNode.getValue());
+
+ } else {
+ ((MultiPhraseQuery) query).setSlop(phraseSlopNode.getValue());
+ }
+
+ return query;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/WildcardQueryNodeBuilder.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/WildcardQueryNodeBuilder.java
new file mode 100644
index 00000000000..389d8439cbc
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/WildcardQueryNodeBuilder.java
@@ -0,0 +1,44 @@
+package org.apache.lucene.queryParser.original.builders;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.search.WildcardQuery;
+
+/**
+ * Builds a {@link WildcardQuery} object from a {@link WildcardQueryNode}
+ * object.
+ */
+public class WildcardQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public WildcardQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public WildcardQuery build(QueryNode queryNode) throws QueryNodeException {
+ WildcardQueryNode wildcardNode = (WildcardQueryNode) queryNode;
+
+ return new WildcardQuery(new Term(wildcardNode.getFieldAsString(),
+ wildcardNode.getTextAsString()));
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/package.html
new file mode 100644
index 00000000000..dbd4559a27b
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/package.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+Original Lucene Query Node Builders
+
+The package org.apache.lucene.queryParser.original.builders contains all the builders needed
+to build a Lucene Query object from a query node tree. These builders expect the query node tree was
+already processed by the {@link org.apache.lucene.queryParser.original.processors.OriginalQueryNodeProcessorPipeline}.
+
+
+{@link org.apache.lucene.queryParser.original.builders.OriginalQueryTreeBuilder} is a builder that already contains a defined map that maps each QueryNode object
+with its respective builder.
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttribute.java
new file mode 100644
index 00000000000..da3b01a6efb
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttribute.java
@@ -0,0 +1,33 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.AllowLeadingWildcardProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link AllowLeadingWildcardProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. It basically tells the
+ * processor if it should allow leading wildcard.
+ *
+ */
+public interface AllowLeadingWildcardAttribute extends Attribute {
+ public void setAllowLeadingWildcard(boolean allowLeadingWildcard);
+ public boolean isAllowLeadingWildcard();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttributeImpl.java
new file mode 100644
index 00000000000..44acdc88ebf
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttributeImpl.java
@@ -0,0 +1,80 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.AllowLeadingWildcardProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link AllowLeadingWildcardProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. It basically tells the
+ * processor if it should allow leading wildcard.
+ *
+ * @see org.apache.lucene.queryParser.original.config.AllowLeadingWildcardAttribute
+ */
+public class AllowLeadingWildcardAttributeImpl extends AttributeImpl
+ implements AllowLeadingWildcardAttribute {
+
+ private static final long serialVersionUID = -2804763012723049527L;
+
+ private boolean allowLeadingWildcard = true;
+
+ public AllowLeadingWildcardAttributeImpl() {
+ allowLeadingWildcard = true; // default in 2.4
+ }
+
+ public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
+ this.allowLeadingWildcard = allowLeadingWildcard;
+ }
+
+ public boolean isAllowLeadingWildcard() {
+ return this.allowLeadingWildcard;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof AllowLeadingWildcardAttributeImpl
+ && ((AllowLeadingWildcardAttributeImpl) other).allowLeadingWildcard == this.allowLeadingWildcard) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return this.allowLeadingWildcard ? -1 : Integer.MAX_VALUE;
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttribute.java
new file mode 100644
index 00000000000..99c1bae7511
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.AnalyzerQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link AnalyzerQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. It provides to this
+ * processor the {@link Analyzer}, if there is one, which will be used to
+ * analyze the query terms.
+ *
+ */
+public interface AnalyzerAttribute extends Attribute {
+ public void setAnalyzer(Analyzer analyzer);
+ public Analyzer getAnalyzer();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttributeImpl.java
new file mode 100644
index 00000000000..0cba759a8c7
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttributeImpl.java
@@ -0,0 +1,87 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.AnalyzerQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link AnalyzerQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. It provides to this
+ * processor the {@link Analyzer}, if there is one, which will be used to
+ * analyze the query terms.
+ *
+ * @see org.apache.lucene.queryParser.original.config.AnalyzerAttribute
+ */
+public class AnalyzerAttributeImpl extends AttributeImpl
+ implements AnalyzerAttribute {
+
+ private static final long serialVersionUID = -6804760312723049526L;
+
+ private Analyzer analyzer;
+
+ public AnalyzerAttributeImpl() {
+ analyzer = null; //default value 2.4
+ }
+
+ public void setAnalyzer(Analyzer analyzer) {
+ this.analyzer = analyzer;
+ }
+
+ public Analyzer getAnalyzer() {
+ return this.analyzer;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof AnalyzerAttributeImpl) {
+ AnalyzerAttributeImpl analyzerAttr = (AnalyzerAttributeImpl) other;
+
+ if (analyzerAttr.analyzer == this.analyzer
+ || (this.analyzer != null && analyzerAttr.analyzer != null && this.analyzer
+ .equals(analyzerAttr.analyzer))) {
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return (this.analyzer == null) ? 0 : this.analyzer.hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttribute.java
new file mode 100644
index 00000000000..881a6c86c83
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.original.processors.MultiFieldQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link MultiFieldQueryNodeProcessor} processor and
+ * it should be defined in a {@link FieldConfig}. This processor uses this
+ * attribute to define which boost a specific field should have when none is
+ * defined to it.
+ *
+ *
+ */
+public interface BoostAttribute extends Attribute {
+ public void setBoost(float boost);
+ public float getBoost();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttributeImpl.java
new file mode 100644
index 00000000000..e86e3b15e79
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttributeImpl.java
@@ -0,0 +1,81 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.original.processors.MultiFieldQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link MultiFieldQueryNodeProcessor} processor and
+ * it should be defined in a {@link FieldConfig}. This processor uses this
+ * attribute to define which boost a specific field should have when none is
+ * defined to it.
+ *
+ *
+ * @see org.apache.lucene.queryParser.original.config.BoostAttribute
+ */
+public class BoostAttributeImpl extends AttributeImpl
+ implements BoostAttribute {
+
+ private static final long serialVersionUID = -2104763012523049527L;
+
+ private float boost = 1.0f;
+
+ public BoostAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setBoost(float boost) {
+ this.boost = boost;
+ }
+
+ public float getBoost() {
+ return this.boost;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof BoostAttributeImpl && other != null
+ && ((BoostAttributeImpl) other).boost == this.boost) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return Float.valueOf(this.boost).hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttribute.java
new file mode 100644
index 00000000000..f5e66dc0e57
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttribute.java
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link ParametricRangeQueryNodeProcessor} processor
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor which {@link Resolution} to use when parsing the date.
+ *
+ */
+public interface DateResolutionAttribute extends Attribute {
+ /**
+ * Sets the default date resolution used by {@link RangeQueryNode}s for
+ * fields for which no specific date resolutions has been set. Field
+ * specific resolutions can be set with
+ *
+ * @param dateResolution the default date resolution to set
+ */
+ public void setDateResolution(DateTools.Resolution dateResolution);
+ public DateTools.Resolution getDateResolution();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttributeImpl.java
new file mode 100644
index 00000000000..4c9de6e0d49
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttributeImpl.java
@@ -0,0 +1,87 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link ParametricRangeQueryNodeProcessor} processor
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor which {@link Resolution} to use when parsing the date.
+ *
+ * @see org.apache.lucene.queryParser.original.config.DateResolutionAttribute
+ */
+public class DateResolutionAttributeImpl extends AttributeImpl
+ implements DateResolutionAttribute {
+
+ private static final long serialVersionUID = -6804360312723049526L;
+
+ private DateTools.Resolution dateResolution = null;
+
+ public DateResolutionAttributeImpl() {
+ dateResolution = null; //default in 2.4
+ }
+
+ public void setDateResolution(DateTools.Resolution dateResolution) {
+ this.dateResolution = dateResolution;
+ }
+
+ public DateTools.Resolution getDateResolution() {
+ return this.dateResolution;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof DateResolutionAttributeImpl) {
+ DateResolutionAttributeImpl dateResAttr = (DateResolutionAttributeImpl) other;
+
+ if (dateResAttr.getDateResolution() == getDateResolution()
+ || dateResAttr.getDateResolution().equals(getDateResolution())) {
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return (this.dateResolution == null) ? 0 : this.dateResolution.hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttribute.java
new file mode 100644
index 00000000000..7ad2ae5ba81
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttribute.java
@@ -0,0 +1,39 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.GroupQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link GroupQueryNodeProcessor} processor and must
+ * be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor which is the default boolean operator when no operator is defined
+ * between terms.
+ *
+ */
+public interface DefaultOperatorAttribute extends Attribute {
+ public static enum Operator {
+ AND, OR;
+ }
+
+ public void setOperator(Operator operator);
+ public Operator getOperator();
+}
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttributeImpl.java
new file mode 100644
index 00000000000..1e377051259
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttributeImpl.java
@@ -0,0 +1,89 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.GroupQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link GroupQueryNodeProcessor} processor and must
+ * be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor which is the default boolean operator when no operator is defined
+ * between terms.
+ *
+ * @see org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute
+ */
+public class DefaultOperatorAttributeImpl extends AttributeImpl
+ implements DefaultOperatorAttribute {
+
+ private static final long serialVersionUID = -6804760312723049526L;
+
+ private Operator operator = Operator.OR;
+
+ public DefaultOperatorAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setOperator(Operator operator) {
+
+ if (operator == null) {
+ throw new IllegalArgumentException("default operator cannot be null!");
+ }
+
+ this.operator = operator;
+
+ }
+
+ public Operator getOperator() {
+ return this.operator;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof DefaultOperatorAttributeImpl) {
+ DefaultOperatorAttributeImpl defaultOperatorAttr = (DefaultOperatorAttributeImpl) other;
+
+ if (defaultOperatorAttr.getOperator() == this.getOperator()) {
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return getOperator().hashCode() * 31;
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttribute.java
new file mode 100644
index 00000000000..2226ac72889
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttribute.java
@@ -0,0 +1,34 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.PhraseSlopQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link PhraseSlopQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor what is the default phrase slop when no slop is defined in a
+ * phrase.
+ *
+ */
+public interface DefaultPhraseSlopAttribute extends Attribute {
+ public void setDefaultPhraseSlop(int defaultPhraseSlop);
+ public int getDefaultPhraseSlop();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttributeImpl.java
new file mode 100644
index 00000000000..2a18c03bce5
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttributeImpl.java
@@ -0,0 +1,82 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.PhraseSlopQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link PhraseSlopQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor what is the default phrase slop when no slop is defined in a
+ * phrase.
+ *
+ * @see org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute
+ */
+public class DefaultPhraseSlopAttributeImpl extends AttributeImpl
+ implements DefaultPhraseSlopAttribute {
+
+ private static final long serialVersionUID = -2104763012527049527L;
+
+ private int defaultPhraseSlop = 0;
+
+ public DefaultPhraseSlopAttributeImpl() {
+ defaultPhraseSlop = 0; //default value in 2.4
+ }
+
+ public void setDefaultPhraseSlop(int defaultPhraseSlop) {
+ this.defaultPhraseSlop = defaultPhraseSlop;
+ }
+
+ public int getDefaultPhraseSlop() {
+ return this.defaultPhraseSlop;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof DefaultPhraseSlopAttributeImpl
+ && other != null
+ && ((DefaultPhraseSlopAttributeImpl) other).defaultPhraseSlop == this.defaultPhraseSlop) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return Integer.valueOf(this.defaultPhraseSlop).hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapAttribute.java
new file mode 100644
index 00000000000..79e889ba59f
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Map;
+
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute enables the user to define a default boost per field.
+ * it's used by {@link FieldBoostMapFCListener#buildFieldConfig(FieldConfig)}
+ */
+public interface FieldBoostMapAttribute extends Attribute {
+ /**
+ * @param boosts a mapping from field name to its default boost
+ */
+ public void setFieldBoostMap(Map boosts);
+ public Map getFieldBoostMap();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapAttributeImpl.java
new file mode 100644
index 00000000000..6856fae4ca0
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapAttributeImpl.java
@@ -0,0 +1,89 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.original.processors.MultiFieldQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link MultiFieldQueryNodeProcessor} processor and
+ * it should be defined in a {@link FieldConfig}. This processor uses this
+ * attribute to define which boost a specific field should have when none is
+ * defined to it.
+ *
+ *
+ * @see org.apache.lucene.queryParser.original.config.BoostAttribute
+ */
+public class FieldBoostMapAttributeImpl extends AttributeImpl
+ implements FieldBoostMapAttribute {
+
+ private static final long serialVersionUID = -2104763012523049527L;
+
+ private Map boosts = new LinkedHashMap();
+
+
+ public FieldBoostMapAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setFieldBoostMap(Map boosts) {
+ this.boosts = boosts;
+ }
+
+ public Map getFieldBoostMap() {
+ return this.boosts;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof FieldBoostMapAttributeImpl && other != null
+ && ((FieldBoostMapAttributeImpl) other).boosts.equals(this.boosts) ) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ final int prime = 97;
+ if (this.boosts != null)
+ return this.boosts.hashCode() * prime;
+ else
+ return Float.valueOf(prime).hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapFCListener.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapFCListener.java
new file mode 100644
index 00000000000..3c7ffa258a2
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostMapFCListener.java
@@ -0,0 +1,59 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.core.config.FieldConfigListener;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+
+/**
+ * This listener listens for every field configuration request and assign a
+ * {@link BoostAttribute} to the equivalent {@link FieldConfig} based on a
+ * defined map: fieldName -> boostValue store in {@link FieldBoostMapAttribute}
+ * in the {@link FieldBoostMapAttribute}.
+ *
+ * @see BoostAttribute
+ * @see FieldBoostMapAttribute
+ * @see FieldConfig
+ * @see FieldConfigListener
+ */
+public class FieldBoostMapFCListener implements FieldConfigListener {
+
+ private static final long serialVersionUID = -5929802948798314067L;
+
+ private QueryConfigHandler config = null;
+
+ public FieldBoostMapFCListener(QueryConfigHandler config) {
+ this.config = config;
+ }
+
+ public void buildFieldConfig(FieldConfig fieldConfig) {
+ if (this.config.hasAttribute(FieldBoostMapAttribute.class)) {
+ FieldBoostMapAttribute fieldBoostMapAttr = (FieldBoostMapAttribute) this.config.getAttribute(FieldBoostMapAttribute.class);
+ BoostAttribute boostAttr = (BoostAttribute) fieldConfig.addAttribute(BoostAttribute.class);
+
+ Float boost = fieldBoostMapAttr.getFieldBoostMap().get(fieldConfig.getFieldName());
+
+ if (boost != null) {
+ boostAttr.setBoost(boost.floatValue());
+ }
+
+ }
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionFCListener.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionFCListener.java
new file mode 100644
index 00000000000..383a338c320
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionFCListener.java
@@ -0,0 +1,73 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.core.config.FieldConfigListener;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+
+/**
+ * This listener listens for every field configuration request and assign a
+ * {@link DateResolutionAttribute} to the equivalent {@link FieldConfig} based on a
+ * defined map: fieldName -> DateTools.Resolution stored in {@link FieldDateResolutionMapAttribute}
+ * in the {@link DateResolutionAttribute}.
+ *
+ * @see DateResolutionAttribute
+ * @see FieldDateResolutionMapAttribute
+ * @see FieldConfig
+ * @see FieldConfigListener
+ */
+public class FieldDateResolutionFCListener implements FieldConfigListener {
+
+ private static final long serialVersionUID = -5929802948798314067L;
+
+ private QueryConfigHandler config = null;
+
+ public FieldDateResolutionFCListener(QueryConfigHandler config) {
+ this.config = config;
+ }
+
+ public void buildFieldConfig(FieldConfig fieldConfig) {
+ DateResolutionAttribute fieldDateResAttr = (DateResolutionAttribute) fieldConfig
+ .addAttribute(DateResolutionAttribute.class);
+ DateTools.Resolution dateRes = null;
+
+ if (this.config.hasAttribute(FieldDateResolutionMapAttribute.class)) {
+ FieldDateResolutionMapAttribute dateResMapAttr = (FieldDateResolutionMapAttribute) this.config
+ .addAttribute(FieldDateResolutionMapAttribute.class);
+ dateRes = dateResMapAttr.getFieldDateResolutionMap().get(
+ fieldConfig.getFieldName().toString());
+ }
+
+ if (dateRes == null) {
+
+ if (this.config.hasAttribute(DateResolutionAttribute.class)) {
+ DateResolutionAttribute dateResAttr = (DateResolutionAttribute) this.config
+ .addAttribute(DateResolutionAttribute.class);
+ dateRes = dateResAttr.getDateResolution();
+
+ }
+
+ }
+
+ fieldDateResAttr.setDateResolution(dateRes);
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionMapAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionMapAttribute.java
new file mode 100644
index 00000000000..2a293c2a880
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionMapAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Map;
+
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute enables the user to define a default DateResolution per field.
+ * it's used by {@link FieldDateResolutionFCListener#buildFieldConfig(org.apache.lucene.queryParser.core.config.FieldConfig)}
+ */
+public interface FieldDateResolutionMapAttribute extends Attribute {
+ /**
+ * @param dateRes a mapping from field name to its default boost
+ */
+ public void setFieldDateResolutionMap(Map dateRes);
+ public Map getFieldDateResolutionMap();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionMapAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionMapAttributeImpl.java
new file mode 100644
index 00000000000..04bffd6826d
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldDateResolutionMapAttributeImpl.java
@@ -0,0 +1,86 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute enables the user to define a default DateResolution per field.
+ * it's used by {@link FieldDateResolutionFCListener#buildFieldConfig(org.apache.lucene.queryParser.core.config.FieldConfig)}
+ *
+ * @see FieldDateResolutionMapAttribute
+ */
+public class FieldDateResolutionMapAttributeImpl extends AttributeImpl
+ implements FieldDateResolutionMapAttribute {
+
+ private static final long serialVersionUID = -2104763012523049527L;
+
+ private Map dateRes = new HashMap();
+
+
+ public FieldDateResolutionMapAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setFieldDateResolutionMap(Map dateRes) {
+ this.dateRes = dateRes;
+ }
+
+ public Map getFieldDateResolutionMap() {
+ return this.dateRes;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof FieldDateResolutionMapAttributeImpl && other != null
+ && ((FieldDateResolutionMapAttributeImpl) other).dateRes.equals(this.dateRes) ) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ final int prime = 97;
+ if (this.dateRes != null)
+ return this.dateRes.hashCode() * prime;
+ else
+ return Float.valueOf(prime).hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttribute.java
new file mode 100644
index 00000000000..5767365c08a
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttribute.java
@@ -0,0 +1,36 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.PhraseSlopQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link PhraseSlopQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor what is the default phrase slop when no slop is defined in a
+ * phrase.
+ *
+ */
+public interface FuzzyAttribute extends Attribute {
+ public void setPrefixLength(int prefixLength);
+ public int getPrefixLength();
+ public void setFuzzyMinSimilarity(float minSimilarity);
+ public float getFuzzyMinSimilarity();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttributeImpl.java
new file mode 100644
index 00000000000..7b8a46efee7
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttributeImpl.java
@@ -0,0 +1,91 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.PhraseSlopQueryNodeProcessor;
+import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link PhraseSlopQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor what is the default phrase slop when no slop is defined in a
+ * phrase.
+ *
+ * @see org.apache.lucene.queryParser.original.config.FuzzyAttribute
+ */
+public class FuzzyAttributeImpl extends AttributeImpl
+ implements FuzzyAttribute {
+
+ private static final long serialVersionUID = -2104763012527049527L;
+
+ private int prefixLength = FuzzyQuery.defaultPrefixLength;
+
+ private float minSimilarity = FuzzyQuery.defaultMinSimilarity;
+
+ public FuzzyAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setPrefixLength(int prefixLength) {
+ this.prefixLength = prefixLength;
+ }
+
+ public int getPrefixLength() {
+ return this.prefixLength;
+ }
+
+ public void setFuzzyMinSimilarity(float minSimilarity) {
+ this.minSimilarity = minSimilarity;
+ }
+
+ public float getFuzzyMinSimilarity() {
+ return this.minSimilarity;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof FuzzyAttributeImpl && other != null
+ && ((FuzzyAttributeImpl) other).prefixLength == this.prefixLength) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return Integer.valueOf(this.prefixLength).hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttribute.java
new file mode 100644
index 00000000000..de382c399fe
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Locale;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by processor {@link ParametricRangeQueryNodeProcessor}
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor what is the default {@link Locale} used to parse a date.
+ *
+ */
+public interface LocaleAttribute extends Attribute {
+ public void setLocale(Locale locale);
+ public Locale getLocale();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttributeImpl.java
new file mode 100644
index 00000000000..9e7df973ba9
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttributeImpl.java
@@ -0,0 +1,87 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Locale;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by processor {@link ParametricRangeQueryNodeProcessor}
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor what is the default {@link Locale} used to parse a date.
+ *
+ * @see org.apache.lucene.queryParser.original.config.LocaleAttribute
+ */
+public class LocaleAttributeImpl extends AttributeImpl
+ implements LocaleAttribute {
+
+ private static final long serialVersionUID = -6804760312720049526L;
+
+ private Locale locale = Locale.getDefault();
+
+ public LocaleAttributeImpl() {
+ locale = Locale.getDefault(); //default in 2.4
+ }
+
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ }
+
+ public Locale getLocale() {
+ return this.locale;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof LocaleAttributeImpl) {
+ LocaleAttributeImpl localeAttr = (LocaleAttributeImpl) other;
+
+ if (localeAttr.locale == this.locale
+ || (this.locale != null && localeAttr.locale != null && this.locale
+ .equals(localeAttr.locale))) {
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return (this.locale == null) ? 0 : this.locale.hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttribute.java
new file mode 100644
index 00000000000..d2d7294759f
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Locale;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by processor {@link ParametricRangeQueryNodeProcessor}
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor what is the default {@link Locale} used to parse a date.
+ *
+ */
+public interface LowercaseExpandedTermsAttribute extends Attribute {
+ public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms);
+ public boolean isLowercaseExpandedTerms();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttributeImpl.java
new file mode 100644
index 00000000000..7be77333001
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttributeImpl.java
@@ -0,0 +1,82 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Locale;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by processor {@link ParametricRangeQueryNodeProcessor}
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor what is the default {@link Locale} used to parse a date.
+ *
+ * @see org.apache.lucene.queryParser.original.config.LowercaseExpandedTermsAttribute
+ */
+public class LowercaseExpandedTermsAttributeImpl extends AttributeImpl
+ implements LowercaseExpandedTermsAttribute {
+
+ private static final long serialVersionUID = -2804760312723049527L;
+
+ private boolean lowercaseExpandedTerms = true;
+
+ public LowercaseExpandedTermsAttributeImpl() {
+ lowercaseExpandedTerms = true; // default in 2.4
+ }
+
+ public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+ this.lowercaseExpandedTerms = lowercaseExpandedTerms;
+ }
+
+ public boolean isLowercaseExpandedTerms() {
+ return this.lowercaseExpandedTerms;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof LowercaseExpandedTermsAttributeImpl
+ && ((LowercaseExpandedTermsAttributeImpl) other).lowercaseExpandedTerms == this.lowercaseExpandedTerms) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return this.lowercaseExpandedTerms ? -1 : Integer.MAX_VALUE;
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttribute.java
new file mode 100644
index 00000000000..e5d02f8cc2a
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttribute.java
@@ -0,0 +1,33 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.MultiFieldQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link MultiFieldQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor to which fields the terms in the query should be expanded.
+ *
+ */
+public interface MultiFieldAttribute extends Attribute {
+ public void setFields(CharSequence[] fields);
+ public CharSequence[] getFields();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttributeImpl.java
new file mode 100644
index 00000000000..ca523875c92
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttributeImpl.java
@@ -0,0 +1,81 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.util.Arrays;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.MultiFieldQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link MultiFieldQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor to which fields the terms in the query should be expanded.
+ *
+ * @see org.apache.lucene.queryParser.original.config.MultiFieldAttribute
+ */
+public class MultiFieldAttributeImpl extends AttributeImpl
+ implements MultiFieldAttribute {
+
+ private static final long serialVersionUID = -6809760312720049526L;
+
+ private CharSequence[] fields;
+
+ public MultiFieldAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setFields(CharSequence[] fields) {
+ this.fields = fields;
+ }
+
+ public CharSequence[] getFields() {
+ return this.fields;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof MultiFieldAttributeImpl) {
+ MultiFieldAttributeImpl fieldsAttr = (MultiFieldAttributeImpl) other;
+
+ return Arrays.equals(this.fields, fieldsAttr.fields);
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return Arrays.hashCode(this.fields);
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiTermRewriteMethodAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiTermRewriteMethodAttribute.java
new file mode 100644
index 00000000000..3f52ab9d0ac
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiTermRewriteMethodAttribute.java
@@ -0,0 +1,37 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.MultiTermQuery.RewriteMethod;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link ParametricRangeQueryNodeProcessor} processor
+ * and should be defined in the {@link QueryConfigHandler} used by this
+ * processor. It basically tells the processor which {@link RewriteMethod} to
+ * use.
+ *
+ */
+public interface MultiTermRewriteMethodAttribute extends Attribute {
+ public void setMultiTermRewriteMethod(MultiTermQuery.RewriteMethod method);
+
+ public MultiTermQuery.RewriteMethod getMultiTermRewriteMethod();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiTermRewriteMethodAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiTermRewriteMethodAttributeImpl.java
new file mode 100644
index 00000000000..dd096640828
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiTermRewriteMethodAttributeImpl.java
@@ -0,0 +1,83 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.MultiTermQuery.RewriteMethod;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link ParametricRangeQueryNodeProcessor} processor
+ * and should be defined in the {@link QueryConfigHandler} used by this
+ * processor. It basically tells the processor which {@link RewriteMethod} to
+ * use.
+ *
+ * @see MultiTermRewriteMethodAttribute
+ */
+public class MultiTermRewriteMethodAttributeImpl extends AttributeImpl
+ implements MultiTermRewriteMethodAttribute {
+
+ private static final long serialVersionUID = -2104763012723049527L;
+
+ private MultiTermQuery.RewriteMethod multiTermRewriteMethod = MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT;
+
+ public MultiTermRewriteMethodAttributeImpl() {
+ // empty constructor
+ }
+
+ public void setMultiTermRewriteMethod(MultiTermQuery.RewriteMethod method) {
+ multiTermRewriteMethod = method;
+ }
+
+ public MultiTermQuery.RewriteMethod getMultiTermRewriteMethod() {
+ return multiTermRewriteMethod;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof MultiTermRewriteMethodAttributeImpl
+ && ((MultiTermRewriteMethodAttributeImpl) other).multiTermRewriteMethod == this.multiTermRewriteMethod) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return multiTermRewriteMethod.hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/OriginalQueryConfigHandler.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/OriginalQueryConfigHandler.java
new file mode 100644
index 00000000000..7c9a70a82be
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/OriginalQueryConfigHandler.java
@@ -0,0 +1,55 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.OriginalQueryNodeProcessorPipeline;
+
+/**
+ * This query configuration handler is used for almost every processor defined
+ * in the {@link OriginalQueryNodeProcessorPipeline} processor pipeline. It holds
+ * attributes that reproduces the configuration that could be set on the old
+ * lucene 2.4 QueryParser class.
+ *
+ * @see OriginalQueryNodeProcessorPipeline
+ */
+public class OriginalQueryConfigHandler extends QueryConfigHandler {
+
+
+
+ public OriginalQueryConfigHandler() {
+ // Add listener that will build the FieldConfig attributes.
+ addFieldConfigListener(new FieldBoostMapFCListener(this));
+ addFieldConfigListener(new FieldDateResolutionFCListener(this));
+
+ // Default Values
+ addAttribute(RangeCollatorAttribute.class);
+ addAttribute(DefaultOperatorAttribute.class);
+ addAttribute(AnalyzerAttribute.class);
+ addAttribute(FuzzyAttribute.class);
+ addAttribute(LowercaseExpandedTermsAttribute.class);
+ addAttribute(MultiTermRewriteMethodAttribute.class);
+ addAttribute(AllowLeadingWildcardAttribute.class);
+ addAttribute(PositionIncrementsAttribute.class);
+ addAttribute(LocaleAttribute.class);
+ addAttribute(DefaultPhraseSlopAttribute.class);
+ //addAttribute(DateResolutionAttribute.class);
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttribute.java
new file mode 100644
index 00000000000..b95d35e94df
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttribute.java
@@ -0,0 +1,33 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.AnalyzerQueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link AnalyzerQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor if the position increment is enabled.
+ *
+ */
+public interface PositionIncrementsAttribute extends Attribute {
+ public void setPositionIncrementsEnabled(boolean positionIncrementsEnabled);
+ public boolean isPositionIncrementsEnabled();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttributeImpl.java
new file mode 100644
index 00000000000..5e2b1b31c17
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttributeImpl.java
@@ -0,0 +1,81 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.AnalyzerQueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link AnalyzerQueryNodeProcessor} processor and
+ * must be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor if the position increment is enabled.
+ *
+ * @see org.apache.lucene.queryParser.original.config.PositionIncrementsAttribute
+ */
+public class PositionIncrementsAttributeImpl extends AttributeImpl
+ implements PositionIncrementsAttribute {
+
+ private static final long serialVersionUID = -2804763012793049527L;
+
+ private boolean positionIncrementsEnabled = false;
+
+ public PositionIncrementsAttributeImpl() {
+ positionIncrementsEnabled = false; //default in 2.4
+ }
+
+ public void setPositionIncrementsEnabled(boolean positionIncrementsEnabled) {
+ this.positionIncrementsEnabled = positionIncrementsEnabled;
+ }
+
+ public boolean isPositionIncrementsEnabled() {
+ return this.positionIncrementsEnabled;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof PositionIncrementsAttributeImpl
+ && other != null
+ && ((PositionIncrementsAttributeImpl) other).positionIncrementsEnabled == this.positionIncrementsEnabled) {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return this.positionIncrementsEnabled ? -1 : Integer.MAX_VALUE;
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttribute.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttribute.java
new file mode 100644
index 00000000000..53b7936fd20
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttribute.java
@@ -0,0 +1,37 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.text.Collator;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by {@link ParametricRangeQueryNodeProcessor} processor
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor which {@link Collator} should be used for a
+ * {@link TermRangeQuery}
+ *
+ */
+public interface RangeCollatorAttribute extends Attribute {
+ public void setDateResolution(Collator rangeCollator);
+ public Collator getRangeCollator();
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttributeImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttributeImpl.java
new file mode 100644
index 00000000000..7850805cd61
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttributeImpl.java
@@ -0,0 +1,89 @@
+package org.apache.lucene.queryParser.original.config;
+
+/**
+ * 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.
+ */
+
+import java.text.Collator;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by {@link ParametricRangeQueryNodeProcessor} processor
+ * and must be defined in the {@link QueryConfigHandler}. This attribute tells
+ * the processor which {@link Collator} should be used for a
+ * {@link TermRangeQuery}
+ *
+ * @see org.apache.lucene.queryParser.original.config.RangeCollatorAttribute
+ */
+public class RangeCollatorAttributeImpl extends AttributeImpl
+ implements RangeCollatorAttribute {
+
+ private static final long serialVersionUID = -6804360312723049526L;
+
+ private Collator rangeCollator;
+
+ public RangeCollatorAttributeImpl() {
+ rangeCollator = null; // default value for 2.4
+ }
+
+ public void setDateResolution(Collator rangeCollator) {
+ this.rangeCollator = rangeCollator;
+ }
+
+ public Collator getRangeCollator() {
+ return this.rangeCollator;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean equals(Object other) {
+
+ if (other instanceof RangeCollatorAttributeImpl) {
+ RangeCollatorAttributeImpl rangeCollatorAttr = (RangeCollatorAttributeImpl) other;
+
+ if (rangeCollatorAttr.rangeCollator == this.rangeCollator
+ || rangeCollatorAttr.rangeCollator.equals(this.rangeCollator)) {
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+ public int hashCode() {
+ return (this.rangeCollator == null) ? 0 : this.rangeCollator.hashCode();
+ }
+
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/package.html
new file mode 100644
index 00000000000..f89fb95462d
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/package.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+Original Lucene Query Configuration
+
+The package org.apache.lucene.queryParser.original.config contains the Lucene
+query configuration handler and all the attributes used by it. This configuration
+handler reproduces almost everything that could be set on the old query parser.
+
+
+OriginalQueryConfigHandler is the class that should be used to configure the OriginalQueryNodeProcessorPipeline.
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/BooleanModifierNode.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/BooleanModifierNode.java
new file mode 100644
index 00000000000..44ae93e8eb5
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/BooleanModifierNode.java
@@ -0,0 +1,39 @@
+package org.apache.lucene.queryParser.original.nodes;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.processors.GroupQueryNodeProcessor;
+
+/**
+ * A {@link BooleanModifierNode} has the same behaviour as
+ * {@link ModifierQueryNode}, it only indicates that this modifier was added by
+ * {@link GroupQueryNodeProcessor} and not by the user.
+ *
+ * @see ModifierQueryNode
+ */
+public class BooleanModifierNode extends ModifierQueryNode {
+
+ private static final long serialVersionUID = -557816496416587068L;
+
+ public BooleanModifierNode(QueryNode node, Modifier mod) {
+ super(node, mod);
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/MultiPhraseQueryNode.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/MultiPhraseQueryNode.java
new file mode 100644
index 00000000000..41d97ea2739
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/MultiPhraseQueryNode.java
@@ -0,0 +1,108 @@
+package org.apache.lucene.queryParser.original.nodes;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.nodes.FieldableNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryParser.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.search.MultiPhraseQuery;
+import org.apache.lucene.search.PhraseQuery;
+
+/**
+ * A {@link MultiPhraseQueryNode} indicates that its children should be used to
+ * build a {@link MultiPhraseQuery} instead of {@link PhraseQuery}.
+ */
+public class MultiPhraseQueryNode extends QueryNodeImpl implements
+ FieldableNode {
+
+ private static final long serialVersionUID = -2138501723963320158L;
+
+ public MultiPhraseQueryNode() {
+ setLeaf(false);
+ allocate();
+
+ }
+
+ public String toString() {
+ if (getChildren() == null || getChildren().size() == 0)
+ return "";
+ StringBuilder sb = new StringBuilder();
+ sb.append("");
+ for (QueryNode child : getChildren()) {
+ sb.append("\n");
+ sb.append(child.toString());
+ }
+ sb.append("\n");
+ return sb.toString();
+ }
+
+ public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+ if (getChildren() == null || getChildren().size() == 0)
+ return "";
+
+ StringBuilder sb = new StringBuilder();
+ String filler = "";
+ for (QueryNode child : getChildren()) {
+ sb.append(filler).append(child.toQueryString(escapeSyntaxParser));
+ filler = ",";
+ }
+
+ return "[MTP[" + sb.toString() + "]]";
+ }
+
+ public QueryNode cloneTree() throws CloneNotSupportedException {
+ MultiPhraseQueryNode clone = (MultiPhraseQueryNode) super.cloneTree();
+
+ // nothing to do
+
+ return clone;
+ }
+
+ public CharSequence getField() {
+ List children = getChildren();
+
+ if (children == null || children.size() == 0) {
+ return null;
+
+ } else {
+ return ((FieldableNode) children.get(0)).getField();
+ }
+
+ }
+
+ public void setField(CharSequence fieldName) {
+ List children = getChildren();
+
+ if (children != null) {
+
+ for (QueryNode child : children) {
+
+ if (child instanceof FieldableNode) {
+ ((FieldableNode) child).setField(fieldName);
+ }
+
+ }
+
+ }
+
+ }
+
+} // end class MultitermQueryNode
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/OriginalBooleanQueryNode.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/OriginalBooleanQueryNode.java
new file mode 100644
index 00000000000..be95c0d08f6
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/OriginalBooleanQueryNode.java
@@ -0,0 +1,55 @@
+package org.apache.lucene.queryParser.original.nodes;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Similarity;
+
+/**
+ * A {@link OriginalBooleanQueryNode} has the same behavior as
+ * {@link BooleanQueryNode}. It only indicates if the coord should be enabled or
+ * not for this boolean query.
+ *
+ * @see Similarity#coord(int, int)
+ * @see BooleanQuery
+ */
+public class OriginalBooleanQueryNode extends BooleanQueryNode {
+
+ private static final long serialVersionUID = 1938287817191138787L;
+
+ private boolean disableCoord;
+
+ /**
+ * @param clauses
+ */
+ public OriginalBooleanQueryNode(List clauses, boolean disableCoord) {
+ super(clauses);
+
+ this.disableCoord = disableCoord;
+
+ }
+
+ public boolean isDisableCoord() {
+ return this.disableCoord;
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/RangeQueryNode.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/RangeQueryNode.java
new file mode 100644
index 00000000000..914da00ba83
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/RangeQueryNode.java
@@ -0,0 +1,80 @@
+package org.apache.lucene.queryParser.original.nodes;
+
+/**
+ * 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.
+ */
+
+import java.text.Collator;
+
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.original.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.search.MultiTermQuery;
+
+/**
+ * This query node represents a range query. It also holds which collator will
+ * be used by the range query and if the constant score rewrite is enabled.
+ *
+ * @see ParametricRangeQueryNodeProcessor
+ * @see RangeCollatorAttribute
+ * @see org.apache.lucene.search.RangeQuery
+ */
+public class RangeQueryNode extends ParametricRangeQueryNode {
+
+ private static final long serialVersionUID = 7400866652044314657L;
+
+ private Collator collator;
+
+ private MultiTermQuery.RewriteMethod multiTermRewriteMethod;
+
+ /**
+ * @param lower
+ * @param upper
+ */
+ public RangeQueryNode(ParametricQueryNode lower, ParametricQueryNode upper,
+ Collator collator, MultiTermQuery.RewriteMethod multiTermRewriteMethod) {
+ super(lower, upper);
+
+ this.multiTermRewriteMethod = multiTermRewriteMethod;
+ this.collator = collator;
+
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("\n\t");
+ sb.append(this.getUpperBound()).append("\n\t");
+ sb.append(this.getLowerBound()).append("\n");
+ sb.append("\n");
+
+ return sb.toString();
+
+ }
+
+ /**
+ * @return the collator
+ */
+ public Collator getCollator() {
+ return this.collator;
+ }
+
+ /**
+ * @return the rewrite method
+ */
+ public MultiTermQuery.RewriteMethod getMultiTermRewriteMethod() {
+ return multiTermRewriteMethod;
+ }
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/package.html
new file mode 100644
index 00000000000..e73399e8890
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/package.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+Original Lucene Query Nodes
+
+The package org.apache.lucene.queryParser.original.nodes contains QueryNode classes
+that are used specifically for Lucene query node tree. Any other generic QueryNode is
+defined under org.apache.lucene.queryParser.nodes.
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html
new file mode 100644
index 00000000000..e47b7b6d152
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+Contains the implementation of the Lucene query parser using the flexible query parser frameworks
+
+Lucene Flexible Query Parser Implementation
+
+The old Lucene query parser used to have only one class that performed
+all the parsing operations. In the new query parser structure, the
+parsing was divided in 3 steps: parsing (syntax), processing (semantic)
+and building.
+
+
+The classes contained in the package org.apache.lucene.queryParser.original
+are used to reproduce the same behavior as the old query parser.
+
+
+
+Check org.apache.lucene.queryParser.original.OriginalQueryParserHelper to quick start using the Lucene query parser.
+
+
+
+There are 2 wrapper classes that extends QueryParser and MultiFieldQueryParser.
+The classes implement internally the new query parser structure. These 2
+classes are deprecated and should only be used when there is a need to use the
+old query parser interface.
+
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/EscapeQuerySyntaxImpl.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/EscapeQuerySyntaxImpl.java
new file mode 100644
index 00000000000..935888c83d6
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/EscapeQuerySyntaxImpl.java
@@ -0,0 +1,296 @@
+package org.apache.lucene.queryParser.original.parser;
+
+/**
+ * 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.
+ */
+
+import java.util.Locale;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryParser.core.util.UnescapedCharSequence;
+
+/**
+ */
+public class EscapeQuerySyntaxImpl implements EscapeQuerySyntax {
+
+ private static final char[] wildcardChars = { '*', '?' };
+
+ private static final String[] escapableTermExtraFirstChars = { "+", "-", "@" };
+
+ private static final String[] escapableTermChars = { "\"", "<", ">", "=",
+ "!", "(", ")", "^", "[", "{", ":", "]", "}", "~" };
+
+ // TODO: check what to do with these "*", "?", "\\"
+ private static final String[] escapableQuotedChars = { "\"" };
+ private static final String[] escapableWhiteChars = { " ", "\t", "\n", "\r",
+ "\f", "\b", "\u3000" };
+ private static final String[] escapableWordTokens = { "AND", "OR", "NOT",
+ "TO", "WITHIN", "SENTENCE", "PARAGRAPH", "INORDER" };
+
+ private static final CharSequence escapeChar(CharSequence str, Locale locale) {
+ if (str == null || str.length() == 0)
+ return str;
+
+ CharSequence buffer = str;
+
+ // regular escapable Char for terms
+ for (int i = 0; i < escapableTermChars.length; i++) {
+ buffer = replaceIgnoreCase(buffer, escapableTermChars[i].toLowerCase(),
+ "\\", locale);
+ }
+
+ // First Character of a term as more escaping chars
+ for (int i = 0; i < escapableTermExtraFirstChars.length; i++) {
+ if (buffer.charAt(0) == escapableTermExtraFirstChars[i].charAt(0)) {
+ buffer = "\\" + buffer.charAt(0)
+ + buffer.subSequence(1, buffer.length());
+ break;
+ }
+ }
+
+ return buffer;
+ }
+
+ private final CharSequence escapeQuoted(CharSequence str, Locale locale) {
+ if (str == null || str.length() == 0)
+ return str;
+
+ CharSequence buffer = str;
+
+ for (int i = 0; i < escapableQuotedChars.length; i++) {
+ buffer = replaceIgnoreCase(buffer, escapableTermChars[i].toLowerCase(),
+ "\\", locale);
+ }
+ return buffer;
+ }
+
+ private static final CharSequence escapeTerm(CharSequence term, Locale locale) {
+ if (term == null)
+ return term;
+
+ // Escape single Chars
+ term = escapeChar(term, locale);
+ term = escapeWhiteChar(term, locale);
+
+ // Escape Parser Words
+ for (int i = 0; i < escapableWordTokens.length; i++) {
+ if (escapableWordTokens[i].equalsIgnoreCase(term.toString()))
+ return "\\" + term;
+ }
+ return term;
+ }
+
+ /**
+ * replace with ignore case
+ *
+ * @param stringOrig
+ * string to get replaced
+ * @param sequence1
+ * the old character sequence in lowercase
+ * @param escapeChar
+ * the new character to prefix sequence1 in return string.
+ * @return the new String
+ */
+ private static CharSequence replaceIgnoreCase(CharSequence string,
+ CharSequence sequence1, CharSequence escapeChar, Locale locale) {
+ if (escapeChar == null || sequence1 == null || string == null)
+ throw new NullPointerException();
+
+ // empty string case
+ int count = string.length();
+ int sequence1Length = sequence1.length();
+ if (sequence1Length == 0) {
+ StringBuilder result = new StringBuilder((count + 1)
+ * escapeChar.length());
+ result.append(escapeChar);
+ for (int i = 0; i < count; i++) {
+ result.append(string.charAt(i));
+ result.append(escapeChar);
+ }
+ return result.toString();
+ }
+
+ // normal case
+ StringBuilder result = new StringBuilder();
+ char first = sequence1.charAt(0);
+ int start = 0, copyStart = 0, firstIndex;
+ while (start < count) {
+ if ((firstIndex = string.toString().toLowerCase(locale).indexOf(first,
+ start)) == -1)
+ break;
+ boolean found = true;
+ if (sequence1.length() > 1) {
+ if (firstIndex + sequence1Length > count)
+ break;
+ for (int i = 1; i < sequence1Length; i++) {
+ if (string.toString().toLowerCase(locale).charAt(firstIndex + i) != sequence1
+ .charAt(i)) {
+ found = false;
+ break;
+ }
+ }
+ }
+ if (found) {
+ result.append(string.toString().substring(copyStart, firstIndex));
+ result.append(escapeChar);
+ result.append(string.toString().substring(firstIndex,
+ firstIndex + sequence1Length));
+ copyStart = start = firstIndex + sequence1Length;
+ } else {
+ start = firstIndex + 1;
+ }
+ }
+ if (result.length() == 0 && copyStart == 0)
+ return string;
+ result.append(string.toString().substring(copyStart));
+ return result.toString();
+ }
+
+ /**
+ * escape all tokens that are part of the parser syntax on a given string
+ *
+ * @param string
+ * string to get replaced
+ * @param locale
+ * locale to be used when performing string compares
+ * @return the new String
+ */
+ private static final CharSequence escapeWhiteChar(CharSequence str,
+ Locale locale) {
+ if (str == null || str.length() == 0)
+ return str;
+
+ CharSequence buffer = str;
+
+ for (int i = 0; i < escapableWhiteChars.length; i++) {
+ buffer = replaceIgnoreCase(buffer, escapableWhiteChars[i].toLowerCase(),
+ "\\", locale);
+ }
+ return buffer;
+ }
+
+ public CharSequence escape(CharSequence text, Locale locale, Type type) {
+ if (text == null || text.length() == 0)
+ return text;
+
+ // escape wildcards and the escape char (this has to be perform before
+ // anything else)
+ // since we need to preserve the UnescapedCharSequence and escape the
+ // original escape chars
+ if (text instanceof UnescapedCharSequence) {
+ text = ((UnescapedCharSequence) text).toStringEscaped(wildcardChars);
+ } else {
+ text = new UnescapedCharSequence(text).toStringEscaped(wildcardChars);
+ }
+
+ if (type == Type.STRING) {
+ return escapeQuoted(text, locale);
+ } else {
+ return escapeTerm(text, locale);
+ }
+ }
+
+ /**
+ * Returns a String where the escape char has been removed, or kept only once
+ * if there was a double escape.
+ *
+ * Supports escaped unicode characters, e. g. translates A
to
+ * A
.
+ *
+ */
+ public static UnescapedCharSequence discardEscapeChar(CharSequence input)
+ throws ParseException {
+ // Create char array to hold unescaped char sequence
+ char[] output = new char[input.length()];
+ boolean[] wasEscaped = new boolean[input.length()];
+
+ // The length of the output can be less than the input
+ // due to discarded escape chars. This variable holds
+ // the actual length of the output
+ int length = 0;
+
+ // We remember whether the last processed character was
+ // an escape character
+ boolean lastCharWasEscapeChar = false;
+
+ // The multiplier the current unicode digit must be multiplied with.
+ // E. g. the first digit must be multiplied with 16^3, the second with
+ // 16^2...
+ int codePointMultiplier = 0;
+
+ // Used to calculate the codepoint of the escaped unicode character
+ int codePoint = 0;
+
+ for (int i = 0; i < input.length(); i++) {
+ char curChar = input.charAt(i);
+ if (codePointMultiplier > 0) {
+ codePoint += hexToInt(curChar) * codePointMultiplier;
+ codePointMultiplier >>>= 4;
+ if (codePointMultiplier == 0) {
+ output[length++] = (char) codePoint;
+ codePoint = 0;
+ }
+ } else if (lastCharWasEscapeChar) {
+ if (curChar == 'u') {
+ // found an escaped unicode character
+ codePointMultiplier = 16 * 16 * 16;
+ } else {
+ // this character was escaped
+ output[length] = curChar;
+ wasEscaped[length] = true;
+ length++;
+ }
+ lastCharWasEscapeChar = false;
+ } else {
+ if (curChar == '\\') {
+ lastCharWasEscapeChar = true;
+ } else {
+ output[length] = curChar;
+ length++;
+ }
+ }
+ }
+
+ if (codePointMultiplier > 0) {
+ throw new ParseException(new MessageImpl(
+ QueryParserMessages.INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION));
+ }
+
+ if (lastCharWasEscapeChar) {
+ throw new ParseException(new MessageImpl(
+ QueryParserMessages.INVALID_SYNTAX_ESCAPE_CHARACTER));
+ }
+
+ return new UnescapedCharSequence(output, wasEscaped, 0, length);
+ }
+
+ /** Returns the numeric value of the hexadecimal character */
+ private static final int hexToInt(char c) throws ParseException {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ } else if ('a' <= c && c <= 'f') {
+ return c - 'a' + 10;
+ } else if ('A' <= c && c <= 'F') {
+ return c - 'A' + 10;
+ } else {
+ throw new ParseException(new MessageImpl(
+ QueryParserMessages.INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE, c));
+ }
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/JavaCharStream.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/JavaCharStream.java
new file mode 100644
index 00000000000..3e9f18a50f9
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/JavaCharStream.java
@@ -0,0 +1,617 @@
+/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 4.1 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.lucene.queryParser.original.parser;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (with java-like unicode escape processing).
+ */
+
+public
+class JavaCharStream
+{
+ /** Whether parser is static. */
+ public static final boolean staticFlag = false;
+
+ static final int hexval(char c) throws java.io.IOException {
+ switch(c)
+ {
+ case '0' :
+ return 0;
+ case '1' :
+ return 1;
+ case '2' :
+ return 2;
+ case '3' :
+ return 3;
+ case '4' :
+ return 4;
+ case '5' :
+ return 5;
+ case '6' :
+ return 6;
+ case '7' :
+ return 7;
+ case '8' :
+ return 8;
+ case '9' :
+ return 9;
+
+ case 'a' :
+ case 'A' :
+ return 10;
+ case 'b' :
+ case 'B' :
+ return 11;
+ case 'c' :
+ case 'C' :
+ return 12;
+ case 'd' :
+ case 'D' :
+ return 13;
+ case 'e' :
+ case 'E' :
+ return 14;
+ case 'f' :
+ case 'F' :
+ return 15;
+ }
+
+ throw new java.io.IOException(); // Should never come here
+ }
+
+/** Position in buffer. */
+ public int bufpos = -1;
+ int bufsize;
+ int available;
+ int tokenBegin;
+ protected int bufline[];
+ protected int bufcolumn[];
+
+ protected int column = 0;
+ protected int line = 1;
+
+ protected boolean prevCharIsCR = false;
+ protected boolean prevCharIsLF = false;
+
+ protected java.io.Reader inputStream;
+
+ protected char[] nextCharBuf;
+ protected char[] buffer;
+ protected int maxNextCharInd = 0;
+ protected int nextCharInd = -1;
+ protected int inBuf = 0;
+ protected int tabSize = 8;
+
+ protected void setTabSize(int i) { tabSize = i; }
+ protected int getTabSize(int i) { return tabSize; }
+
+ protected void ExpandBuff(boolean wrapAround)
+ {
+ char[] newbuffer = new char[bufsize + 2048];
+ int newbufline[] = new int[bufsize + 2048];
+ int newbufcolumn[] = new int[bufsize + 2048];
+
+ try
+ {
+ if (wrapAround)
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+ bufcolumn = newbufcolumn;
+
+ bufpos += (bufsize - tokenBegin);
+ }
+ else
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ bufcolumn = newbufcolumn;
+
+ bufpos -= tokenBegin;
+ }
+ }
+ catch (Throwable t)
+ {
+ throw new Error(t.getMessage());
+ }
+
+ available = (bufsize += 2048);
+ tokenBegin = 0;
+ }
+
+ protected void FillBuff() throws java.io.IOException
+ {
+ int i;
+ if (maxNextCharInd == 4096)
+ maxNextCharInd = nextCharInd = 0;
+
+ try {
+ if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
+ 4096 - maxNextCharInd)) == -1)
+ {
+ inputStream.close();
+ throw new java.io.IOException();
+ }
+ else
+ maxNextCharInd += i;
+ return;
+ }
+ catch(java.io.IOException e) {
+ if (bufpos != 0)
+ {
+ --bufpos;
+ backup(0);
+ }
+ else
+ {
+ bufline[bufpos] = line;
+ bufcolumn[bufpos] = column;
+ }
+ throw e;
+ }
+ }
+
+ protected char ReadByte() throws java.io.IOException
+ {
+ if (++nextCharInd >= maxNextCharInd)
+ FillBuff();
+
+ return nextCharBuf[nextCharInd];
+ }
+
+/** @return starting character for token. */
+ public char BeginToken() throws java.io.IOException
+ {
+ if (inBuf > 0)
+ {
+ --inBuf;
+
+ if (++bufpos == bufsize)
+ bufpos = 0;
+
+ tokenBegin = bufpos;
+ return buffer[bufpos];
+ }
+
+ tokenBegin = 0;
+ bufpos = -1;
+
+ return readChar();
+ }
+
+ protected void AdjustBuffSize()
+ {
+ if (available == bufsize)
+ {
+ if (tokenBegin > 2048)
+ {
+ bufpos = 0;
+ available = tokenBegin;
+ }
+ else
+ ExpandBuff(false);
+ }
+ else if (available > tokenBegin)
+ available = bufsize;
+ else if ((tokenBegin - available) < 2048)
+ ExpandBuff(true);
+ else
+ available = tokenBegin;
+ }
+
+ protected void UpdateLineColumn(char c)
+ {
+ column++;
+
+ if (prevCharIsLF)
+ {
+ prevCharIsLF = false;
+ line += (column = 1);
+ }
+ else if (prevCharIsCR)
+ {
+ prevCharIsCR = false;
+ if (c == '\n')
+ {
+ prevCharIsLF = true;
+ }
+ else
+ line += (column = 1);
+ }
+
+ switch (c)
+ {
+ case '\r' :
+ prevCharIsCR = true;
+ break;
+ case '\n' :
+ prevCharIsLF = true;
+ break;
+ case '\t' :
+ column--;
+ column += (tabSize - (column % tabSize));
+ break;
+ default :
+ break;
+ }
+
+ bufline[bufpos] = line;
+ bufcolumn[bufpos] = column;
+ }
+
+/** Read a character. */
+ public char readChar() throws java.io.IOException
+ {
+ if (inBuf > 0)
+ {
+ --inBuf;
+
+ if (++bufpos == bufsize)
+ bufpos = 0;
+
+ return buffer[bufpos];
+ }
+
+ char c;
+
+ if (++bufpos == available)
+ AdjustBuffSize();
+
+ if ((buffer[bufpos] = c = ReadByte()) == '\\')
+ {
+ UpdateLineColumn(c);
+
+ int backSlashCnt = 1;
+
+ for (;;) // Read all the backslashes
+ {
+ if (++bufpos == available)
+ AdjustBuffSize();
+
+ try
+ {
+ if ((buffer[bufpos] = c = ReadByte()) != '\\')
+ {
+ UpdateLineColumn(c);
+ // found a non-backslash char.
+ if ((c == 'u') && ((backSlashCnt & 1) == 1))
+ {
+ if (--bufpos < 0)
+ bufpos = bufsize - 1;
+
+ break;
+ }
+
+ backup(backSlashCnt);
+ return '\\';
+ }
+ }
+ catch(java.io.IOException e)
+ {
+ // We are returning one backslash so we should only backup (count-1)
+ if (backSlashCnt > 1)
+ backup(backSlashCnt-1);
+
+ return '\\';
+ }
+
+ UpdateLineColumn(c);
+ backSlashCnt++;
+ }
+
+ // Here, we have seen an odd number of backslash's followed by a 'u'
+ try
+ {
+ while ((c = ReadByte()) == 'u')
+ ++column;
+
+ buffer[bufpos] = c = (char)(hexval(c) << 12 |
+ hexval(ReadByte()) << 8 |
+ hexval(ReadByte()) << 4 |
+ hexval(ReadByte()));
+
+ column += 4;
+ }
+ catch(java.io.IOException e)
+ {
+ throw new Error("Invalid escape character at line " + line +
+ " column " + column + ".");
+ }
+
+ if (backSlashCnt == 1)
+ return c;
+ else
+ {
+ backup(backSlashCnt - 1);
+ return '\\';
+ }
+ }
+ else
+ {
+ UpdateLineColumn(c);
+ return c;
+ }
+ }
+
+ @Deprecated
+ /**
+ * @deprecated
+ * @see #getEndColumn
+ */
+ public int getColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ @Deprecated
+ /**
+ * @deprecated
+ * @see #getEndLine
+ */
+ public int getLine() {
+ return bufline[bufpos];
+ }
+
+/** Get end column. */
+ public int getEndColumn() {
+ return bufcolumn[bufpos];
+ }
+
+/** Get end line. */
+ public int getEndLine() {
+ return bufline[bufpos];
+ }
+
+/** @return column of token start */
+ public int getBeginColumn() {
+ return bufcolumn[tokenBegin];
+ }
+
+/** @return line number of token start */
+ public int getBeginLine() {
+ return bufline[tokenBegin];
+ }
+
+/** Retreat. */
+ public void backup(int amount) {
+
+ inBuf += amount;
+ if ((bufpos -= amount) < 0)
+ bufpos += bufsize;
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.Reader dstream,
+ int startline, int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ nextCharBuf = new char[4096];
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.Reader dstream,
+ int startline, int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.Reader dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+/** Reinitialise. */
+ public void ReInit(java.io.Reader dstream,
+ int startline, int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ if (buffer == null || buffersize != buffer.length)
+ {
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ nextCharBuf = new char[4096];
+ }
+ prevCharIsLF = prevCharIsCR = false;
+ tokenBegin = inBuf = maxNextCharInd = 0;
+ nextCharInd = bufpos = -1;
+ }
+
+/** Reinitialise. */
+ public void ReInit(java.io.Reader dstream,
+ int startline, int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+
+/** Reinitialise. */
+ public void ReInit(java.io.Reader dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+/** Constructor. */
+ public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, startline, startcolumn, 4096);
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, 1, 1, 4096);
+ }
+
+/** Constructor. */
+ public JavaCharStream(java.io.InputStream dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+
+/** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+/** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+/** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, startline, startcolumn, 4096);
+ }
+/** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+/** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, 1, 1, 4096);
+ }
+
+/** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+
+ /** @return token image as String */
+ public String GetImage()
+ {
+ if (bufpos >= tokenBegin)
+ return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+ else
+ return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+ new String(buffer, 0, bufpos + 1);
+ }
+
+ /** @return suffix */
+ public char[] GetSuffix(int len)
+ {
+ char[] ret = new char[len];
+
+ if ((bufpos + 1) >= len)
+ System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+ else
+ {
+ System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+ len - bufpos - 1);
+ System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+ }
+
+ return ret;
+ }
+
+ /** Set buffers back to null when finished. */
+ public void Done()
+ {
+ nextCharBuf = null;
+ buffer = null;
+ bufline = null;
+ bufcolumn = null;
+ }
+
+ /**
+ * Method to adjust line and column numbers for the start of a token.
+ */
+ public void adjustBeginLineColumn(int newLine, int newCol)
+ {
+ int start = tokenBegin;
+ int len;
+
+ if (bufpos >= tokenBegin)
+ {
+ len = bufpos - tokenBegin + inBuf + 1;
+ }
+ else
+ {
+ len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+ }
+
+ int i = 0, j = 0, k = 0;
+ int nextColDiff = 0, columnDiff = 0;
+
+ while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+ {
+ bufline[j] = newLine;
+ nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+ bufcolumn[j] = newCol + columnDiff;
+ columnDiff = nextColDiff;
+ i++;
+ }
+
+ if (i < len)
+ {
+ bufline[j] = newLine++;
+ bufcolumn[j] = newCol + columnDiff;
+
+ while (i++ < len)
+ {
+ if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+ bufline[j] = newLine++;
+ else
+ bufline[j] = newLine;
+ }
+ }
+
+ line = bufline[j];
+ column = bufcolumn[j];
+ }
+
+}
+/* JavaCC - OriginalChecksum=065d79d49fcd02f542903038e37bd9d9 (do not edit this line) */
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParser.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParser.java
new file mode 100644
index 00000000000..24723062bc7
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParser.java
@@ -0,0 +1,955 @@
+/* Generated By:JavaCC: Do not edit this line. OriginalSyntaxParser.java */
+package org.apache.lucene.queryParser.original.parser;
+
+/**
+ * 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.
+ */
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.lucene.messages.Message;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeError;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.QueryNodeParseException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.OpaqueQueryNode;
+import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.core.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.core.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ProximityQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryParser.core.nodes.QuotedFieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.parser.SyntaxParser;
+
+@SuppressWarnings("all")
+public class OriginalSyntaxParser implements SyntaxParser, OriginalSyntaxParserConstants {
+
+ private static final int CONJ_NONE =0;
+ private static final int CONJ_AND =2;
+ private static final int CONJ_OR =2;
+
+
+ // syntax parser constructor
+ public OriginalSyntaxParser() {
+ this(new StringReader(""));
+ }
+ /** Parses a query string, returning a {@link org.apache.lucene.queryParser.core.nodes.QueryNode}.
+ * @param query the query string to be parsed.
+ * @throws ParseException if the parsing fails
+ */
+ public QueryNode parse(CharSequence query, CharSequence field) throws QueryNodeParseException {
+ ReInit(new StringReader(query.toString()));
+ try {
+ // TopLevelQuery is a Query followed by the end-of-input (EOF)
+ QueryNode querynode = TopLevelQuery(field);
+ return querynode;
+ }
+ catch (ParseException tme) {
+ tme.setQuery(query);
+ throw tme;
+ }
+ catch (Error tme) {
+ Message message = new MessageImpl(QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, tme.getMessage());
+ QueryNodeParseException e = new QueryNodeParseException(tme);
+ e.setQuery(query);
+ e.setNonLocalizedMessage(message);
+ throw e;
+ }
+ }
+
+// * Query ::= ( Clause )*
+// * Clause ::= ["+", "-"] [ ":"] ( | "(" Query ")" )
+ final public int Conjunction() throws ParseException {
+ int ret = CONJ_NONE;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case AND:
+ case OR:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case AND:
+ jj_consume_token(AND);
+ ret = CONJ_AND;
+ break;
+ case OR:
+ jj_consume_token(OR);
+ ret = CONJ_OR;
+ break;
+ default:
+ jj_la1[0] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ break;
+ default:
+ jj_la1[1] = jj_gen;
+ ;
+ }
+ {if (true) return ret;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public ModifierQueryNode.Modifier Modifiers() throws ParseException {
+ ModifierQueryNode.Modifier ret = ModifierQueryNode.Modifier.MOD_NONE;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case NOT:
+ case PLUS:
+ case MINUS:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case PLUS:
+ jj_consume_token(PLUS);
+ ret = ModifierQueryNode.Modifier.MOD_REQ;
+ break;
+ case MINUS:
+ jj_consume_token(MINUS);
+ ret = ModifierQueryNode.Modifier.MOD_NOT;
+ break;
+ case NOT:
+ jj_consume_token(NOT);
+ ret = ModifierQueryNode.Modifier.MOD_NOT;
+ break;
+ default:
+ jj_la1[2] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ break;
+ default:
+ jj_la1[3] = jj_gen;
+ ;
+ }
+ {if (true) return ret;}
+ throw new Error("Missing return statement in function");
+ }
+
+// This makes sure that there is no garbage after the query string
+ final public QueryNode TopLevelQuery(CharSequence field) throws ParseException {
+ QueryNode q;
+ q = Query(field);
+ jj_consume_token(0);
+ {if (true) return q;}
+ throw new Error("Missing return statement in function");
+ }
+
+// These changes were made to introduce operator precedence:
+// - Clause() now returns a QueryNode.
+// - The modifiers are consumed by Clause() and returned as part of the QueryNode Object
+// - Query does not consume conjunctions (AND, OR) anymore.
+// - This is now done by two new non-terminals: ConjClause and DisjClause
+// The parse tree looks similar to this:
+// Query ::= DisjQuery ( DisjQuery )*
+// DisjQuery ::= ConjQuery ( OR ConjQuery )*
+// ConjQuery ::= Clause ( AND Clause )*
+// Clause ::= [ Modifier ] ...
+ final public QueryNode Query(CharSequence field) throws ParseException {
+ Vector clauses = null;
+ QueryNode c, first=null;
+ first = DisjQuery(field);
+ label_1:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case NOT:
+ case PLUS:
+ case MINUS:
+ case LPAREN:
+ case STAR:
+ case QUOTED:
+ case TERM:
+ case PREFIXTERM:
+ case WILDTERM:
+ case RANGEIN_START:
+ case RANGEEX_START:
+ case NUMBER:
+ ;
+ break;
+ default:
+ jj_la1[4] = jj_gen;
+ break label_1;
+ }
+ c = DisjQuery(field);
+ if (clauses == null) {
+ clauses = new Vector();
+ clauses.addElement(first);
+ }
+ clauses.addElement(c);
+ }
+ if (clauses != null) {
+ {if (true) return new BooleanQueryNode(clauses);}
+ } else {
+ {if (true) return first;}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public QueryNode DisjQuery(CharSequence field) throws ParseException {
+ QueryNode first, c;
+ Vector clauses = null;
+ first = ConjQuery(field);
+ label_2:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case OR:
+ ;
+ break;
+ default:
+ jj_la1[5] = jj_gen;
+ break label_2;
+ }
+ jj_consume_token(OR);
+ c = ConjQuery(field);
+ if (clauses == null) {
+ clauses = new Vector();
+ clauses.addElement(first);
+ }
+ clauses.addElement(c);
+ }
+ if (clauses != null) {
+ {if (true) return new OrQueryNode(clauses);}
+ } else {
+ {if (true) return first;}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public QueryNode ConjQuery(CharSequence field) throws ParseException {
+ QueryNode first, c;
+ Vector clauses = null;
+ first = ModClause(field);
+ label_3:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case AND:
+ ;
+ break;
+ default:
+ jj_la1[6] = jj_gen;
+ break label_3;
+ }
+ jj_consume_token(AND);
+ c = ModClause(field);
+ if (clauses == null) {
+ clauses = new Vector();
+ clauses.addElement(first);
+ }
+ clauses.addElement(c);
+ }
+ if (clauses != null) {
+ {if (true) return new AndQueryNode(clauses);}
+ } else {
+ {if (true) return first;}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+// QueryNode Query(CharSequence field) :
+// {
+// List clauses = new ArrayList();
+// List modifiers = new ArrayList();
+// QueryNode q, firstQuery=null;
+// ModifierQueryNode.Modifier mods;
+// int conj;
+// }
+// {
+// mods=Modifiers() q=Clause(field)
+// {
+// if (mods == ModifierQueryNode.Modifier.MOD_NONE) firstQuery=q;
+//
+// // do not create modifier nodes with MOD_NONE
+// if (mods != ModifierQueryNode.Modifier.MOD_NONE) {
+// q = new ModifierQueryNode(q, mods);
+// }
+// clauses.add(q);
+// }
+// (
+// conj=Conjunction() mods=Modifiers() q=Clause(field)
+// {
+// // do not create modifier nodes with MOD_NONE
+// if (mods != ModifierQueryNode.Modifier.MOD_NONE) {
+// q = new ModifierQueryNode(q, mods);
+// }
+// clauses.add(q);
+// //TODO: figure out what to do with AND and ORs
+// }
+// )*
+// {
+// if (clauses.size() == 1 && firstQuery != null)
+// return firstQuery;
+// else {
+// return new BooleanQueryNode(clauses);
+// }
+// }
+// }
+ final public QueryNode ModClause(CharSequence field) throws ParseException {
+ QueryNode q;
+ ModifierQueryNode.Modifier mods;
+ mods = Modifiers();
+ q = Clause(field);
+ if (mods != ModifierQueryNode.Modifier.MOD_NONE) {
+ q = new ModifierQueryNode(q, mods);
+ }
+ {if (true) return q;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public QueryNode Clause(CharSequence field) throws ParseException {
+ QueryNode q;
+ Token fieldToken=null, boost=null;
+ boolean group = false;
+ if (jj_2_1(2)) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case TERM:
+ fieldToken = jj_consume_token(TERM);
+ jj_consume_token(COLON);
+ field=EscapeQuerySyntaxImpl.discardEscapeChar(fieldToken.image);
+ break;
+ case STAR:
+ jj_consume_token(STAR);
+ jj_consume_token(COLON);
+ field="*";
+ break;
+ default:
+ jj_la1[7] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ } else {
+ ;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case STAR:
+ case QUOTED:
+ case TERM:
+ case PREFIXTERM:
+ case WILDTERM:
+ case RANGEIN_START:
+ case RANGEEX_START:
+ case NUMBER:
+ q = Term(field);
+ break;
+ case LPAREN:
+ jj_consume_token(LPAREN);
+ q = Query(field);
+ jj_consume_token(RPAREN);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARAT:
+ jj_consume_token(CARAT);
+ boost = jj_consume_token(NUMBER);
+ break;
+ default:
+ jj_la1[8] = jj_gen;
+ ;
+ }
+ group=true;
+ break;
+ default:
+ jj_la1[9] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ if (boost != null) {
+ float f = (float)1.0;
+ try {
+ f = Float.valueOf(boost.image).floatValue();
+ // avoid boosting null queries, such as those caused by stop words
+ if (q != null) {
+ q = new BoostQueryNode(q, f);
+ }
+ } catch (Exception ignored) {
+ /* Should this be handled somehow? (defaults to "no boost", if
+ * boost number is invalid)
+ */
+ }
+ }
+ if (group) { q = new GroupQueryNode(q);}
+ {if (true) return q;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public QueryNode Term(CharSequence field) throws ParseException {
+ Token term, boost=null, fuzzySlop=null, goop1, goop2;
+ boolean prefix = false;
+ boolean wildcard = false;
+ boolean fuzzy = false;
+ QueryNode q =null;
+ ParametricQueryNode qLower, qUpper;
+ float defaultMinSimilarity = 0.5f;
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case STAR:
+ case TERM:
+ case PREFIXTERM:
+ case WILDTERM:
+ case NUMBER:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case TERM:
+ term = jj_consume_token(TERM);
+ q = new FieldQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn);
+ break;
+ case STAR:
+ term = jj_consume_token(STAR);
+ wildcard=true; q = new WildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn);
+ break;
+ case PREFIXTERM:
+ term = jj_consume_token(PREFIXTERM);
+ prefix=true; q = new PrefixWildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn);
+ break;
+ case WILDTERM:
+ term = jj_consume_token(WILDTERM);
+ wildcard=true; q = new WildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn);
+ break;
+ case NUMBER:
+ term = jj_consume_token(NUMBER);
+ break;
+ default:
+ jj_la1[10] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case FUZZY_SLOP:
+ fuzzySlop = jj_consume_token(FUZZY_SLOP);
+ fuzzy=true;
+ break;
+ default:
+ jj_la1[11] = jj_gen;
+ ;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARAT:
+ jj_consume_token(CARAT);
+ boost = jj_consume_token(NUMBER);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case FUZZY_SLOP:
+ fuzzySlop = jj_consume_token(FUZZY_SLOP);
+ fuzzy=true;
+ break;
+ default:
+ jj_la1[12] = jj_gen;
+ ;
+ }
+ break;
+ default:
+ jj_la1[13] = jj_gen;
+ ;
+ }
+ if (!wildcard && !prefix && fuzzy) {
+ float fms = defaultMinSimilarity;
+ try {
+ fms = Float.valueOf(fuzzySlop.image.substring(1)).floatValue();
+ } catch (Exception ignored) { }
+ if(fms < 0.0f || fms > 1.0f){
+ {if (true) throw new ParseException(new MessageImpl(QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS));}
+ }
+ q = new FuzzyQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), fms, term.beginColumn, term.endColumn);
+ }
+ break;
+ case RANGEIN_START:
+ jj_consume_token(RANGEIN_START);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEIN_GOOP:
+ goop1 = jj_consume_token(RANGEIN_GOOP);
+ break;
+ case RANGEIN_QUOTED:
+ goop1 = jj_consume_token(RANGEIN_QUOTED);
+ break;
+ default:
+ jj_la1[14] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEIN_TO:
+ jj_consume_token(RANGEIN_TO);
+ break;
+ default:
+ jj_la1[15] = jj_gen;
+ ;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEIN_GOOP:
+ goop2 = jj_consume_token(RANGEIN_GOOP);
+ break;
+ case RANGEIN_QUOTED:
+ goop2 = jj_consume_token(RANGEIN_QUOTED);
+ break;
+ default:
+ jj_la1[16] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ jj_consume_token(RANGEIN_END);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARAT:
+ jj_consume_token(CARAT);
+ boost = jj_consume_token(NUMBER);
+ break;
+ default:
+ jj_la1[17] = jj_gen;
+ ;
+ }
+ if (goop1.kind == RANGEIN_QUOTED) {
+ goop1.image = goop1.image.substring(1, goop1.image.length()-1);
+ }
+ if (goop2.kind == RANGEIN_QUOTED) {
+ goop2.image = goop2.image.substring(1, goop2.image.length()-1);
+ }
+
+ qLower = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.GE,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop1.image), goop1.beginColumn, goop1.endColumn);
+ qUpper = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.LE,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop2.image), goop2.beginColumn, goop2.endColumn);
+ q = new ParametricRangeQueryNode(qLower, qUpper);
+ break;
+ case RANGEEX_START:
+ jj_consume_token(RANGEEX_START);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEEX_GOOP:
+ goop1 = jj_consume_token(RANGEEX_GOOP);
+ break;
+ case RANGEEX_QUOTED:
+ goop1 = jj_consume_token(RANGEEX_QUOTED);
+ break;
+ default:
+ jj_la1[18] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEEX_TO:
+ jj_consume_token(RANGEEX_TO);
+ break;
+ default:
+ jj_la1[19] = jj_gen;
+ ;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RANGEEX_GOOP:
+ goop2 = jj_consume_token(RANGEEX_GOOP);
+ break;
+ case RANGEEX_QUOTED:
+ goop2 = jj_consume_token(RANGEEX_QUOTED);
+ break;
+ default:
+ jj_la1[20] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ jj_consume_token(RANGEEX_END);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARAT:
+ jj_consume_token(CARAT);
+ boost = jj_consume_token(NUMBER);
+ break;
+ default:
+ jj_la1[21] = jj_gen;
+ ;
+ }
+ if (goop1.kind == RANGEEX_QUOTED) {
+ goop1.image = goop1.image.substring(1, goop1.image.length()-1);
+ }
+ if (goop2.kind == RANGEEX_QUOTED) {
+ goop2.image = goop2.image.substring(1, goop2.image.length()-1);
+ }
+ qLower = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.GT,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop1.image), goop1.beginColumn, goop1.endColumn);
+ qUpper = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.LT,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop2.image), goop2.beginColumn, goop2.endColumn);
+ q = new ParametricRangeQueryNode(qLower, qUpper);
+ break;
+ case QUOTED:
+ term = jj_consume_token(QUOTED);
+ q = new QuotedFieldQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image.substring(1, term.image.length()-1)), term.beginColumn + 1, term.endColumn - 1);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case FUZZY_SLOP:
+ fuzzySlop = jj_consume_token(FUZZY_SLOP);
+ break;
+ default:
+ jj_la1[22] = jj_gen;
+ ;
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case CARAT:
+ jj_consume_token(CARAT);
+ boost = jj_consume_token(NUMBER);
+ break;
+ default:
+ jj_la1[23] = jj_gen;
+ ;
+ }
+ int phraseSlop = 0;
+
+ if (fuzzySlop != null) {
+ try {
+ phraseSlop = Float.valueOf(fuzzySlop.image.substring(1)).intValue();
+ q = new SlopQueryNode(q, phraseSlop);
+ }
+ catch (Exception ignored) {
+ /* Should this be handled somehow? (defaults to "no PhraseSlop", if
+ * slop number is invalid)
+ */
+ }
+ }
+ break;
+ default:
+ jj_la1[24] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ if (boost != null) {
+ float f = (float)1.0;
+ try {
+ f = Float.valueOf(boost.image).floatValue();
+ // avoid boosting null queries, such as those caused by stop words
+ if (q != null) {
+ q = new BoostQueryNode(q, f);
+ }
+ } catch (Exception ignored) {
+ /* Should this be handled somehow? (defaults to "no boost", if
+ * boost number is invalid)
+ */
+ }
+ }
+ {if (true) return q;}
+ throw new Error("Missing return statement in function");
+ }
+
+ private boolean jj_2_1(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_1(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(0, xla); }
+ }
+
+ private boolean jj_3R_5() {
+ if (jj_scan_token(STAR)) return true;
+ if (jj_scan_token(COLON)) return true;
+ return false;
+ }
+
+ private boolean jj_3R_4() {
+ if (jj_scan_token(TERM)) return true;
+ if (jj_scan_token(COLON)) return true;
+ return false;
+ }
+
+ private boolean jj_3_1() {
+ Token xsp;
+ xsp = jj_scanpos;
+ if (jj_3R_4()) {
+ jj_scanpos = xsp;
+ if (jj_3R_5()) return true;
+ }
+ return false;
+ }
+
+ /** Generated Token Manager. */
+ public OriginalSyntaxParserTokenManager token_source;
+ JavaCharStream jj_input_stream;
+ /** Current token. */
+ public Token token;
+ /** Next token. */
+ public Token jj_nt;
+ private int jj_ntk;
+ private Token jj_scanpos, jj_lastpos;
+ private int jj_la;
+ private int jj_gen;
+ final private int[] jj_la1 = new int[25];
+ static private int[] jj_la1_0;
+ static private int[] jj_la1_1;
+ static {
+ jj_la1_init_0();
+ jj_la1_init_1();
+ }
+ private static void jj_la1_init_0() {
+ jj_la1_0 = new int[] {0x300,0x300,0x1c00,0x1c00,0x3ed3c00,0x200,0x100,0x90000,0x20000,0x3ed2000,0x2690000,0x100000,0x100000,0x20000,0x30000000,0x4000000,0x30000000,0x20000,0x0,0x40000000,0x0,0x20000,0x100000,0x20000,0x3ed0000,};
+ }
+ private static void jj_la1_init_1() {
+ jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0,0x3,0x0,0x0,0x0,0x0,};
+ }
+ final private JJCalls[] jj_2_rtns = new JJCalls[1];
+ private boolean jj_rescan = false;
+ private int jj_gc = 0;
+
+ /** Constructor with InputStream. */
+ public OriginalSyntaxParser(java.io.InputStream stream) {
+ this(stream, null);
+ }
+ /** Constructor with InputStream and supplied encoding */
+ public OriginalSyntaxParser(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source = new OriginalSyntaxParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream stream) {
+ ReInit(stream, null);
+ }
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Constructor. */
+ public OriginalSyntaxParser(java.io.Reader stream) {
+ jj_input_stream = new JavaCharStream(stream, 1, 1);
+ token_source = new OriginalSyntaxParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader stream) {
+ jj_input_stream.ReInit(stream, 1, 1);
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Constructor with generated Token Manager. */
+ public OriginalSyntaxParser(OriginalSyntaxParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Reinitialise. */
+ public void ReInit(OriginalSyntaxParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 25; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ private Token jj_consume_token(int kind) throws ParseException {
+ Token oldToken;
+ if ((oldToken = token).next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ if (token.kind == kind) {
+ jj_gen++;
+ if (++jj_gc > 100) {
+ jj_gc = 0;
+ for (int i = 0; i < jj_2_rtns.length; i++) {
+ JJCalls c = jj_2_rtns[i];
+ while (c != null) {
+ if (c.gen < jj_gen) c.first = null;
+ c = c.next;
+ }
+ }
+ }
+ return token;
+ }
+ token = oldToken;
+ jj_kind = kind;
+ throw generateParseException();
+ }
+
+ static private final class LookaheadSuccess extends java.lang.Error { }
+ final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+ private boolean jj_scan_token(int kind) {
+ if (jj_scanpos == jj_lastpos) {
+ jj_la--;
+ if (jj_scanpos.next == null) {
+ jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+ } else {
+ jj_lastpos = jj_scanpos = jj_scanpos.next;
+ }
+ } else {
+ jj_scanpos = jj_scanpos.next;
+ }
+ if (jj_rescan) {
+ int i = 0; Token tok = token;
+ while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+ if (tok != null) jj_add_error_token(kind, i);
+ }
+ if (jj_scanpos.kind != kind) return true;
+ if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+ return false;
+ }
+
+
+/** Get the next Token. */
+ final public Token getNextToken() {
+ if (token.next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ jj_gen++;
+ return token;
+ }
+
+/** Get the specific Token. */
+ final public Token getToken(int index) {
+ Token t = token;
+ for (int i = 0; i < index; i++) {
+ if (t.next != null) t = t.next;
+ else t = t.next = token_source.getNextToken();
+ }
+ return t;
+ }
+
+ private int jj_ntk() {
+ if ((jj_nt=token.next) == null)
+ return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+ else
+ return (jj_ntk = jj_nt.kind);
+ }
+
+ private java.util.List jj_expentries = new java.util.ArrayList();
+ private int[] jj_expentry;
+ private int jj_kind = -1;
+ private int[] jj_lasttokens = new int[100];
+ private int jj_endpos;
+
+ private void jj_add_error_token(int kind, int pos) {
+ if (pos >= 100) return;
+ if (pos == jj_endpos + 1) {
+ jj_lasttokens[jj_endpos++] = kind;
+ } else if (jj_endpos != 0) {
+ jj_expentry = new int[jj_endpos];
+ for (int i = 0; i < jj_endpos; i++) {
+ jj_expentry[i] = jj_lasttokens[i];
+ }
+ jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) {
+ int[] oldentry = (int[])(it.next());
+ if (oldentry.length == jj_expentry.length) {
+ for (int i = 0; i < jj_expentry.length; i++) {
+ if (oldentry[i] != jj_expentry[i]) {
+ continue jj_entries_loop;
+ }
+ }
+ jj_expentries.add(jj_expentry);
+ break jj_entries_loop;
+ }
+ }
+ if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+ }
+ }
+
+ /** Generate ParseException. */
+ public ParseException generateParseException() {
+ jj_expentries.clear();
+ boolean[] la1tokens = new boolean[34];
+ if (jj_kind >= 0) {
+ la1tokens[jj_kind] = true;
+ jj_kind = -1;
+ }
+ for (int i = 0; i < 25; i++) {
+ if (jj_la1[i] == jj_gen) {
+ for (int j = 0; j < 32; j++) {
+ if ((jj_la1_0[i] & (1< jj_gen) {
+ jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+ switch (i) {
+ case 0: jj_3_1(); break;
+ }
+ }
+ p = p.next;
+ } while (p != null);
+ } catch(LookaheadSuccess ls) { }
+ }
+ jj_rescan = false;
+ }
+
+ private void jj_save(int index, int xla) {
+ JJCalls p = jj_2_rtns[index];
+ while (p.gen > jj_gen) {
+ if (p.next == null) { p = p.next = new JJCalls(); break; }
+ p = p.next;
+ }
+ p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+ }
+
+ static final class JJCalls {
+ int gen;
+ Token first;
+ int arg;
+ JJCalls next;
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParser.jj b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParser.jj
new file mode 100644
index 00000000000..125edc07e9e
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParser.jj
@@ -0,0 +1,484 @@
+/**
+ * Original file is based on the TextParser.jj from lucene 2.3
+ */
+
+options {
+ STATIC=false;
+ JAVA_UNICODE_ESCAPE=true;
+ USER_CHAR_STREAM=false;
+ IGNORE_CASE=false;
+ JDK_VERSION="1.5";
+}
+
+PARSER_BEGIN(OriginalSyntaxParser)
+package org.apache.lucene.queryParser.original.parser;
+
+/**
+ * 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.
+ */
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.apache.lucene.messages.Message;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeError;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.QueryNodeParseException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.OpaqueQueryNode;
+import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.core.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.core.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ProximityQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryParser.core.nodes.QuotedFieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.parser.SyntaxParser;
+
+@SuppressWarnings("all")
+public class OriginalSyntaxParser implements SyntaxParser {
+
+ private static final int CONJ_NONE =0;
+ private static final int CONJ_AND =2;
+ private static final int CONJ_OR =2;
+
+
+ // syntax parser constructor
+ public OriginalSyntaxParser() {
+ this(new StringReader(""));
+ }
+ /** Parses a query string, returning a {@link org.apache.lucene.queryParser.core.nodes.QueryNode}.
+ * @param query the query string to be parsed.
+ * @throws ParseException if the parsing fails
+ */
+ public QueryNode parse(CharSequence query, CharSequence field) throws QueryNodeParseException {
+ ReInit(new StringReader(query.toString()));
+ try {
+ // TopLevelQuery is a Query followed by the end-of-input (EOF)
+ QueryNode querynode = TopLevelQuery(field);
+ return querynode;
+ }
+ catch (ParseException tme) {
+ tme.setQuery(query);
+ throw tme;
+ }
+ catch (Error tme) {
+ Message message = new MessageImpl(QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, tme.getMessage());
+ QueryNodeParseException e = new QueryNodeParseException(tme);
+ e.setQuery(query);
+ e.setNonLocalizedMessage(message);
+ throw e;
+ }
+ }
+
+}
+
+PARSER_END(OriginalSyntaxParser)
+
+/* ***************** */
+/* Token Definitions */
+/* ***************** */
+
+<*> TOKEN : {
+ <#_NUM_CHAR: ["0"-"9"] >
+// every character that follows a backslash is considered as an escaped character
+| <#_ESCAPED_CHAR: "\\" ~[] >
+| <#_TERM_START_CHAR: ( ~[ " ", "\t", "\n", "\r", "\u3000", "+", "-", "!", "(", ")", ":", "^",
+ "[", "]", "\"", "{", "}", "~", "*", "?", "\\" ]
+ | <_ESCAPED_CHAR> ) >
+| <#_TERM_CHAR: ( <_TERM_START_CHAR> | <_ESCAPED_CHAR> | "-" | "+" ) >
+| <#_WHITESPACE: ( " " | "\t" | "\n" | "\r" | "\u3000") >
+| <#_QUOTED_CHAR: ( ~[ "\"", "\\" ] | <_ESCAPED_CHAR> ) >
+}
+
+ SKIP : {
+ < <_WHITESPACE>>
+}
+
+ TOKEN : {
+
+|
+|
+|
+|
+|
+|
+|
+|
+| : Boost
+| )* "\"">
+| (<_TERM_CHAR>)* >
+| )+ ( "." (<_NUM_CHAR>)+ )? )? >
+| (<_TERM_CHAR>)* "*" ) >
+| | [ "*", "?" ]) (<_TERM_CHAR> | ( [ "*", "?" ] ))* >
+| : RangeIn
+| : RangeEx
+}
+
+ TOKEN : {
+)+ ( "." (<_NUM_CHAR>)+ )? > : DEFAULT
+}
+
+ TOKEN : {
+
+| : DEFAULT
+|
+|
+}
+
+ TOKEN : {
+
+| : DEFAULT
+|
+|
+}
+
+// * Query ::= ( Clause )*
+// * Clause ::= ["+", "-"] [ ":"] ( | "(" Query ")" )
+
+int Conjunction() : {
+ int ret = CONJ_NONE;
+}
+{
+ [
+ { ret = CONJ_AND; }
+ | { ret = CONJ_OR; }
+ ]
+ { return ret; }
+}
+
+ModifierQueryNode.Modifier Modifiers() : {
+ ModifierQueryNode.Modifier ret = ModifierQueryNode.Modifier.MOD_NONE;
+}
+{
+ [
+ { ret = ModifierQueryNode.Modifier.MOD_REQ; }
+ | { ret = ModifierQueryNode.Modifier.MOD_NOT; }
+ | { ret = ModifierQueryNode.Modifier.MOD_NOT; }
+ ]
+ { return ret; }
+}
+
+// This makes sure that there is no garbage after the query string
+QueryNode TopLevelQuery(CharSequence field) :
+{
+ QueryNode q;
+}
+{
+ q=Query(field)
+ {
+ return q;
+ }
+}
+
+// These changes were made to introduce operator precedence:
+// - Clause() now returns a QueryNode.
+// - The modifiers are consumed by Clause() and returned as part of the QueryNode Object
+// - Query does not consume conjunctions (AND, OR) anymore.
+// - This is now done by two new non-terminals: ConjClause and DisjClause
+// The parse tree looks similar to this:
+// Query ::= DisjQuery ( DisjQuery )*
+// DisjQuery ::= ConjQuery ( OR ConjQuery )*
+// ConjQuery ::= Clause ( AND Clause )*
+// Clause ::= [ Modifier ] ...
+
+
+QueryNode Query(CharSequence field) :
+{
+ Vector clauses = null;
+ QueryNode c, first=null;
+}
+{
+ first=DisjQuery(field)
+ (
+ c=DisjQuery(field)
+ {
+ if (clauses == null) {
+ clauses = new Vector();
+ clauses.addElement(first);
+ }
+ clauses.addElement(c);
+ }
+ )*
+ {
+ if (clauses != null) {
+ return new BooleanQueryNode(clauses);
+ } else {
+ return first;
+ }
+ }
+}
+
+QueryNode DisjQuery(CharSequence field) : {
+ QueryNode first, c;
+ Vector clauses = null;
+}
+{
+ first = ConjQuery(field)
+ (
+ c=ConjQuery(field)
+ {
+ if (clauses == null) {
+ clauses = new Vector();
+ clauses.addElement(first);
+ }
+ clauses.addElement(c);
+ }
+ )*
+ {
+ if (clauses != null) {
+ return new OrQueryNode(clauses);
+ } else {
+ return first;
+ }
+ }
+}
+
+QueryNode ConjQuery(CharSequence field) : {
+ QueryNode first, c;
+ Vector clauses = null;
+}
+{
+ first = ModClause(field)
+ (
+ c=ModClause(field)
+ {
+ if (clauses == null) {
+ clauses = new Vector();
+ clauses.addElement(first);
+ }
+ clauses.addElement(c);
+ }
+ )*
+ {
+ if (clauses != null) {
+ return new AndQueryNode(clauses);
+ } else {
+ return first;
+ }
+ }
+}
+
+// QueryNode Query(CharSequence field) :
+// {
+// List clauses = new ArrayList();
+// List modifiers = new ArrayList();
+// QueryNode q, firstQuery=null;
+// ModifierQueryNode.Modifier mods;
+// int conj;
+// }
+// {
+// mods=Modifiers() q=Clause(field)
+// {
+// if (mods == ModifierQueryNode.Modifier.MOD_NONE) firstQuery=q;
+//
+// // do not create modifier nodes with MOD_NONE
+// if (mods != ModifierQueryNode.Modifier.MOD_NONE) {
+// q = new ModifierQueryNode(q, mods);
+// }
+// clauses.add(q);
+// }
+// (
+// conj=Conjunction() mods=Modifiers() q=Clause(field)
+// {
+// // do not create modifier nodes with MOD_NONE
+// if (mods != ModifierQueryNode.Modifier.MOD_NONE) {
+// q = new ModifierQueryNode(q, mods);
+// }
+// clauses.add(q);
+// //TODO: figure out what to do with AND and ORs
+// }
+// )*
+// {
+// if (clauses.size() == 1 && firstQuery != null)
+// return firstQuery;
+// else {
+// return new BooleanQueryNode(clauses);
+// }
+// }
+// }
+
+QueryNode ModClause(CharSequence field) : {
+ QueryNode q;
+ ModifierQueryNode.Modifier mods;
+}
+{
+ mods=Modifiers() q= Clause(field) {
+ if (mods != ModifierQueryNode.Modifier.MOD_NONE) {
+ q = new ModifierQueryNode(q, mods);
+ }
+ return q;
+ }
+}
+
+QueryNode Clause(CharSequence field) : {
+ QueryNode q;
+ Token fieldToken=null, boost=null;
+ boolean group = false;
+}
+{
+ [
+ LOOKAHEAD(2)
+ (
+ fieldToken= {field=EscapeQuerySyntaxImpl.discardEscapeChar(fieldToken.image);}
+ | {field="*";}
+ )
+ ]
+
+ (
+ q=Term(field)
+ | q=Query(field) ( boost=)? {group=true;}
+
+ )
+ {
+ if (boost != null) {
+ float f = (float)1.0;
+ try {
+ f = Float.valueOf(boost.image).floatValue();
+ // avoid boosting null queries, such as those caused by stop words
+ if (q != null) {
+ q = new BoostQueryNode(q, f);
+ }
+ } catch (Exception ignored) {
+ /* Should this be handled somehow? (defaults to "no boost", if
+ * boost number is invalid)
+ */
+ }
+ }
+ if (group) { q = new GroupQueryNode(q);}
+ return q;
+ }
+}
+
+
+QueryNode Term(CharSequence field) : {
+ Token term, boost=null, fuzzySlop=null, goop1, goop2;
+ boolean prefix = false;
+ boolean wildcard = false;
+ boolean fuzzy = false;
+ QueryNode q =null;
+ ParametricQueryNode qLower, qUpper;
+ float defaultMinSimilarity = 0.5f;
+}
+{
+ (
+ (
+ term= { q = new FieldQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+ | term= { wildcard=true; q = new WildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+ | term= { prefix=true; q = new PrefixWildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+ | term= { wildcard=true; q = new WildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+ | term=
+ )
+ [ fuzzySlop= { fuzzy=true; } ]
+ [ boost= [ fuzzySlop= { fuzzy=true; } ] ]
+ {
+ if (!wildcard && !prefix && fuzzy) {
+ float fms = defaultMinSimilarity;
+ try {
+ fms = Float.valueOf(fuzzySlop.image.substring(1)).floatValue();
+ } catch (Exception ignored) { }
+ if(fms < 0.0f || fms > 1.0f){
+ throw new ParseException(new MessageImpl(QueryParserMessages.INVALID_SYNTAX_FUZZY_LIMITS));
+ }
+ q = new FuzzyQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), fms, term.beginColumn, term.endColumn);
+ }
+ }
+ | ( ( goop1=|goop1= )
+ [ ] ( goop2=|goop2= )
+ )
+ [ boost= ]
+ {
+ if (goop1.kind == RANGEIN_QUOTED) {
+ goop1.image = goop1.image.substring(1, goop1.image.length()-1);
+ }
+ if (goop2.kind == RANGEIN_QUOTED) {
+ goop2.image = goop2.image.substring(1, goop2.image.length()-1);
+ }
+
+ qLower = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.GE,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop1.image), goop1.beginColumn, goop1.endColumn);
+ qUpper = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.LE,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop2.image), goop2.beginColumn, goop2.endColumn);
+ q = new ParametricRangeQueryNode(qLower, qUpper);
+ }
+ | ( ( goop1=|goop1= )
+ [ ] ( goop2=|goop2= )
+ )
+ [ boost= ]
+ {
+ if (goop1.kind == RANGEEX_QUOTED) {
+ goop1.image = goop1.image.substring(1, goop1.image.length()-1);
+ }
+ if (goop2.kind == RANGEEX_QUOTED) {
+ goop2.image = goop2.image.substring(1, goop2.image.length()-1);
+ }
+ qLower = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.GT,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop1.image), goop1.beginColumn, goop1.endColumn);
+ qUpper = new ParametricQueryNode(field, ParametricQueryNode.CompareOperator.LT,
+ EscapeQuerySyntaxImpl.discardEscapeChar(goop2.image), goop2.beginColumn, goop2.endColumn);
+ q = new ParametricRangeQueryNode(qLower, qUpper);
+ }
+ | term= {q = new QuotedFieldQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image.substring(1, term.image.length()-1)), term.beginColumn + 1, term.endColumn - 1);}
+ [ fuzzySlop= ]
+ [ boost= ]
+ {
+ int phraseSlop = 0;
+
+ if (fuzzySlop != null) {
+ try {
+ phraseSlop = Float.valueOf(fuzzySlop.image.substring(1)).intValue();
+ q = new SlopQueryNode(q, phraseSlop);
+ }
+ catch (Exception ignored) {
+ /* Should this be handled somehow? (defaults to "no PhraseSlop", if
+ * slop number is invalid)
+ */
+ }
+ }
+
+ }
+ )
+ {
+ if (boost != null) {
+ float f = (float)1.0;
+ try {
+ f = Float.valueOf(boost.image).floatValue();
+ // avoid boosting null queries, such as those caused by stop words
+ if (q != null) {
+ q = new BoostQueryNode(q, f);
+ }
+ } catch (Exception ignored) {
+ /* Should this be handled somehow? (defaults to "no boost", if
+ * boost number is invalid)
+ */
+ }
+ }
+ return q;
+ }
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParserConstants.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParserConstants.java
new file mode 100644
index 00000000000..6fa5a47570b
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParserConstants.java
@@ -0,0 +1,125 @@
+/* Generated By:JavaCC: Do not edit this line. OriginalSyntaxParserConstants.java */
+package org.apache.lucene.queryParser.original.parser;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface OriginalSyntaxParserConstants {
+
+ /** End of File. */
+ int EOF = 0;
+ /** RegularExpression Id. */
+ int _NUM_CHAR = 1;
+ /** RegularExpression Id. */
+ int _ESCAPED_CHAR = 2;
+ /** RegularExpression Id. */
+ int _TERM_START_CHAR = 3;
+ /** RegularExpression Id. */
+ int _TERM_CHAR = 4;
+ /** RegularExpression Id. */
+ int _WHITESPACE = 5;
+ /** RegularExpression Id. */
+ int _QUOTED_CHAR = 6;
+ /** RegularExpression Id. */
+ int AND = 8;
+ /** RegularExpression Id. */
+ int OR = 9;
+ /** RegularExpression Id. */
+ int NOT = 10;
+ /** RegularExpression Id. */
+ int PLUS = 11;
+ /** RegularExpression Id. */
+ int MINUS = 12;
+ /** RegularExpression Id. */
+ int LPAREN = 13;
+ /** RegularExpression Id. */
+ int RPAREN = 14;
+ /** RegularExpression Id. */
+ int COLON = 15;
+ /** RegularExpression Id. */
+ int STAR = 16;
+ /** RegularExpression Id. */
+ int CARAT = 17;
+ /** RegularExpression Id. */
+ int QUOTED = 18;
+ /** RegularExpression Id. */
+ int TERM = 19;
+ /** RegularExpression Id. */
+ int FUZZY_SLOP = 20;
+ /** RegularExpression Id. */
+ int PREFIXTERM = 21;
+ /** RegularExpression Id. */
+ int WILDTERM = 22;
+ /** RegularExpression Id. */
+ int RANGEIN_START = 23;
+ /** RegularExpression Id. */
+ int RANGEEX_START = 24;
+ /** RegularExpression Id. */
+ int NUMBER = 25;
+ /** RegularExpression Id. */
+ int RANGEIN_TO = 26;
+ /** RegularExpression Id. */
+ int RANGEIN_END = 27;
+ /** RegularExpression Id. */
+ int RANGEIN_QUOTED = 28;
+ /** RegularExpression Id. */
+ int RANGEIN_GOOP = 29;
+ /** RegularExpression Id. */
+ int RANGEEX_TO = 30;
+ /** RegularExpression Id. */
+ int RANGEEX_END = 31;
+ /** RegularExpression Id. */
+ int RANGEEX_QUOTED = 32;
+ /** RegularExpression Id. */
+ int RANGEEX_GOOP = 33;
+
+ /** Lexical state. */
+ int Boost = 0;
+ /** Lexical state. */
+ int RangeEx = 1;
+ /** Lexical state. */
+ int RangeIn = 2;
+ /** Lexical state. */
+ int DEFAULT = 3;
+
+ /** Literal token values. */
+ String[] tokenImage = {
+ "",
+ "<_NUM_CHAR>",
+ "<_ESCAPED_CHAR>",
+ "<_TERM_START_CHAR>",
+ "<_TERM_CHAR>",
+ "<_WHITESPACE>",
+ "<_QUOTED_CHAR>",
+ "",
+ "",
+ "",
+ "",
+ "\"+\"",
+ "\"-\"",
+ "\"(\"",
+ "\")\"",
+ "\":\"",
+ "\"*\"",
+ "\"^\"",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "\"[\"",
+ "\"{\"",
+ "",
+ "\"TO\"",
+ "\"]\"",
+ "",
+ "",
+ "\"TO\"",
+ "\"}\"",
+ "",
+ "",
+ };
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParserTokenManager.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParserTokenManager.java
new file mode 100644
index 00000000000..2ff8d395816
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/OriginalSyntaxParserTokenManager.java
@@ -0,0 +1,1247 @@
+/* Generated By:JavaCC: Do not edit this line. OriginalSyntaxParserTokenManager.java */
+package org.apache.lucene.queryParser.original.parser;
+/**
+ * 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.
+ */
+
+
+/** Token Manager. */
+@SuppressWarnings("unused")
+public class OriginalSyntaxParserTokenManager implements OriginalSyntaxParserConstants
+{
+
+ /** Debug output. */
+ public java.io.PrintStream debugStream = System.out;
+ /** Set debug output. */
+ public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_3(int pos, long active0)
+{
+ switch (pos)
+ {
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_3(int pos, long active0)
+{
+ return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_3()
+{
+ switch(curChar)
+ {
+ case 40:
+ return jjStopAtPos(0, 13);
+ case 41:
+ return jjStopAtPos(0, 14);
+ case 42:
+ return jjStartNfaWithStates_3(0, 16, 36);
+ case 43:
+ return jjStopAtPos(0, 11);
+ case 45:
+ return jjStopAtPos(0, 12);
+ case 58:
+ return jjStopAtPos(0, 15);
+ case 91:
+ return jjStopAtPos(0, 23);
+ case 94:
+ return jjStopAtPos(0, 17);
+ case 123:
+ return jjStopAtPos(0, 24);
+ default :
+ return jjMoveNfa_3(0, 0);
+ }
+}
+private int jjStartNfaWithStates_3(int pos, int kind, int state)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return pos + 1; }
+ return jjMoveNfa_3(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+ 0x1L, 0x0L, 0x0L, 0x0L
+};
+static final long[] jjbitVec1 = {
+ 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec3 = {
+ 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec4 = {
+ 0xfffefffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_3(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 36;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 36:
+ case 25:
+ if ((0xfbfffcf8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 0:
+ if ((0xfbffd4f8ffffd9ffL & l) != 0L)
+ {
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ }
+ else if ((0x100002600L & l) != 0L)
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ else if (curChar == 34)
+ jjCheckNAddStates(0, 2);
+ else if (curChar == 33)
+ {
+ if (kind > 10)
+ kind = 10;
+ }
+ if ((0x7bffd0f8ffffd9ffL & l) != 0L)
+ {
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddStates(3, 7);
+ }
+ else if (curChar == 42)
+ {
+ if (kind > 21)
+ kind = 21;
+ }
+ if (curChar == 38)
+ jjstateSet[jjnewStateCnt++] = 4;
+ break;
+ case 4:
+ if (curChar == 38 && kind > 8)
+ kind = 8;
+ break;
+ case 5:
+ if (curChar == 38)
+ jjstateSet[jjnewStateCnt++] = 4;
+ break;
+ case 13:
+ if (curChar == 33 && kind > 10)
+ kind = 10;
+ break;
+ case 14:
+ if (curChar == 34)
+ jjCheckNAddStates(0, 2);
+ break;
+ case 15:
+ if ((0xfffffffbffffffffL & l) != 0L)
+ jjCheckNAddStates(0, 2);
+ break;
+ case 17:
+ jjCheckNAddStates(0, 2);
+ break;
+ case 18:
+ if (curChar == 34 && kind > 18)
+ kind = 18;
+ break;
+ case 20:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ jjAddStates(8, 9);
+ break;
+ case 21:
+ if (curChar == 46)
+ jjCheckNAdd(22);
+ break;
+ case 22:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 20)
+ kind = 20;
+ jjCheckNAdd(22);
+ break;
+ case 23:
+ if (curChar == 42 && kind > 21)
+ kind = 21;
+ break;
+ case 24:
+ if ((0xfbffd4f8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 27:
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 28:
+ if ((0x7bffd0f8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddStates(3, 7);
+ break;
+ case 29:
+ if ((0x7bfff8f8ffffd9ffL & l) == 0L)
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddTwoStates(29, 30);
+ break;
+ case 31:
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddTwoStates(29, 30);
+ break;
+ case 32:
+ if ((0x7bfff8f8ffffd9ffL & l) != 0L)
+ jjCheckNAddStates(10, 12);
+ break;
+ case 34:
+ jjCheckNAddStates(10, 12);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 36:
+ if ((0x97ffffff87ffffffL & l) != 0L)
+ {
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ }
+ else if (curChar == 92)
+ jjCheckNAddTwoStates(27, 27);
+ break;
+ case 0:
+ if ((0x97ffffff87ffffffL & l) != 0L)
+ {
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddStates(3, 7);
+ }
+ else if (curChar == 92)
+ jjCheckNAddStates(13, 15);
+ else if (curChar == 126)
+ {
+ if (kind > 20)
+ kind = 20;
+ jjstateSet[jjnewStateCnt++] = 20;
+ }
+ if ((0x97ffffff87ffffffL & l) != 0L)
+ {
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ }
+ if (curChar == 78)
+ jjstateSet[jjnewStateCnt++] = 11;
+ else if (curChar == 124)
+ jjstateSet[jjnewStateCnt++] = 8;
+ else if (curChar == 79)
+ jjstateSet[jjnewStateCnt++] = 6;
+ else if (curChar == 65)
+ jjstateSet[jjnewStateCnt++] = 2;
+ break;
+ case 1:
+ if (curChar == 68 && kind > 8)
+ kind = 8;
+ break;
+ case 2:
+ if (curChar == 78)
+ jjstateSet[jjnewStateCnt++] = 1;
+ break;
+ case 3:
+ if (curChar == 65)
+ jjstateSet[jjnewStateCnt++] = 2;
+ break;
+ case 6:
+ if (curChar == 82 && kind > 9)
+ kind = 9;
+ break;
+ case 7:
+ if (curChar == 79)
+ jjstateSet[jjnewStateCnt++] = 6;
+ break;
+ case 8:
+ if (curChar == 124 && kind > 9)
+ kind = 9;
+ break;
+ case 9:
+ if (curChar == 124)
+ jjstateSet[jjnewStateCnt++] = 8;
+ break;
+ case 10:
+ if (curChar == 84 && kind > 10)
+ kind = 10;
+ break;
+ case 11:
+ if (curChar == 79)
+ jjstateSet[jjnewStateCnt++] = 10;
+ break;
+ case 12:
+ if (curChar == 78)
+ jjstateSet[jjnewStateCnt++] = 11;
+ break;
+ case 15:
+ if ((0xffffffffefffffffL & l) != 0L)
+ jjCheckNAddStates(0, 2);
+ break;
+ case 16:
+ if (curChar == 92)
+ jjstateSet[jjnewStateCnt++] = 17;
+ break;
+ case 17:
+ jjCheckNAddStates(0, 2);
+ break;
+ case 19:
+ if (curChar != 126)
+ break;
+ if (kind > 20)
+ kind = 20;
+ jjstateSet[jjnewStateCnt++] = 20;
+ break;
+ case 24:
+ if ((0x97ffffff87ffffffL & l) == 0L)
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 25:
+ if ((0x97ffffff87ffffffL & l) == 0L)
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 26:
+ if (curChar == 92)
+ jjCheckNAddTwoStates(27, 27);
+ break;
+ case 27:
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 28:
+ if ((0x97ffffff87ffffffL & l) == 0L)
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddStates(3, 7);
+ break;
+ case 29:
+ if ((0x97ffffff87ffffffL & l) == 0L)
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddTwoStates(29, 30);
+ break;
+ case 30:
+ if (curChar == 92)
+ jjCheckNAddTwoStates(31, 31);
+ break;
+ case 31:
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddTwoStates(29, 30);
+ break;
+ case 32:
+ if ((0x97ffffff87ffffffL & l) != 0L)
+ jjCheckNAddStates(10, 12);
+ break;
+ case 33:
+ if (curChar == 92)
+ jjCheckNAddTwoStates(34, 34);
+ break;
+ case 34:
+ jjCheckNAddStates(10, 12);
+ break;
+ case 35:
+ if (curChar == 92)
+ jjCheckNAddStates(13, 15);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 36:
+ case 25:
+ if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 0:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ if (jjCanMove_2(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ }
+ if (jjCanMove_2(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddStates(3, 7);
+ }
+ break;
+ case 15:
+ case 17:
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ jjCheckNAddStates(0, 2);
+ break;
+ case 24:
+ if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 27:
+ if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 22)
+ kind = 22;
+ jjCheckNAddTwoStates(25, 26);
+ break;
+ case 28:
+ if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddStates(3, 7);
+ break;
+ case 29:
+ if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddTwoStates(29, 30);
+ break;
+ case 31:
+ if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 19)
+ kind = 19;
+ jjCheckNAddTwoStates(29, 30);
+ break;
+ case 32:
+ if (jjCanMove_2(hiByte, i1, i2, l1, l2))
+ jjCheckNAddStates(10, 12);
+ break;
+ case 34:
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ jjCheckNAddStates(10, 12);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 36 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private final int jjStopStringLiteralDfa_1(int pos, long active0)
+{
+ switch (pos)
+ {
+ case 0:
+ if ((active0 & 0x40000000L) != 0L)
+ {
+ jjmatchedKind = 33;
+ return 6;
+ }
+ return -1;
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_1(int pos, long active0)
+{
+ return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_1()
+{
+ switch(curChar)
+ {
+ case 84:
+ return jjMoveStringLiteralDfa1_1(0x40000000L);
+ case 125:
+ return jjStopAtPos(0, 31);
+ default :
+ return jjMoveNfa_1(0, 0);
+ }
+}
+private int jjMoveStringLiteralDfa1_1(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_1(0, active0);
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 79:
+ if ((active0 & 0x40000000L) != 0L)
+ return jjStartNfaWithStates_1(1, 30, 6);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_1(0, active0);
+}
+private int jjStartNfaWithStates_1(int pos, int kind, int state)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return pos + 1; }
+ return jjMoveNfa_1(state, pos + 1);
+}
+private int jjMoveNfa_1(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 7;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0xfffffffeffffffffL & l) != 0L)
+ {
+ if (kind > 33)
+ kind = 33;
+ jjCheckNAdd(6);
+ }
+ if ((0x100002600L & l) != 0L)
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ else if (curChar == 34)
+ jjCheckNAddTwoStates(2, 4);
+ break;
+ case 1:
+ if (curChar == 34)
+ jjCheckNAddTwoStates(2, 4);
+ break;
+ case 2:
+ if ((0xfffffffbffffffffL & l) != 0L)
+ jjCheckNAddStates(16, 18);
+ break;
+ case 3:
+ if (curChar == 34)
+ jjCheckNAddStates(16, 18);
+ break;
+ case 5:
+ if (curChar == 34 && kind > 32)
+ kind = 32;
+ break;
+ case 6:
+ if ((0xfffffffeffffffffL & l) == 0L)
+ break;
+ if (kind > 33)
+ kind = 33;
+ jjCheckNAdd(6);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ case 6:
+ if ((0xdfffffffffffffffL & l) == 0L)
+ break;
+ if (kind > 33)
+ kind = 33;
+ jjCheckNAdd(6);
+ break;
+ case 2:
+ jjAddStates(16, 18);
+ break;
+ case 4:
+ if (curChar == 92)
+ jjstateSet[jjnewStateCnt++] = 3;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 33)
+ kind = 33;
+ jjCheckNAdd(6);
+ }
+ break;
+ case 2:
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ jjAddStates(16, 18);
+ break;
+ case 6:
+ if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 33)
+ kind = 33;
+ jjCheckNAdd(6);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+ return jjMoveNfa_0(0, 0);
+}
+private int jjMoveNfa_0(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 3;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 25)
+ kind = 25;
+ jjAddStates(19, 20);
+ break;
+ case 1:
+ if (curChar == 46)
+ jjCheckNAdd(2);
+ break;
+ case 2:
+ if ((0x3ff000000000000L & l) == 0L)
+ break;
+ if (kind > 25)
+ kind = 25;
+ jjCheckNAdd(2);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private final int jjStopStringLiteralDfa_2(int pos, long active0)
+{
+ switch (pos)
+ {
+ case 0:
+ if ((active0 & 0x4000000L) != 0L)
+ {
+ jjmatchedKind = 29;
+ return 6;
+ }
+ return -1;
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_2(int pos, long active0)
+{
+ return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_2()
+{
+ switch(curChar)
+ {
+ case 84:
+ return jjMoveStringLiteralDfa1_2(0x4000000L);
+ case 93:
+ return jjStopAtPos(0, 27);
+ default :
+ return jjMoveNfa_2(0, 0);
+ }
+}
+private int jjMoveStringLiteralDfa1_2(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_2(0, active0);
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 79:
+ if ((active0 & 0x4000000L) != 0L)
+ return jjStartNfaWithStates_2(1, 26, 6);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_2(0, active0);
+}
+private int jjStartNfaWithStates_2(int pos, int kind, int state)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return pos + 1; }
+ return jjMoveNfa_2(state, pos + 1);
+}
+private int jjMoveNfa_2(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 7;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0xfffffffeffffffffL & l) != 0L)
+ {
+ if (kind > 29)
+ kind = 29;
+ jjCheckNAdd(6);
+ }
+ if ((0x100002600L & l) != 0L)
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ else if (curChar == 34)
+ jjCheckNAddTwoStates(2, 4);
+ break;
+ case 1:
+ if (curChar == 34)
+ jjCheckNAddTwoStates(2, 4);
+ break;
+ case 2:
+ if ((0xfffffffbffffffffL & l) != 0L)
+ jjCheckNAddStates(16, 18);
+ break;
+ case 3:
+ if (curChar == 34)
+ jjCheckNAddStates(16, 18);
+ break;
+ case 5:
+ if (curChar == 34 && kind > 28)
+ kind = 28;
+ break;
+ case 6:
+ if ((0xfffffffeffffffffL & l) == 0L)
+ break;
+ if (kind > 29)
+ kind = 29;
+ jjCheckNAdd(6);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ case 6:
+ if ((0xffffffffdfffffffL & l) == 0L)
+ break;
+ if (kind > 29)
+ kind = 29;
+ jjCheckNAdd(6);
+ break;
+ case 2:
+ jjAddStates(16, 18);
+ break;
+ case 4:
+ if (curChar == 92)
+ jjstateSet[jjnewStateCnt++] = 3;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 7)
+ kind = 7;
+ }
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ {
+ if (kind > 29)
+ kind = 29;
+ jjCheckNAdd(6);
+ }
+ break;
+ case 2:
+ if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+ jjAddStates(16, 18);
+ break;
+ case 6:
+ if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 29)
+ kind = 29;
+ jjCheckNAdd(6);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+static final int[] jjnextStates = {
+ 15, 16, 18, 29, 32, 23, 33, 30, 20, 21, 32, 23, 33, 31, 34, 27,
+ 2, 4, 5, 0, 1,
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+ switch(hiByte)
+ {
+ case 48:
+ return ((jjbitVec0[i2] & l2) != 0L);
+ default :
+ return false;
+ }
+}
+private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2)
+{
+ switch(hiByte)
+ {
+ case 0:
+ return ((jjbitVec3[i2] & l2) != 0L);
+ default :
+ if ((jjbitVec1[i1] & l1) != 0L)
+ return true;
+ return false;
+ }
+}
+private static final boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2)
+{
+ switch(hiByte)
+ {
+ case 0:
+ return ((jjbitVec3[i2] & l2) != 0L);
+ case 48:
+ return ((jjbitVec1[i2] & l2) != 0L);
+ default :
+ if ((jjbitVec4[i1] & l1) != 0L)
+ return true;
+ return false;
+ }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, "\53", "\55",
+"\50", "\51", "\72", "\52", "\136", null, null, null, null, null, "\133", "\173",
+null, "\124\117", "\135", null, null, "\124\117", "\175", null, null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+ "Boost",
+ "RangeEx",
+ "RangeIn",
+ "DEFAULT",
+};
+
+/** Lex State array. */
+public static final int[] jjnewLexState = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 2, 1,
+ 3, -1, 3, -1, -1, -1, 3, -1, -1,
+};
+static final long[] jjtoToken = {
+ 0x3ffffff01L,
+};
+static final long[] jjtoSkip = {
+ 0x80L,
+};
+protected JavaCharStream input_stream;
+private final int[] jjrounds = new int[36];
+private final int[] jjstateSet = new int[72];
+protected char curChar;
+/** Constructor. */
+public OriginalSyntaxParserTokenManager(JavaCharStream stream){
+ if (JavaCharStream.staticFlag)
+ throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+ input_stream = stream;
+}
+
+/** Constructor. */
+public OriginalSyntaxParserTokenManager(JavaCharStream stream, int lexState){
+ this(stream);
+ SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(JavaCharStream stream)
+{
+ jjmatchedPos = jjnewStateCnt = 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+}
+private void ReInitRounds()
+{
+ int i;
+ jjround = 0x80000001;
+ for (i = 36; i-- > 0;)
+ jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(JavaCharStream stream, int lexState)
+{
+ ReInit(stream);
+ SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+ if (lexState >= 4 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+ final Token t;
+ final String curTokenImage;
+ final int beginLine;
+ final int endLine;
+ final int beginColumn;
+ final int endColumn;
+ String im = jjstrLiteralImages[jjmatchedKind];
+ curTokenImage = (im == null) ? input_stream.GetImage() : im;
+ beginLine = input_stream.getBeginLine();
+ beginColumn = input_stream.getBeginColumn();
+ endLine = input_stream.getEndLine();
+ endColumn = input_stream.getEndColumn();
+ t = Token.newToken(jjmatchedKind, curTokenImage);
+
+ t.beginLine = beginLine;
+ t.endLine = endLine;
+ t.beginColumn = beginColumn;
+ t.endColumn = endColumn;
+
+ return t;
+}
+
+int curLexState = 3;
+int defaultLexState = 3;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken()
+{
+ Token matchedToken;
+ int curPos = 0;
+
+ EOFLoop :
+ for (;;)
+ {
+ try
+ {
+ curChar = input_stream.BeginToken();
+ }
+ catch(java.io.IOException e)
+ {
+ jjmatchedKind = 0;
+ matchedToken = jjFillToken();
+ return matchedToken;
+ }
+
+ switch(curLexState)
+ {
+ case 0:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_0();
+ break;
+ case 1:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_1();
+ break;
+ case 2:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_2();
+ break;
+ case 3:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_3();
+ break;
+ }
+ if (jjmatchedKind != 0x7fffffff)
+ {
+ if (jjmatchedPos + 1 < curPos)
+ input_stream.backup(curPos - jjmatchedPos - 1);
+ if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+ {
+ matchedToken = jjFillToken();
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ return matchedToken;
+ }
+ else
+ {
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ continue EOFLoop;
+ }
+ }
+ int error_line = input_stream.getEndLine();
+ int error_column = input_stream.getEndColumn();
+ String error_after = null;
+ boolean EOFSeen = false;
+ try { input_stream.readChar(); input_stream.backup(1); }
+ catch (java.io.IOException e1) {
+ EOFSeen = true;
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ if (curChar == '\n' || curChar == '\r') {
+ error_line++;
+ error_column = 0;
+ }
+ else
+ error_column++;
+ }
+ if (!EOFSeen) {
+ input_stream.backup(1);
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ }
+ throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+ }
+}
+
+private void jjCheckNAdd(int state)
+{
+ if (jjrounds[state] != jjround)
+ {
+ jjstateSet[jjnewStateCnt++] = state;
+ jjrounds[state] = jjround;
+ }
+}
+private void jjAddStates(int start, int end)
+{
+ do {
+ jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+ } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+ jjCheckNAdd(state1);
+ jjCheckNAdd(state2);
+}
+
+private void jjCheckNAddStates(int start, int end)
+{
+ do {
+ jjCheckNAdd(jjnextStates[start]);
+ } while (start++ != end);
+}
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/ParseException.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/ParseException.java
new file mode 100644
index 00000000000..15f87d7cad0
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/ParseException.java
@@ -0,0 +1,197 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package org.apache.lucene.queryParser.original.parser;
+
+/**
+ * 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.
+ */
+import org.apache.lucene.messages.Message;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeParseException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+
+/**
+ * This exception is thrown when parse errors are encountered. You can
+ * explicitly create objects of this exception type by calling the method
+ * generateParseException in the generated parser.
+ *
+ * You can modify this class to customize your error reporting mechanisms so
+ * long as you retain the public fields.
+ */
+public class ParseException extends QueryNodeParseException {
+
+ /**
+ * The version identifier for this Serializable class. Increment only if the
+ * serialized form of the class changes.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * This constructor is used by the method "generateParseException" in the
+ * generated parser. Calling this constructor generates a new object of this
+ * type with the fields "currentToken", "expectedTokenSequences", and
+ * "tokenImage" set.
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal, String[] tokenImageVal) {
+ super(new MessageImpl(QueryParserMessages.INVALID_SYNTAX, initialise(
+ currentTokenVal, expectedTokenSequencesVal, tokenImageVal)));
+ this.currentToken = currentTokenVal;
+ this.expectedTokenSequences = expectedTokenSequencesVal;
+ this.tokenImage = tokenImageVal;
+ }
+
+ public ParseException(Message message) {
+ super(message);
+ }
+
+ public ParseException() {
+ super(new MessageImpl(QueryParserMessages.INVALID_SYNTAX, "Error"));
+ }
+
+ /**
+ * This is the last token that has been consumed successfully. If this object
+ * has been created due to a parse error, the token followng this token will
+ * (therefore) be the first error token.
+ */
+ @SuppressWarnings("unused")
+ private Token currentToken;
+
+ /**
+ * Each entry in this array is an array of integers. Each array of integers
+ * represents a sequence of tokens (by their ordinal values) that is expected
+ * at this point of the parse.
+ */
+ @SuppressWarnings("unused")
+ private int[][] expectedTokenSequences;
+
+ /**
+ * This is a reference to the "tokenImage" array of the generated parser
+ * within which the parse error occurred. This array is defined in the
+ * generated ...Constants interface.
+ */
+ @SuppressWarnings("unused")
+ private String[] tokenImage;
+
+ /**
+ * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created due to a
+ * parse error, and you do not catch it (it gets thrown from the parser) the
+ * correct error message gets displayed.
+ */
+ private static String initialise(Token currentToken,
+ int[][] expectedTokenSequences, String[] tokenImage) {
+ String eol = System.getProperty("line.separator", "\n");
+ StringBuffer expected = new StringBuffer();
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+ expected.append("...");
+ }
+ expected.append(eol).append(" ");
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0)
+ retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += " " + tokenImage[tok.kind];
+ retval += " \"";
+ retval += add_escapes(tok.image);
+ retval += " \"";
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column "
+ + currentToken.next.beginColumn;
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected.toString();
+ return retval;
+ }
+
+ /**
+ * The end of line string for this machine.
+ */
+ @SuppressWarnings("unused")
+ private String eol = System.getProperty("line.separator", "\n");
+
+ /**
+ * Used to convert raw characters to their escaped version when these raw
+ * version cannot be used as part of an ASCII string literal.
+ */
+ static private String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i)) {
+ case 0:
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+}
+/*
+ * JavaCC - OriginalChecksum=c04ac45b94787832e67e6d1b49d8774c (do not edit this
+ * line)
+ */
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/Token.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/Token.java
new file mode 100644
index 00000000000..f877707971e
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/Token.java
@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.lucene.queryParser.original.parser;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+ /**
+ * The version identifier for this Serializable class.
+ * Increment only if the serialized form of the
+ * class changes.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * An integer that describes the kind of this token. This numbering
+ * system is determined by JavaCCParser, and a table of these numbers is
+ * stored in the file ...Constants.java.
+ */
+ public int kind;
+
+ /** The line number of the first character of this Token. */
+ public int beginLine;
+ /** The column number of the first character of this Token. */
+ public int beginColumn;
+ /** The line number of the last character of this Token. */
+ public int endLine;
+ /** The column number of the last character of this Token. */
+ public int endColumn;
+
+ /**
+ * The string image of the token.
+ */
+ public String image;
+
+ /**
+ * A reference to the next regular (non-special) token from the input
+ * stream. If this is the last token from the input stream, or if the
+ * token manager has not read tokens beyond this one, this field is
+ * set to null. This is true only if this token is also a regular
+ * token. Otherwise, see below for a description of the contents of
+ * this field.
+ */
+ public Token next;
+
+ /**
+ * This field is used to access special tokens that occur prior to this
+ * token, but after the immediately preceding regular (non-special) token.
+ * If there are no such special tokens, this field is set to null.
+ * When there are more than one such special token, this field refers
+ * to the last of these special tokens, which in turn refers to the next
+ * previous special token through its specialToken field, and so on
+ * until the first special token (whose specialToken field is null).
+ * The next fields of special tokens refer to other special tokens that
+ * immediately follow it (without an intervening regular token). If there
+ * is no such token, this field is null.
+ */
+ public Token specialToken;
+
+ /**
+ * An optional attribute value of the Token.
+ * Tokens which are not used as syntactic sugar will often contain
+ * meaningful values that will be used later on by the compiler or
+ * interpreter. This attribute value is often different from the image.
+ * Any subclass of Token that actually wants to return a non-null value can
+ * override this method as appropriate.
+ */
+ public Object getValue() {
+ return null;
+ }
+
+ /**
+ * No-argument constructor
+ */
+ public Token() {}
+
+ /**
+ * Constructs a new token for the specified Image.
+ */
+ public Token(int kind)
+ {
+ this(kind, null);
+ }
+
+ /**
+ * Constructs a new token for the specified Image and Kind.
+ */
+ public Token(int kind, String image)
+ {
+ this.kind = kind;
+ this.image = image;
+ }
+
+ /**
+ * Returns the image.
+ */
+ public String toString()
+ {
+ return image;
+ }
+
+ /**
+ * Returns a new Token object, by default. However, if you want, you
+ * can create and return subclass objects based on the value of ofKind.
+ * Simply add the cases to the switch for all those special cases.
+ * For example, if you have a subclass of Token called IDToken that
+ * you want to create if ofKind is ID, simply add something like :
+ *
+ * case MyParserConstants.ID : return new IDToken(ofKind, image);
+ *
+ * to the following switch statement. Then you can cast matchedToken
+ * variable to the appropriate type and use sit in your lexical actions.
+ */
+ public static Token newToken(int ofKind, String image)
+ {
+ switch(ofKind)
+ {
+ default : return new Token(ofKind, image);
+ }
+ }
+
+ public static Token newToken(int ofKind)
+ {
+ return newToken(ofKind, null);
+ }
+
+}
+/* JavaCC - OriginalChecksum=f9eb36a076cde62bf39ccbf828bc2117 (do not edit this line) */
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TokenMgrError.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TokenMgrError.java
new file mode 100644
index 00000000000..07af72b6277
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TokenMgrError.java
@@ -0,0 +1,147 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
+/* JavaCCOptions: */
+package org.apache.lucene.queryParser.original.parser;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+ /**
+ * The version identifier for this Serializable class.
+ * Increment only if the serialized form of the
+ * class changes.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * Ordinals for various reasons why an Error of this type can be thrown.
+ */
+
+ /**
+ * Lexical error occurred.
+ */
+ static final int LEXICAL_ERROR = 0;
+
+ /**
+ * An attempt was made to create a second instance of a static token manager.
+ */
+ static final int STATIC_LEXER_ERROR = 1;
+
+ /**
+ * Tried to change to an invalid lexical state.
+ */
+ static final int INVALID_LEXICAL_STATE = 2;
+
+ /**
+ * Detected (and bailed out of) an infinite loop in the token manager.
+ */
+ static final int LOOP_DETECTED = 3;
+
+ /**
+ * Indicates the reason why the exception is thrown. It will have
+ * one of the above 4 values.
+ */
+ int errorCode;
+
+ /**
+ * Replaces unprintable characters by their escaped (or unicode escaped)
+ * equivalents in the given string
+ */
+ protected static final String addEscapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+ /**
+ * Returns a detailed message for the Error when it is thrown by the
+ * token manager to indicate a lexical error.
+ * Parameters :
+ * EOFSeen : indicates if EOF caused the lexical error
+ * curLexState : lexical state in which this error occurred
+ * errorLine : line number when the error occurred
+ * errorColumn : column number when the error occurred
+ * errorAfter : prefix that was seen before this error occurred
+ * curchar : the offending character
+ * Note: You can customize the lexical error message by modifying this method.
+ */
+ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+ return("Lexical error at line " +
+ errorLine + ", column " +
+ errorColumn + ". Encountered: " +
+ (EOFSeen ? " " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+ "after : \"" + addEscapes(errorAfter) + "\"");
+ }
+
+ /**
+ * You can also modify the body of this method to customize your error messages.
+ * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+ * of end-users concern, so you can return something like :
+ *
+ * "Internal Error : Please file a bug report .... "
+ *
+ * from this method for such cases in the release version of your parser.
+ */
+ public String getMessage() {
+ return super.getMessage();
+ }
+
+ /*
+ * Constructors of various flavors follow.
+ */
+
+ /** No arg constructor. */
+ public TokenMgrError() {
+ }
+
+ /** Constructor with message and reason. */
+ public TokenMgrError(String message, int reason) {
+ super(message);
+ errorCode = reason;
+ }
+
+ /** Full Constructor. */
+ public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+ this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+ }
+}
+/* JavaCC - OriginalChecksum=91ba9c9f5e0e552a815530d639ce15ed (do not edit this line) */
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/package.html
new file mode 100644
index 00000000000..464b26dbf4f
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/package.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+Lucene Query Parser
+
+The package org.apache.lucene.queryParser.original.parser contains the query parser.
+
+
+This text parser only performs the syntax validation and creates an QueryNode tree
+from a query string.
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AllowLeadingWildcardProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AllowLeadingWildcardProcessor.java
new file mode 100644
index 00000000000..75b55b25d98
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AllowLeadingWildcardProcessor.java
@@ -0,0 +1,98 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+
+/**
+ * This processor verifies if the attribute
+ * {@link AllowLeadingWildcardAttribute} is defined in the
+ * {@link QueryConfigHandler}. If it is and leading wildcard is not allowed, it
+ * looks for every {@link WildcardQueryNode} contained in the query node tree
+ * and throws an exception if any of them has a leading wildcard ('*' or '?').
+ *
+ * @see AllowLeadingWildcardAttribute
+ */
+public class AllowLeadingWildcardProcessor extends QueryNodeProcessorImpl {
+
+ public AllowLeadingWildcardProcessor() {
+ // empty constructor
+ }
+
+ public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+
+ if (getQueryConfigHandler().hasAttribute(
+ AllowLeadingWildcardAttribute.class)) {
+
+ if (!((AllowLeadingWildcardAttribute) getQueryConfigHandler()
+ .getAttribute(AllowLeadingWildcardAttribute.class))
+ .isAllowLeadingWildcard()) {
+ return super.process(queryTree);
+ }
+
+ }
+
+ return queryTree;
+
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof WildcardQueryNode) {
+ WildcardQueryNode wildcardNode = (WildcardQueryNode) node;
+
+ switch (wildcardNode.getText().charAt(0)) {
+
+ case '*':
+ case '?':
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LEADING_WILDCARD_NOT_ALLOWED, node
+ .toQueryString(new EscapeQuerySyntaxImpl())));
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AnalyzerQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AnalyzerQueryNodeProcessor.java
new file mode 100644
index 00000000000..e6877e74b4c
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AnalyzerQueryNodeProcessor.java
@@ -0,0 +1,337 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.CachingTokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
+import org.apache.lucene.analysis.tokenattributes.TermAttribute;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.NoTokenFoundQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.TextableQueryNode;
+import org.apache.lucene.queryParser.core.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.original.nodes.OriginalBooleanQueryNode;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+
+/**
+ * This processor verifies if the attribute {@link AnalyzerQueryNodeProcessor}
+ * is defined in the {@link QueryConfigHandler}. If it is and the analyzer is
+ * not null
, it looks for every {@link FieldQueryNode} that is not
+ * {@link WildcardQueryNode}, {@link FuzzyQueryNode} or
+ * {@link ParametricQueryNode} contained in the query node tree, then it applies
+ * the analyzer to that {@link FieldQueryNode} object.
+ *
+ * If the analyzer return only one term, the returned term is set to the
+ * {@link FieldQueryNode} and it's returned.
+ *
+ * If the analyzer return more than one term, a {@link TokenizedPhraseQueryNode}
+ * or {@link MultiPhraseQueryNode} is created, whether there is one or more
+ * terms at the same position, and it's returned.
+ *
+ * If no term is returned by the analyzer a {@link NoTokenFoundQueryNode} object
+ * is returned.
+ *
+ * @see Analyzer
+ * @see TokenStream
+ */
+public class AnalyzerQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ private Analyzer analyzer;
+
+ private boolean positionIncrementsEnabled;
+
+ public AnalyzerQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+
+ if (getQueryConfigHandler().hasAttribute(AnalyzerAttribute.class)) {
+
+ this.analyzer = ((AnalyzerAttribute) getQueryConfigHandler()
+ .getAttribute(AnalyzerAttribute.class)).getAnalyzer();
+
+ this.positionIncrementsEnabled = false;
+
+ if (getQueryConfigHandler().hasAttribute(
+ PositionIncrementsAttribute.class)) {
+
+ if (((PositionIncrementsAttribute) getQueryConfigHandler()
+ .getAttribute(PositionIncrementsAttribute.class))
+ .isPositionIncrementsEnabled()) {
+
+ this.positionIncrementsEnabled = true;
+
+ }
+
+ }
+
+ if (this.analyzer != null) {
+ return super.process(queryTree);
+ }
+
+ }
+
+ return queryTree;
+
+ }
+
+ @Override
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof TextableQueryNode
+ && !(node instanceof WildcardQueryNode)
+ && !(node instanceof FuzzyQueryNode)
+ && !(node instanceof ParametricQueryNode)) {
+
+ FieldQueryNode fieldNode = ((FieldQueryNode) node);
+ String text = fieldNode.getTextAsString();
+ String field = fieldNode.getFieldAsString();
+
+ TokenStream source = this.analyzer.tokenStream(field, new StringReader(
+ text));
+ CachingTokenFilter buffer = new CachingTokenFilter(source);
+
+ PositionIncrementAttribute posIncrAtt = null;
+ int numTokens = 0;
+ int positionCount = 0;
+ boolean severalTokensAtSamePosition = false;
+
+ if (buffer.hasAttribute(PositionIncrementAttribute.class)) {
+ posIncrAtt = (PositionIncrementAttribute) buffer
+ .getAttribute(PositionIncrementAttribute.class);
+ }
+
+ try {
+
+ while (buffer.incrementToken()) {
+ numTokens++;
+ int positionIncrement = (posIncrAtt != null) ? posIncrAtt
+ .getPositionIncrement() : 1;
+ if (positionIncrement != 0) {
+ positionCount += positionIncrement;
+
+ } else {
+ severalTokensAtSamePosition = true;
+ }
+
+ }
+
+ } catch (IOException e) {
+ // ignore
+ }
+
+ try {
+ // rewind the buffer stream
+ buffer.reset();
+
+ // close original stream - all tokens buffered
+ source.close();
+ } catch (IOException e) {
+ // ignore
+ }
+
+ if (!buffer.hasAttribute(TermAttribute.class)) {
+ return new NoTokenFoundQueryNode();
+ }
+
+ TermAttribute termAtt = (TermAttribute) buffer
+ .getAttribute(TermAttribute.class);
+
+ if (numTokens == 0) {
+ return new NoTokenFoundQueryNode();
+
+ } else if (numTokens == 1) {
+ String term = null;
+ try {
+ boolean hasNext;
+ hasNext = buffer.incrementToken();
+ assert hasNext == true;
+ term = termAtt.term();
+
+ } catch (IOException e) {
+ // safe to ignore, because we know the number of tokens
+ }
+
+ fieldNode.setText(term);
+
+ return fieldNode;
+
+ } else if (severalTokensAtSamePosition) {
+ if (positionCount == 1) {
+ // no phrase query:
+ LinkedList children = new LinkedList();
+
+ for (int i = 0; i < numTokens; i++) {
+ String term = null;
+ try {
+ boolean hasNext = buffer.incrementToken();
+ assert hasNext == true;
+ term = termAtt.term();
+
+ } catch (IOException e) {
+ // safe to ignore, because we know the number of tokens
+ }
+
+ children.add(new FieldQueryNode(field, term, -1, -1));
+
+ }
+
+ return new GroupQueryNode(new OriginalBooleanQueryNode(children, true));
+
+ } else {
+ // phrase query:
+ MultiPhraseQueryNode mpq = new MultiPhraseQueryNode();
+
+ List multiTerms = new ArrayList();
+ int position = -1;
+ int i = 0;
+ for (; i < numTokens; i++) {
+ String term = null;
+ int positionIncrement = 1;
+ try {
+ boolean hasNext = buffer.incrementToken();
+ assert hasNext == true;
+ term = termAtt.term();
+ if (posIncrAtt != null) {
+ positionIncrement = posIncrAtt.getPositionIncrement();
+ }
+
+ } catch (IOException e) {
+ // safe to ignore, because we know the number of tokens
+ }
+
+ if (positionIncrement > 0 && multiTerms.size() > 0) {
+
+ for (FieldQueryNode termNode : multiTerms) {
+
+ if (this.positionIncrementsEnabled) {
+ termNode.setPositionIncrement(position);
+
+ } else {
+ termNode.setPositionIncrement(i);
+ }
+
+ mpq.add(termNode);
+
+ }
+
+ multiTerms.clear();
+
+ }
+
+ position += positionIncrement;
+ multiTerms.add(new FieldQueryNode(field, term, -1, -1));
+
+ }
+
+ for (FieldQueryNode termNode : multiTerms) {
+
+ if (this.positionIncrementsEnabled) {
+ termNode.setPositionIncrement(position);
+
+ } else {
+ termNode.setPositionIncrement(i);
+ }
+
+ mpq.add(termNode);
+
+ }
+
+ return mpq;
+
+ }
+
+ } else {
+
+ TokenizedPhraseQueryNode pq = new TokenizedPhraseQueryNode();
+
+ int position = -1;
+
+ for (int i = 0; i < numTokens; i++) {
+ String term = null;
+ int positionIncrement = 1;
+
+ try {
+ boolean hasNext = buffer.incrementToken();
+ assert hasNext == true;
+ term = termAtt.term();
+
+ if (posIncrAtt != null) {
+ positionIncrement = posIncrAtt.getPositionIncrement();
+ }
+
+ } catch (IOException e) {
+ // safe to ignore, because we know the number of tokens
+ }
+
+ FieldQueryNode newFieldNode = new FieldQueryNode(field, term, -1, -1);
+
+ if (this.positionIncrementsEnabled) {
+ position += positionIncrement;
+ newFieldNode.setPositionIncrement(position);
+
+ } else {
+ newFieldNode.setPositionIncrement(i);
+ }
+
+ pq.add(newFieldNode);
+
+ }
+
+ return pq;
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java
new file mode 100644
index 00000000000..1e8c4bd74a4
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java
@@ -0,0 +1,88 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.nodes.BooleanModifierNode;
+
+/**
+ * This processor removes every {@link BooleanQueryNode} that contains only one
+ * child and returns this child. If this child is {@link ModifierQueryNode} that
+ * was defined by the user. A modifier is not defined by the user when it's a
+ * {@link BooleanModifierNode}
+ *
+ * @see ModifierQueryNode
+ */
+public class BooleanSingleChildOptimizationQueryNodeProcessor extends
+ QueryNodeProcessorImpl {
+
+ public BooleanSingleChildOptimizationQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof BooleanQueryNode) {
+ List children = node.getChildren();
+
+ if (children != null && children.size() == 1) {
+ QueryNode child = children.get(0);
+
+ if (child instanceof ModifierQueryNode) {
+ ModifierQueryNode modNode = (ModifierQueryNode) child;
+
+ if (modNode instanceof BooleanModifierNode
+ || modNode.getModifier() == Modifier.MOD_NONE) {
+
+ return child;
+
+ }
+
+ } else {
+ return child;
+ }
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BoostQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BoostQueryNodeProcessor.java
new file mode 100644
index 00000000000..b4f03ab82a7
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BoostQueryNodeProcessor.java
@@ -0,0 +1,84 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldableNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.BoostAttribute;
+
+/**
+ * This processor iterates the query node tree looking for every
+ * {@link FieldableNode} that has the attribute {@link BoostAttribute} in its
+ * config. If there is, the boost is applied to that {@link FieldableNode}.
+ *
+ * @see BoostAttribute
+ * @see QueryConfigHandler
+ * @see FieldableNode
+ */
+public class BoostQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ @Override
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof FieldableNode &&
+ (node.getParent() == null || !(node.getParent() instanceof FieldableNode))) {
+
+ FieldableNode fieldNode = (FieldableNode) node;
+ QueryConfigHandler config = getQueryConfigHandler();
+
+ if (config != null) {
+ FieldConfig fieldConfig = config.getFieldConfig(fieldNode.getField());
+
+ if (fieldConfig != null && fieldConfig.hasAttribute(BoostAttribute.class)) {
+ BoostAttribute boostAttr = (BoostAttribute) fieldConfig.getAttribute(BoostAttribute.class);
+
+ return new BoostQueryNode(node, boostAttr.getBoost());
+
+ }
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ @Override
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ @Override
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/DefaultPhraseSlopQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/DefaultPhraseSlopQueryNodeProcessor.java
new file mode 100644
index 00000000000..141431b0f78
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/DefaultPhraseSlopQueryNodeProcessor.java
@@ -0,0 +1,115 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.core.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.DefaultPhraseSlopAttribute;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+
+/**
+ * This processor verifies if the attribute {@link DefaultPhraseSlopAttribute}
+ * is defined in the {@link QueryConfigHandler}. If it is, it looks for every
+ * {@link TokenizedPhraseQueryNode} and {@link MultiPhraseQueryNode} that does
+ * not have any {@link SlopQueryNode} applied to it and creates an
+ * {@link SlopQueryNode} and apply to it. The new {@link SlopQueryNode} has the
+ * same slop value defined in the attribute.
+ *
+ * @see SlopQueryNode
+ * @see DefaultPhraseSlopAttribute
+ */
+public class DefaultPhraseSlopQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ private boolean processChildren = true;
+
+ private int defaultPhraseSlop;
+
+ public DefaultPhraseSlopQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+ QueryConfigHandler queryConfig = getQueryConfigHandler();
+
+ if (queryConfig != null) {
+
+ if (queryConfig.hasAttribute(DefaultPhraseSlopAttribute.class)) {
+ this.defaultPhraseSlop = ((DefaultPhraseSlopAttribute) queryConfig
+ .getAttribute(DefaultPhraseSlopAttribute.class))
+ .getDefaultPhraseSlop();
+
+ return super.process(queryTree);
+
+ }
+
+ }
+
+ return queryTree;
+
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof TokenizedPhraseQueryNode
+ || node instanceof MultiPhraseQueryNode) {
+
+ return new SlopQueryNode(node, this.defaultPhraseSlop);
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof SlopQueryNode) {
+ this.processChildren = false;
+
+ }
+
+ return node;
+
+ }
+
+ protected void processChildren(QueryNode queryTree) throws QueryNodeException {
+
+ if (this.processChildren) {
+ super.processChildren(queryTree);
+
+ } else {
+ this.processChildren = true;
+ }
+
+ }
+
+ @Override
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/FuzzyQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/FuzzyQueryNodeProcessor.java
new file mode 100644
index 00000000000..1dfe86bb497
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/FuzzyQueryNodeProcessor.java
@@ -0,0 +1,86 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.FuzzyAttribute;
+import org.apache.lucene.search.FuzzyQuery;
+
+/**
+ * This processor iterates the query node tree looking for every
+ * {@link FuzzyQueryNode}, when this kind of node is found, it checks on the
+ * query configuration for {@link FuzzyAttribute}, gets the fuzzy prefix length
+ * and default similarity from it and set to the fuzzy node. For more
+ * information about fuzzy prefix length check: {@link FuzzyQuery}.
+ *
+ * @see FuzzyAttribute
+ * @see FuzzyQuery
+ * @see FuzzyQueryNode
+ */
+public class FuzzyQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ @Override
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ @Override
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof FuzzyQueryNode) {
+ FuzzyQueryNode fuzzyNode = (FuzzyQueryNode) node;
+ QueryConfigHandler config = getQueryConfigHandler();
+
+ if (config != null && config.hasAttribute(FuzzyAttribute.class)) {
+ FuzzyAttribute fuzzyAttr = (FuzzyAttribute) config
+ .getAttribute(FuzzyAttribute.class);
+ fuzzyNode.setPrefixLength(fuzzyAttr.getPrefixLength());
+
+ if (fuzzyNode.getSimilarity() < 0) {
+ fuzzyNode.setSimilarity(fuzzyAttr.getFuzzyMinSimilarity());
+
+ }
+
+ } else if (fuzzyNode.getSimilarity() < 0) {
+ throw new IllegalArgumentException("No "
+ + FuzzyAttribute.class.getName() + " set in the config");
+ }
+
+ }
+
+ return node;
+
+ }
+
+ @Override
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/GroupQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/GroupQueryNodeProcessor.java
new file mode 100644
index 00000000000..cca37c468e4
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/GroupQueryNodeProcessor.java
@@ -0,0 +1,219 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryParser.core.parser.SyntaxParser;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessor;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator;
+import org.apache.lucene.queryParser.original.nodes.BooleanModifierNode;
+
+/**
+ * The {@link SyntaxParser}
+ * generates query node trees that consider the boolean operator precedence, but
+ * Lucene current syntax does not support boolean precedence, so this processor
+ * remove all the precedence and apply the equivalent modifier according to the
+ * boolean operation defined on an specific query node.
+ *
+ * If there is a {@link GroupQueryNode} in the query node tree, the query node
+ * tree is not merged with the one above it.
+ *
+ * Example: TODO: describe a good example to show how this processor works
+ *
+ * @see org.apache.lucene.queryParser.original.config.OriginalQueryConfigHandler
+ */
+public class GroupQueryNodeProcessor implements QueryNodeProcessor {
+
+ private ArrayList queryNodeList;
+
+ private boolean latestNodeVerified;
+
+ private QueryConfigHandler queryConfig;
+
+ private Boolean usingAnd = false;
+
+ public GroupQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+
+ if (!getQueryConfigHandler().hasAttribute(DefaultOperatorAttribute.class)) {
+ throw new IllegalArgumentException(
+ "DefaultOperatorAttribute should be set on the QueryConfigHandler");
+ }
+
+ usingAnd = Operator.AND == ((DefaultOperatorAttribute) getQueryConfigHandler()
+ .getAttribute(DefaultOperatorAttribute.class)).getOperator();
+
+ if (queryTree instanceof GroupQueryNode) {
+ queryTree = ((GroupQueryNode) queryTree).getChild();
+ }
+
+ this.queryNodeList = new ArrayList();
+ this.latestNodeVerified = false;
+ readTree(queryTree);
+
+ List actualQueryNodeList = this.queryNodeList;
+
+ for (int i = 0; i < actualQueryNodeList.size(); i++) {
+ QueryNode node = actualQueryNodeList.get(i);
+
+ if (node instanceof GroupQueryNode) {
+ actualQueryNodeList.set(i, process(node));
+ }
+
+ }
+
+ this.usingAnd = false;
+
+ if (queryTree instanceof BooleanQueryNode) {
+ queryTree.set(actualQueryNodeList);
+
+ return queryTree;
+
+ } else {
+ return new BooleanQueryNode(actualQueryNodeList);
+ }
+
+ }
+
+ /**
+ * @param node
+ * @return
+ */
+ private QueryNode applyModifier(QueryNode node, QueryNode parent) {
+
+ if (this.usingAnd) {
+
+ if (parent instanceof OrQueryNode) {
+
+ if (node instanceof ModifierQueryNode) {
+
+ ModifierQueryNode modNode = (ModifierQueryNode) node;
+
+ if (modNode.getModifier() == Modifier.MOD_REQ) {
+ return modNode.getChild();
+ }
+
+ }
+
+ } else {
+
+ if (node instanceof ModifierQueryNode) {
+
+ ModifierQueryNode modNode = (ModifierQueryNode) node;
+
+ if (modNode.getModifier() == Modifier.MOD_NONE) {
+ return new BooleanModifierNode(modNode.getChild(), Modifier.MOD_REQ);
+ }
+
+ } else {
+ return new BooleanModifierNode(node, Modifier.MOD_REQ);
+ }
+
+ }
+
+ } else {
+
+ if (node.getParent() instanceof AndQueryNode) {
+
+ if (node instanceof ModifierQueryNode) {
+
+ ModifierQueryNode modNode = (ModifierQueryNode) node;
+
+ if (modNode.getModifier() == Modifier.MOD_NONE) {
+ return new BooleanModifierNode(modNode.getChild(), Modifier.MOD_REQ);
+ }
+
+ } else {
+ return new BooleanModifierNode(node, Modifier.MOD_REQ);
+ }
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ private void readTree(QueryNode node) {
+
+ if (node instanceof BooleanQueryNode) {
+ List children = node.getChildren();
+
+ if (children != null && children.size() > 0) {
+
+ for (int i = 0; i < children.size() - 1; i++) {
+ readTree(children.get(i));
+ }
+
+ processNode(node);
+ readTree(children.get(children.size() - 1));
+
+ } else {
+ processNode(node);
+ }
+
+ } else {
+ processNode(node);
+ }
+
+ }
+
+ private void processNode(QueryNode node) {
+
+ if (node instanceof AndQueryNode || node instanceof OrQueryNode) {
+
+ if (!this.latestNodeVerified && !this.queryNodeList.isEmpty()) {
+ this.queryNodeList.add(applyModifier(this.queryNodeList
+ .remove(this.queryNodeList.size() - 1), node));
+ this.latestNodeVerified = true;
+
+ }
+
+ } else if (!(node instanceof BooleanQueryNode)) {
+ this.queryNodeList.add(applyModifier(node, node.getParent()));
+ this.latestNodeVerified = false;
+
+ }
+
+ }
+
+ public QueryConfigHandler getQueryConfigHandler() {
+ return this.queryConfig;
+ }
+
+ public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
+ this.queryConfig = queryConfigHandler;
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LowercaseExpandedTermsQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LowercaseExpandedTermsQueryNodeProcessor.java
new file mode 100644
index 00000000000..c779fccfb31
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LowercaseExpandedTermsQueryNodeProcessor.java
@@ -0,0 +1,93 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.LowercaseExpandedTermsAttribute;
+
+/**
+ * This processor verifies if the attribute
+ * {@link LowercaseExpandedTermsAttribute} is defined in the
+ * {@link QueryConfigHandler}. If it is and the expanded terms should be
+ * lower-cased, it looks for every {@link WildcardQueryNode},
+ * {@link FuzzyQueryNode} and {@link ParametricQueryNode} and lower-case its
+ * term.
+ *
+ * @see LowercaseExpandedTermsAttribute
+ */
+public class LowercaseExpandedTermsQueryNodeProcessor extends
+ QueryNodeProcessorImpl {
+
+ public LowercaseExpandedTermsQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+
+ if (getQueryConfigHandler().hasAttribute(
+ LowercaseExpandedTermsAttribute.class)) {
+
+ if (((LowercaseExpandedTermsAttribute) getQueryConfigHandler()
+ .getAttribute(LowercaseExpandedTermsAttribute.class))
+ .isLowercaseExpandedTerms()) {
+ return super.process(queryTree);
+ }
+
+ }
+
+ return queryTree;
+
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof WildcardQueryNode || node instanceof FuzzyQueryNode
+ || node instanceof ParametricQueryNode) {
+
+ FieldQueryNode fieldNode = (FieldQueryNode) node;
+ fieldNode.setText(fieldNode.getText().toString().toLowerCase());
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MatchAllDocsQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MatchAllDocsQueryNodeProcessor.java
new file mode 100644
index 00000000000..08f5a325803
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MatchAllDocsQueryNodeProcessor.java
@@ -0,0 +1,73 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.search.MatchAllDocsQuery;
+
+/**
+ * This processor converts every {@link WildcardQueryNode} that is "*:*" to
+ * {@link MatchAllDocsQueryNode}.
+ *
+ * @see MatchAllDocsQueryNode
+ * @see MatchAllDocsQuery
+ */
+public class MatchAllDocsQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ public MatchAllDocsQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof WildcardQueryNode) {
+ WildcardQueryNode wildcardNode = (WildcardQueryNode) node;
+
+ if (wildcardNode.getField().toString().equals("*")
+ && wildcardNode.getText().toString().equals("*")) {
+
+ return new MatchAllDocsQueryNode();
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MultiFieldQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MultiFieldQueryNodeProcessor.java
new file mode 100644
index 00000000000..a03ddeed813
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MultiFieldQueryNodeProcessor.java
@@ -0,0 +1,131 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldableNode;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.MultiFieldAttribute;
+
+/**
+ * This processor is used to expand terms so the query looks for the same term
+ * in different fields. It also boosts a query based on its field.
+ *
+ * This processor looks for every {@link FieldableNode} contained in the query
+ * node tree. If a {@link FieldableNode} is found, it checks if there is a
+ * {@link MultiFieldAttribute} defined in the {@link QueryConfigHandler}. If
+ * there is, the {@link FieldableNode} is cloned N times and the clones are
+ * added to a {@link BooleanQueryNode} together with the original node. N is
+ * defined by the number of fields that it will be expanded to. The
+ * {@link BooleanQueryNode} is returned.
+ *
+ * @see MultiFieldAttribute
+ */
+public class MultiFieldQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ private boolean processChildren = true;
+
+ public MultiFieldQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected void processChildren(QueryNode queryTree) throws QueryNodeException {
+
+ if (this.processChildren) {
+ super.processChildren(queryTree);
+
+ } else {
+ this.processChildren = true;
+ }
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof FieldableNode) {
+ this.processChildren = false;
+ FieldableNode fieldNode = (FieldableNode) node;
+
+ if (fieldNode.getField() == null) {
+
+ if (!getQueryConfigHandler().hasAttribute(MultiFieldAttribute.class)) {
+ throw new IllegalArgumentException(
+ "MultiFieldAttribute should be set on the QueryConfigHandler");
+ }
+
+ CharSequence[] fields = ((MultiFieldAttribute) getQueryConfigHandler()
+ .getAttribute(MultiFieldAttribute.class)).getFields();
+
+ if (fields != null && fields.length > 0) {
+ fieldNode.setField(fields[0]);
+
+ if (fields.length == 1) {
+ return fieldNode;
+
+ } else {
+ LinkedList children = new LinkedList();
+ children.add(fieldNode);
+
+ for (int i = 1; i < fields.length; i++) {
+ try {
+ fieldNode = (FieldableNode) fieldNode.cloneTree();
+ fieldNode.setField(fields[i]);
+
+ children.add(fieldNode);
+
+ } catch (CloneNotSupportedException e) {
+ // should never happen
+ }
+
+ }
+
+ return new GroupQueryNode(new BooleanQueryNode(children));
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/OriginalQueryNodeProcessorPipeline.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/OriginalQueryNodeProcessorPipeline.java
new file mode 100644
index 00000000000..39669def82b
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/OriginalQueryNodeProcessorPipeline.java
@@ -0,0 +1,70 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.processors.NoChildOptimizationQueryNodeProcessor;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.core.processors.RemoveDeletedQueryNodesProcessor;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.OriginalQueryConfigHandler;
+import org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser;
+import org.apache.lucene.search.Query;
+
+/**
+ * This pipeline has all the processors needed to process a query node tree,
+ * generated by {@link OriginalSyntaxParser}, already assembled.
+ *
+ * The order they are assembled affects the results.
+ *
+ * This processor pipeline was designed to work with
+ * {@link OriginalQueryConfigHandler}.
+ *
+ * The result query node tree can be used to build a {@link Query} object using
+ * {@link OriginalQueryTreeBuilder}.
+ *
+ * @see OriginalQueryTreeBuilder
+ * @see OriginalQueryConfigHandler
+ * @see OriginalSyntaxParser
+ */
+public class OriginalQueryNodeProcessorPipeline extends
+ QueryNodeProcessorPipeline {
+
+ public OriginalQueryNodeProcessorPipeline(QueryConfigHandler queryConfig) {
+ super(queryConfig);
+
+ addProcessor(new MultiFieldQueryNodeProcessor());
+ addProcessor(new FuzzyQueryNodeProcessor());
+ addProcessor(new MatchAllDocsQueryNodeProcessor());
+ addProcessor(new LowercaseExpandedTermsQueryNodeProcessor());
+ addProcessor(new ParametricRangeQueryNodeProcessor());
+ addProcessor(new AllowLeadingWildcardProcessor());
+ addProcessor(new PrefixWildcardQueryNodeProcessor());
+ addProcessor(new AnalyzerQueryNodeProcessor());
+ addProcessor(new PhraseSlopQueryNodeProcessor());
+ addProcessor(new GroupQueryNodeProcessor());
+ addProcessor(new NoChildOptimizationQueryNodeProcessor());
+ addProcessor(new RemoveDeletedQueryNodesProcessor());
+ addProcessor(new RemoveEmptyNonLeafQueryNodeProcessor());
+ addProcessor(new BooleanSingleChildOptimizationQueryNodeProcessor());
+ addProcessor(new DefaultPhraseSlopQueryNodeProcessor());
+ addProcessor(new BoostQueryNodeProcessor());
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/ParametricRangeQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/ParametricRangeQueryNodeProcessor.java
new file mode 100644
index 00000000000..7158922360a
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/ParametricRangeQueryNodeProcessor.java
@@ -0,0 +1,188 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.text.Collator;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.lucene.document.DateField;
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.ParametricQueryNode.CompareOperator;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.config.MultiTermRewriteMethodAttribute;
+import org.apache.lucene.queryParser.original.config.DateResolutionAttribute;
+import org.apache.lucene.queryParser.original.config.LocaleAttribute;
+import org.apache.lucene.queryParser.original.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.search.MultiTermQuery;
+
+/**
+ * This processor converts {@link ParametricRangeQueryNode} objects to
+ * {@link RangeQueryNode} objects. It reads the lower and upper bounds value
+ * from the {@link ParametricRangeQueryNode} object and try to parse their
+ * values using a {@link DateFormat}. If the values cannot be parsed to a date
+ * value, it will only create the {@link RangeQueryNode} using the non-parsed
+ * values.
+ *
+ * If a {@link LocaleAttribute} is defined in the {@link QueryConfigHandler} it
+ * will be used to parse the date, otherwise {@link Locale#getDefault()} will be
+ * used.
+ *
+ * If a {@link DateResolutionAttribute} is defined and the {@link Resolution} is
+ * not null
it will also be used to parse the date value.
+ *
+ * This processor will also try to retrieve a {@link RangeCollatorAttribute}
+ * from the {@link QueryConfigHandler}. If a {@link RangeCollatorAttribute} is
+ * found and the {@link Collator} is not null
, it's set on the
+ * {@link RangeQueryNode}.
+ *
+ * @see RangeCollatorAttribute
+ * @see DateResolutionAttribute
+ * @see LocaleAttribute
+ * @see RangeQueryNode
+ * @see ParametricRangeQueryNode
+ */
+public class ParametricRangeQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ public ParametricRangeQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof ParametricRangeQueryNode) {
+ ParametricRangeQueryNode parametricRangeNode = (ParametricRangeQueryNode) node;
+ ParametricQueryNode upper = parametricRangeNode.getUpperBound();
+ ParametricQueryNode lower = parametricRangeNode.getLowerBound();
+ Locale locale = Locale.getDefault();
+ Collator collator = null;
+ DateTools.Resolution dateRes = null;
+ boolean inclusive = false;
+
+ if (!getQueryConfigHandler().hasAttribute(
+ MultiTermRewriteMethodAttribute.class)) {
+ throw new IllegalArgumentException(
+ "MultiTermRewriteMethodAttribute should be set on the QueryConfigHandler");
+ }
+
+ MultiTermQuery.RewriteMethod rewriteMethod = ((MultiTermRewriteMethodAttribute) getQueryConfigHandler()
+ .getAttribute(MultiTermRewriteMethodAttribute.class))
+ .getMultiTermRewriteMethod();
+
+ if (getQueryConfigHandler().hasAttribute(RangeCollatorAttribute.class)) {
+ collator = ((RangeCollatorAttribute) getQueryConfigHandler()
+ .getAttribute(RangeCollatorAttribute.class)).getRangeCollator();
+ }
+
+ if (getQueryConfigHandler().hasAttribute(LocaleAttribute.class)) {
+ locale = ((LocaleAttribute) getQueryConfigHandler().getAttribute(
+ LocaleAttribute.class)).getLocale();
+ }
+
+ FieldConfig fieldConfig = getQueryConfigHandler().getFieldConfig(
+ parametricRangeNode.getField());
+
+ if (fieldConfig != null) {
+
+ if (fieldConfig.hasAttribute(DateResolutionAttribute.class)) {
+ dateRes = ((DateResolutionAttribute) fieldConfig
+ .getAttribute(DateResolutionAttribute.class)).getDateResolution();
+ }
+
+ }
+
+ if (upper.getOperator() == CompareOperator.LE) {
+ inclusive = true;
+
+ } else if (lower.getOperator() == CompareOperator.GE) {
+ inclusive = true;
+ }
+
+ String part1 = lower.getTextAsString();
+ String part2 = upper.getTextAsString();
+
+ try {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, Locale
+ .getDefault());
+ df.setLenient(true);
+ Date d1 = df.parse(part1);
+ Date d2 = df.parse(part2);
+ if (inclusive) {
+ // The user can only specify the date, not the time, so make sure
+ // the time is set to the latest possible time of that date to really
+ // include all documents:
+ Calendar cal = Calendar.getInstance(locale);
+ cal.setTime(d2);
+ cal.set(Calendar.HOUR_OF_DAY, 23);
+ cal.set(Calendar.MINUTE, 59);
+ cal.set(Calendar.SECOND, 59);
+ cal.set(Calendar.MILLISECOND, 999);
+ d2 = cal.getTime();
+ }
+
+ if (dateRes == null) {
+ // no default or field specific date resolution has been set,
+ // use deprecated DateField to maintain compatibilty with
+ // pre-1.9 Lucene versions.
+ part1 = DateField.dateToString(d1);
+ part2 = DateField.dateToString(d2);
+
+ } else {
+ part1 = DateTools.dateToString(d1, dateRes);
+ part2 = DateTools.dateToString(d2, dateRes);
+ }
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ lower.setText(part1);
+ upper.setText(part2);
+
+ return new RangeQueryNode(lower, upper, collator, rewriteMethod);
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PhraseSlopQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PhraseSlopQueryNodeProcessor.java
new file mode 100644
index 00000000000..086809cca28
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PhraseSlopQueryNodeProcessor.java
@@ -0,0 +1,71 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.core.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+
+/**
+ * This processor removes invalid {@link SlopQueryNode} objects in the query
+ * node tree. A {@link SlopQueryNode} is invalid if its child is neither a
+ * {@link TokenizedPhraseQueryNode} nor a {@link MultiPhraseQueryNode}.
+ *
+ * @see SlopQueryNode
+ */
+public class PhraseSlopQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ public PhraseSlopQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof SlopQueryNode) {
+ SlopQueryNode phraseSlopNode = (SlopQueryNode) node;
+
+ if (!(phraseSlopNode.getChild() instanceof TokenizedPhraseQueryNode)
+ && !(phraseSlopNode.getChild() instanceof MultiPhraseQueryNode)) {
+ return phraseSlopNode.getChild();
+ }
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PrefixWildcardQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PrefixWildcardQueryNodeProcessor.java
new file mode 100644
index 00000000000..afee0cfb820
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PrefixWildcardQueryNodeProcessor.java
@@ -0,0 +1,72 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser;
+import org.apache.lucene.search.PrefixQuery;
+
+/**
+ * The {@link OriginalSyntaxParser} creates {@link PrefixWildcardQueryNode} nodes which
+ * have values containing the prefixed wildcard. However, Lucene
+ * {@link PrefixQuery} cannot contain the prefixed wildcard. So, this processor
+ * basically removed the prefixed wildcard from the
+ * {@link PrefixWildcardQueryNode} value.
+ *
+ * @see PrefixQuery
+ * @see PrefixWildcardQueryNode
+ */
+public class PrefixWildcardQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ public PrefixWildcardQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof PrefixWildcardQueryNode) {
+ PrefixWildcardQueryNode prefixWildcardNode = (PrefixWildcardQueryNode) node;
+ CharSequence text = prefixWildcardNode.getText();
+
+ prefixWildcardNode.setText(text.subSequence(0, text.length() - 1));
+
+ }
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/RemoveEmptyNonLeafQueryNodeProcessor.java b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/RemoveEmptyNonLeafQueryNodeProcessor.java
new file mode 100644
index 00000000000..d922cb31c0d
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/RemoveEmptyNonLeafQueryNodeProcessor.java
@@ -0,0 +1,112 @@
+package org.apache.lucene.queryParser.original.processors;
+
+/**
+ * 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.
+ */
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.core.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+
+/**
+ * This processor removes every {@link QueryNode} that is not a leaf and has not
+ * children. If after processing the entire tree the root node is not a leaf and
+ * has no children, a {@link MatchNoDocsQueryNode} object is returned.
+ *
+ * This processor is used at the end of a pipeline to avoid invalid query node
+ * tree structures like a {@link GroupQueryNode} or {@link ModifierQueryNode}
+ * with no children.
+ *
+ * @see QueryNode
+ * @see MatchNoDocsQueryNode
+ */
+public class RemoveEmptyNonLeafQueryNodeProcessor extends
+ QueryNodeProcessorImpl {
+
+ private LinkedList childrenBuffer = new LinkedList();
+
+ public RemoveEmptyNonLeafQueryNodeProcessor() {
+ // empty constructor
+ }
+
+ public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+ queryTree = super.process(queryTree);
+
+ if (!queryTree.isLeaf()) {
+
+ List children = queryTree.getChildren();
+
+ if (children == null || children.size() == 0) {
+ return new MatchNoDocsQueryNode();
+ }
+
+ }
+
+ return queryTree;
+
+ }
+
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ try {
+
+ for (QueryNode child : children) {
+
+ if (!child.isLeaf()) {
+
+ List grandChildren = child.getChildren();
+
+ if (grandChildren != null && grandChildren.size() > 0) {
+ this.childrenBuffer.add(child);
+ }
+
+ } else {
+ this.childrenBuffer.add(child);
+ }
+
+ }
+
+ children.clear();
+ children.addAll(this.childrenBuffer);
+
+ } finally {
+ this.childrenBuffer.clear();
+ }
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/package.html
new file mode 100644
index 00000000000..16d11107580
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/package.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+Lucene Query Node Processors
+
+The package org.apache.lucene.queryParser.original.processors contains every processor needed to assembly a pipeline
+that modifies the query node tree according to the actual Lucene queries.
+
+
+This processors are already assembled correctly in the OriginalQueryNodeProcessorPipeline.
+
+
+
diff --git a/contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html b/contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html
new file mode 100644
index 00000000000..82767b91d4c
--- /dev/null
+++ b/contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+Flexible Query Parser
+
+Features:
+
+ - Full support for lucene 2.4.2 syntax
+ - Full support for boolean logic (not enabled)
+ - QueryNode Trees - support for several syntaxes,
+ that can be converted into similar syntax QueryNode trees.
+ - QueryNode Processors - Optimize, validate, rewrite the
+ QueryNode trees
+ - Processors Pipelines - Select your favorite Processor
+ and build a processor pipeline, to implement the features you need
+ - Config Interfaces - Allow the consumer of the Query Parser to implement
+ a diff Config Handler Objects to suite their needs.
+ - Original Builders - convert QueryNode's into several lucene
+ representations. Supported conversion is using a 2.4 compatible logic
+ - QueryNode tree's can be converted to a lucene 2.4 syntax string, using toQueryString
+
+
+
+
+
+This new query parser was designed to have very generic
+architecture, so that it can be easily used for different
+products with varying query syntaxes. This code is much more
+flexible and extensible than the Lucene query parser in 2.4.X.
+
+
+The new query parser goal is to separate syntax and semantics of a query. E.g. 'a AND
+b', '+a +b', 'AND(a,b)' could be different syntaxes for the same query.
+It distinguishes the semantics of the different query components, e.g.
+whether and how to tokenize/lemmatize/normalize the different terms or
+which Query objects to create for the terms. It allows to
+write a parser with a new syntax, while reusing the underlying
+semantics, as quickly as possible.
+
+
+The query parser has three layers and its core is what we call the
+QueryNode tree. It is a tree that initially represents the syntax of the
+original query, e.g. for 'a AND b':
+
+
+ AND
+ / \
+A B
+
+
+The three layers are:
+1. QueryParser
+2. QueryNodeProcessor
+3. QueryBuilder
+
+
+1. This layer is the text parsing layer which simply transforms the
+query text string into a {@link org.apache.lucene.queryParser.core.nodes.QueryNode} tree. Every text parser
+must implement the interface {@link org.apache.lucene.queryParser.core.parser.SyntaxParser}.
+Lucene default implementations implements it using JavaCC.
+
+2. The query node processors do most of the work. It is in fact a
+configurable chain of processors. Each processors can walk the tree and
+modify nodes or even the tree's structure. That makes it possible to
+e.g. do query optimization before the query is executed or to tokenize
+terms.
+
+
+3. The third layer is a configurable map of builders, which map {@link org.apache.lucene.queryParser.core.nodes.QueryNode} types to its specific
+builder that will transform the QueryNode into Lucene Query object.
+
+
+Furthermore, the query parser uses flexible configuration objects, which
+are based on AttributeSource/Attribute. It also uses message classes that
+allow to attach resource bundles. This makes it possible to translate
+messages, which is an important feature of a query parser.
+
+
+This design allows to develop different query syntaxes very quickly.
+
+
+A original lucene-compatible syntax is implemented using this new query parser
+API and is located under org.apache.lucene.queryParser.original.
+
+To make it simpler to use the new query parser
+the class {@link org.apache.lucene.queryParser.original.OriginalQueryParserHelper} may be helpful,
+specially for people that do not want to extend the Query Parser.
+It uses the default Lucene query processors, text parser and builders, so
+you don't need to worry about dealing with those.
+
+{@link org.apache.lucene.queryParser.original.OriginalQueryParserHelper} usage:
+
+OriginalQueryParserHelper qpHelper = new OriginalQueryParserHelper();
+
+
+OriginalQueryConfigHandler config = qpHelper.getQueryConfigHandler();
+
+config.setAllowLeadingWildcard(true);
+
+config.setAnalyzer(new WhitespaceAnalyzer());
+
+Query query = qpHelper.parse("apache AND lucene", "defaultField");
+
+To make it easy for people who are using current Lucene's query parser to switch to
+the new one, there is a {@link org.apache.lucene.queryParser.original.QueryParserWrapper} under org.apache.lucene.queryParser.original
+that keeps the old query parser interface, but uses the new query parser infrastructure.
+
+
+
+
+
diff --git a/contrib/queryparser/src/java/overview.html b/contrib/queryparser/src/java/overview.html
new file mode 100644
index 00000000000..c0afd906b52
--- /dev/null
+++ b/contrib/queryparser/src/java/overview.html
@@ -0,0 +1,39 @@
+
+
+
+ Apache Lucene Flexible Query Parser
+
+
+
+Apache Lucene Flexible Query Parser
+
+
+This contrib project contains the new Lucene query parser implementation, which is going to replace the old query parser on Lucene 3.0.
+
+
+
+It's currently divided in 3 main packages:
+
+- {@link org.apache.lucene.messages}: it contains the API to defined lazily loaded messages. This message API is used by the new query parser to support localized messages.
+- {@link org.apache.lucene.queryParser.core}: it contains the query parser API classes, which should be extended by query parser implementations.
+- {@link org.apache.lucene.queryParser.original}: it contains the current Lucene query parser implementation using the new query parser API.
+
+
+
+
+
diff --git a/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java b/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java
new file mode 100644
index 00000000000..d12b6d55e99
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java
@@ -0,0 +1,40 @@
+package org.apache.lucene.messages;
+
+/**
+ * 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.
+ */
+
+public class MessagesTestBundle extends NLS {
+
+ private static final String BUNDLE_NAME = MessagesTestBundle.class.getName();
+
+ private MessagesTestBundle() {
+ // should never be instantiated
+ }
+
+ static {
+ // register all string ids with NLS class and initialize static string
+ // values
+ NLS.initializeMessages(BUNDLE_NAME, MessagesTestBundle.class);
+ }
+
+ // static string must match the strings in the property files.
+ public static String Q0001E_INVALID_SYNTAX;
+ public static String Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+
+ // this message is missing from the properties file
+ public static String Q0005E_MESSAGE_NOT_IN_BUNDLE;
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties b/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties
new file mode 100644
index 00000000000..870ff7312a5
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties
@@ -0,0 +1,3 @@
+Q0001E_INVALID_SYNTAX = Syntax Error: {0}
+
+Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION = Truncated unicode escape sequence.
diff --git a/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties b/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties
new file mode 100644
index 00000000000..2235294ca91
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties
@@ -0,0 +1,3 @@
+Q0001E_INVALID_SYNTAX = \u69cb\u6587\u30a8\u30e9\u30fc: {0}
+
+Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION = \u5207\u308a\u6368\u3066\u3089\u308c\u305f\u30e6\u30cb\u30b3\u30fc\u30c9\u30fb\u30a8\u30b9\u30b1\u30fc\u30d7\u30fb\u30b7\u30fc\u30b1\u30f3\u30b9\u3002
diff --git a/contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java b/contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java
new file mode 100644
index 00000000000..35e35a973f3
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java
@@ -0,0 +1,81 @@
+package org.apache.lucene.messages;
+
+/**
+ * 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.
+ */
+
+import java.util.Locale;
+
+import junit.framework.TestCase;
+
+/**
+ */
+public class TestNLS extends TestCase {
+ public void testMessageLoading() {
+ Message invalidSyntax = new MessageImpl(
+ MessagesTestBundle.Q0001E_INVALID_SYNTAX, "XXX");
+ assertEquals("Syntax Error: XXX", invalidSyntax.getLocalizedMessage());
+ }
+
+ public void testMessageLoading_ja() {
+ Message invalidSyntax = new MessageImpl(
+ MessagesTestBundle.Q0001E_INVALID_SYNTAX, "XXX");
+ assertEquals("構文エラー: XXX", invalidSyntax
+ .getLocalizedMessage(Locale.JAPANESE));
+ }
+
+ public void testNLSLoading() {
+ String message = NLS
+ .getLocalizedMessage(MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION);
+ assertEquals("Truncated unicode escape sequence.", message);
+
+ message = NLS.getLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
+ "XXX");
+ assertEquals("Syntax Error: XXX", message);
+ }
+
+ public void testNLSLoading_ja() {
+ String message = NLS.getLocalizedMessage(
+ MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION,
+ Locale.JAPANESE);
+ assertEquals("切り捨てられたユニコード・エスケープ・シーケンス。", message);
+
+ message = NLS.getLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
+ Locale.JAPANESE, "XXX");
+ assertEquals("構文エラー: XXX", message);
+ }
+
+ public void testNLSLoading_xx_XX() {
+ Locale locale = new Locale("xx", "XX", "");
+ String message = NLS.getLocalizedMessage(
+ MessagesTestBundle.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION,
+ locale);
+ assertEquals("Truncated unicode escape sequence.", message);
+
+ message = NLS.getLocalizedMessage(MessagesTestBundle.Q0001E_INVALID_SYNTAX,
+ locale, "XXX");
+ assertEquals("Syntax Error: XXX", message);
+ }
+
+ public void testMissingMessage() {
+ Locale locale = Locale.ENGLISH;
+ String message = NLS.getLocalizedMessage(
+ MessagesTestBundle.Q0005E_MESSAGE_NOT_IN_BUNDLE, locale);
+
+ assertEquals("Message with key:Q0005E_MESSAGE_NOT_IN_BUNDLE and locale: "
+ + locale.toString() + " not found.", message);
+ }
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerQPHelper.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerQPHelper.java
new file mode 100644
index 00000000000..e3a0434ad61
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerQPHelper.java
@@ -0,0 +1,326 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.LowerCaseFilter;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.standard.StandardTokenizer;
+import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
+import org.apache.lucene.analysis.tokenattributes.TermAttribute;
+import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.original.OriginalQueryParserHelper;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * This test case is a copy of the core Lucene query parser test, it was adapted
+ * to use new QueryParserHelper instead of the old query parser.
+ *
+ * Test QueryParser's ability to deal with Analyzers that return more than one
+ * token per position or that return tokens with a position increment > 1.
+ */
+public class TestMultiAnalyzerQPHelper extends LuceneTestCase {
+
+ private static int multiToken = 0;
+
+ public void testMultiAnalyzer() throws QueryNodeException {
+
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new MultiAnalyzer());
+
+ // trivial, no multiple tokens:
+ assertEquals("foo", qp.parse("foo", "").toString());
+ assertEquals("foo", qp.parse("\"foo\"", "").toString());
+ assertEquals("foo foobar", qp.parse("foo foobar", "").toString());
+ assertEquals("\"foo foobar\"", qp.parse("\"foo foobar\"", "").toString());
+ assertEquals("\"foo foobar blah\"", qp.parse("\"foo foobar blah\"", "")
+ .toString());
+
+ // two tokens at the same position:
+ assertEquals("(multi multi2) foo", qp.parse("multi foo", "").toString());
+ assertEquals("foo (multi multi2)", qp.parse("foo multi", "").toString());
+ assertEquals("(multi multi2) (multi multi2)", qp.parse("multi multi", "")
+ .toString());
+ assertEquals("+(foo (multi multi2)) +(bar (multi multi2))", qp.parse(
+ "+(foo multi) +(bar multi)", "").toString());
+ assertEquals("+(foo (multi multi2)) field:\"bar (multi multi2)\"", qp
+ .parse("+(foo multi) field:\"bar multi\"", "").toString());
+
+ // phrases:
+ assertEquals("\"(multi multi2) foo\"", qp.parse("\"multi foo\"", "")
+ .toString());
+ assertEquals("\"foo (multi multi2)\"", qp.parse("\"foo multi\"", "")
+ .toString());
+ assertEquals("\"foo (multi multi2) foobar (multi multi2)\"", qp.parse(
+ "\"foo multi foobar multi\"", "").toString());
+
+ // fields:
+ assertEquals("(field:multi field:multi2) field:foo", qp.parse(
+ "field:multi field:foo", "").toString());
+ assertEquals("field:\"(multi multi2) foo\"", qp.parse(
+ "field:\"multi foo\"", "").toString());
+
+ // three tokens at one position:
+ assertEquals("triplemulti multi3 multi2", qp.parse("triplemulti", "")
+ .toString());
+ assertEquals("foo (triplemulti multi3 multi2) foobar", qp.parse(
+ "foo triplemulti foobar", "").toString());
+
+ // phrase with non-default slop:
+ assertEquals("\"(multi multi2) foo\"~10", qp.parse("\"multi foo\"~10", "")
+ .toString());
+
+ // phrase with non-default boost:
+ assertEquals("\"(multi multi2) foo\"^2.0", qp.parse("\"multi foo\"^2", "")
+ .toString());
+
+ // phrase after changing default slop
+ qp.setDefaultPhraseSlop(99);
+ assertEquals("\"(multi multi2) foo\"~99 bar", qp.parse("\"multi foo\" bar",
+ "").toString());
+ assertEquals("\"(multi multi2) foo\"~99 \"foo bar\"~2", qp.parse(
+ "\"multi foo\" \"foo bar\"~2", "").toString());
+ qp.setDefaultPhraseSlop(0);
+
+ // non-default operator:
+ qp.setDefaultOperator(Operator.AND);
+ assertEquals("+(multi multi2) +foo", qp.parse("multi foo", "").toString());
+
+ }
+
+ // public void testMultiAnalyzerWithSubclassOfQueryParser() throws
+ // ParseException {
+ // this test doesn't make sense when using the new QueryParser API
+ // DumbQueryParser qp = new DumbQueryParser("", new MultiAnalyzer());
+ // qp.setPhraseSlop(99); // modified default slop
+ //
+ // // direct call to (super's) getFieldQuery to demonstrate differnce
+ // // between phrase and multiphrase with modified default slop
+ // assertEquals("\"foo bar\"~99",
+ // qp.getSuperFieldQuery("","foo bar").toString());
+ // assertEquals("\"(multi multi2) bar\"~99",
+ // qp.getSuperFieldQuery("","multi bar").toString());
+ //
+ //
+ // // ask sublcass to parse phrase with modified default slop
+ // assertEquals("\"(multi multi2) foo\"~99 bar",
+ // qp.parse("\"multi foo\" bar").toString());
+ //
+ // }
+
+ public void testPosIncrementAnalyzer() throws QueryNodeException {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new PosIncrementAnalyzer());
+
+ assertEquals("quick brown", qp.parse("the quick brown", "").toString());
+ assertEquals("\"quick brown\"", qp.parse("\"the quick brown\"", "")
+ .toString());
+ assertEquals("quick brown fox", qp.parse("the quick brown fox", "")
+ .toString());
+ assertEquals("\"quick brown fox\"", qp.parse("\"the quick brown fox\"", "")
+ .toString());
+ }
+
+ /**
+ * Expands "multi" to "multi" and "multi2", both at the same position, and
+ * expands "triplemulti" to "triplemulti", "multi3", and "multi2".
+ */
+ private class MultiAnalyzer extends Analyzer {
+
+ public MultiAnalyzer() {
+ }
+
+ public TokenStream tokenStream(String fieldName, Reader reader) {
+ TokenStream result = new StandardTokenizer(reader);
+ result = new TestFilter(result);
+ result = new LowerCaseFilter(result);
+ return result;
+ }
+ }
+
+ private final class TestFilter extends TokenFilter {
+
+ private String prevType;
+ private int prevStartOffset;
+ private int prevEndOffset;
+
+ TermAttribute termAtt;
+ PositionIncrementAttribute posIncrAtt;
+ OffsetAttribute offsetAtt;
+ TypeAttribute typeAtt;
+
+ public TestFilter(TokenStream in) {
+ super(in);
+ termAtt = (TermAttribute) addAttribute(TermAttribute.class);
+ posIncrAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class);
+ offsetAtt = (OffsetAttribute) addAttribute(OffsetAttribute.class);
+ typeAtt = (TypeAttribute) addAttribute(TypeAttribute.class);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.lucene.analysis.TokenStream#next(org.apache.lucene.analysis
+ * .Token)
+ */
+ @Override
+ public Token next(Token reusableToken) throws IOException {
+
+ if (multiToken > 0) {
+ reusableToken.setTermBuffer("multi" + (multiToken + 1));
+ reusableToken.setStartOffset(prevStartOffset);
+ reusableToken.setEndOffset(prevEndOffset);
+ reusableToken.setType(prevType);
+ reusableToken.setPositionIncrement(0);
+ multiToken--;
+ return reusableToken;
+ } else {
+ boolean next = (reusableToken = input.next(token)) != null;
+ if (next == false) {
+ return null;
+ }
+ prevType = reusableToken.type();
+ prevStartOffset = reusableToken.startOffset();
+ prevEndOffset = reusableToken.endOffset();
+ String text = reusableToken.term();
+ if (text.equals("triplemulti")) {
+ multiToken = 2;
+ return reusableToken;
+ } else if (text.equals("multi")) {
+ multiToken = 1;
+ return reusableToken;
+ } else {
+ return reusableToken;
+ }
+ }
+
+ }
+
+ private Token token = new Token();
+
+ public final boolean incrementToken() throws java.io.IOException {
+ if (multiToken > 0) {
+ termAtt.setTermBuffer("multi" + (multiToken + 1));
+ offsetAtt.setOffset(prevStartOffset, prevEndOffset);
+ typeAtt.setType(prevType);
+ posIncrAtt.setPositionIncrement(0);
+ multiToken--;
+ return true;
+ } else {
+ boolean next = input.incrementToken();
+ if (next == false) {
+ return false;
+ }
+ prevType = typeAtt.type();
+ prevStartOffset = offsetAtt.startOffset();
+ prevEndOffset = offsetAtt.endOffset();
+ String text = termAtt.term();
+ if (text.equals("triplemulti")) {
+ multiToken = 2;
+ return true;
+ } else if (text.equals("multi")) {
+ multiToken = 1;
+ return true;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Analyzes "the quick brown" as: quick(incr=2) brown(incr=1). Does not work
+ * correctly for input other than "the quick brown ...".
+ */
+ private class PosIncrementAnalyzer extends Analyzer {
+
+ public PosIncrementAnalyzer() {
+ }
+
+ public TokenStream tokenStream(String fieldName, Reader reader) {
+ TokenStream result = new StandardTokenizer(reader);
+ result = new TestPosIncrementFilter(result);
+ result = new LowerCaseFilter(result);
+ return result;
+ }
+ }
+
+ private class TestPosIncrementFilter extends TokenFilter {
+
+ TermAttribute termAtt;
+ PositionIncrementAttribute posIncrAtt;
+
+ public TestPosIncrementFilter(TokenStream in) {
+ super(in);
+ termAtt = (TermAttribute) addAttribute(TermAttribute.class);
+ posIncrAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class);
+ }
+
+ private Token token = new Token();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.lucene.analysis.TokenStream#next()
+ */
+ @Override
+ public Token next(Token reusableToken) throws IOException {
+ while (null != (reusableToken = input.next(token))) {
+ String term = reusableToken.term();
+ if (term.equals("the")) {
+ // stopword, do nothing
+ } else if (term.equals("quick")) {
+ reusableToken.setPositionIncrement(2);
+ return reusableToken;
+ } else {
+ reusableToken.setPositionIncrement(1);
+ return reusableToken;
+ }
+ }
+ return null;
+ }
+
+ public final boolean incrementToken() throws java.io.IOException {
+ while (input.incrementToken()) {
+ if (termAtt.term().equals("the")) {
+ // stopword, do nothing
+ } else if (termAtt.term().equals("quick")) {
+ posIncrAtt.setPositionIncrement(2);
+ return true;
+ } else {
+ posIncrAtt.setPositionIncrement(1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerWrapper.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerWrapper.java
new file mode 100644
index 00000000000..fcfcab4567e
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerWrapper.java
@@ -0,0 +1,320 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.LowerCaseFilter;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.standard.StandardTokenizer;
+import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
+import org.apache.lucene.analysis.tokenattributes.TermAttribute;
+import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * This test case is a copy of the core Lucene query parser test, it was adapted
+ * to use new QueryParserWrapper instead of the old query parser.
+ *
+ * Test QueryParser's ability to deal with Analyzers that return more than one
+ * token per position or that return tokens with a position increment > 1.
+ *
+ */
+public class TestMultiAnalyzerWrapper extends LuceneTestCase {
+
+ private static int multiToken = 0;
+
+ public void testMultiAnalyzer() throws ParseException {
+
+ QueryParserWrapper qp = new QueryParserWrapper("", new MultiAnalyzer());
+
+ // trivial, no multiple tokens:
+ assertEquals("foo", qp.parse("foo").toString());
+ assertEquals("foo", qp.parse("\"foo\"").toString());
+ assertEquals("foo foobar", qp.parse("foo foobar").toString());
+ assertEquals("\"foo foobar\"", qp.parse("\"foo foobar\"").toString());
+ assertEquals("\"foo foobar blah\"", qp.parse("\"foo foobar blah\"")
+ .toString());
+
+ // two tokens at the same position:
+ assertEquals("(multi multi2) foo", qp.parse("multi foo").toString());
+ assertEquals("foo (multi multi2)", qp.parse("foo multi").toString());
+ assertEquals("(multi multi2) (multi multi2)", qp.parse("multi multi")
+ .toString());
+ assertEquals("+(foo (multi multi2)) +(bar (multi multi2))", qp.parse(
+ "+(foo multi) +(bar multi)").toString());
+ assertEquals("+(foo (multi multi2)) field:\"bar (multi multi2)\"", qp
+ .parse("+(foo multi) field:\"bar multi\"").toString());
+
+ // phrases:
+ assertEquals("\"(multi multi2) foo\"", qp.parse("\"multi foo\"").toString());
+ assertEquals("\"foo (multi multi2)\"", qp.parse("\"foo multi\"").toString());
+ assertEquals("\"foo (multi multi2) foobar (multi multi2)\"", qp.parse(
+ "\"foo multi foobar multi\"").toString());
+
+ // fields:
+ assertEquals("(field:multi field:multi2) field:foo", qp.parse(
+ "field:multi field:foo").toString());
+ assertEquals("field:\"(multi multi2) foo\"", qp
+ .parse("field:\"multi foo\"").toString());
+
+ // three tokens at one position:
+ assertEquals("triplemulti multi3 multi2", qp.parse("triplemulti")
+ .toString());
+ assertEquals("foo (triplemulti multi3 multi2) foobar", qp.parse(
+ "foo triplemulti foobar").toString());
+
+ // phrase with non-default slop:
+ assertEquals("\"(multi multi2) foo\"~10", qp.parse("\"multi foo\"~10")
+ .toString());
+
+ // phrase with non-default boost:
+ assertEquals("\"(multi multi2) foo\"^2.0", qp.parse("\"multi foo\"^2")
+ .toString());
+
+ // phrase after changing default slop
+ qp.setPhraseSlop(99);
+ assertEquals("\"(multi multi2) foo\"~99 bar", qp.parse("\"multi foo\" bar")
+ .toString());
+ assertEquals("\"(multi multi2) foo\"~99 \"foo bar\"~2", qp.parse(
+ "\"multi foo\" \"foo bar\"~2").toString());
+ qp.setPhraseSlop(0);
+
+ // non-default operator:
+ qp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
+ assertEquals("+(multi multi2) +foo", qp.parse("multi foo").toString());
+
+ }
+
+ // public void testMultiAnalyzerWithSubclassOfQueryParser() throws
+ // ParseException {
+ // this test doesn't make sense when using the new QueryParser API
+ // DumbQueryParser qp = new DumbQueryParser("", new MultiAnalyzer());
+ // qp.setPhraseSlop(99); // modified default slop
+ //
+ // // direct call to (super's) getFieldQuery to demonstrate differnce
+ // // between phrase and multiphrase with modified default slop
+ // assertEquals("\"foo bar\"~99",
+ // qp.getSuperFieldQuery("","foo bar").toString());
+ // assertEquals("\"(multi multi2) bar\"~99",
+ // qp.getSuperFieldQuery("","multi bar").toString());
+ //
+ //
+ // // ask sublcass to parse phrase with modified default slop
+ // assertEquals("\"(multi multi2) foo\"~99 bar",
+ // qp.parse("\"multi foo\" bar").toString());
+ //
+ // }
+
+ public void testPosIncrementAnalyzer() throws ParseException {
+ QueryParserWrapper qp = new QueryParserWrapper("",
+ new PosIncrementAnalyzer());
+ assertEquals("quick brown", qp.parse("the quick brown").toString());
+ assertEquals("\"quick brown\"", qp.parse("\"the quick brown\"").toString());
+ assertEquals("quick brown fox", qp.parse("the quick brown fox").toString());
+ assertEquals("\"quick brown fox\"", qp.parse("\"the quick brown fox\"")
+ .toString());
+ }
+
+ /**
+ * Expands "multi" to "multi" and "multi2", both at the same position, and
+ * expands "triplemulti" to "triplemulti", "multi3", and "multi2".
+ */
+ private class MultiAnalyzer extends Analyzer {
+
+ public MultiAnalyzer() {
+ }
+
+ public TokenStream tokenStream(String fieldName, Reader reader) {
+ TokenStream result = new StandardTokenizer(reader);
+ result = new TestFilter(result);
+ result = new LowerCaseFilter(result);
+ return result;
+ }
+ }
+
+ private final class TestFilter extends TokenFilter {
+
+ private String prevType;
+ private int prevStartOffset;
+ private int prevEndOffset;
+
+ TermAttribute termAtt;
+ PositionIncrementAttribute posIncrAtt;
+ OffsetAttribute offsetAtt;
+ TypeAttribute typeAtt;
+
+ public TestFilter(TokenStream in) {
+ super(in);
+ termAtt = (TermAttribute) addAttribute(TermAttribute.class);
+ posIncrAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class);
+ offsetAtt = (OffsetAttribute) addAttribute(OffsetAttribute.class);
+ typeAtt = (TypeAttribute) addAttribute(TypeAttribute.class);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.apache.lucene.analysis.TokenStream#next(org.apache.lucene.analysis
+ * .Token)
+ */
+ @Override
+ public Token next(Token reusableToken) throws IOException {
+
+ if (multiToken > 0) {
+ reusableToken.setTermBuffer("multi" + (multiToken + 1));
+ reusableToken.setStartOffset(prevStartOffset);
+ reusableToken.setEndOffset(prevEndOffset);
+ reusableToken.setType(prevType);
+ reusableToken.setPositionIncrement(0);
+ multiToken--;
+ return reusableToken;
+ } else {
+ boolean next = (reusableToken = input.next(token)) != null;
+ if (next == false) {
+ return null;
+ }
+ prevType = reusableToken.type();
+ prevStartOffset = reusableToken.startOffset();
+ prevEndOffset = reusableToken.endOffset();
+ String text = reusableToken.term();
+ if (text.equals("triplemulti")) {
+ multiToken = 2;
+ return reusableToken;
+ } else if (text.equals("multi")) {
+ multiToken = 1;
+ return reusableToken;
+ } else {
+ return reusableToken;
+ }
+ }
+
+ }
+
+ private Token token = new Token();
+
+ public final boolean incrementToken() throws java.io.IOException {
+ if (multiToken > 0) {
+ termAtt.setTermBuffer("multi" + (multiToken + 1));
+ offsetAtt.setOffset(prevStartOffset, prevEndOffset);
+ typeAtt.setType(prevType);
+ posIncrAtt.setPositionIncrement(0);
+ multiToken--;
+ return true;
+ } else {
+ boolean next = input.incrementToken();
+ if (next == false) {
+ return false;
+ }
+ prevType = typeAtt.type();
+ prevStartOffset = offsetAtt.startOffset();
+ prevEndOffset = offsetAtt.endOffset();
+ String text = termAtt.term();
+ if (text.equals("triplemulti")) {
+ multiToken = 2;
+ return true;
+ } else if (text.equals("multi")) {
+ multiToken = 1;
+ return true;
+ } else {
+ return true;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Analyzes "the quick brown" as: quick(incr=2) brown(incr=1). Does not work
+ * correctly for input other than "the quick brown ...".
+ */
+ private class PosIncrementAnalyzer extends Analyzer {
+
+ public PosIncrementAnalyzer() {
+ }
+
+ public TokenStream tokenStream(String fieldName, Reader reader) {
+ TokenStream result = new StandardTokenizer(reader);
+ result = new TestPosIncrementFilter(result);
+ result = new LowerCaseFilter(result);
+ return result;
+ }
+ }
+
+ private class TestPosIncrementFilter extends TokenFilter {
+
+ TermAttribute termAtt;
+ PositionIncrementAttribute posIncrAtt;
+
+ public TestPosIncrementFilter(TokenStream in) {
+ super(in);
+ termAtt = (TermAttribute) addAttribute(TermAttribute.class);
+ posIncrAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class);
+ }
+
+ private Token token = new Token();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.lucene.analysis.TokenStream#next()
+ */
+ @Override
+ public Token next(Token reusableToken) throws IOException {
+ while (null != (reusableToken = input.next(token))) {
+ String term = reusableToken.term();
+ if (term.equals("the")) {
+ // stopword, do nothing
+ } else if (term.equals("quick")) {
+ reusableToken.setPositionIncrement(2);
+ return reusableToken;
+ } else {
+ reusableToken.setPositionIncrement(1);
+ return reusableToken;
+ }
+ }
+ return null;
+ }
+
+ public final boolean incrementToken() throws java.io.IOException {
+ while (input.incrementToken()) {
+ if (termAtt.term().equals("the")) {
+ // stopword, do nothing
+ } else if (termAtt.term().equals("quick")) {
+ posIncrAtt.setPositionIncrement(2);
+ return true;
+ } else {
+ posIncrAtt.setPositionIncrement(1);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQPHelper.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQPHelper.java
new file mode 100644
index 00000000000..3430d3cd082
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQPHelper.java
@@ -0,0 +1,368 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.original.config.OriginalQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * This test case is a copy of the core Lucene query parser test, it was adapted
+ * to use new QueryParserHelper instead of the old query parser.
+ *
+ * Tests QueryParser.
+ */
+public class TestMultiFieldQPHelper extends LuceneTestCase {
+
+ /**
+ * test stop words arsing for both the non static form, and for the
+ * corresponding static form (qtxt, fields[]).
+ */
+ public void tesStopwordsParsing() throws Exception {
+ assertStopQueryEquals("one", "b:one t:one");
+ assertStopQueryEquals("one stop", "b:one t:one");
+ assertStopQueryEquals("one (stop)", "b:one t:one");
+ assertStopQueryEquals("one ((stop))", "b:one t:one");
+ assertStopQueryEquals("stop", null);
+ assertStopQueryEquals("(stop)", null);
+ assertStopQueryEquals("((stop))", null);
+ }
+
+ // verify parsing of query using a stopping analyzer
+ private void assertStopQueryEquals(String qtxt, String expectedRes)
+ throws Exception {
+ String[] fields = { "b", "t" };
+ Occur occur[] = { Occur.SHOULD, Occur.SHOULD };
+ TestQPHelper.QPTestAnalyzer a = new TestQPHelper.QPTestAnalyzer();
+ OriginalQueryParserHelper mfqp = new OriginalQueryParserHelper();
+ mfqp.setMultiFields(fields);
+ mfqp.setAnalyzer(a);
+
+ Query q = mfqp.parse(qtxt, null);
+ assertEquals(expectedRes, q.toString());
+
+ q = QueryParserUtil.parse(qtxt, fields, occur, a);
+ assertEquals(expectedRes, q.toString());
+ }
+
+ public void testSimple() throws Exception {
+ String[] fields = { "b", "t" };
+ OriginalQueryParserHelper mfqp = new OriginalQueryParserHelper();
+ mfqp.setMultiFields(fields);
+ mfqp.setAnalyzer(new StandardAnalyzer());
+
+ Query q = mfqp.parse("one", null);
+ assertEquals("b:one t:one", q.toString());
+
+ q = mfqp.parse("one two", null);
+ assertEquals("(b:one t:one) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("+one +two", null);
+ assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+
+ q = mfqp.parse("+one -two -three", null);
+ assertEquals("+(b:one t:one) -(b:two t:two) -(b:three t:three)", q
+ .toString());
+
+ q = mfqp.parse("one^2 two", null);
+ assertEquals("((b:one t:one)^2.0) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("one~ two", null);
+ assertEquals("(b:one~0.5 t:one~0.5) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("one~0.8 two^2", null);
+ assertEquals("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)", q.toString());
+
+ q = mfqp.parse("one* two*", null);
+ assertEquals("(b:one* t:one*) (b:two* t:two*)", q.toString());
+
+ q = mfqp.parse("[a TO c] two", null);
+ assertEquals("(b:[a TO c] t:[a TO c]) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("w?ldcard", null);
+ assertEquals("b:w?ldcard t:w?ldcard", q.toString());
+
+ q = mfqp.parse("\"foo bar\"", null);
+ assertEquals("b:\"foo bar\" t:\"foo bar\"", q.toString());
+
+ q = mfqp.parse("\"aa bb cc\" \"dd ee\"", null);
+ assertEquals("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")", q
+ .toString());
+
+ q = mfqp.parse("\"foo bar\"~4", null);
+ assertEquals("b:\"foo bar\"~4 t:\"foo bar\"~4", q.toString());
+
+ // LUCENE-1213: QueryParser was ignoring slop when phrase
+ // had a field.
+ q = mfqp.parse("b:\"foo bar\"~4", null);
+ assertEquals("b:\"foo bar\"~4", q.toString());
+
+ // make sure that terms which have a field are not touched:
+ q = mfqp.parse("one f:two", null);
+ assertEquals("(b:one t:one) f:two", q.toString());
+
+ // AND mode:
+ mfqp.setDefaultOperator(Operator.AND);
+ q = mfqp.parse("one two", null);
+ assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+ q = mfqp.parse("\"aa bb cc\" \"dd ee\"", null);
+ assertEquals("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")",
+ q.toString());
+
+ }
+
+ public void testBoostsSimple() throws Exception {
+ Map boosts = new HashMap();
+ boosts.put("b", new Float(5));
+ boosts.put("t", new Float(10));
+ String[] fields = { "b", "t" };
+ OriginalQueryParserHelper mfqp = new OriginalQueryParserHelper();
+ mfqp.setMultiFields(fields);
+ mfqp.setFieldsBoost(boosts);
+ mfqp.setAnalyzer(new StandardAnalyzer());
+
+ // Check for simple
+ Query q = mfqp.parse("one", null);
+ assertEquals("b:one^5.0 t:one^10.0", q.toString());
+
+ // Check for AND
+ q = mfqp.parse("one AND two", null);
+ assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0)", q
+ .toString());
+
+ // Check for OR
+ q = mfqp.parse("one OR two", null);
+ assertEquals("(b:one^5.0 t:one^10.0) (b:two^5.0 t:two^10.0)", q.toString());
+
+ // Check for AND and a field
+ q = mfqp.parse("one AND two AND foo:test", null);
+ assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0) +foo:test", q
+ .toString());
+
+ q = mfqp.parse("one^3 AND two^4", null);
+ assertEquals("+((b:one^5.0 t:one^10.0)^3.0) +((b:two^5.0 t:two^10.0)^4.0)",
+ q.toString());
+ }
+
+ public void testStaticMethod1() throws QueryNodeException {
+ String[] fields = { "b", "t" };
+ String[] queries = { "one", "two" };
+ Query q = QueryParserUtil.parse(queries, fields, new StandardAnalyzer());
+ assertEquals("b:one t:two", q.toString());
+
+ String[] queries2 = { "+one", "+two" };
+ q = QueryParserUtil.parse(queries2, fields, new StandardAnalyzer());
+ assertEquals("(+b:one) (+t:two)", q.toString());
+
+ String[] queries3 = { "one", "+two" };
+ q = QueryParserUtil.parse(queries3, fields, new StandardAnalyzer());
+ assertEquals("b:one (+t:two)", q.toString());
+
+ String[] queries4 = { "one +more", "+two" };
+ q = QueryParserUtil.parse(queries4, fields, new StandardAnalyzer());
+ assertEquals("(b:one +b:more) (+t:two)", q.toString());
+
+ String[] queries5 = { "blah" };
+ try {
+ q = QueryParserUtil.parse(queries5, fields, new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+
+ // check also with stop words for this static form (qtxts[], fields[]).
+ TestQPHelper.QPTestAnalyzer stopA = new TestQPHelper.QPTestAnalyzer();
+
+ String[] queries6 = { "((+stop))", "+((stop))" };
+ q = QueryParserUtil.parse(queries6, fields, stopA);
+ assertEquals("", q.toString());
+
+ String[] queries7 = { "one ((+stop)) +more", "+((stop)) +two" };
+ q = QueryParserUtil.parse(queries7, fields, stopA);
+ assertEquals("(b:one +b:more) (+t:two)", q.toString());
+
+ }
+
+ public void testStaticMethod2() throws QueryNodeException {
+ String[] fields = { "b", "t" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT };
+ Query q = QueryParserUtil.parse("one", fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+b:one -t:one", q.toString());
+
+ q = QueryParserUtil.parse("one two", fields, flags, new StandardAnalyzer());
+ assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = QueryParserUtil.parse("blah", fields, flags2, new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testStaticMethod2Old() throws QueryNodeException {
+ String[] fields = { "b", "t" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT };
+ OriginalQueryParserHelper parser = new OriginalQueryParserHelper();
+ parser.setMultiFields(fields);
+ parser.setAnalyzer(new StandardAnalyzer());
+
+ Query q = QueryParserUtil.parse("one", fields, flags,
+ new StandardAnalyzer());// , fields, flags, new
+ // StandardAnalyzer());
+ assertEquals("+b:one -t:one", q.toString());
+
+ q = QueryParserUtil.parse("one two", fields, flags, new StandardAnalyzer());
+ assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = QueryParserUtil.parse("blah", fields, flags2, new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testStaticMethod3() throws QueryNodeException {
+ String[] queries = { "one", "two", "three" };
+ String[] fields = { "f1", "f2", "f3" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT, BooleanClause.Occur.SHOULD };
+ Query q = QueryParserUtil.parse(queries, fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+f1:one -f2:two f3:three", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = QueryParserUtil
+ .parse(queries, fields, flags2, new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testStaticMethod3Old() throws QueryNodeException {
+ String[] queries = { "one", "two" };
+ String[] fields = { "b", "t" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT };
+ Query q = QueryParserUtil.parse(queries, fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+b:one -t:two", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = QueryParserUtil
+ .parse(queries, fields, flags2, new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testAnalyzerReturningNull() throws QueryNodeException {
+ String[] fields = new String[] { "f1", "f2", "f3" };
+ OriginalQueryParserHelper parser = new OriginalQueryParserHelper();
+ parser.setMultiFields(fields);
+ parser.setAnalyzer(new AnalyzerReturningNull());
+
+ Query q = parser.parse("bla AND blo", null);
+ assertEquals("+(f2:bla f3:bla) +(f2:blo f3:blo)", q.toString());
+ // the following queries are not affected as their terms are not
+ // analyzed anyway:
+ q = parser.parse("bla*", null);
+ assertEquals("f1:bla* f2:bla* f3:bla*", q.toString());
+ q = parser.parse("bla~", null);
+ assertEquals("f1:bla~0.5 f2:bla~0.5 f3:bla~0.5", q.toString());
+ q = parser.parse("[a TO c]", null);
+ assertEquals("f1:[a TO c] f2:[a TO c] f3:[a TO c]", q.toString());
+ }
+
+ public void testStopWordSearching() throws Exception {
+ Analyzer analyzer = new StandardAnalyzer();
+ Directory ramDir = new RAMDirectory();
+ IndexWriter iw = new IndexWriter(ramDir, analyzer, true,
+ IndexWriter.MaxFieldLength.LIMITED);
+ Document doc = new Document();
+ doc.add(new Field("body", "blah the footest blah", Field.Store.NO,
+ Field.Index.ANALYZED));
+ iw.addDocument(doc);
+ iw.close();
+
+ OriginalQueryParserHelper mfqp = new OriginalQueryParserHelper();
+
+ mfqp.setMultiFields(new String[] { "body" });
+ mfqp.setAnalyzer(analyzer);
+ mfqp.setDefaultOperator(Operator.AND);
+ Query q = mfqp.parse("the footest", null);
+ IndexSearcher is = new IndexSearcher(ramDir);
+ ScoreDoc[] hits = is.search(q, null, 1000).scoreDocs;
+ assertEquals(1, hits.length);
+ is.close();
+ }
+
+ /**
+ * Return empty tokens for field "f1".
+ */
+ private static class AnalyzerReturningNull extends Analyzer {
+ StandardAnalyzer stdAnalyzer = new StandardAnalyzer();
+
+ public AnalyzerReturningNull() {
+ }
+
+ public TokenStream tokenStream(String fieldName, Reader reader) {
+ if ("f1".equals(fieldName)) {
+ return new EmptyTokenStream();
+ } else {
+ return stdAnalyzer.tokenStream(fieldName, reader);
+ }
+ }
+
+ private static class EmptyTokenStream extends TokenStream {
+ public Token next(final Token reusableToken) {
+ return null;
+ }
+ }
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParserWrapper.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParserWrapper.java
new file mode 100644
index 00000000000..02ce64ee2d7
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParserWrapper.java
@@ -0,0 +1,366 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.io.Reader;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.original.MultiFieldQueryParserWrapper;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * Tests multi field query parsing using the {@link MultiFieldQueryParserWrapper}.
+ */
+public class TestMultiFieldQueryParserWrapper extends LuceneTestCase {
+
+ /**
+ * test stop words arsing for both the non static form, and for the
+ * corresponding static form (qtxt, fields[]).
+ */
+ public void tesStopwordsParsing() throws Exception {
+ assertStopQueryEquals("one", "b:one t:one");
+ assertStopQueryEquals("one stop", "b:one t:one");
+ assertStopQueryEquals("one (stop)", "b:one t:one");
+ assertStopQueryEquals("one ((stop))", "b:one t:one");
+ assertStopQueryEquals("stop", "");
+ assertStopQueryEquals("(stop)", "");
+ assertStopQueryEquals("((stop))", "");
+ }
+
+ // verify parsing of query using a stopping analyzer
+ private void assertStopQueryEquals(String qtxt, String expectedRes)
+ throws Exception {
+ String[] fields = { "b", "t" };
+ Occur occur[] = { Occur.SHOULD, Occur.SHOULD };
+ TestQueryParserWrapper.QPTestAnalyzer a = new TestQueryParserWrapper.QPTestAnalyzer();
+ MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
+ fields, a);
+
+ Query q = mfqp.parse(qtxt);
+ assertEquals(expectedRes, q.toString());
+
+ q = MultiFieldQueryParserWrapper.parse(qtxt, fields, occur, a);
+ assertEquals(expectedRes, q.toString());
+ }
+
+ public void testSimple() throws Exception {
+ String[] fields = { "b", "t" };
+ MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
+ fields, new StandardAnalyzer());
+
+ Query q = mfqp.parse("one");
+ assertEquals("b:one t:one", q.toString());
+
+ q = mfqp.parse("one two");
+ assertEquals("(b:one t:one) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("+one +two");
+ assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+
+ q = mfqp.parse("+one -two -three");
+ assertEquals("+(b:one t:one) -(b:two t:two) -(b:three t:three)", q
+ .toString());
+
+ q = mfqp.parse("one^2 two");
+ assertEquals("((b:one t:one)^2.0) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("one~ two");
+ assertEquals("(b:one~0.5 t:one~0.5) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("one~0.8 two^2");
+ assertEquals("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)", q.toString());
+
+ q = mfqp.parse("one* two*");
+ assertEquals("(b:one* t:one*) (b:two* t:two*)", q.toString());
+
+ q = mfqp.parse("[a TO c] two");
+ assertEquals("(b:[a TO c] t:[a TO c]) (b:two t:two)", q.toString());
+
+ q = mfqp.parse("w?ldcard");
+ assertEquals("b:w?ldcard t:w?ldcard", q.toString());
+
+ q = mfqp.parse("\"foo bar\"");
+ assertEquals("b:\"foo bar\" t:\"foo bar\"", q.toString());
+
+ q = mfqp.parse("\"aa bb cc\" \"dd ee\"");
+ assertEquals("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")", q
+ .toString());
+
+ q = mfqp.parse("\"foo bar\"~4");
+ assertEquals("b:\"foo bar\"~4 t:\"foo bar\"~4", q.toString());
+
+ // LUCENE-1213: MultiFieldQueryParserWrapper was ignoring slop when phrase
+ // had a field.
+ q = mfqp.parse("b:\"foo bar\"~4");
+ assertEquals("b:\"foo bar\"~4", q.toString());
+
+ // make sure that terms which have a field are not touched:
+ q = mfqp.parse("one f:two");
+ assertEquals("(b:one t:one) f:two", q.toString());
+
+ // AND mode:
+ mfqp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
+ q = mfqp.parse("one two");
+ assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+ q = mfqp.parse("\"aa bb cc\" \"dd ee\"");
+ assertEquals("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")",
+ q.toString());
+
+ }
+
+ public void testBoostsSimple() throws Exception {
+ Map boosts = new HashMap();
+ boosts.put("b", new Float(5));
+ boosts.put("t", new Float(10));
+ String[] fields = { "b", "t" };
+ MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
+ fields, new StandardAnalyzer(), boosts);
+
+ // Check for simple
+ Query q = mfqp.parse("one");
+ assertEquals("b:one^5.0 t:one^10.0", q.toString());
+
+ // Check for AND
+ q = mfqp.parse("one AND two");
+ assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0)", q
+ .toString());
+
+ // Check for OR
+ q = mfqp.parse("one OR two");
+ assertEquals("(b:one^5.0 t:one^10.0) (b:two^5.0 t:two^10.0)", q.toString());
+
+ // Check for AND and a field
+ q = mfqp.parse("one AND two AND foo:test");
+ assertEquals("+(b:one^5.0 t:one^10.0) +(b:two^5.0 t:two^10.0) +foo:test", q
+ .toString());
+
+ q = mfqp.parse("one^3 AND two^4");
+ assertEquals("+((b:one^5.0 t:one^10.0)^3.0) +((b:two^5.0 t:two^10.0)^4.0)",
+ q.toString());
+ }
+
+ public void testStaticMethod1() throws ParseException {
+ String[] fields = { "b", "t" };
+ String[] queries = { "one", "two" };
+ Query q = MultiFieldQueryParserWrapper.parse(queries, fields,
+ new StandardAnalyzer());
+ assertEquals("b:one t:two", q.toString());
+
+ String[] queries2 = { "+one", "+two" };
+ q = MultiFieldQueryParserWrapper.parse(queries2, fields,
+ new StandardAnalyzer());
+ assertEquals("(+b:one) (+t:two)", q.toString());
+
+ String[] queries3 = { "one", "+two" };
+ q = MultiFieldQueryParserWrapper.parse(queries3, fields,
+ new StandardAnalyzer());
+ assertEquals("b:one (+t:two)", q.toString());
+
+ String[] queries4 = { "one +more", "+two" };
+ q = MultiFieldQueryParserWrapper.parse(queries4, fields,
+ new StandardAnalyzer());
+ assertEquals("(b:one +b:more) (+t:two)", q.toString());
+
+ String[] queries5 = { "blah" };
+ try {
+ q = MultiFieldQueryParserWrapper.parse(queries5, fields,
+ new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+
+ // check also with stop words for this static form (qtxts[], fields[]).
+ TestQueryParserWrapper.QPTestAnalyzer stopA = new TestQueryParserWrapper.QPTestAnalyzer();
+
+ String[] queries6 = { "((+stop))", "+((stop))" };
+ q = MultiFieldQueryParserWrapper.parse(queries6, fields, stopA);
+ assertEquals("", q.toString());
+
+ String[] queries7 = { "one ((+stop)) +more", "+((stop)) +two" };
+ q = MultiFieldQueryParserWrapper.parse(queries7, fields, stopA);
+ assertEquals("(b:one +b:more) (+t:two)", q.toString());
+
+ }
+
+ public void testStaticMethod2() throws ParseException {
+ String[] fields = { "b", "t" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT };
+ Query q = MultiFieldQueryParserWrapper.parse("one", fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+b:one -t:one", q.toString());
+
+ q = MultiFieldQueryParserWrapper.parse("one two", fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = MultiFieldQueryParserWrapper.parse("blah", fields, flags2,
+ new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testStaticMethod2Old() throws ParseException {
+ String[] fields = { "b", "t" };
+ // int[] flags = {MultiFieldQueryParserWrapper.REQUIRED_FIELD,
+ // MultiFieldQueryParserWrapper.PROHIBITED_FIELD};
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT };
+ MultiFieldQueryParserWrapper parser = new MultiFieldQueryParserWrapper(
+ fields, new StandardAnalyzer());
+
+ Query q = MultiFieldQueryParserWrapper.parse("one", fields, flags,
+ new StandardAnalyzer());// , fields, flags, new StandardAnalyzer());
+ assertEquals("+b:one -t:one", q.toString());
+
+ q = MultiFieldQueryParserWrapper.parse("one two", fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+(b:one b:two) -(t:one t:two)", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = MultiFieldQueryParserWrapper.parse("blah", fields, flags2,
+ new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testStaticMethod3() throws ParseException {
+ String[] queries = { "one", "two", "three" };
+ String[] fields = { "f1", "f2", "f3" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT, BooleanClause.Occur.SHOULD };
+ Query q = MultiFieldQueryParserWrapper.parse(queries, fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+f1:one -f2:two f3:three", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = MultiFieldQueryParserWrapper.parse(queries, fields, flags2,
+ new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testStaticMethod3Old() throws ParseException {
+ String[] queries = { "one", "two" };
+ String[] fields = { "b", "t" };
+ BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+ BooleanClause.Occur.MUST_NOT };
+ Query q = MultiFieldQueryParserWrapper.parse(queries, fields, flags,
+ new StandardAnalyzer());
+ assertEquals("+b:one -t:two", q.toString());
+
+ try {
+ BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+ q = MultiFieldQueryParserWrapper.parse(queries, fields, flags2,
+ new StandardAnalyzer());
+ fail();
+ } catch (IllegalArgumentException e) {
+ // expected exception, array length differs
+ }
+ }
+
+ public void testAnalyzerReturningNull() throws ParseException {
+ String[] fields = new String[] { "f1", "f2", "f3" };
+ MultiFieldQueryParserWrapper parser = new MultiFieldQueryParserWrapper(
+ fields, new AnalyzerReturningNull());
+ Query q = parser.parse("bla AND blo");
+ assertEquals("+(f2:bla f3:bla) +(f2:blo f3:blo)", q.toString());
+ // the following queries are not affected as their terms are not analyzed
+ // anyway:
+ q = parser.parse("bla*");
+ assertEquals("f1:bla* f2:bla* f3:bla*", q.toString());
+ q = parser.parse("bla~");
+ assertEquals("f1:bla~0.5 f2:bla~0.5 f3:bla~0.5", q.toString());
+ q = parser.parse("[a TO c]");
+ assertEquals("f1:[a TO c] f2:[a TO c] f3:[a TO c]", q.toString());
+ }
+
+ public void testStopWordSearching() throws Exception {
+ Analyzer analyzer = new StandardAnalyzer();
+ Directory ramDir = new RAMDirectory();
+ IndexWriter iw = new IndexWriter(ramDir, analyzer, true,
+ IndexWriter.MaxFieldLength.LIMITED);
+ Document doc = new Document();
+ doc.add(new Field("body", "blah the footest blah", Field.Store.NO,
+ Field.Index.ANALYZED));
+ iw.addDocument(doc);
+ iw.close();
+
+ MultiFieldQueryParserWrapper mfqp = new MultiFieldQueryParserWrapper(
+ new String[] { "body" }, analyzer);
+ mfqp.setDefaultOperator(QueryParserWrapper.Operator.AND);
+ Query q = mfqp.parse("the footest");
+ IndexSearcher is = new IndexSearcher(ramDir);
+ ScoreDoc[] hits = is.search(q, null, 1000).scoreDocs;
+ assertEquals(1, hits.length);
+ is.close();
+ }
+
+ /**
+ * Return empty tokens for field "f1".
+ */
+ private static class AnalyzerReturningNull extends Analyzer {
+ StandardAnalyzer stdAnalyzer = new StandardAnalyzer();
+
+ public AnalyzerReturningNull() {
+ }
+
+ public TokenStream tokenStream(String fieldName, Reader reader) {
+ if ("f1".equals(fieldName)) {
+ return new EmptyTokenStream();
+ } else {
+ return stdAnalyzer.tokenStream(fieldName, reader);
+ }
+ }
+
+ private static class EmptyTokenStream extends TokenStream {
+ public Token next(final Token reusableToken) {
+ return null;
+ }
+ }
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQPHelper.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQPHelper.java
new file mode 100644
index 00000000000..ddc1e2aa43d
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQPHelper.java
@@ -0,0 +1,1130 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+import java.text.Collator;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.KeywordAnalyzer;
+import org.apache.lucene.analysis.LowerCaseTokenizer;
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.analysis.StopAnalyzer;
+import org.apache.lucene.analysis.StopFilter;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.WhitespaceAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.tokenattributes.TermAttribute;
+import org.apache.lucene.document.DateField;
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.original.config.OriginalQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute.Operator;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.PrefixQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * This test case is a copy of the core Lucene query parser test, it was adapted
+ * to use new QueryParserHelper instead of the old query parser.
+ *
+ * Tests QueryParser.
+ */
+public class TestQPHelper extends LuceneTestCase {
+
+ public static Analyzer qpAnalyzer = new QPTestAnalyzer();
+
+ public static class QPTestFilter extends TokenFilter {
+ TermAttribute termAtt;
+ OffsetAttribute offsetAtt;
+
+ /**
+ * Filter which discards the token 'stop' and which expands the token
+ * 'phrase' into 'phrase1 phrase2'
+ */
+ public QPTestFilter(TokenStream in) {
+ super(in);
+ termAtt = (TermAttribute) addAttribute(TermAttribute.class);
+ offsetAtt = (OffsetAttribute) addAttribute(OffsetAttribute.class);
+ }
+
+ boolean inPhrase = false;
+ int savedStart = 0, savedEnd = 0;
+
+ public Token next(Token reusableToken) throws IOException {
+ Token token = reusableToken;
+
+ if (inPhrase) {
+ inPhrase = false;
+ token.setTermBuffer("phrase2");
+ token.setStartOffset(savedStart);
+ token.setEndOffset(savedEnd);
+ return reusableToken;
+ } else
+ while ((token = this.input.next(reusableToken)) != null) {
+ if (token.term().equals("phrase")) {
+ inPhrase = true;
+ savedStart = token.startOffset();
+ savedEnd = token.endOffset();
+ token.setTermBuffer("phrase1");
+ token.setStartOffset(savedStart);
+ token.setEndOffset(savedEnd);
+ return token;
+ } else if (!token.term().equals("stop"))
+ return token;
+ }
+
+ return null;
+
+ }
+
+ public boolean incrementToken() throws IOException {
+ if (inPhrase) {
+ inPhrase = false;
+ termAtt.setTermBuffer("phrase2");
+ offsetAtt.setOffset(savedStart, savedEnd);
+ return true;
+ } else
+ while (input.incrementToken()) {
+ if (termAtt.term().equals("phrase")) {
+ inPhrase = true;
+ savedStart = offsetAtt.startOffset();
+ savedEnd = offsetAtt.endOffset();
+ termAtt.setTermBuffer("phrase1");
+ offsetAtt.setOffset(savedStart, savedEnd);
+ return true;
+ } else if (!termAtt.term().equals("stop"))
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public static class QPTestAnalyzer extends Analyzer {
+
+ /** Filters LowerCaseTokenizer with StopFilter. */
+ public final TokenStream tokenStream(String fieldName, Reader reader) {
+ return new QPTestFilter(new LowerCaseTokenizer(reader));
+ }
+ }
+
+ public static class QPTestParser extends OriginalQueryParserHelper {
+ public QPTestParser(Analyzer a) {
+ ((QueryNodeProcessorPipeline)getQueryNodeProcessor())
+ .addProcessor(new QPTestParserQueryNodeProcessor());
+ this.setAnalyzer(a);
+
+ }
+
+ private static class QPTestParserQueryNodeProcessor extends
+ QueryNodeProcessorImpl {
+
+ protected QueryNode postProcessNode(QueryNode node)
+ throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node)
+ throws QueryNodeException {
+
+ if (node instanceof WildcardQueryNode || node instanceof FuzzyQueryNode) {
+
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.EMPTY_MESSAGE));
+
+ }
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+ }
+
+ }
+
+ private int originalMaxClauses;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ originalMaxClauses = BooleanQuery.getMaxClauseCount();
+ }
+
+ public OriginalQueryParserHelper getParser(Analyzer a) throws Exception {
+ if (a == null)
+ a = new SimpleAnalyzer();
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(a);
+
+ qp.setDefaultOperator(Operator.OR);
+
+ return qp;
+
+ }
+
+ public Query getQuery(String query, Analyzer a) throws Exception {
+ return getParser(a).parse(query, "field");
+ }
+
+ public void assertQueryEquals(String query, Analyzer a, String result)
+ throws Exception {
+ Query q = getQuery(query, a);
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
+ + "/");
+ }
+ }
+
+ public void assertQueryEquals(OriginalQueryParserHelper qp, String field,
+ String query, String result) throws Exception {
+ Query q = qp.parse(query, field);
+ String s = q.toString(field);
+ if (!s.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
+ + "/");
+ }
+ }
+
+ public void assertEscapedQueryEquals(String query, Analyzer a, String result)
+ throws Exception {
+ String escapedQuery = QueryParserUtil.escape(query);
+ if (!escapedQuery.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + escapedQuery + "/, expecting /"
+ + result + "/");
+ }
+ }
+
+ public void assertWildcardQueryEquals(String query, boolean lowercase,
+ String result, boolean allowLeadingWildcard) throws Exception {
+ OriginalQueryParserHelper qp = getParser(null);
+ qp.setLowercaseExpandedTerms(lowercase);
+ qp.setAllowLeadingWildcard(allowLeadingWildcard);
+ Query q = qp.parse(query, "field");
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("WildcardQuery /" + query + "/ yielded /" + s + "/, expecting /"
+ + result + "/");
+ }
+ }
+
+ public void assertWildcardQueryEquals(String query, boolean lowercase,
+ String result) throws Exception {
+ assertWildcardQueryEquals(query, lowercase, result, false);
+ }
+
+ public void assertWildcardQueryEquals(String query, String result)
+ throws Exception {
+ OriginalQueryParserHelper qp = getParser(null);
+ Query q = qp.parse(query, "field");
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("WildcardQuery /" + query + "/ yielded /" + s + "/, expecting /"
+ + result + "/");
+ }
+ }
+
+ public Query getQueryDOA(String query, Analyzer a) throws Exception {
+ if (a == null)
+ a = new SimpleAnalyzer();
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(a);
+ qp.setDefaultOperator(Operator.AND);
+
+ return qp.parse(query, "field");
+
+ }
+
+ public void assertQueryEqualsDOA(String query, Analyzer a, String result)
+ throws Exception {
+ Query q = getQueryDOA(query, a);
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
+ + "/");
+ }
+ }
+
+ public void testCJK() throws Exception {
+ // Test Ideographic Space - As wide as a CJK character cell (fullwidth)
+ // used google to translate the word "term" to japanese -> ??
+ assertQueryEquals("term\u3000term\u3000term", null,
+ "term\u0020term\u0020term");
+ assertQueryEquals("??\u3000??\u3000??", null, "??\u0020??\u0020??");
+ }
+
+ public void testSimple() throws Exception {
+ assertQueryEquals("\"term germ\"~2", null, "\"term germ\"~2");
+ assertQueryEquals("term term term", null, "term term term");
+ assertQueryEquals("t�rm term term", new WhitespaceAnalyzer(),
+ "t�rm term term");
+ assertQueryEquals("�mlaut", new WhitespaceAnalyzer(), "�mlaut");
+
+ assertQueryEquals("\"\"", new KeywordAnalyzer(), "");
+ assertQueryEquals("foo:\"\"", new KeywordAnalyzer(), "foo:");
+
+ assertQueryEquals("a AND b", null, "+a +b");
+ assertQueryEquals("(a AND b)", null, "+a +b");
+ assertQueryEquals("c OR (a AND b)", null, "c (+a +b)");
+
+ assertQueryEquals("a AND NOT b", null, "+a -b");
+
+ assertQueryEquals("a AND -b", null, "+a -b");
+
+ assertQueryEquals("a AND !b", null, "+a -b");
+
+ assertQueryEquals("a && b", null, "+a +b");
+
+ assertQueryEquals("a && ! b", null, "+a -b");
+
+ assertQueryEquals("a OR b", null, "a b");
+ assertQueryEquals("a || b", null, "a b");
+
+ assertQueryEquals("a OR !b", null, "a -b");
+
+ assertQueryEquals("a OR ! b", null, "a -b");
+
+ assertQueryEquals("a OR -b", null, "a -b");
+
+ assertQueryEquals("+term -term term", null, "+term -term term");
+ assertQueryEquals("foo:term AND field:anotherTerm", null,
+ "+foo:term +anotherterm");
+ assertQueryEquals("term AND \"phrase phrase\"", null,
+ "+term +\"phrase phrase\"");
+ assertQueryEquals("\"hello there\"", null, "\"hello there\"");
+ assertTrue(getQuery("a AND b", null) instanceof BooleanQuery);
+ assertTrue(getQuery("hello", null) instanceof TermQuery);
+ assertTrue(getQuery("\"hello there\"", null) instanceof PhraseQuery);
+
+ assertQueryEquals("germ term^2.0", null, "germ term^2.0");
+ assertQueryEquals("(term)^2.0", null, "term^2.0");
+ assertQueryEquals("(germ term)^2.0", null, "(germ term)^2.0");
+ assertQueryEquals("term^2.0", null, "term^2.0");
+ assertQueryEquals("term^2", null, "term^2.0");
+ assertQueryEquals("\"germ term\"^2.0", null, "\"germ term\"^2.0");
+ assertQueryEquals("\"term germ\"^2", null, "\"term germ\"^2.0");
+
+ assertQueryEquals("(foo OR bar) AND (baz OR boo)", null,
+ "+(foo bar) +(baz boo)");
+ assertQueryEquals("((a OR b) AND NOT c) OR d", null, "(+(a b) -c) d");
+ assertQueryEquals("+(apple \"steve jobs\") -(foo bar baz)", null,
+ "+(apple \"steve jobs\") -(foo bar baz)");
+ assertQueryEquals("+title:(dog OR cat) -author:\"bob dole\"", null,
+ "+(title:dog title:cat) -author:\"bob dole\"");
+
+ }
+
+ public void testPunct() throws Exception {
+ Analyzer a = new WhitespaceAnalyzer();
+ assertQueryEquals("a&b", a, "a&b");
+ assertQueryEquals("a&&b", a, "a&&b");
+ assertQueryEquals(".NET", a, ".NET");
+ }
+
+ public void testSlop() throws Exception {
+
+ assertQueryEquals("\"term germ\"~2", null, "\"term germ\"~2");
+ assertQueryEquals("\"term germ\"~2 flork", null, "\"term germ\"~2 flork");
+ assertQueryEquals("\"term\"~2", null, "term");
+ assertQueryEquals("\" \"~2 germ", null, "germ");
+ assertQueryEquals("\"term germ\"~2^2", null, "\"term germ\"~2^2.0");
+ }
+
+ public void testNumber() throws Exception {
+ // The numbers go away because SimpleAnalzyer ignores them
+ assertQueryEquals("3", null, "");
+ assertQueryEquals("term 1.0 1 2", null, "term");
+ assertQueryEquals("term term1 term2", null, "term term term");
+
+ Analyzer a = new StandardAnalyzer();
+ assertQueryEquals("3", a, "3");
+ assertQueryEquals("term 1.0 1 2", a, "term 1.0 1 2");
+ assertQueryEquals("term term1 term2", a, "term term1 term2");
+ }
+
+ public void testWildcard() throws Exception {
+ assertQueryEquals("term*", null, "term*");
+ assertQueryEquals("term*^2", null, "term*^2.0");
+ assertQueryEquals("term~", null, "term~0.5");
+ assertQueryEquals("term~0.7", null, "term~0.7");
+
+ assertQueryEquals("term~^2", null, "term~0.5^2.0");
+
+ assertQueryEquals("term^2~", null, "term~0.5^2.0");
+ assertQueryEquals("term*germ", null, "term*germ");
+ assertQueryEquals("term*germ^3", null, "term*germ^3.0");
+
+ assertTrue(getQuery("term*", null) instanceof PrefixQuery);
+ assertTrue(getQuery("term*^2", null) instanceof PrefixQuery);
+ assertTrue(getQuery("term~", null) instanceof FuzzyQuery);
+ assertTrue(getQuery("term~0.7", null) instanceof FuzzyQuery);
+ FuzzyQuery fq = (FuzzyQuery) getQuery("term~0.7", null);
+ assertEquals(0.7f, fq.getMinSimilarity(), 0.1f);
+ assertEquals(FuzzyQuery.defaultPrefixLength, fq.getPrefixLength());
+ fq = (FuzzyQuery) getQuery("term~", null);
+ assertEquals(0.5f, fq.getMinSimilarity(), 0.1f);
+ assertEquals(FuzzyQuery.defaultPrefixLength, fq.getPrefixLength());
+
+ assertQueryNodeException("term~1.1"); // value > 1, throws exception
+
+ assertTrue(getQuery("term*germ", null) instanceof WildcardQuery);
+
+ /*
+ * Tests to see that wild card terms are (or are not) properly lower-cased
+ * with propery parser configuration
+ */
+ // First prefix queries:
+ // by default, convert to lowercase:
+ assertWildcardQueryEquals("Term*", true, "term*");
+ // explicitly set lowercase:
+ assertWildcardQueryEquals("term*", true, "term*");
+ assertWildcardQueryEquals("Term*", true, "term*");
+ assertWildcardQueryEquals("TERM*", true, "term*");
+ // explicitly disable lowercase conversion:
+ assertWildcardQueryEquals("term*", false, "term*");
+ assertWildcardQueryEquals("Term*", false, "Term*");
+ assertWildcardQueryEquals("TERM*", false, "TERM*");
+ // Then 'full' wildcard queries:
+ // by default, convert to lowercase:
+ assertWildcardQueryEquals("Te?m", "te?m");
+ // explicitly set lowercase:
+ assertWildcardQueryEquals("te?m", true, "te?m");
+ assertWildcardQueryEquals("Te?m", true, "te?m");
+ assertWildcardQueryEquals("TE?M", true, "te?m");
+ assertWildcardQueryEquals("Te?m*gerM", true, "te?m*germ");
+ // explicitly disable lowercase conversion:
+ assertWildcardQueryEquals("te?m", false, "te?m");
+ assertWildcardQueryEquals("Te?m", false, "Te?m");
+ assertWildcardQueryEquals("TE?M", false, "TE?M");
+ assertWildcardQueryEquals("Te?m*gerM", false, "Te?m*gerM");
+ // Fuzzy queries:
+ assertWildcardQueryEquals("Term~", "term~0.5");
+ assertWildcardQueryEquals("Term~", true, "term~0.5");
+ assertWildcardQueryEquals("Term~", false, "Term~0.5");
+ // Range queries:
+
+ // TODO: implement this on QueryParser
+ // Q0002E_INVALID_SYNTAX_CANNOT_PARSE: Syntax Error, cannot parse '[A TO
+ // C]': Lexical error at line 1, column 1. Encountered: "[" (91), after
+ // : ""
+ assertWildcardQueryEquals("[A TO C]", "[a TO c]");
+ assertWildcardQueryEquals("[A TO C]", true, "[a TO c]");
+ assertWildcardQueryEquals("[A TO C]", false, "[A TO C]");
+ // Test suffix queries: first disallow
+ try {
+ assertWildcardQueryEquals("*Term", true, "*term");
+ fail();
+ } catch (QueryNodeException pe) {
+ // expected exception
+ }
+ try {
+ assertWildcardQueryEquals("?Term", true, "?term");
+ fail();
+ } catch (QueryNodeException pe) {
+ // expected exception
+ }
+ // Test suffix queries: then allow
+ assertWildcardQueryEquals("*Term", true, "*term", true);
+ assertWildcardQueryEquals("?Term", true, "?term", true);
+ }
+
+ public void testLeadingWildcardType() throws Exception {
+ OriginalQueryParserHelper qp = getParser(null);
+ qp.setAllowLeadingWildcard(true);
+ assertEquals(WildcardQuery.class, qp.parse("t*erm*", "field").getClass());
+ assertEquals(WildcardQuery.class, qp.parse("?term*", "field").getClass());
+ assertEquals(WildcardQuery.class, qp.parse("*term*", "field").getClass());
+ }
+
+ public void testQPA() throws Exception {
+ assertQueryEquals("term term^3.0 term", qpAnalyzer, "term term^3.0 term");
+ assertQueryEquals("term stop^3.0 term", qpAnalyzer, "term term");
+
+ assertQueryEquals("term term term", qpAnalyzer, "term term term");
+ assertQueryEquals("term +stop term", qpAnalyzer, "term term");
+ assertQueryEquals("term -stop term", qpAnalyzer, "term term");
+
+ assertQueryEquals("drop AND (stop) AND roll", qpAnalyzer, "+drop +roll");
+ assertQueryEquals("term +(stop) term", qpAnalyzer, "term term");
+ assertQueryEquals("term -(stop) term", qpAnalyzer, "term term");
+
+ assertQueryEquals("drop AND stop AND roll", qpAnalyzer, "+drop +roll");
+ assertQueryEquals("term phrase term", qpAnalyzer,
+ "term \"phrase1 phrase2\" term");
+
+ assertQueryEquals("term AND NOT phrase term", qpAnalyzer,
+ "+term -\"phrase1 phrase2\" term");
+
+ assertQueryEquals("stop^3", qpAnalyzer, "");
+ assertQueryEquals("stop", qpAnalyzer, "");
+ assertQueryEquals("(stop)^3", qpAnalyzer, "");
+ assertQueryEquals("((stop))^3", qpAnalyzer, "");
+ assertQueryEquals("(stop^3)", qpAnalyzer, "");
+ assertQueryEquals("((stop)^3)", qpAnalyzer, "");
+ assertQueryEquals("(stop)", qpAnalyzer, "");
+ assertQueryEquals("((stop))", qpAnalyzer, "");
+ assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery);
+ assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery);
+ }
+
+ public void testRange() throws Exception {
+ assertQueryEquals("[ a TO z]", null, "[a TO z]");
+ assertEquals(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT, ((TermRangeQuery)getQuery("[ a TO z]", null)).getRewriteMethod());
+
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+
+ qp.setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
+ assertEquals(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE,((TermRangeQuery)qp.parse("[ a TO z]", "field")).getRewriteMethod());
+
+ assertQueryEquals("[ a TO z ]", null, "[a TO z]");
+ assertQueryEquals("{ a TO z}", null, "{a TO z}");
+ assertQueryEquals("{ a TO z }", null, "{a TO z}");
+ assertQueryEquals("{ a TO z }^2.0", null, "{a TO z}^2.0");
+ assertQueryEquals("[ a TO z] OR bar", null, "[a TO z] bar");
+ assertQueryEquals("[ a TO z] AND bar", null, "+[a TO z] +bar");
+ assertQueryEquals("( bar blar { a TO z}) ", null, "bar blar {a TO z}");
+ assertQueryEquals("gack ( bar blar { a TO z}) ", null,
+ "gack (bar blar {a TO z})");
+ }
+
+ public void testFarsiRangeCollating() throws Exception {
+
+ RAMDirectory ramDir = new RAMDirectory();
+ IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(), true,
+ IndexWriter.MaxFieldLength.LIMITED);
+ Document doc = new Document();
+ doc.add(new Field("content", "\u0633\u0627\u0628", Field.Store.YES,
+ Field.Index.UN_TOKENIZED));
+ iw.addDocument(doc);
+ iw.close();
+ IndexSearcher is = new IndexSearcher(ramDir);
+
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new WhitespaceAnalyzer());
+
+ // Neither Java 1.4.2 nor 1.5.0 has Farsi Locale collation available in
+ // RuleBasedCollator. However, the Arabic Locale seems to order the
+ // Farsi
+ // characters properly.
+ Collator c = Collator.getInstance(new Locale("ar"));
+ qp.setRangeCollator(c);
+
+ // Unicode order would include U+0633 in [ U+062F - U+0698 ], but Farsi
+ // orders the U+0698 character before the U+0633 character, so the
+ // single
+ // index Term below should NOT be returned by a ConstantScoreRangeQuery
+ // with a Farsi Collator (or an Arabic one for the case when Farsi is
+ // not
+ // supported).
+
+ // Test ConstantScoreRangeQuery
+ qp.setMultiTermRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
+ ScoreDoc[] result = is.search(qp.parse("[ \u062F TO \u0698 ]", "content"),
+ null, 1000).scoreDocs;
+ assertEquals("The index Term should not be included.", 0, result.length);
+
+ result = is.search(qp.parse("[ \u0633 TO \u0638 ]", "content"), null, 1000).scoreDocs;
+ assertEquals("The index Term should be included.", 1, result.length);
+
+ // Test RangeQuery
+ qp.setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
+ result = is.search(qp.parse("[ \u062F TO \u0698 ]", "content"), null, 1000).scoreDocs;
+ assertEquals("The index Term should not be included.", 0, result.length);
+
+ result = is.search(qp.parse("[ \u0633 TO \u0638 ]", "content"), null, 1000).scoreDocs;
+ assertEquals("The index Term should be included.", 1, result.length);
+
+ is.close();
+ }
+
+ /** for testing legacy DateField support */
+ private String getLegacyDate(String s) throws Exception {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+ return DateField.dateToString(df.parse(s));
+ }
+
+ /** for testing DateTools support */
+ private String getDate(String s, DateTools.Resolution resolution)
+ throws Exception {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+ return getDate(df.parse(s), resolution);
+ }
+
+ /** for testing DateTools support */
+ private String getDate(Date d, DateTools.Resolution resolution)
+ throws Exception {
+ if (resolution == null) {
+ return DateField.dateToString(d);
+ } else {
+ return DateTools.dateToString(d, resolution);
+ }
+ }
+
+ private String getLocalizedDate(int year, int month, int day,
+ boolean extendLastDate) {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(year, month, day);
+ if (extendLastDate) {
+ calendar.set(Calendar.HOUR_OF_DAY, 23);
+ calendar.set(Calendar.MINUTE, 59);
+ calendar.set(Calendar.SECOND, 59);
+ calendar.set(Calendar.MILLISECOND, 999);
+ }
+ return df.format(calendar.getTime());
+ }
+
+ /** for testing legacy DateField support */
+ public void testLegacyDateRange() throws Exception {
+ String startDate = getLocalizedDate(2002, 1, 1, false);
+ String endDate = getLocalizedDate(2002, 1, 4, false);
+ Calendar endDateExpected = Calendar.getInstance();
+ endDateExpected.set(2002, 1, 4, 23, 59, 59);
+ endDateExpected.set(Calendar.MILLISECOND, 999);
+ assertQueryEquals("[ " + startDate + " TO " + endDate + "]", null, "["
+ + getLegacyDate(startDate) + " TO "
+ + DateField.dateToString(endDateExpected.getTime()) + "]");
+ assertQueryEquals("{ " + startDate + " " + endDate + " }", null, "{"
+ + getLegacyDate(startDate) + " TO " + getLegacyDate(endDate) + "}");
+ }
+
+ public void testDateRange() throws Exception {
+ String startDate = getLocalizedDate(2002, 1, 1, false);
+ String endDate = getLocalizedDate(2002, 1, 4, false);
+ Calendar endDateExpected = Calendar.getInstance();
+ endDateExpected.set(2002, 1, 4, 23, 59, 59);
+ endDateExpected.set(Calendar.MILLISECOND, 999);
+ final String defaultField = "default";
+ final String monthField = "month";
+ final String hourField = "hour";
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+
+ // Don't set any date resolution and verify if DateField is used
+ assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
+ endDateExpected.getTime(), null);
+
+ Map dateRes = new HashMap();
+
+ // set a field specific date resolution
+ dateRes.put(monthField, DateTools.Resolution.MONTH);
+ qp.setDateResolution(dateRes);
+
+ // DateField should still be used for defaultField
+ assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
+ endDateExpected.getTime(), null);
+
+ // set default date resolution to MILLISECOND
+ qp.setDateResolution(DateTools.Resolution.MILLISECOND);
+
+ // set second field specific date resolution
+ dateRes.put(hourField, DateTools.Resolution.HOUR);
+ qp.setDateResolution(dateRes);
+
+ // for this field no field specific date resolution has been set,
+ // so verify if the default resolution is used
+ assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
+ endDateExpected.getTime(), DateTools.Resolution.MILLISECOND);
+
+ // verify if field specific date resolutions are used for these two
+ // fields
+ assertDateRangeQueryEquals(qp, monthField, startDate, endDate,
+ endDateExpected.getTime(), DateTools.Resolution.MONTH);
+
+ assertDateRangeQueryEquals(qp, hourField, startDate, endDate,
+ endDateExpected.getTime(), DateTools.Resolution.HOUR);
+ }
+
+ public void assertDateRangeQueryEquals(OriginalQueryParserHelper qp,
+ String field, String startDate, String endDate, Date endDateInclusive,
+ DateTools.Resolution resolution) throws Exception {
+ assertQueryEquals(qp, field, field + ":[" + startDate + " TO " + endDate
+ + "]", "[" + getDate(startDate, resolution) + " TO "
+ + getDate(endDateInclusive, resolution) + "]");
+ assertQueryEquals(qp, field, field + ":{" + startDate + " TO " + endDate
+ + "}", "{" + getDate(startDate, resolution) + " TO "
+ + getDate(endDate, resolution) + "}");
+ }
+
+ public void testEscaped() throws Exception {
+ Analyzer a = new WhitespaceAnalyzer();
+
+ /*
+ * assertQueryEquals("\\[brackets", a, "\\[brackets");
+ * assertQueryEquals("\\[brackets", null, "brackets");
+ * assertQueryEquals("\\\\", a, "\\\\"); assertQueryEquals("\\+blah", a,
+ * "\\+blah"); assertQueryEquals("\\(blah", a, "\\(blah");
+ *
+ * assertQueryEquals("\\-blah", a, "\\-blah"); assertQueryEquals("\\!blah",
+ * a, "\\!blah"); assertQueryEquals("\\{blah", a, "\\{blah");
+ * assertQueryEquals("\\}blah", a, "\\}blah"); assertQueryEquals("\\:blah",
+ * a, "\\:blah"); assertQueryEquals("\\^blah", a, "\\^blah");
+ * assertQueryEquals("\\[blah", a, "\\[blah"); assertQueryEquals("\\]blah",
+ * a, "\\]blah"); assertQueryEquals("\\\"blah", a, "\\\"blah");
+ * assertQueryEquals("\\(blah", a, "\\(blah"); assertQueryEquals("\\)blah",
+ * a, "\\)blah"); assertQueryEquals("\\~blah", a, "\\~blah");
+ * assertQueryEquals("\\*blah", a, "\\*blah"); assertQueryEquals("\\?blah",
+ * a, "\\?blah"); //assertQueryEquals("foo \\&\\& bar", a,
+ * "foo \\&\\& bar"); //assertQueryEquals("foo \\|| bar", a,
+ * "foo \\|| bar"); //assertQueryEquals("foo \\AND bar", a,
+ * "foo \\AND bar");
+ */
+
+ assertQueryEquals("\\a", a, "a");
+
+ 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");
+
+ 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");
+
+ 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*");
+
+ 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");
+
+ assertQueryEquals("a:b\\-c~", a, "a:b-c~0.5");
+ assertQueryEquals("a:b\\+c~", a, "a:b+c~0.5");
+ assertQueryEquals("a:b\\:c~", a, "a:b:c~0.5");
+ assertQueryEquals("a:b\\\\c~", a, "a:b\\c~0.5");
+
+ // TODO: implement Range queries on QueryParser
+ assertQueryEquals("[ a\\- TO a\\+ ]", null, "[a- TO a+]");
+ assertQueryEquals("[ a\\: TO a\\~ ]", null, "[a: TO a~]");
+ assertQueryEquals("[ a\\\\ TO a\\* ]", null, "[a\\ TO a*]");
+
+ assertQueryEquals(
+ "[\"c\\:\\\\temp\\\\\\~foo0.txt\" TO \"c\\:\\\\temp\\\\\\~foo9.txt\"]",
+ a, "[c:\\temp\\~foo0.txt TO c:\\temp\\~foo9.txt]");
+
+ assertQueryEquals("a\\\\\\+b", a, "a\\+b");
+
+ assertQueryEquals("a \\\"b c\\\" d", a, "a \"b c\" d");
+ assertQueryEquals("\"a \\\"b c\\\" d\"", a, "\"a \"b c\" d\"");
+ assertQueryEquals("\"a \\+b c d\"", a, "\"a +b c d\"");
+
+ assertQueryEquals("c\\:\\\\temp\\\\\\~foo.txt", a, "c:\\temp\\~foo.txt");
+
+ assertQueryNodeException("XY\\"); // there must be a character after the
+ // escape char
+
+ // test unicode escaping
+ assertQueryEquals("a\\u0062c", a, "abc");
+ assertQueryEquals("XY\\u005a", a, "XYZ");
+ assertQueryEquals("XY\\u005A", a, "XYZ");
+ assertQueryEquals("\"a \\\\\\u0028\\u0062\\\" c\"", a, "\"a \\(b\" c\"");
+
+ assertQueryNodeException("XY\\u005G"); // test non-hex character in escaped
+ // unicode sequence
+ assertQueryNodeException("XY\\u005"); // test incomplete escaped unicode
+ // sequence
+
+ // Tests bug LUCENE-800
+ assertQueryEquals("(item:\\\\ item:ABCD\\\\)", a, "item:\\ item:ABCD\\");
+ assertQueryNodeException("(item:\\\\ item:ABCD\\\\))"); // unmatched closing
+ // paranthesis
+ assertQueryEquals("\\*", a, "*");
+ assertQueryEquals("\\\\", a, "\\"); // escaped backslash
+
+ assertQueryNodeException("\\"); // a backslash must always be escaped
+
+ // LUCENE-1189
+ assertQueryEquals("(\"a\\\\\") or (\"b\")", a, "a\\ or b");
+ }
+
+ public void testQueryStringEscaping() throws Exception {
+ Analyzer a = new WhitespaceAnalyzer();
+
+ assertEscapedQueryEquals("a-b:c", a, "a\\-b\\:c");
+ assertEscapedQueryEquals("a+b:c", a, "a\\+b\\:c");
+ assertEscapedQueryEquals("a:b:c", a, "a\\:b\\:c");
+ assertEscapedQueryEquals("a\\b:c", a, "a\\\\b\\:c");
+
+ assertEscapedQueryEquals("a:b-c", a, "a\\:b\\-c");
+ assertEscapedQueryEquals("a:b+c", a, "a\\:b\\+c");
+ assertEscapedQueryEquals("a:b:c", a, "a\\:b\\:c");
+ assertEscapedQueryEquals("a:b\\c", a, "a\\:b\\\\c");
+
+ assertEscapedQueryEquals("a:b-c*", a, "a\\:b\\-c\\*");
+ assertEscapedQueryEquals("a:b+c*", a, "a\\:b\\+c\\*");
+ assertEscapedQueryEquals("a:b:c*", a, "a\\:b\\:c\\*");
+
+ assertEscapedQueryEquals("a:b\\\\c*", a, "a\\:b\\\\\\\\c\\*");
+
+ assertEscapedQueryEquals("a:b-?c", a, "a\\:b\\-\\?c");
+ assertEscapedQueryEquals("a:b+?c", a, "a\\:b\\+\\?c");
+ assertEscapedQueryEquals("a:b:?c", a, "a\\:b\\:\\?c");
+
+ assertEscapedQueryEquals("a:b?c", a, "a\\:b\\?c");
+
+ assertEscapedQueryEquals("a:b-c~", a, "a\\:b\\-c\\~");
+ assertEscapedQueryEquals("a:b+c~", a, "a\\:b\\+c\\~");
+ assertEscapedQueryEquals("a:b:c~", a, "a\\:b\\:c\\~");
+ assertEscapedQueryEquals("a:b\\c~", a, "a\\:b\\\\c\\~");
+
+ assertEscapedQueryEquals("[ a - TO a+ ]", null, "\\[ a \\- TO a\\+ \\]");
+ assertEscapedQueryEquals("[ a : TO a~ ]", null, "\\[ a \\: TO a\\~ \\]");
+ assertEscapedQueryEquals("[ a\\ TO a* ]", null, "\\[ a\\\\ TO a\\* \\]");
+
+ // LUCENE-881
+ assertEscapedQueryEquals("|| abc ||", a, "\\|\\| abc \\|\\|");
+ assertEscapedQueryEquals("&& abc &&", a, "\\&\\& abc \\&\\&");
+ }
+
+ public void testTabNewlineCarriageReturn() throws Exception {
+ assertQueryEqualsDOA("+weltbank +worlbank", null, "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \n +worlbank", null, "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\r+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r +worlbank", null, "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\r\n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r\n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r\n +worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r \n +worlbank", null,
+ "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\t+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \t+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \t +worlbank", null, "+weltbank +worlbank");
+ }
+
+ public void testSimpleDAO() throws Exception {
+ assertQueryEqualsDOA("term term term", null, "+term +term +term");
+ assertQueryEqualsDOA("term +term term", null, "+term +term +term");
+ assertQueryEqualsDOA("term term +term", null, "+term +term +term");
+ assertQueryEqualsDOA("term +term +term", null, "+term +term +term");
+ assertQueryEqualsDOA("-term term term", null, "-term +term +term");
+ }
+
+ public void testBoost() throws Exception {
+ StandardAnalyzer oneStopAnalyzer = new StandardAnalyzer(
+ new String[] { "on" });
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(oneStopAnalyzer);
+
+ Query q = qp.parse("on^1.0", "field");
+ assertNotNull(q);
+ q = qp.parse("\"hello\"^2.0", "field");
+ assertNotNull(q);
+ assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
+ q = qp.parse("hello^2.0", "field");
+ assertNotNull(q);
+ assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
+ q = qp.parse("\"on\"^1.0", "field");
+ assertNotNull(q);
+
+ OriginalQueryParserHelper qp2 = new OriginalQueryParserHelper();
+ qp2.setAnalyzer(new StandardAnalyzer());
+
+ q = qp2.parse("the^3", "field");
+ // "the" is a stop word so the result is an empty query:
+ assertNotNull(q);
+ assertEquals("", q.toString());
+ assertEquals(1.0f, q.getBoost(), 0.01f);
+ }
+
+ public void assertQueryNodeException(String queryString) throws Exception {
+ try {
+ getQuery(queryString, null);
+ } catch (QueryNodeException expected) {
+ return;
+ }
+ fail("ParseException expected, not thrown");
+ }
+
+ public void testException() throws Exception {
+ assertQueryNodeException("\"some phrase");
+ assertQueryNodeException("(foo bar");
+ assertQueryNodeException("foo bar))");
+ assertQueryNodeException("field:term:with:colon some more terms");
+ assertQueryNodeException("(sub query)^5.0^2.0 plus more");
+ assertQueryNodeException("secret AND illegal) AND access:confidential");
+ }
+
+ public void testCustomQueryParserWildcard() {
+ try {
+ new QPTestParser(new WhitespaceAnalyzer()).parse("a?t", "contents");
+ fail("Wildcard queries should not be allowed");
+ } catch (QueryNodeException expected) {
+ // expected exception
+ }
+ }
+
+ public void testCustomQueryParserFuzzy() throws Exception {
+ try {
+ new QPTestParser(new WhitespaceAnalyzer()).parse("xunit~", "contents");
+ fail("Fuzzy queries should not be allowed");
+ } catch (QueryNodeException expected) {
+ // expected exception
+ }
+ }
+
+ public void testBooleanQuery() throws Exception {
+ BooleanQuery.setMaxClauseCount(2);
+ try {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new WhitespaceAnalyzer());
+
+ qp.parse("one two three", "field");
+ fail("ParseException expected due to too many boolean clauses");
+ } catch (QueryNodeException expected) {
+ // too many boolean clauses, so ParseException is expected
+ }
+ }
+
+ /**
+ * This test differs from TestPrecedenceQueryParser
+ */
+ public void testPrecedence() throws Exception {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new WhitespaceAnalyzer());
+
+ Query query1 = qp.parse("A AND B OR C AND D", "field");
+ Query query2 = qp.parse("+A +B +C +D", "field");
+
+ assertEquals(query1, query2);
+ }
+
+ public void testLocalDateFormat() throws IOException, QueryNodeException {
+
+ RAMDirectory ramDir = new RAMDirectory();
+ IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(), true,
+ IndexWriter.MaxFieldLength.LIMITED);
+ addDateDoc("a", 2005, 12, 2, 10, 15, 33, iw);
+ addDateDoc("b", 2005, 12, 4, 22, 15, 00, iw);
+ iw.close();
+ IndexSearcher is = new IndexSearcher(ramDir);
+ assertHits(1, "[12/1/2005 TO 12/3/2005]", is);
+ assertHits(2, "[12/1/2005 TO 12/4/2005]", is);
+ assertHits(1, "[12/3/2005 TO 12/4/2005]", is);
+ assertHits(1, "{12/1/2005 TO 12/3/2005}", is);
+ assertHits(1, "{12/1/2005 TO 12/4/2005}", is);
+ assertHits(0, "{12/3/2005 TO 12/4/2005}", is);
+ is.close();
+ }
+
+ public void testStarParsing() throws Exception {
+ // final int[] type = new int[1];
+ // OriginalQueryParserHelper qp = new OriginalQueryParserHelper("field", new
+ // WhitespaceAnalyzer()) {
+ // protected Query getWildcardQuery(String field, String termStr) throws
+ // ParseException {
+ // // override error checking of superclass
+ // type[0]=1;
+ // return new TermQuery(new Term(field,termStr));
+ // }
+ // protected Query getPrefixQuery(String field, String termStr) throws
+ // ParseException {
+ // // override error checking of superclass
+ // type[0]=2;
+ // return new TermQuery(new Term(field,termStr));
+ // }
+ //
+ // protected Query getFieldQuery(String field, String queryText) throws
+ // ParseException {
+ // type[0]=3;
+ // return super.getFieldQuery(field, queryText);
+ // }
+ // };
+ //
+ // TermQuery tq;
+ //
+ // tq = (TermQuery)qp.parse("foo:zoo*");
+ // assertEquals("zoo",tq.getTerm().text());
+ // assertEquals(2,type[0]);
+ //
+ // tq = (TermQuery)qp.parse("foo:zoo*^2");
+ // assertEquals("zoo",tq.getTerm().text());
+ // assertEquals(2,type[0]);
+ // assertEquals(tq.getBoost(),2,0);
+ //
+ // tq = (TermQuery)qp.parse("foo:*");
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]); // could be a valid prefix query in the
+ // future too
+ //
+ // tq = (TermQuery)qp.parse("foo:*^2");
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]);
+ // assertEquals(tq.getBoost(),2,0);
+ //
+ // tq = (TermQuery)qp.parse("*:foo");
+ // assertEquals("*",tq.getTerm().field());
+ // assertEquals("foo",tq.getTerm().text());
+ // assertEquals(3,type[0]);
+ //
+ // tq = (TermQuery)qp.parse("*:*");
+ // assertEquals("*",tq.getTerm().field());
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]); // could be handled as a prefix query in the
+ // future
+ //
+ // tq = (TermQuery)qp.parse("(*:*)");
+ // assertEquals("*",tq.getTerm().field());
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]);
+
+ }
+
+ public void testStopwords() throws Exception {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(
+ new StopAnalyzer(new String[] { "the", "foo" }));
+
+ Query result = qp.parse("a:the OR a:foo", "a");
+ assertNotNull("result is null and it shouldn't be", result);
+ assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery);
+ assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: "
+ + 0, ((BooleanQuery) result).clauses().size() == 0);
+ result = qp.parse("a:woo OR a:the", "a");
+ assertNotNull("result is null and it shouldn't be", result);
+ assertTrue("result is not a TermQuery", result instanceof TermQuery);
+ result = qp.parse(
+ "(fieldX:xxxxx OR fieldy:xxxxxxxx)^2 AND (fieldx:the OR fieldy:foo)",
+ "a");
+ assertNotNull("result is null and it shouldn't be", result);
+ assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery);
+ System.out.println("Result: " + result);
+ assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: "
+ + 2, ((BooleanQuery) result).clauses().size() == 2);
+ }
+
+ public void testPositionIncrement() throws Exception {
+ boolean dflt = StopFilter.getEnablePositionIncrementsDefault();
+ StopFilter.setEnablePositionIncrementsDefault(true);
+ try {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(
+ new StopAnalyzer(new String[] { "the", "in", "are", "this" }));
+
+ qp.setEnablePositionIncrements(true);
+
+ String qtxt = "\"the words in poisitions pos02578 are stopped in this phrasequery\"";
+ // 0 2 5 7 8
+ int expectedPositions[] = { 1, 3, 4, 6, 9 };
+ PhraseQuery pq = (PhraseQuery) qp.parse(qtxt, "a");
+ // System.out.println("Query text: "+qtxt);
+ // System.out.println("Result: "+pq);
+ Term t[] = pq.getTerms();
+ int pos[] = pq.getPositions();
+ for (int i = 0; i < t.length; i++) {
+ // System.out.println(i+". "+t[i]+" pos: "+pos[i]);
+ assertEquals("term " + i + " = " + t[i] + " has wrong term-position!",
+ expectedPositions[i], pos[i]);
+ }
+
+ } finally {
+ StopFilter.setEnablePositionIncrementsDefault(dflt);
+ }
+ }
+
+ public void testMatchAllDocs() throws Exception {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new WhitespaceAnalyzer());
+
+ assertEquals(new MatchAllDocsQuery(), qp.parse("*:*", "field"));
+ assertEquals(new MatchAllDocsQuery(), qp.parse("(*:*)", "field"));
+ BooleanQuery bq = (BooleanQuery) qp.parse("+*:* -*:*", "field");
+ assertTrue(bq.getClauses()[0].getQuery() instanceof MatchAllDocsQuery);
+ assertTrue(bq.getClauses()[1].getQuery() instanceof MatchAllDocsQuery);
+ }
+
+ private void assertHits(int expected, String query, IndexSearcher is)
+ throws IOException, QueryNodeException {
+ OriginalQueryParserHelper qp = new OriginalQueryParserHelper();
+ qp.setAnalyzer(new WhitespaceAnalyzer());
+ qp.setLocale(Locale.ENGLISH);
+
+ Query q = qp.parse(query, "date");
+ ScoreDoc[] hits = is.search(q, null, 1000).scoreDocs;
+ assertEquals(expected, hits.length);
+ }
+
+ private static void addDateDoc(String content, int year, int month, int day,
+ int hour, int minute, int second, IndexWriter iw) throws IOException {
+ Document d = new Document();
+ d.add(new Field("f", content, Field.Store.YES, Field.Index.ANALYZED));
+ Calendar cal = Calendar.getInstance();
+ cal.set(year, month - 1, day, hour, minute, second);
+ d.add(new Field("date", DateField.dateToString(cal.getTime()),
+ Field.Store.YES, Field.Index.NOT_ANALYZED));
+ iw.addDocument(d);
+ }
+
+ public void tearDown() throws Exception {
+ super.tearDown();
+ BooleanQuery.setMaxClauseCount(originalMaxClauses);
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParserWrapper.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParserWrapper.java
new file mode 100644
index 00000000000..8360f1e9ccc
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParserWrapper.java
@@ -0,0 +1,1122 @@
+package org.apache.lucene.queryParser.original;
+
+/**
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+import java.text.Collator;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.KeywordAnalyzer;
+import org.apache.lucene.analysis.LowerCaseTokenizer;
+import org.apache.lucene.analysis.SimpleAnalyzer;
+import org.apache.lucene.analysis.StopAnalyzer;
+import org.apache.lucene.analysis.StopFilter;
+import org.apache.lucene.analysis.Token;
+import org.apache.lucene.analysis.TokenFilter;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.WhitespaceAnalyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
+import org.apache.lucene.analysis.tokenattributes.TermAttribute;
+import org.apache.lucene.document.DateField;
+import org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.MultiTermQuery;
+import org.apache.lucene.search.PhraseQuery;
+import org.apache.lucene.search.PrefixQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * This test case is a copy of the core Lucene query parser test, it was adapted
+ * to use new {@link QueryParserWrapper} instead of the old query parser.
+ *
+ * Tests QueryParser.
+ */
+public class TestQueryParserWrapper extends LuceneTestCase {
+
+ public static Analyzer qpAnalyzer = new QPTestAnalyzer();
+
+ public static class QPTestFilter extends TokenFilter {
+ TermAttribute termAtt;
+ OffsetAttribute offsetAtt;
+
+ /**
+ * Filter which discards the token 'stop' and which expands the token
+ * 'phrase' into 'phrase1 phrase2'
+ */
+ public QPTestFilter(TokenStream in) {
+ super(in);
+ termAtt = (TermAttribute) addAttribute(TermAttribute.class);
+ offsetAtt = (OffsetAttribute) addAttribute(OffsetAttribute.class);
+ }
+
+ boolean inPhrase = false;
+ int savedStart = 0, savedEnd = 0;
+
+ public Token next(Token reusableToken) throws IOException {
+ Token token = reusableToken;
+
+ if (inPhrase) {
+ inPhrase = false;
+ token.setTermBuffer("phrase2");
+ token.setStartOffset(savedStart);
+ token.setEndOffset(savedEnd);
+ return reusableToken;
+ } else
+ while ((token = this.input.next(reusableToken)) != null) {
+ if (token.term().equals("phrase")) {
+ inPhrase = true;
+ savedStart = token.startOffset();
+ savedEnd = token.endOffset();
+ token.setTermBuffer("phrase1");
+ token.setStartOffset(savedStart);
+ token.setEndOffset(savedEnd);
+ return token;
+ } else if (!token.term().equals("stop"))
+ return token;
+ }
+
+ return null;
+
+ }
+
+ public boolean incrementToken() throws IOException {
+ if (inPhrase) {
+ inPhrase = false;
+ termAtt.setTermBuffer("phrase2");
+ offsetAtt.setOffset(savedStart, savedEnd);
+ return true;
+ } else
+ while (input.incrementToken()) {
+ if (termAtt.term().equals("phrase")) {
+ inPhrase = true;
+ savedStart = offsetAtt.startOffset();
+ savedEnd = offsetAtt.endOffset();
+ termAtt.setTermBuffer("phrase1");
+ offsetAtt.setOffset(savedStart, savedEnd);
+ return true;
+ } else if (!termAtt.term().equals("stop"))
+ return true;
+ }
+ return false;
+ }
+ }
+
+ public static class QPTestAnalyzer extends Analyzer {
+
+ /** Filters LowerCaseTokenizer with StopFilter. */
+ public final TokenStream tokenStream(String fieldName, Reader reader) {
+ return new QPTestFilter(new LowerCaseTokenizer(reader));
+ }
+ }
+
+ public static class QPTestParser extends QueryParserWrapper {
+ public QPTestParser(String f, Analyzer a) {
+ super(f, a);
+
+ QueryNodeProcessorPipeline newProcessorPipeline = new QueryNodeProcessorPipeline(
+ getQueryProcessor().getQueryConfigHandler());
+ newProcessorPipeline.addProcessor(new QPTestParserQueryNodeProcessor());
+ newProcessorPipeline.addProcessor(getQueryProcessor());
+
+ setQueryProcessor(newProcessorPipeline);
+
+ }
+
+ protected Query getFuzzyQuery(String field, String termStr,
+ float minSimilarity) throws ParseException {
+ throw new ParseException("Fuzzy queries not allowed");
+ }
+
+ protected Query getWildcardQuery(String field, String termStr)
+ throws ParseException {
+ throw new ParseException("Wildcard queries not allowed");
+ }
+
+ private static class QPTestParserQueryNodeProcessor extends
+ QueryNodeProcessorImpl {
+
+ protected QueryNode postProcessNode(QueryNode node)
+ throws QueryNodeException {
+
+ return node;
+
+ }
+
+ protected QueryNode preProcessNode(QueryNode node)
+ throws QueryNodeException {
+
+ if (node instanceof WildcardQueryNode || node instanceof FuzzyQueryNode) {
+
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.EMPTY_MESSAGE));
+
+ }
+
+ return node;
+
+ }
+
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+ }
+
+ }
+
+ private int originalMaxClauses;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ originalMaxClauses = BooleanQuery.getMaxClauseCount();
+ }
+
+ public QueryParserWrapper getParser(Analyzer a) throws Exception {
+ if (a == null)
+ a = new SimpleAnalyzer();
+ QueryParserWrapper qp = new QueryParserWrapper("field", a);
+ qp.setDefaultOperator(QueryParserWrapper.OR_OPERATOR);
+ return qp;
+ }
+
+ public Query getQuery(String query, Analyzer a) throws Exception {
+ return getParser(a).parse(query);
+ }
+
+ public void assertQueryEquals(String query, Analyzer a, String result)
+ throws Exception {
+ Query q = getQuery(query, a);
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
+ + "/");
+ }
+ }
+
+ public void assertQueryEquals(QueryParserWrapper qp, String field,
+ String query, String result) throws Exception {
+ Query q = qp.parse(query);
+ String s = q.toString(field);
+ if (!s.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
+ + "/");
+ }
+ }
+
+ public void assertEscapedQueryEquals(String query, Analyzer a, String result)
+ throws Exception {
+ String escapedQuery = QueryParserWrapper.escape(query);
+ if (!escapedQuery.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + escapedQuery + "/, expecting /"
+ + result + "/");
+ }
+ }
+
+ public void assertWildcardQueryEquals(String query, boolean lowercase,
+ String result, boolean allowLeadingWildcard) throws Exception {
+ QueryParserWrapper qp = getParser(null);
+ qp.setLowercaseExpandedTerms(lowercase);
+ qp.setAllowLeadingWildcard(allowLeadingWildcard);
+ Query q = qp.parse(query);
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("WildcardQuery /" + query + "/ yielded /" + s + "/, expecting /"
+ + result + "/");
+ }
+ }
+
+ public void assertWildcardQueryEquals(String query, boolean lowercase,
+ String result) throws Exception {
+ assertWildcardQueryEquals(query, lowercase, result, false);
+ }
+
+ public void assertWildcardQueryEquals(String query, String result)
+ throws Exception {
+ QueryParserWrapper qp = getParser(null);
+ Query q = qp.parse(query);
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("WildcardQuery /" + query + "/ yielded /" + s + "/, expecting /"
+ + result + "/");
+ }
+ }
+
+ public Query getQueryDOA(String query, Analyzer a) throws Exception {
+ if (a == null)
+ a = new SimpleAnalyzer();
+ QueryParserWrapper qp = new QueryParserWrapper("field", a);
+ qp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
+ return qp.parse(query);
+ }
+
+ public void assertQueryEqualsDOA(String query, Analyzer a, String result)
+ throws Exception {
+ Query q = getQueryDOA(query, a);
+ String s = q.toString("field");
+ if (!s.equals(result)) {
+ fail("Query /" + query + "/ yielded /" + s + "/, expecting /" + result
+ + "/");
+ }
+ }
+
+ public void testCJK() throws Exception {
+ // Test Ideographic Space - As wide as a CJK character cell (fullwidth)
+ // used google to translate the word "term" to japanese -> ??
+ assertQueryEquals("term\u3000term\u3000term", null,
+ "term\u0020term\u0020term");
+ assertQueryEquals("??\u3000??\u3000??", null, "??\u0020??\u0020??");
+ }
+
+ public void testSimple() throws Exception {
+ assertQueryEquals("\"term germ\"~2", null, "\"term germ\"~2");
+ assertQueryEquals("term term term", null, "term term term");
+ assertQueryEquals("t�rm term term", new WhitespaceAnalyzer(),
+ "t�rm term term");
+ assertQueryEquals("�mlaut", new WhitespaceAnalyzer(), "�mlaut");
+
+ assertQueryEquals("\"\"", new KeywordAnalyzer(), "");
+ assertQueryEquals("foo:\"\"", new KeywordAnalyzer(), "foo:");
+
+ assertQueryEquals("a AND b", null, "+a +b");
+ assertQueryEquals("(a AND b)", null, "+a +b");
+ assertQueryEquals("c OR (a AND b)", null, "c (+a +b)");
+
+ assertQueryEquals("a AND NOT b", null, "+a -b");
+
+ assertQueryEquals("a AND -b", null, "+a -b");
+
+ assertQueryEquals("a AND !b", null, "+a -b");
+
+ assertQueryEquals("a && b", null, "+a +b");
+
+ assertQueryEquals("a && ! b", null, "+a -b");
+
+ assertQueryEquals("a OR b", null, "a b");
+ assertQueryEquals("a || b", null, "a b");
+
+ assertQueryEquals("a OR !b", null, "a -b");
+
+ assertQueryEquals("a OR ! b", null, "a -b");
+
+ assertQueryEquals("a OR -b", null, "a -b");
+
+ assertQueryEquals("+term -term term", null, "+term -term term");
+ assertQueryEquals("foo:term AND field:anotherTerm", null,
+ "+foo:term +anotherterm");
+ assertQueryEquals("term AND \"phrase phrase\"", null,
+ "+term +\"phrase phrase\"");
+ assertQueryEquals("\"hello there\"", null, "\"hello there\"");
+ assertTrue(getQuery("a AND b", null) instanceof BooleanQuery);
+ assertTrue(getQuery("hello", null) instanceof TermQuery);
+ assertTrue(getQuery("\"hello there\"", null) instanceof PhraseQuery);
+
+ assertQueryEquals("germ term^2.0", null, "germ term^2.0");
+ assertQueryEquals("(term)^2.0", null, "term^2.0");
+ assertQueryEquals("(germ term)^2.0", null, "(germ term)^2.0");
+ assertQueryEquals("term^2.0", null, "term^2.0");
+ assertQueryEquals("term^2", null, "term^2.0");
+ assertQueryEquals("\"germ term\"^2.0", null, "\"germ term\"^2.0");
+ assertQueryEquals("\"term germ\"^2", null, "\"term germ\"^2.0");
+
+ assertQueryEquals("(foo OR bar) AND (baz OR boo)", null,
+ "+(foo bar) +(baz boo)");
+ assertQueryEquals("((a OR b) AND NOT c) OR d", null, "(+(a b) -c) d");
+ assertQueryEquals("+(apple \"steve jobs\") -(foo bar baz)", null,
+ "+(apple \"steve jobs\") -(foo bar baz)");
+ assertQueryEquals("+title:(dog OR cat) -author:\"bob dole\"", null,
+ "+(title:dog title:cat) -author:\"bob dole\"");
+
+ QueryParserWrapper qp = new QueryParserWrapper("field",
+ new StandardAnalyzer());
+ // make sure OR is the default:
+ assertEquals(QueryParserWrapper.OR_OPERATOR, qp.getDefaultOperator());
+ qp.setDefaultOperator(QueryParserWrapper.AND_OPERATOR);
+ assertEquals(QueryParserWrapper.AND_OPERATOR, qp.getDefaultOperator());
+ qp.setDefaultOperator(QueryParserWrapper.OR_OPERATOR);
+ assertEquals(QueryParserWrapper.OR_OPERATOR, qp.getDefaultOperator());
+ }
+
+ public void testPunct() throws Exception {
+ Analyzer a = new WhitespaceAnalyzer();
+ assertQueryEquals("a&b", a, "a&b");
+ assertQueryEquals("a&&b", a, "a&&b");
+ assertQueryEquals(".NET", a, ".NET");
+ }
+
+ public void testSlop() throws Exception {
+
+ assertQueryEquals("\"term germ\"~2", null, "\"term germ\"~2");
+ assertQueryEquals("\"term germ\"~2 flork", null, "\"term germ\"~2 flork");
+ assertQueryEquals("\"term\"~2", null, "term");
+ assertQueryEquals("\" \"~2 germ", null, "germ");
+ assertQueryEquals("\"term germ\"~2^2", null, "\"term germ\"~2^2.0");
+ }
+
+ public void testNumber() throws Exception {
+ // The numbers go away because SimpleAnalzyer ignores them
+ assertQueryEquals("3", null, "");
+ assertQueryEquals("term 1.0 1 2", null, "term");
+ assertQueryEquals("term term1 term2", null, "term term term");
+
+ Analyzer a = new StandardAnalyzer();
+ assertQueryEquals("3", a, "3");
+ assertQueryEquals("term 1.0 1 2", a, "term 1.0 1 2");
+ assertQueryEquals("term term1 term2", a, "term term1 term2");
+ }
+
+ public void testWildcard() throws Exception {
+ assertQueryEquals("term*", null, "term*");
+ assertQueryEquals("term*^2", null, "term*^2.0");
+ assertQueryEquals("term~", null, "term~0.5");
+ assertQueryEquals("term~0.7", null, "term~0.7");
+
+ assertQueryEquals("term~^2", null, "term~0.5^2.0");
+
+ assertQueryEquals("term^2~", null, "term~0.5^2.0");
+ assertQueryEquals("term*germ", null, "term*germ");
+ assertQueryEquals("term*germ^3", null, "term*germ^3.0");
+
+ assertTrue(getQuery("term*", null) instanceof PrefixQuery);
+ assertTrue(getQuery("term*^2", null) instanceof PrefixQuery);
+ assertTrue(getQuery("term~", null) instanceof FuzzyQuery);
+ assertTrue(getQuery("term~0.7", null) instanceof FuzzyQuery);
+ FuzzyQuery fq = (FuzzyQuery) getQuery("term~0.7", null);
+ assertEquals(0.7f, fq.getMinSimilarity(), 0.1f);
+ assertEquals(FuzzyQuery.defaultPrefixLength, fq.getPrefixLength());
+ fq = (FuzzyQuery) getQuery("term~", null);
+ assertEquals(0.5f, fq.getMinSimilarity(), 0.1f);
+ assertEquals(FuzzyQuery.defaultPrefixLength, fq.getPrefixLength());
+
+ assertParseException("term~1.1"); // value > 1, throws exception
+
+ assertTrue(getQuery("term*germ", null) instanceof WildcardQuery);
+
+ /*
+ * Tests to see that wild card terms are (or are not) properly lower-cased
+ * with propery parser configuration
+ */
+ // First prefix queries:
+ // by default, convert to lowercase:
+ assertWildcardQueryEquals("Term*", true, "term*");
+ // explicitly set lowercase:
+ assertWildcardQueryEquals("term*", true, "term*");
+ assertWildcardQueryEquals("Term*", true, "term*");
+ assertWildcardQueryEquals("TERM*", true, "term*");
+ // explicitly disable lowercase conversion:
+ assertWildcardQueryEquals("term*", false, "term*");
+ assertWildcardQueryEquals("Term*", false, "Term*");
+ assertWildcardQueryEquals("TERM*", false, "TERM*");
+ // Then 'full' wildcard queries:
+ // by default, convert to lowercase:
+ assertWildcardQueryEquals("Te?m", "te?m");
+ // explicitly set lowercase:
+ assertWildcardQueryEquals("te?m", true, "te?m");
+ assertWildcardQueryEquals("Te?m", true, "te?m");
+ assertWildcardQueryEquals("TE?M", true, "te?m");
+ assertWildcardQueryEquals("Te?m*gerM", true, "te?m*germ");
+ // explicitly disable lowercase conversion:
+ assertWildcardQueryEquals("te?m", false, "te?m");
+ assertWildcardQueryEquals("Te?m", false, "Te?m");
+ assertWildcardQueryEquals("TE?M", false, "TE?M");
+ assertWildcardQueryEquals("Te?m*gerM", false, "Te?m*gerM");
+ // Fuzzy queries:
+ assertWildcardQueryEquals("Term~", "term~0.5");
+ assertWildcardQueryEquals("Term~", true, "term~0.5");
+ assertWildcardQueryEquals("Term~", false, "Term~0.5");
+ // Range queries:
+
+ // TODO: implement this on QueryParser
+ // Q0002E_INVALID_SYNTAX_CANNOT_PARSE: Syntax Error, cannot parse '[A TO
+ // C]': Lexical error at line 1, column 1. Encountered: "[" (91), after : ""
+ assertWildcardQueryEquals("[A TO C]", "[a TO c]");
+ assertWildcardQueryEquals("[A TO C]", true, "[a TO c]");
+ assertWildcardQueryEquals("[A TO C]", false, "[A TO C]");
+ // Test suffix queries: first disallow
+ try {
+ assertWildcardQueryEquals("*Term", true, "*term");
+ fail();
+ } catch (ParseException pe) {
+ // expected exception
+ }
+ try {
+ assertWildcardQueryEquals("?Term", true, "?term");
+ fail();
+ } catch (ParseException pe) {
+ // expected exception
+ }
+ // Test suffix queries: then allow
+ assertWildcardQueryEquals("*Term", true, "*term", true);
+ assertWildcardQueryEquals("?Term", true, "?term", true);
+ }
+
+ public void testLeadingWildcardType() throws Exception {
+ QueryParserWrapper qp = getParser(null);
+ qp.setAllowLeadingWildcard(true);
+ assertEquals(WildcardQuery.class, qp.parse("t*erm*").getClass());
+ assertEquals(WildcardQuery.class, qp.parse("?term*").getClass());
+ assertEquals(WildcardQuery.class, qp.parse("*term*").getClass());
+ }
+
+ public void testQPA() throws Exception {
+ assertQueryEquals("term term^3.0 term", qpAnalyzer, "term term^3.0 term");
+ assertQueryEquals("term stop^3.0 term", qpAnalyzer, "term term");
+
+ assertQueryEquals("term term term", qpAnalyzer, "term term term");
+ assertQueryEquals("term +stop term", qpAnalyzer, "term term");
+ assertQueryEquals("term -stop term", qpAnalyzer, "term term");
+
+ assertQueryEquals("drop AND (stop) AND roll", qpAnalyzer, "+drop +roll");
+ assertQueryEquals("term +(stop) term", qpAnalyzer, "term term");
+ assertQueryEquals("term -(stop) term", qpAnalyzer, "term term");
+
+ assertQueryEquals("drop AND stop AND roll", qpAnalyzer, "+drop +roll");
+ assertQueryEquals("term phrase term", qpAnalyzer,
+ "term \"phrase1 phrase2\" term");
+
+ assertQueryEquals("term AND NOT phrase term", qpAnalyzer,
+ "+term -\"phrase1 phrase2\" term");
+
+ assertQueryEquals("stop^3", qpAnalyzer, "");
+ assertQueryEquals("stop", qpAnalyzer, "");
+ assertQueryEquals("(stop)^3", qpAnalyzer, "");
+ assertQueryEquals("((stop))^3", qpAnalyzer, "");
+ assertQueryEquals("(stop^3)", qpAnalyzer, "");
+ assertQueryEquals("((stop)^3)", qpAnalyzer, "");
+ assertQueryEquals("(stop)", qpAnalyzer, "");
+ assertQueryEquals("((stop))", qpAnalyzer, "");
+ assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery);
+ assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery);
+ }
+
+ public void testRange() throws Exception {
+ assertQueryEquals("[ a TO z]", null, "[a TO z]");
+ assertEquals(MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT, ((TermRangeQuery)getQuery("[ a TO z]", null)).getRewriteMethod());
+
+ QueryParserWrapper qp = new QueryParserWrapper("field",
+ new SimpleAnalyzer());
+
+ qp.setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
+ assertEquals(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE,((TermRangeQuery)qp.parse("[ a TO z]")).getRewriteMethod());
+
+ assertQueryEquals("[ a TO z ]", null, "[a TO z]");
+ assertQueryEquals("{ a TO z}", null, "{a TO z}");
+ assertQueryEquals("{ a TO z }", null, "{a TO z}");
+ assertQueryEquals("{ a TO z }^2.0", null, "{a TO z}^2.0");
+ assertQueryEquals("[ a TO z] OR bar", null, "[a TO z] bar");
+ assertQueryEquals("[ a TO z] AND bar", null, "+[a TO z] +bar");
+ assertQueryEquals("( bar blar { a TO z}) ", null, "bar blar {a TO z}");
+ assertQueryEquals("gack ( bar blar { a TO z}) ", null,
+ "gack (bar blar {a TO z})");
+ }
+
+ public void testFarsiRangeCollating() throws Exception {
+
+ RAMDirectory ramDir = new RAMDirectory();
+ IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(), true,
+ IndexWriter.MaxFieldLength.LIMITED);
+ Document doc = new Document();
+ doc.add(new Field("content", "\u0633\u0627\u0628", Field.Store.YES,
+ Field.Index.UN_TOKENIZED));
+ iw.addDocument(doc);
+ iw.close();
+ IndexSearcher is = new IndexSearcher(ramDir);
+
+ QueryParserWrapper qp = new QueryParserWrapper("content",
+ new WhitespaceAnalyzer());
+
+ // Neither Java 1.4.2 nor 1.5.0 has Farsi Locale collation available in
+ // RuleBasedCollator. However, the Arabic Locale seems to order the Farsi
+ // characters properly.
+ Collator c = Collator.getInstance(new Locale("ar"));
+ qp.setRangeCollator(c);
+
+ // Unicode order would include U+0633 in [ U+062F - U+0698 ], but Farsi
+ // orders the U+0698 character before the U+0633 character, so the single
+ // index Term below should NOT be returned by a ConstantScoreRangeQuery
+ // with a Farsi Collator (or an Arabic one for the case when Farsi is not
+ // supported).
+
+ // Test ConstantScoreRangeQuery
+ qp.setMultiTermRewriteMethod(MultiTermQuery.CONSTANT_SCORE_FILTER_REWRITE);
+ ScoreDoc[] result = is.search(qp.parse("[ \u062F TO \u0698 ]"), null, 1000).scoreDocs;
+ assertEquals("The index Term should not be included.", 0, result.length);
+
+ result = is.search(qp.parse("[ \u0633 TO \u0638 ]"), null, 1000).scoreDocs;
+ assertEquals("The index Term should be included.", 1, result.length);
+
+ // Test RangeQuery
+ qp.setMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
+ result = is.search(qp.parse("[ \u062F TO \u0698 ]"), null, 1000).scoreDocs;
+ assertEquals("The index Term should not be included.", 0, result.length);
+
+ result = is.search(qp.parse("[ \u0633 TO \u0638 ]"), null, 1000).scoreDocs;
+ assertEquals("The index Term should be included.", 1, result.length);
+
+ is.close();
+ }
+
+ /** for testing legacy DateField support */
+ private String getLegacyDate(String s) throws Exception {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+ return DateField.dateToString(df.parse(s));
+ }
+
+ /** for testing DateTools support */
+ private String getDate(String s, DateTools.Resolution resolution)
+ throws Exception {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+ return getDate(df.parse(s), resolution);
+ }
+
+ /** for testing DateTools support */
+ private String getDate(Date d, DateTools.Resolution resolution)
+ throws Exception {
+ if (resolution == null) {
+ return DateField.dateToString(d);
+ } else {
+ return DateTools.dateToString(d, resolution);
+ }
+ }
+
+ private String getLocalizedDate(int year, int month, int day,
+ boolean extendLastDate) {
+ DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(year, month, day);
+ if (extendLastDate) {
+ calendar.set(Calendar.HOUR_OF_DAY, 23);
+ calendar.set(Calendar.MINUTE, 59);
+ calendar.set(Calendar.SECOND, 59);
+ calendar.set(Calendar.MILLISECOND, 999);
+ }
+ return df.format(calendar.getTime());
+ }
+
+ /** for testing legacy DateField support */
+ public void testLegacyDateRange() throws Exception {
+ String startDate = getLocalizedDate(2002, 1, 1, false);
+ String endDate = getLocalizedDate(2002, 1, 4, false);
+ Calendar endDateExpected = Calendar.getInstance();
+ endDateExpected.set(2002, 1, 4, 23, 59, 59);
+ endDateExpected.set(Calendar.MILLISECOND, 999);
+ assertQueryEquals("[ " + startDate + " TO " + endDate + "]", null, "["
+ + getLegacyDate(startDate) + " TO "
+ + DateField.dateToString(endDateExpected.getTime()) + "]");
+ assertQueryEquals("{ " + startDate + " " + endDate + " }", null, "{"
+ + getLegacyDate(startDate) + " TO " + getLegacyDate(endDate) + "}");
+ }
+
+ public void testDateRange() throws Exception {
+ String startDate = getLocalizedDate(2002, 1, 1, false);
+ String endDate = getLocalizedDate(2002, 1, 4, false);
+ Calendar endDateExpected = Calendar.getInstance();
+ endDateExpected.set(2002, 1, 4, 23, 59, 59);
+ endDateExpected.set(Calendar.MILLISECOND, 999);
+ final String defaultField = "default";
+ final String monthField = "month";
+ final String hourField = "hour";
+ QueryParserWrapper qp = new QueryParserWrapper("field",
+ new SimpleAnalyzer());
+
+ // Don't set any date resolution and verify if DateField is used
+ assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
+ endDateExpected.getTime(), null);
+
+ // set a field specific date resolution
+ qp.setDateResolution(monthField, DateTools.Resolution.MONTH);
+
+ // DateField should still be used for defaultField
+ assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
+ endDateExpected.getTime(), null);
+
+ // set default date resolution to MILLISECOND
+ qp.setDateResolution(DateTools.Resolution.MILLISECOND);
+
+ // set second field specific date resolution
+ qp.setDateResolution(hourField, DateTools.Resolution.HOUR);
+
+ // for this field no field specific date resolution has been set,
+ // so verify if the default resolution is used
+ assertDateRangeQueryEquals(qp, defaultField, startDate, endDate,
+ endDateExpected.getTime(), DateTools.Resolution.MILLISECOND);
+
+ // verify if field specific date resolutions are used for these two fields
+ assertDateRangeQueryEquals(qp, monthField, startDate, endDate,
+ endDateExpected.getTime(), DateTools.Resolution.MONTH);
+
+ assertDateRangeQueryEquals(qp, hourField, startDate, endDate,
+ endDateExpected.getTime(), DateTools.Resolution.HOUR);
+ }
+
+ public void assertDateRangeQueryEquals(QueryParserWrapper qp, String field,
+ String startDate, String endDate, Date endDateInclusive,
+ DateTools.Resolution resolution) throws Exception {
+ assertQueryEquals(qp, field, field + ":[" + startDate + " TO " + endDate
+ + "]", "[" + getDate(startDate, resolution) + " TO "
+ + getDate(endDateInclusive, resolution) + "]");
+ assertQueryEquals(qp, field, field + ":{" + startDate + " TO " + endDate
+ + "}", "{" + getDate(startDate, resolution) + " TO "
+ + getDate(endDate, resolution) + "}");
+ }
+
+ public void testEscaped() throws Exception {
+ Analyzer a = new WhitespaceAnalyzer();
+
+ /*
+ * assertQueryEquals("\\[brackets", a, "\\[brackets");
+ * assertQueryEquals("\\[brackets", null, "brackets");
+ * assertQueryEquals("\\\\", a, "\\\\"); assertQueryEquals("\\+blah", a,
+ * "\\+blah"); assertQueryEquals("\\(blah", a, "\\(blah");
+ *
+ * assertQueryEquals("\\-blah", a, "\\-blah"); assertQueryEquals("\\!blah",
+ * a, "\\!blah"); assertQueryEquals("\\{blah", a, "\\{blah");
+ * assertQueryEquals("\\}blah", a, "\\}blah"); assertQueryEquals("\\:blah",
+ * a, "\\:blah"); assertQueryEquals("\\^blah", a, "\\^blah");
+ * assertQueryEquals("\\[blah", a, "\\[blah"); assertQueryEquals("\\]blah",
+ * a, "\\]blah"); assertQueryEquals("\\\"blah", a, "\\\"blah");
+ * assertQueryEquals("\\(blah", a, "\\(blah"); assertQueryEquals("\\)blah",
+ * a, "\\)blah"); assertQueryEquals("\\~blah", a, "\\~blah");
+ * assertQueryEquals("\\*blah", a, "\\*blah"); assertQueryEquals("\\?blah",
+ * a, "\\?blah"); //assertQueryEquals("foo \\&\\& bar", a,
+ * "foo \\&\\& bar"); //assertQueryEquals("foo \\|| bar", a,
+ * "foo \\|| bar"); //assertQueryEquals("foo \\AND bar", a,
+ * "foo \\AND bar");
+ */
+
+ assertQueryEquals("\\a", a, "a");
+
+ 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");
+
+ 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");
+
+ 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*");
+
+ 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");
+
+ assertQueryEquals("a:b\\-c~", a, "a:b-c~0.5");
+ assertQueryEquals("a:b\\+c~", a, "a:b+c~0.5");
+ assertQueryEquals("a:b\\:c~", a, "a:b:c~0.5");
+ assertQueryEquals("a:b\\\\c~", a, "a:b\\c~0.5");
+
+ // TODO: implement Range queries on QueryParser
+ assertQueryEquals("[ a\\- TO a\\+ ]", null, "[a- TO a+]");
+ assertQueryEquals("[ a\\: TO a\\~ ]", null, "[a: TO a~]");
+ assertQueryEquals("[ a\\\\ TO a\\* ]", null, "[a\\ TO a*]");
+
+ assertQueryEquals(
+ "[\"c\\:\\\\temp\\\\\\~foo0.txt\" TO \"c\\:\\\\temp\\\\\\~foo9.txt\"]",
+ a, "[c:\\temp\\~foo0.txt TO c:\\temp\\~foo9.txt]");
+
+ assertQueryEquals("a\\\\\\+b", a, "a\\+b");
+
+ assertQueryEquals("a \\\"b c\\\" d", a, "a \"b c\" d");
+ assertQueryEquals("\"a \\\"b c\\\" d\"", a, "\"a \"b c\" d\"");
+ assertQueryEquals("\"a \\+b c d\"", a, "\"a +b c d\"");
+
+ assertQueryEquals("c\\:\\\\temp\\\\\\~foo.txt", a, "c:\\temp\\~foo.txt");
+
+ assertParseException("XY\\"); // there must be a character after the escape
+ // char
+
+ // test unicode escaping
+ assertQueryEquals("a\\u0062c", a, "abc");
+ assertQueryEquals("XY\\u005a", a, "XYZ");
+ assertQueryEquals("XY\\u005A", a, "XYZ");
+ assertQueryEquals("\"a \\\\\\u0028\\u0062\\\" c\"", a, "\"a \\(b\" c\"");
+
+ assertParseException("XY\\u005G"); // test non-hex character in escaped
+ // unicode sequence
+ assertParseException("XY\\u005"); // test incomplete escaped unicode
+ // sequence
+
+ // Tests bug LUCENE-800
+ assertQueryEquals("(item:\\\\ item:ABCD\\\\)", a, "item:\\ item:ABCD\\");
+ assertParseException("(item:\\\\ item:ABCD\\\\))"); // unmatched closing
+ // paranthesis
+ assertQueryEquals("\\*", a, "*");
+ assertQueryEquals("\\\\", a, "\\"); // escaped backslash
+
+ assertParseException("\\"); // a backslash must always be escaped
+
+ // LUCENE-1189
+ assertQueryEquals("(\"a\\\\\") or (\"b\")", a, "a\\ or b");
+ }
+
+ public void testQueryStringEscaping() throws Exception {
+ Analyzer a = new WhitespaceAnalyzer();
+
+ assertEscapedQueryEquals("a-b:c", a, "a\\-b\\:c");
+ assertEscapedQueryEquals("a+b:c", a, "a\\+b\\:c");
+ assertEscapedQueryEquals("a:b:c", a, "a\\:b\\:c");
+ assertEscapedQueryEquals("a\\b:c", a, "a\\\\b\\:c");
+
+ assertEscapedQueryEquals("a:b-c", a, "a\\:b\\-c");
+ assertEscapedQueryEquals("a:b+c", a, "a\\:b\\+c");
+ assertEscapedQueryEquals("a:b:c", a, "a\\:b\\:c");
+ assertEscapedQueryEquals("a:b\\c", a, "a\\:b\\\\c");
+
+ assertEscapedQueryEquals("a:b-c*", a, "a\\:b\\-c\\*");
+ assertEscapedQueryEquals("a:b+c*", a, "a\\:b\\+c\\*");
+ assertEscapedQueryEquals("a:b:c*", a, "a\\:b\\:c\\*");
+
+ assertEscapedQueryEquals("a:b\\\\c*", a, "a\\:b\\\\\\\\c\\*");
+
+ assertEscapedQueryEquals("a:b-?c", a, "a\\:b\\-\\?c");
+ assertEscapedQueryEquals("a:b+?c", a, "a\\:b\\+\\?c");
+ assertEscapedQueryEquals("a:b:?c", a, "a\\:b\\:\\?c");
+
+ assertEscapedQueryEquals("a:b?c", a, "a\\:b\\?c");
+
+ assertEscapedQueryEquals("a:b-c~", a, "a\\:b\\-c\\~");
+ assertEscapedQueryEquals("a:b+c~", a, "a\\:b\\+c\\~");
+ assertEscapedQueryEquals("a:b:c~", a, "a\\:b\\:c\\~");
+ assertEscapedQueryEquals("a:b\\c~", a, "a\\:b\\\\c\\~");
+
+ assertEscapedQueryEquals("[ a - TO a+ ]", null, "\\[ a \\- TO a\\+ \\]");
+ assertEscapedQueryEquals("[ a : TO a~ ]", null, "\\[ a \\: TO a\\~ \\]");
+ assertEscapedQueryEquals("[ a\\ TO a* ]", null, "\\[ a\\\\ TO a\\* \\]");
+
+ // LUCENE-881
+ assertEscapedQueryEquals("|| abc ||", a, "\\|\\| abc \\|\\|");
+ assertEscapedQueryEquals("&& abc &&", a, "\\&\\& abc \\&\\&");
+ }
+
+ public void testTabNewlineCarriageReturn() throws Exception {
+ assertQueryEqualsDOA("+weltbank +worlbank", null, "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \n +worlbank", null, "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\r+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r +worlbank", null, "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\r\n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r\n+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r\n +worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \r \n +worlbank", null,
+ "+weltbank +worlbank");
+
+ assertQueryEqualsDOA("+weltbank\t+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \t+worlbank", null, "+weltbank +worlbank");
+ assertQueryEqualsDOA("weltbank \t +worlbank", null, "+weltbank +worlbank");
+ }
+
+ public void testSimpleDAO() throws Exception {
+ assertQueryEqualsDOA("term term term", null, "+term +term +term");
+ assertQueryEqualsDOA("term +term term", null, "+term +term +term");
+ assertQueryEqualsDOA("term term +term", null, "+term +term +term");
+ assertQueryEqualsDOA("term +term +term", null, "+term +term +term");
+ assertQueryEqualsDOA("-term term term", null, "-term +term +term");
+ }
+
+ public void testBoost() throws Exception {
+ StandardAnalyzer oneStopAnalyzer = new StandardAnalyzer(
+ new String[] { "on" });
+ QueryParserWrapper qp = new QueryParserWrapper("field", oneStopAnalyzer);
+ Query q = qp.parse("on^1.0");
+ assertNotNull(q);
+ q = qp.parse("\"hello\"^2.0");
+ assertNotNull(q);
+ assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
+ q = qp.parse("hello^2.0");
+ assertNotNull(q);
+ assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
+ q = qp.parse("\"on\"^1.0");
+ assertNotNull(q);
+
+ QueryParserWrapper qp2 = new QueryParserWrapper("field",
+ new StandardAnalyzer());
+ q = qp2.parse("the^3");
+ // "the" is a stop word so the result is an empty query:
+ assertNotNull(q);
+ assertEquals("", q.toString());
+ assertEquals(1.0f, q.getBoost(), 0.01f);
+ }
+
+ public void assertParseException(String queryString) throws Exception {
+ try {
+ getQuery(queryString, null);
+ } catch (ParseException expected) {
+ return;
+ }
+ fail("ParseException expected, not thrown");
+ }
+
+ public void testException() throws Exception {
+ assertParseException("\"some phrase");
+ assertParseException("(foo bar");
+ assertParseException("foo bar))");
+ assertParseException("field:term:with:colon some more terms");
+ assertParseException("(sub query)^5.0^2.0 plus more");
+ assertParseException("secret AND illegal) AND access:confidential");
+ }
+
+ public void testCustomQueryParserWildcard() {
+ try {
+ new QPTestParser("contents", new WhitespaceAnalyzer()).parse("a?t");
+ fail("Wildcard queries should not be allowed");
+ } catch (ParseException expected) {
+ // expected exception
+ }
+ }
+
+ public void testCustomQueryParserFuzzy() throws Exception {
+ try {
+ new QPTestParser("contents", new WhitespaceAnalyzer()).parse("xunit~");
+ fail("Fuzzy queries should not be allowed");
+ } catch (ParseException expected) {
+ // expected exception
+ }
+ }
+
+ public void testBooleanQuery() throws Exception {
+ BooleanQuery.setMaxClauseCount(2);
+ try {
+ QueryParserWrapper qp = new QueryParserWrapper("field",
+ new WhitespaceAnalyzer());
+ qp.parse("one two three");
+ fail("ParseException expected due to too many boolean clauses");
+ } catch (ParseException expected) {
+ // too many boolean clauses, so ParseException is expected
+ }
+ }
+
+ /**
+ * This test differs from TestPrecedenceQueryParser
+ */
+ public void testPrecedence() throws Exception {
+ QueryParserWrapper qp = new QueryParserWrapper("field",
+ new WhitespaceAnalyzer());
+ Query query1 = qp.parse("A AND B OR C AND D");
+ Query query2 = qp.parse("+A +B +C +D");
+
+ assertEquals(query1, query2);
+ }
+
+ public void testLocalDateFormat() throws IOException, ParseException {
+
+ RAMDirectory ramDir = new RAMDirectory();
+ IndexWriter iw = new IndexWriter(ramDir, new WhitespaceAnalyzer(), true,
+ IndexWriter.MaxFieldLength.LIMITED);
+ addDateDoc("a", 2005, 12, 2, 10, 15, 33, iw);
+ addDateDoc("b", 2005, 12, 4, 22, 15, 00, iw);
+ iw.close();
+ IndexSearcher is = new IndexSearcher(ramDir);
+ assertHits(1, "[12/1/2005 TO 12/3/2005]", is);
+ assertHits(2, "[12/1/2005 TO 12/4/2005]", is);
+ assertHits(1, "[12/3/2005 TO 12/4/2005]", is);
+ assertHits(1, "{12/1/2005 TO 12/3/2005}", is);
+ assertHits(1, "{12/1/2005 TO 12/4/2005}", is);
+ assertHits(0, "{12/3/2005 TO 12/4/2005}", is);
+ is.close();
+ }
+
+ public void testStarParsing() throws Exception {
+ // final int[] type = new int[1];
+ // QueryParser qp = new QueryParserWrapper("field", new
+ // WhitespaceAnalyzer()) {
+ // protected Query getWildcardQuery(String field, String termStr) throws
+ // ParseException {
+ // // override error checking of superclass
+ // type[0]=1;
+ // return new TermQuery(new Term(field,termStr));
+ // }
+ // protected Query getPrefixQuery(String field, String termStr) throws
+ // ParseException {
+ // // override error checking of superclass
+ // type[0]=2;
+ // return new TermQuery(new Term(field,termStr));
+ // }
+ //
+ // protected Query getFieldQuery(String field, String queryText) throws
+ // ParseException {
+ // type[0]=3;
+ // return super.getFieldQuery(field, queryText);
+ // }
+ // };
+ //
+ // TermQuery tq;
+ //
+ // tq = (TermQuery)qp.parse("foo:zoo*");
+ // assertEquals("zoo",tq.getTerm().text());
+ // assertEquals(2,type[0]);
+ //
+ // tq = (TermQuery)qp.parse("foo:zoo*^2");
+ // assertEquals("zoo",tq.getTerm().text());
+ // assertEquals(2,type[0]);
+ // assertEquals(tq.getBoost(),2,0);
+ //
+ // tq = (TermQuery)qp.parse("foo:*");
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]); // could be a valid prefix query in the future
+ // too
+ //
+ // tq = (TermQuery)qp.parse("foo:*^2");
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]);
+ // assertEquals(tq.getBoost(),2,0);
+ //
+ // tq = (TermQuery)qp.parse("*:foo");
+ // assertEquals("*",tq.getTerm().field());
+ // assertEquals("foo",tq.getTerm().text());
+ // assertEquals(3,type[0]);
+ //
+ // tq = (TermQuery)qp.parse("*:*");
+ // assertEquals("*",tq.getTerm().field());
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]); // could be handled as a prefix query in the
+ // future
+ //
+ // tq = (TermQuery)qp.parse("(*:*)");
+ // assertEquals("*",tq.getTerm().field());
+ // assertEquals("*",tq.getTerm().text());
+ // assertEquals(1,type[0]);
+
+ }
+
+ public void testStopwords() throws Exception {
+ QueryParserWrapper qp = new QueryParserWrapper("a", new StopAnalyzer(
+ new String[] { "the", "foo" }));
+ Query result = qp.parse("a:the OR a:foo");
+ assertNotNull("result is null and it shouldn't be", result);
+ assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery);
+ assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: "
+ + 0, ((BooleanQuery) result).clauses().size() == 0);
+ result = qp.parse("a:woo OR a:the");
+ assertNotNull("result is null and it shouldn't be", result);
+ assertTrue("result is not a TermQuery", result instanceof TermQuery);
+ result = qp
+ .parse("(fieldX:xxxxx OR fieldy:xxxxxxxx)^2 AND (fieldx:the OR fieldy:foo)");
+ assertNotNull("result is null and it shouldn't be", result);
+ assertTrue("result is not a BooleanQuery", result instanceof BooleanQuery);
+ System.out.println("Result: " + result);
+ assertTrue(((BooleanQuery) result).clauses().size() + " does not equal: "
+ + 2, ((BooleanQuery) result).clauses().size() == 2);
+ }
+
+ public void testPositionIncrement() throws Exception {
+ boolean dflt = StopFilter.getEnablePositionIncrementsDefault();
+ StopFilter.setEnablePositionIncrementsDefault(true);
+ try {
+ QueryParserWrapper qp = new QueryParserWrapper("a", new StopAnalyzer(
+ new String[] { "the", "in", "are", "this" }));
+ qp.setEnablePositionIncrements(true);
+ String qtxt = "\"the words in poisitions pos02578 are stopped in this phrasequery\"";
+ // 0 2 5 7 8
+ int expectedPositions[] = { 1, 3, 4, 6, 9 };
+ PhraseQuery pq = (PhraseQuery) qp.parse(qtxt);
+ // System.out.println("Query text: "+qtxt);
+ // System.out.println("Result: "+pq);
+ Term t[] = pq.getTerms();
+ int pos[] = pq.getPositions();
+ for (int i = 0; i < t.length; i++) {
+ // System.out.println(i+". "+t[i]+" pos: "+pos[i]);
+ assertEquals("term " + i + " = " + t[i] + " has wrong term-position!",
+ expectedPositions[i], pos[i]);
+ }
+
+ } finally {
+ StopFilter.setEnablePositionIncrementsDefault(dflt);
+ }
+ }
+
+ public void testMatchAllDocs() throws Exception {
+ QueryParserWrapper qp = new QueryParserWrapper("field",
+ new WhitespaceAnalyzer());
+ assertEquals(new MatchAllDocsQuery(), qp.parse("*:*"));
+ assertEquals(new MatchAllDocsQuery(), qp.parse("(*:*)"));
+ BooleanQuery bq = (BooleanQuery) qp.parse("+*:* -*:*");
+ assertTrue(bq.getClauses()[0].getQuery() instanceof MatchAllDocsQuery);
+ assertTrue(bq.getClauses()[1].getQuery() instanceof MatchAllDocsQuery);
+ }
+
+ private void assertHits(int expected, String query, IndexSearcher is)
+ throws ParseException, IOException {
+ QueryParserWrapper qp = new QueryParserWrapper("date",
+ new WhitespaceAnalyzer());
+ qp.setLocale(Locale.ENGLISH);
+ Query q = qp.parse(query);
+ ScoreDoc[] hits = is.search(q, null, 1000).scoreDocs;
+ assertEquals(expected, hits.length);
+ }
+
+ private static void addDateDoc(String content, int year, int month, int day,
+ int hour, int minute, int second, IndexWriter iw) throws IOException {
+ Document d = new Document();
+ d.add(new Field("f", content, Field.Store.YES, Field.Index.ANALYZED));
+ Calendar cal = Calendar.getInstance();
+ cal.set(year, month - 1, day, hour, minute, second);
+ d.add(new Field("date", DateField.dateToString(cal.getTime()),
+ Field.Store.YES, Field.Index.NOT_ANALYZED));
+ iw.addDocument(d);
+ }
+
+ public void tearDown() throws Exception {
+ super.tearDown();
+ BooleanQuery.setMaxClauseCount(originalMaxClauses);
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java
new file mode 100644
index 00000000000..ca300b17ca9
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java
@@ -0,0 +1,56 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryBuilder;
+import org.apache.lucene.search.spans.SpanOrQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+
+/**
+ * This builder creates {@link SpanOrQuery}s from a {@link BooleanQueryNode}.
+ *
+ *
+ * It assumes that the {@link BooleanQueryNode} instance has at least one child.
+ */
+public class SpanOrQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public SpanOrQuery build(QueryNode node) throws QueryNodeException {
+
+ // validates node
+ BooleanQueryNode booleanNode = (BooleanQueryNode) node;
+
+ List children = booleanNode.getChildren();
+ SpanQuery[] spanQueries = new SpanQuery[children.size()];
+
+ int i = 0;
+ for (QueryNode child : children) {
+ spanQueries[i++] = (SpanQuery) child
+ .getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+ }
+
+ return new SpanOrQuery(spanQueries);
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java
new file mode 100644
index 00000000000..5270d45af9c
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java
@@ -0,0 +1,41 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryBuilder;
+import org.apache.lucene.search.spans.SpanTermQuery;
+
+/**
+ * This builder creates {@link SpanTermQuery}s from a {@link FieldQueryNode}
+ * object.
+ */
+public class SpanTermQueryNodeBuilder implements OriginalQueryBuilder {
+
+ public SpanTermQuery build(QueryNode node) throws QueryNodeException {
+ FieldQueryNode fieldQueryNode = (FieldQueryNode) node;
+
+ return new SpanTermQuery(new Term(fieldQueryNode.getFieldAsString(),
+ fieldQueryNode.getTextAsString()));
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java
new file mode 100644
index 00000000000..520d4efeb73
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.config.FieldConfig;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+
+/**
+ * This query config handler only adds the {@link UniqueFieldAttribute} to it.
+ *
+ *
+ * It does not return any configuration for a field in specific.
+ */
+public class SpansQueryConfigHandler extends QueryConfigHandler {
+
+ public SpansQueryConfigHandler() {
+ addAttribute(UniqueFieldAttribute.class);
+ }
+
+ @Override
+ public FieldConfig getFieldConfig(CharSequence fieldName) {
+
+ // there is no field configuration, always return null
+ return null;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java
new file mode 100644
index 00000000000..0f88d407ffe
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java
@@ -0,0 +1,51 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.OriginalQueryBuilder;
+import org.apache.lucene.search.spans.SpanQuery;
+
+/**
+ * Sets up a query tree builder to build a span query tree from a query node
+ * tree.
+ *
+ *
+ * The defined map is:
+ * - every BooleanQueryNode instance is delegated to the SpanOrQueryNodeBuilder
+ * - every FieldQueryNode instance is delegated to the SpanTermQueryNodeBuilder
+ *
+ */
+public class SpansQueryTreeBuilder extends QueryTreeBuilder implements
+ OriginalQueryBuilder {
+
+ public SpansQueryTreeBuilder() {
+ setBuilder(BooleanQueryNode.class, new SpanOrQueryNodeBuilder());
+ setBuilder(FieldQueryNode.class, new SpanTermQueryNodeBuilder());
+
+ }
+
+ public SpanQuery build(QueryNode queryTree) throws QueryNodeException {
+ return (SpanQuery) super.build(queryTree);
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java
new file mode 100644
index 00000000000..335adb447d2
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java
@@ -0,0 +1,72 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.core.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+
+/**
+ * Validates every query node in a query node tree. This processor will pass
+ * fine if the query nodes are only {@link BooleanQueryNode}s,
+ * {@link OrQueryNode}s or {@link FieldQueryNode}s, otherwise an exception will
+ * be thrown.
+ *
+ *
+ * If they are {@link AndQueryNode} or an instance of anything else that
+ * implements {@link FieldQueryNode} the exception will also be thrown.
+ */
+public class SpansValidatorQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ @Override
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ @Override
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (!((node instanceof BooleanQueryNode && !(node instanceof AndQueryNode)) || node
+ .getClass() == FieldQueryNode.class)) {
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+ }
+
+ return node;
+
+ }
+
+ @Override
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java
new file mode 100644
index 00000000000..049953c8b6c
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java
@@ -0,0 +1,233 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import javax.management.Query;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.parser.SyntaxParser;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser;
+import org.apache.lucene.search.spans.SpanOrQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanTermQuery;
+
+/**
+ * This test case demonstrates how the new query parser can be used.
+ *
+ *
+ * It tests queries likes "term", "field:term" "term1 term2" "term1 OR term2",
+ * which are all already supported by the current syntax parser (
+ * {@link OriginalSyntaxParser}).
+ *
+ *
+ * The goals is to create a new query parser that supports only the pair
+ * "field:term" or a list of pairs separated or not by an OR operator, and from
+ * this query generate {@link SpanQuery} objects instead of the regular
+ * {@link Query} objects. Basically, every pair will be converted to a
+ * {@link SpanTermQuery} object and if there are more than one pair they will be
+ * grouped by an {@link OrQueryNode}.
+ *
+ *
+ * Another functionality that will be added is the ability to convert every
+ * field defined in the query to an unique specific field.
+ *
+ *
+ * The query generation is divided in three different steps: parsing (syntax),
+ * processing (semantic) and building.
+ *
+ *
+ * The parsing phase, as already mentioned will be performed by the current
+ * query parser: {@link OriginalSyntaxParser}.
+ *
+ *
+ * The processing phase will be performed by a processor pipeline which is
+ * compound by 2 processors: {@link SpansValidatorQueryNodeProcessor} and
+ * {@link UniqueFieldQueryNodeProcessor}.
+ *
+ *
+ *
+ * {@link SpansValidatorQueryNodeProcessor}: as it's going to use the current
+ * query parser to parse the syntax, it will support more features than we want,
+ * this processor basically validates the query node tree generated by the parser
+ * and just let got through the elements we want, all the other elements as
+ * wildcards, range queries, etc...if found, an exception is thrown.
+ *
+ * {@link UniqueFieldQueryNodeProcessor}: this processor will take care of reading
+ * what is the "unique field" from the configuration and convert every field defined
+ * in every pair to this "unique field". For that, a {@link SpansQueryConfigHandler} is
+ * used, which has the {@link UniqueFieldAttribute} defined in it.
+ *
+ *
+ * The building phase is performed by the {@link SpansQueryTreeBuilder}, which
+ * basically contains a map that defines which builder will be used to generate
+ * {@link SpanQuery} objects from {@link QueryNode} objects.
+ *
+ *
+ * @see SpansQueryConfigHandler
+ * @see SpansQueryTreeBuilder
+ * @see SpansValidatorQueryNodeProcessor
+ * @see SpanOrQueryNodeBuilder
+ * @see SpanTermQueryNodeBuilder
+ * @see OriginalSyntaxParser
+ * @see UniqueFieldQueryNodeProcessor
+ * @see UniqueFieldAttribute
+ */
+public class TestSpanQueryParser extends TestCase {
+
+ private QueryNodeProcessorPipeline spanProcessorPipeline;
+
+ private SpansQueryConfigHandler spanQueryConfigHandler;
+
+ private SpansQueryTreeBuilder spansQueryTreeBuilder;
+
+ private SyntaxParser queryParser = new OriginalSyntaxParser();
+
+ public TestSpanQueryParser() {
+ // empty constructor
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ this.spanProcessorPipeline = new QueryNodeProcessorPipeline();
+ this.spanQueryConfigHandler = new SpansQueryConfigHandler();
+ this.spansQueryTreeBuilder = new SpansQueryTreeBuilder();
+
+ // set up the processor pipeline
+ this.spanProcessorPipeline
+ .setQueryConfigHandler(this.spanQueryConfigHandler);
+
+ this.spanProcessorPipeline
+ .addProcessor(new SpansValidatorQueryNodeProcessor());
+ this.spanProcessorPipeline
+ .addProcessor(new UniqueFieldQueryNodeProcessor());
+
+ }
+
+ public SpanQuery getSpanQuery(CharSequence query) throws QueryNodeException {
+ return getSpanQuery("", query);
+ }
+
+ public SpanQuery getSpanQuery(CharSequence uniqueField, CharSequence query)
+ throws QueryNodeException {
+ UniqueFieldAttribute uniqueFieldAtt = (UniqueFieldAttribute) this.spanQueryConfigHandler
+ .getAttribute(UniqueFieldAttribute.class);
+ uniqueFieldAtt.setUniqueField(uniqueField);
+
+ QueryNode queryTree = this.queryParser.parse(query, "defaultField");
+ queryTree = this.spanProcessorPipeline.process(queryTree);
+
+ return this.spansQueryTreeBuilder.build(queryTree);
+
+ }
+
+ public void testTermSpans() throws Exception {
+ assertEquals(getSpanQuery("field:term").toString(), "term");
+ assertEquals(getSpanQuery("term").toString(), "term");
+
+ assertTrue(getSpanQuery("field:term") instanceof SpanTermQuery);
+ assertTrue(getSpanQuery("term") instanceof SpanTermQuery);
+
+ }
+
+ public void testUniqueField() throws Exception {
+ assertEquals(getSpanQuery("field", "term").toString(), "field:term");
+ assertEquals(getSpanQuery("field", "field:term").toString(), "field:term");
+ assertEquals(getSpanQuery("field", "anotherField:term").toString(),
+ "field:term");
+
+ }
+
+ public void testOrSpans() throws Exception {
+ assertEquals(getSpanQuery("term1 term2").toString(),
+ "spanOr([term1, term2])");
+ assertEquals(getSpanQuery("term1 OR term2").toString(),
+ "spanOr([term1, term2])");
+
+ assertTrue(getSpanQuery("term1 term2") instanceof SpanOrQuery);
+ assertTrue(getSpanQuery("term1 term2") instanceof SpanOrQuery);
+
+ }
+
+ public void testQueryValidator() throws QueryNodeException {
+
+ try {
+ getSpanQuery("term*");
+ fail("QueryNodeException was expected, wildcard queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ try {
+ getSpanQuery("[a TO z]");
+ fail("QueryNodeException was expected, range queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ try {
+ getSpanQuery("a~0.5");
+ fail("QueryNodeException was expected, boost queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ try {
+ getSpanQuery("a^0.5");
+ fail("QueryNodeException was expected, fuzzy queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ try {
+ getSpanQuery("\"a b\"");
+ fail("QueryNodeException was expected, quoted queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ try {
+ getSpanQuery("(a b)");
+ fail("QueryNodeException was expected, parenthesized queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ try {
+ getSpanQuery("a AND b");
+ fail("QueryNodeException was expected, and queries should not be supported");
+
+ } catch (QueryNodeException ex) {
+ // expected exception
+ }
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java
new file mode 100644
index 00000000000..623f3bad96f
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java
@@ -0,0 +1,155 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import javax.management.Query;
+
+import junit.framework.TestCase;
+
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.parser.SyntaxParser;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.original.parser.OriginalSyntaxParser;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanTermQuery;
+
+/**
+ * This test case demonstrates how the new query parser can be used.
+ *
+ *
+ * It tests queries likes "term", "field:term" "term1 term2" "term1 OR term2",
+ * which are all already supported by the current syntax parser (
+ * {@link OriginalSyntaxParser}).
+ *
+ *
+ * The goals is to create a new query parser that supports only the pair
+ * "field:term" or a list of pairs separated or not by an OR operator, and from
+ * this query generate {@link SpanQuery} objects instead of the regular
+ * {@link Query} objects. Basically, every pair will be converted to a
+ * {@link SpanTermQuery} object and if there are more than one pair they will be
+ * grouped by an {@link OrQueryNode}.
+ *
+ *
+ * Another functionality that will be added is the ability to convert every
+ * field defined in the query to an unique specific field.
+ *
+ *
+ * The query generation is divided in three different steps: parsing (syntax),
+ * processing (semantic) and building.
+ *
+ *
+ * The parsing phase, as already mentioned will be performed by the current
+ * query parser: {@link OriginalSyntaxParser}.
+ *
+ *
+ * The processing phase will be performed by a processor pipeline which is
+ * compound by 2 processors: {@link SpansValidatorQueryNodeProcessor} and
+ * {@link UniqueFieldQueryNodeProcessor}.
+ *
+ *
+ *
+ * {@link SpansValidatorQueryNodeProcessor}: as it's going to use the current
+ * query parser to parse the syntax, it will support more features than we want,
+ * this processor basically validates the query node tree generated by the parser
+ * and just let got through the elements we want, all the other elements as
+ * wildcards, range queries, etc...if found, an exception is thrown.
+ *
+ * {@link UniqueFieldQueryNodeProcessor}: this processor will take care of reading
+ * what is the "unique field" from the configuration and convert every field defined
+ * in every pair to this "unique field". For that, a {@link SpansQueryConfigHandler} is
+ * used, which has the {@link UniqueFieldAttribute} defined in it.
+ *
+ *
+ * The building phase is performed by the {@link SpansQueryTreeBuilder}, which
+ * basically contains a map that defines which builder will be used to generate
+ * {@link SpanQuery} objects from {@link QueryNode} objects.
+ *
+ *
+ * @see TestSpanQueryParser for a more advanced example
+ *
+ * @see SpansQueryConfigHandler
+ * @see SpansQueryTreeBuilder
+ * @see SpansValidatorQueryNodeProcessor
+ * @see SpanOrQueryNodeBuilder
+ * @see SpanTermQueryNodeBuilder
+ * @see OriginalSyntaxParser
+ * @see UniqueFieldQueryNodeProcessor
+ * @see UniqueFieldAttribute
+ *
+ */
+public class TestSpanQueryParserSimpleSample extends TestCase {
+
+ public TestSpanQueryParserSimpleSample() {
+ // empty constructor
+ }
+
+ public TestSpanQueryParserSimpleSample(String testName) {
+ super(testName);
+ }
+
+ public static junit.framework.Test suite() {
+ junit.framework.TestSuite suite = new junit.framework.TestSuite(
+ TestSpanQueryParserSimpleSample.class);
+ return suite;
+ }
+
+ public void testBasicDemo() throws Exception {
+ SyntaxParser queryParser = new OriginalSyntaxParser();
+
+ // convert the CharSequence into a QueryNode tree
+ QueryNode queryTree = queryParser.parse("body:text", null);
+
+ // create a config handler with a attribute used in
+ // UniqueFieldQueryNodeProcessor
+ QueryConfigHandler spanQueryConfigHandler = new SpansQueryConfigHandler();
+ UniqueFieldAttribute uniqueFieldAtt = (UniqueFieldAttribute) spanQueryConfigHandler
+ .getAttribute(UniqueFieldAttribute.class);
+ uniqueFieldAtt.setUniqueField("index");
+
+ // set up the processor pipeline with the ConfigHandler
+ // and create the pipeline for this simple demo
+ QueryNodeProcessorPipeline spanProcessorPipeline = new QueryNodeProcessorPipeline(
+ spanQueryConfigHandler);
+ // @see SpansValidatorQueryNodeProcessor
+ spanProcessorPipeline.addProcessor(new SpansValidatorQueryNodeProcessor());
+ // @see UniqueFieldQueryNodeProcessor
+ spanProcessorPipeline.addProcessor(new UniqueFieldQueryNodeProcessor());
+
+ // print to show out the QueryNode tree before being processed
+ System.out.println(queryTree);
+
+ // Process the QueryTree using our new Processors
+ queryTree = spanProcessorPipeline.process(queryTree);
+
+ // print to show out the QueryNode tree after being processed
+ System.out.println(queryTree);
+
+ // create a instance off the Builder
+ SpansQueryTreeBuilder spansQueryTreeBuilder = new SpansQueryTreeBuilder();
+
+ // convert QueryNode tree to span query Objects
+ SpanQuery spanquery = spansQueryTreeBuilder.build(queryTree);
+
+ assertTrue(spanquery instanceof SpanTermQuery);
+ assertEquals(spanquery.toString(), "index:text");
+
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java
new file mode 100644
index 00000000000..adbae05cbe7
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.nodes.FieldableNode;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used by the {@link UniqueFieldQueryNodeProcessor}
+ * processor. It holds a value that defines which is the unique field name that
+ * should be set in every {@link FieldableNode}.
+ *
+ *
+ * @see UniqueFieldQueryNodeProcessor
+ */
+public interface UniqueFieldAttribute extends Attribute {
+ public void setUniqueField(CharSequence uniqueField);
+
+ public CharSequence getUniqueField();
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttributeImpl.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttributeImpl.java
new file mode 100644
index 00000000000..0cb8b4ab7dd
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttributeImpl.java
@@ -0,0 +1,93 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import org.apache.lucene.queryParser.core.nodes.FieldableNode;
+import org.apache.lucene.util.AttributeImpl;
+
+/**
+ * This attribute is used by the {@link UniqueFieldQueryNodeProcessor}
+ * processor. It holds a value that defines which is the unique field name that
+ * should be set in every {@link FieldableNode}.
+ *
+ *
+ * @see UniqueFieldQueryNodeProcessor
+ */
+public class UniqueFieldAttributeImpl extends AttributeImpl implements
+ UniqueFieldAttribute {
+
+ private static final long serialVersionUID = 8553318595851064232L;
+
+ private CharSequence uniqueField;
+
+ public UniqueFieldAttributeImpl() {
+ clear();
+ }
+
+ @Override
+ public void clear() {
+ this.uniqueField = "";
+ }
+
+ public void setUniqueField(CharSequence uniqueField) {
+ this.uniqueField = uniqueField;
+ }
+
+ public CharSequence getUniqueField() {
+ return this.uniqueField;
+ }
+
+ @Override
+ public void copyTo(AttributeImpl target) {
+
+ if (!(target instanceof UniqueFieldAttributeImpl)) {
+ throw new IllegalArgumentException(
+ "cannot copy the values from attribute UniqueFieldAttribute to an instance of "
+ + target.getClass().getName());
+ }
+
+ UniqueFieldAttributeImpl uniqueFieldAttr = (UniqueFieldAttributeImpl) target;
+ uniqueFieldAttr.uniqueField = uniqueField.toString();
+
+ }
+
+ @Override
+ public boolean equals(Object other) {
+
+ if (other instanceof UniqueFieldAttributeImpl) {
+
+ return ((UniqueFieldAttributeImpl) other).uniqueField
+ .equals(this.uniqueField);
+
+ }
+
+ return false;
+
+ }
+
+ @Override
+ public int hashCode() {
+ return this.uniqueField.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "";
+ }
+
+}
diff --git a/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java
new file mode 100644
index 00000000000..c20b1049491
--- /dev/null
+++ b/contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java
@@ -0,0 +1,84 @@
+package org.apache.lucene.queryParser.spans;
+
+/**
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.lucene.queryParser.core.QueryNodeException;
+import org.apache.lucene.queryParser.core.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.core.nodes.FieldableNode;
+import org.apache.lucene.queryParser.core.nodes.QueryNode;
+import org.apache.lucene.queryParser.core.processors.QueryNodeProcessorImpl;
+
+/**
+ * This processor changes every field name of each {@link FieldableNode} query
+ * node contained in the query tree to the field name defined in the
+ * {@link UniqueFieldAttribute}. So, the {@link UniqueFieldAttribute} must be
+ * defined in the {@link QueryConfigHandler} object set in this processor,
+ * otherwise it throws an exception.
+ *
+ *
+ * @see UniqueFieldAttribute
+ */
+public class UniqueFieldQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+ @Override
+ protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+ return node;
+
+ }
+
+ @Override
+ protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+ if (node instanceof FieldableNode) {
+ FieldableNode fieldNode = (FieldableNode) node;
+
+ QueryConfigHandler queryConfig = getQueryConfigHandler();
+
+ if (queryConfig == null) {
+ throw new IllegalArgumentException(
+ "A config handler is expected by the processor UniqueFieldQueryNodeProcessor!");
+ }
+
+ if (!queryConfig.hasAttribute(UniqueFieldAttribute.class)) {
+ throw new IllegalArgumentException(
+ "UniqueFieldAttribute should be defined in the config handler!");
+ }
+
+ CharSequence uniqueField = ((UniqueFieldAttribute) queryConfig
+ .getAttribute(UniqueFieldAttribute.class)).getUniqueField();
+
+ fieldNode.setField(uniqueField);
+
+ }
+
+ return node;
+
+ }
+
+ @Override
+ protected List setChildrenOrder(List children)
+ throws QueryNodeException {
+
+ return children;
+
+ }
+
+}
diff --git a/src/java/org/apache/lucene/queryParser/CharStream.java b/src/java/org/apache/lucene/queryParser/CharStream.java
index 9e546d50a41..c67321c1b38 100644
--- a/src/java/org/apache/lucene/queryParser/CharStream.java
+++ b/src/java/org/apache/lucene/queryParser/CharStream.java
@@ -15,6 +15,8 @@ package org.apache.lucene.queryParser;
* column number and the String that constitutes a token and are not used
* by the lexer. Hence their implementation won't affect the generated lexer's
* operation.
+ *
+ * @deprecated this class will be removed in Lucene 3.0, when the {@link QueryParser} is removed
*/
public interface CharStream {
diff --git a/src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java b/src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java
index 0531a5a49bb..f7c5dc1b8df 100644
--- a/src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java
+++ b/src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java
@@ -54,8 +54,8 @@ import org.apache.lucene.search.spans.SpanTermQuery;
* currently simply feeds all phrase content through an analyzer to select
* phrase terms - any "special" syntax such as * ~ * etc are not given special
* status
- *
- *
+ *
+ * @deprecated use new the flexible query parser instead
*/
public class ComplexPhraseQueryParser extends QueryParser {
private ArrayList/**/complexPhrases = null;
diff --git a/src/java/org/apache/lucene/queryParser/FastCharStream.java b/src/java/org/apache/lucene/queryParser/FastCharStream.java
index 3306c110396..415ab9d099e 100644
--- a/src/java/org/apache/lucene/queryParser/FastCharStream.java
+++ b/src/java/org/apache/lucene/queryParser/FastCharStream.java
@@ -16,6 +16,7 @@ package org.apache.lucene.queryParser;
* 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.
+ *
*/
import java.io.*;
@@ -23,7 +24,11 @@ import java.io.*;
/** An efficient implementation of JavaCC's CharStream interface. Note that
* this does not do line-number counting, but instead keeps track of the
* character position of the token in the input, as required by Lucene's {@link
- * org.apache.lucene.analysis.Token} API. */
+ * org.apache.lucene.analysis.Token} API.
+ *
+ * @deprecated this class will be removed in Lucene 3.0, when the {@link QueryParser} is removed
+ *
+ * */
public final class FastCharStream implements CharStream {
char[] buffer = null;
diff --git a/src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java b/src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java
index 0784c4f36ec..8d29c791f0a 100644
--- a/src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java
+++ b/src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java
@@ -20,7 +20,6 @@ package org.apache.lucene.queryParser;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Vector;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.search.BooleanClause;
@@ -32,6 +31,8 @@ import org.apache.lucene.search.Query;
/**
* A QueryParser which constructs queries to search multiple fields.
*
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.OriginalQueryParserHelper
*
* @version $Revision$
*/
diff --git a/src/java/org/apache/lucene/queryParser/ParseException.java b/src/java/org/apache/lucene/queryParser/ParseException.java
index fdb47847a38..465bd9b155d 100644
--- a/src/java/org/apache/lucene/queryParser/ParseException.java
+++ b/src/java/org/apache/lucene/queryParser/ParseException.java
@@ -10,6 +10,9 @@ package org.apache.lucene.queryParser;
*
* You can modify this class to customize your error reporting
* mechanisms so long as you retain the public fields.
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.parser.ParseException
*/
public class ParseException extends Exception {
diff --git a/src/java/org/apache/lucene/queryParser/QueryParser.java b/src/java/org/apache/lucene/queryParser/QueryParser.java
index 81acf6928e1..d1ed9abb6b5 100644
--- a/src/java/org/apache/lucene/queryParser/QueryParser.java
+++ b/src/java/org/apache/lucene/queryParser/QueryParser.java
@@ -97,6 +97,9 @@ import org.apache.lucene.util.Parameter;
*
*
* Note that QueryParser is not thread-safe.
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.OriginalQueryParserHelper
*/
public class QueryParser implements QueryParserConstants {
diff --git a/src/java/org/apache/lucene/queryParser/QueryParser.jj b/src/java/org/apache/lucene/queryParser/QueryParser.jj
index 9fd125c90f3..0c99696103a 100644
--- a/src/java/org/apache/lucene/queryParser/QueryParser.jj
+++ b/src/java/org/apache/lucene/queryParser/QueryParser.jj
@@ -120,7 +120,11 @@ import org.apache.lucene.util.Parameter;
* use a different method for date conversion.
*
*
- * Note that QueryParser is not thread-safe.
+ * Note that QueryParser is not thread-safe.
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.LuceneQueryParserHelper
+ *
*/
public class QueryParser {
diff --git a/src/java/org/apache/lucene/queryParser/QueryParserConstants.java b/src/java/org/apache/lucene/queryParser/QueryParserConstants.java
index 0073663cb42..3359f7c80d3 100644
--- a/src/java/org/apache/lucene/queryParser/QueryParserConstants.java
+++ b/src/java/org/apache/lucene/queryParser/QueryParserConstants.java
@@ -5,6 +5,10 @@ package org.apache.lucene.queryParser;
/**
* Token literal values and constants.
* Generated by org.javacc.parser.OtherFilesGen#start()
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.parser.TextParserConstants
+ *
*/
public interface QueryParserConstants {
diff --git a/src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java b/src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java
index 2dc793f1dc5..3686967b791 100644
--- a/src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java
+++ b/src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java
@@ -34,7 +34,11 @@ import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.Parameter;
-/** Token Manager. */
+/** Token Manager.
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.parser.TextParserTokenManager
+ */
public class QueryParserTokenManager implements QueryParserConstants
{
diff --git a/src/java/org/apache/lucene/queryParser/Token.java b/src/java/org/apache/lucene/queryParser/Token.java
index 97677981cd7..173af6867b6 100644
--- a/src/java/org/apache/lucene/queryParser/Token.java
+++ b/src/java/org/apache/lucene/queryParser/Token.java
@@ -4,6 +4,10 @@ package org.apache.lucene.queryParser;
/**
* Describes the input token stream.
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.parser.Token
+ *
*/
public class Token {
diff --git a/src/java/org/apache/lucene/queryParser/TokenMgrError.java b/src/java/org/apache/lucene/queryParser/TokenMgrError.java
index 2208bc238ae..601be367be2 100644
--- a/src/java/org/apache/lucene/queryParser/TokenMgrError.java
+++ b/src/java/org/apache/lucene/queryParser/TokenMgrError.java
@@ -2,7 +2,12 @@
/* JavaCCOptions: */
package org.apache.lucene.queryParser;
-/** Token Manager Error. */
+/** Token Manager Error.
+ *
+ * @deprecated use the equivalent class defined in the new queryparser project,
+ * currently located in contrib: org.apache.lucene.queryParser.original.parser.TokenMgrError
+ *
+ */
public class TokenMgrError extends Error
{
diff --git a/src/java/org/apache/lucene/queryParser/package.html b/src/java/org/apache/lucene/queryParser/package.html
index a254ed47979..90e146e9282 100644
--- a/src/java/org/apache/lucene/queryParser/package.html
+++ b/src/java/org/apache/lucene/queryParser/package.html
@@ -20,6 +20,8 @@
+NOTE: Please look into lucene contrib/queryparser for the new flexible queryparser api.
+
A simple query parser implemented with JavaCC.
Note that JavaCC defines lots of public classes, methods and fields
that do not need to be public. These clutter the documentation.