it = listOfProcessors.listIterator();
+ while (it.hasNext()) {
+ newPipeline.add(it.next());
+ }
+ this.setQueryNodeProcessor(newPipeline);
+
+
+ QueryBuilder newBuilder = builder.getClass().newInstance();
+ if (newBuilder instanceof AqpQueryTreeBuilder) {
+ ((AqpQueryTreeBuilder) newBuilder).setDebug(debug);
+ this.setQueryBuilder(newBuilder);
+ }
+
+ }
+ debugMode = debug;
+ }
+
+ public boolean getDebug() {
+ return debugMode;
+ }
+
+ /**
+ * 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 {
+
+ if (defaultField != null) {
+ setDefaultField(defaultField);
+ }
+ try {
+ return (Query) super.parse(query, defaultField);
+ } catch (NestedParseException e) {
+ throw new QueryNodeException(e);
+ }
+
+ }
+
+ public String getDefaultField() {
+ return getQueryConfigHandler().get(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.DEFAULT_FIELD);
+ }
+
+ public void setDefaultField(String field) {
+ getQueryConfigHandler().set(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.DEFAULT_FIELD, field);
+ }
+
+ public Integer getDefaultProximity() {
+ return getQueryConfigHandler().get(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.DEFAULT_PROXIMITY);
+ }
+
+ public void setDefaultProximity(Integer value) {
+ getQueryConfigHandler().set(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.DEFAULT_PROXIMITY,
+ value);
+ }
+
+ public Float getImplicitBoost() {
+ return getQueryConfigHandler().get(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_BOOST);
+ }
+
+ public void setImplicitBoost(Float value) {
+ getQueryConfigHandler().set(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_BOOST, value);
+ }
+
+ public AqpFeedback getFeedback() {
+ return getQueryConfigHandler().get(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.FEEDBACK);
+ }
+
+ public void setFeedback(AqpFeedback feedbackInstance) {
+ getQueryConfigHandler().set(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.FEEDBACK,
+ feedbackInstance);
+ }
+
+ public Float getImplicitFuzzy() {
+ return getQueryConfigHandler().get(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_FUZZY);
+ }
+
+ public void setImplicitFuzzy(Float value) {
+ getQueryConfigHandler().set(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.IMPLICIT_FUZZY, value);
+ }
+
+ public Boolean getAllowSlowFuzzy() {
+ return getQueryConfigHandler().get(
+ AqpStandardQueryConfigHandler.ConfigurationKeys.ALLOW_SLOW_FUZZY);
+ }
+
+ public void setAllowSlowFuzzy(Boolean value) {
+ getQueryConfigHandler()
+ .set(AqpStandardQueryConfigHandler.ConfigurationKeys.ALLOW_SLOW_FUZZY,
+ value);
+ }
+
+ /********************************************************************
+ * Everything below is simpy copy of the StandardQueryParser *
+ *******************************************************************/
+
+ /**
+ * Gets implicit operator setting, which will be either {@link Operator#AND}
+ * or {@link Operator#OR}.
+ */
+ public StandardQueryConfigHandler.Operator getDefaultOperator() {
+ return getQueryConfigHandler().get(ConfigurationKeys.DEFAULT_OPERATOR);
+
+ }
+
+ /**
+ * 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(StandardQueryConfigHandler.Operator operator) {
+ getQueryConfigHandler().set(ConfigurationKeys.DEFAULT_OPERATOR, 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) {
+ getQueryConfigHandler().set(ConfigurationKeys.LOWERCASE_EXPANDED_TERMS,
+ lowercaseExpandedTerms);
+ }
+
+ /**
+ * @see #setLowercaseExpandedTerms(boolean)
+ */
+ public boolean getLowercaseExpandedTerms() {
+ Boolean lowercaseExpandedTerms = getQueryConfigHandler().get(
+ ConfigurationKeys.LOWERCASE_EXPANDED_TERMS);
+
+ if (lowercaseExpandedTerms == null) {
+ return true;
+
+ } else {
+ return lowercaseExpandedTerms;
+ }
+
+ }
+
+ /**
+ * 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) {
+ getQueryConfigHandler().set(ConfigurationKeys.ALLOW_LEADING_WILDCARD,
+ 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) {
+ getQueryConfigHandler().set(ConfigurationKeys.ENABLE_POSITION_INCREMENTS,
+ enabled);
+ }
+
+ /**
+ * @see #setEnablePositionIncrements(boolean)
+ */
+ public boolean getEnablePositionIncrements() {
+ Boolean enablePositionsIncrements = getQueryConfigHandler().get(
+ ConfigurationKeys.ENABLE_POSITION_INCREMENTS);
+
+ if (enablePositionsIncrements == null) {
+ return false;
+
+ } else {
+ return enablePositionsIncrements;
+ }
+
+ }
+
+ /**
+ * 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) {
+ getQueryConfigHandler().set(ConfigurationKeys.MULTI_TERM_REWRITE_METHOD,
+ method);
+ }
+
+ /**
+ * @see #setMultiTermRewriteMethod(org.apache.lucene.search.MultiTermQuery.RewriteMethod)
+ */
+ public MultiTermQuery.RewriteMethod getMultiTermRewriteMethod() {
+ return getQueryConfigHandler().get(
+ ConfigurationKeys.MULTI_TERM_REWRITE_METHOD);
+ }
+
+ /**
+ * Set the fields a query should be expanded to when the field is
+ * null
+ *
+ * @param fields
+ * the fields used to expand the query
+ */
+ public void setMultiFields(CharSequence[] fields) {
+
+ if (fields == null) {
+ fields = new CharSequence[0];
+ }
+
+ getQueryConfigHandler().set(ConfigurationKeys.MULTI_FIELDS, fields);
+
+ }
+
+ /**
+ * Returns the fields used to expand the query when the field for a certain
+ * query is null
+ *
+ * @param fields
+ * the fields used to expand the query
+ */
+ public void getMultiFields(CharSequence[] fields) {
+ getQueryConfigHandler().get(ConfigurationKeys.MULTI_FIELDS);
+ }
+
+ /**
+ * Set the prefix length for fuzzy queries. Default is 0.
+ *
+ * @param fuzzyPrefixLength
+ * The fuzzyPrefixLength to set.
+ */
+ public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
+ QueryConfigHandler config = getQueryConfigHandler();
+ FuzzyConfig fuzzyConfig = config.get(ConfigurationKeys.FUZZY_CONFIG);
+
+ if (fuzzyConfig == null) {
+ fuzzyConfig = new FuzzyConfig();
+ config.set(ConfigurationKeys.FUZZY_CONFIG, fuzzyConfig);
+ }
+
+ fuzzyConfig.setPrefixLength(fuzzyPrefixLength);
+
+ }
+
+ public void setNumericConfigMap(Map numericConfigMap) {
+ getQueryConfigHandler().set(ConfigurationKeys.NUMERIC_CONFIG_MAP,
+ numericConfigMap);
+ }
+
+ public Map getNumericConfigMap() {
+ return getQueryConfigHandler().get(ConfigurationKeys.NUMERIC_CONFIG_MAP);
+ }
+
+ /**
+ * Set locale used by date range parsing.
+ */
+ public void setLocale(Locale locale) {
+ getQueryConfigHandler().set(ConfigurationKeys.LOCALE, locale);
+ }
+
+ /**
+ * Returns current locale, allowing access by subclasses.
+ */
+ public Locale getLocale() {
+ return getQueryConfigHandler().get(ConfigurationKeys.LOCALE);
+ }
+
+ /**
+ * Sets the default slop for phrases. If zero, then exact phrase matches are
+ * required. Default value is zero.
+ *
+ * @deprecated renamed to {@link #setPhraseSlop(int)}
+ */
+ @Deprecated
+ public void setDefaultPhraseSlop(int defaultPhraseSlop) {
+ getQueryConfigHandler().set(ConfigurationKeys.PHRASE_SLOP,
+ defaultPhraseSlop);
+ }
+
+ /**
+ * Sets the default slop for phrases. If zero, then exact phrase matches are
+ * required. Default value is zero.
+ */
+ public void setPhraseSlop(int defaultPhraseSlop) {
+ getQueryConfigHandler().set(ConfigurationKeys.PHRASE_SLOP,
+ defaultPhraseSlop);
+ }
+
+ public void setAnalyzer(Analyzer analyzer) {
+ getQueryConfigHandler().set(ConfigurationKeys.ANALYZER, analyzer);
+ }
+
+ public Analyzer getAnalyzer() {
+ return getQueryConfigHandler().get(ConfigurationKeys.ANALYZER);
+ }
+
+ /**
+ * @see #setAllowLeadingWildcard(boolean)
+ */
+ public boolean getAllowLeadingWildcard() {
+ Boolean allowLeadingWildcard = getQueryConfigHandler().get(
+ ConfigurationKeys.ALLOW_LEADING_WILDCARD);
+
+ if (allowLeadingWildcard == null) {
+ return false;
+
+ } else {
+ return allowLeadingWildcard;
+ }
+ }
+
+ /**
+ * Get the minimal similarity for fuzzy queries.
+ */
+ public float getFuzzyMinSim() {
+ FuzzyConfig fuzzyConfig = getQueryConfigHandler().get(
+ ConfigurationKeys.FUZZY_CONFIG);
+
+ if (fuzzyConfig == null) {
+ return FuzzyQuery.defaultMinSimilarity;
+ } else {
+ return fuzzyConfig.getMinSimilarity();
+ }
+ }
+
+ /**
+ * Get the prefix length for fuzzy queries.
+ *
+ * @return Returns the fuzzyPrefixLength.
+ */
+ public int getFuzzyPrefixLength() {
+ FuzzyConfig fuzzyConfig = getQueryConfigHandler().get(
+ ConfigurationKeys.FUZZY_CONFIG);
+
+ if (fuzzyConfig == null) {
+ return FuzzyQuery.defaultPrefixLength;
+ } else {
+ return fuzzyConfig.getPrefixLength();
+ }
+ }
+
+ /**
+ * Gets the default slop for phrases.
+ */
+ public int getPhraseSlop() {
+ Integer phraseSlop = getQueryConfigHandler().get(
+ ConfigurationKeys.PHRASE_SLOP);
+
+ if (phraseSlop == null) {
+ return 0;
+
+ } else {
+ return phraseSlop;
+ }
+ }
+
+ /**
+ * Set the minimum similarity for fuzzy queries. Default is defined on
+ * {@link FuzzyQuery#defaultMinSimilarity}.
+ */
+ public void setFuzzyMinSim(float fuzzyMinSim) {
+ QueryConfigHandler config = getQueryConfigHandler();
+ FuzzyConfig fuzzyConfig = config.get(ConfigurationKeys.FUZZY_CONFIG);
+
+ if (fuzzyConfig == null) {
+ fuzzyConfig = new FuzzyConfig();
+ config.set(ConfigurationKeys.FUZZY_CONFIG, fuzzyConfig);
+ }
+
+ fuzzyConfig.setMinSimilarity(fuzzyMinSim);
+ }
+
+ /**
+ * Sets the boost used for each field.
+ *
+ * @param boosts
+ * a collection that maps a field to its boost
+ */
+ public void setFieldsBoost(Map boosts) {
+ getQueryConfigHandler().set(ConfigurationKeys.FIELD_BOOST_MAP, boosts);
+ }
+
+ /**
+ * Returns the field to boost map used to set boost for each field.
+ *
+ * @return the field to boost map
+ */
+ public Map getFieldsBoost() {
+ return getQueryConfigHandler().get(ConfigurationKeys.FIELD_BOOST_MAP);
+ }
+
+ /**
+ * Sets the default {@link Resolution} used for certain field when no
+ * {@link Resolution} is defined for this field.
+ *
+ * @param dateResolution
+ * the default {@link Resolution}
+ */
+ public void setDateResolution(DateTools.Resolution dateResolution) {
+ getQueryConfigHandler().set(ConfigurationKeys.DATE_RESOLUTION,
+ dateResolution);
+ }
+
+ /**
+ * Returns the default {@link Resolution} used for certain field when no
+ * {@link Resolution} is defined for this field.
+ *
+ * @return the default {@link Resolution}
+ */
+ public DateTools.Resolution getDateResolution() {
+ return getQueryConfigHandler().get(ConfigurationKeys.DATE_RESOLUTION);
+ }
+
+ /**
+ * Sets the {@link Resolution} used for each field
+ *
+ * @param dateRes
+ * a collection that maps a field to its {@link Resolution}
+ *
+ * @deprecated this method was renamed to {@link #setDateResolutionMap(Map)}
+ */
+ @Deprecated
+ public void setDateResolution(Map dateRes) {
+ setDateResolutionMap(dateRes);
+ }
+
+ /**
+ * Returns the field to {@link Resolution} map used to normalize each date
+ * field.
+ *
+ * @return the field to {@link Resolution} map
+ */
+ public Map getDateResolutionMap() {
+ return getQueryConfigHandler().get(
+ ConfigurationKeys.FIELD_DATE_RESOLUTION_MAP);
+ }
+
+ /**
+ * Sets the {@link Resolution} used for each field
+ *
+ * @param dateRes
+ * a collection that maps a field to its {@link Resolution}
+ */
+ public void setDateResolutionMap(
+ Map dateRes) {
+ getQueryConfigHandler().set(ConfigurationKeys.FIELD_DATE_RESOLUTION_MAP,
+ dateRes);
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParser.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParser.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParser.java (revision 0)
@@ -0,0 +1,40 @@
+package org.apache.lucene.queryparser.flexible.aqp;
+
+import org.antlr.runtime.TokenStream;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.parser.SyntaxParser;
+
+public interface AqpSyntaxParser extends SyntaxParser {
+ /**
+ * @param grammarName
+ * - the name of the query
+ * @throws Exception
+ * - there are different implementations (should we want different
+ * interfaces?) some may be loading grammars on the fly, others will
+ * load grammars directly
+ *
+ * @return AqpSyntaxParser
+ */
+ public AqpSyntaxParser initializeGrammar(String grammarName)
+ throws QueryNodeParseException;
+
+ /**
+ * This method should return the stream of tokens, it can be used to modify
+ * the original query before it gets executed
+ *
+ * @param input
+ * - original query
+ * @return TokenStream
+ * - (un)modified stream of tokens
+ * @throws QueryNodeParseException
+ */
+ public TokenStream getTokenStream(CharSequence input)
+ throws QueryNodeParseException;
+
+ public QueryNode parseTokenStream(TokenStream tokens, CharSequence query,
+ CharSequence field) throws QueryNodeParseException;
+
+ public QueryNode parse(CharSequence query, CharSequence field)
+ throws QueryNodeParseException;
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEventHandler.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEventHandler.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEventHandler.java (revision 0)
@@ -0,0 +1,21 @@
+package org.apache.lucene.queryparser.flexible.aqp.config;
+
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedbackEvent;
+
+public interface AqpFeedbackEventHandler {
+
+ public enum ACTION {
+ STOP, SAVE_EVENT
+ };
+
+ /**
+ * Handles the {@link AqpFeedbackEvent}
+ *
+ * If it returns false, the next registered event handler will not get a
+ * chance to handle the event.
+ *
+ * @param event
+ * @return
+ */
+ public ACTION handle(AqpFeedbackEvent event);
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedback.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedback.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedback.java (revision 0)
@@ -0,0 +1,48 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+/**
+ * This attribute is used to collect feedback messages and suggestions from the
+ * query parser
+ *
+ * WARNING: experimental, may change soon!
+ */
+public interface AqpFeedback extends Attribute {
+
+ public enum TYPE {
+ DEBUG, INFO, WARN, ERROR, SYNTAX_SUGGESTION, DEPRECATED
+ };
+
+ /*
+ * I am NOT trying to re-implement a wheel, I am just confused what is the
+ * proper way to wrap SLF4J used by SOLR (but not by Lucene) and not introduce
+ * it as a dependency to Lucene
+ */
+ public AqpFeedbackEvent createEvent(TYPE level,
+ Class extends QueryNodeProcessor> qnClass, QueryNode node, String msg,
+ Object... args);
+
+ public void sendEvent(AqpFeedbackEvent event);
+
+ public void registerEventHandler(AqpFeedbackEventHandler handler);
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackImpl.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackImpl.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackImpl.java (revision 0)
@@ -0,0 +1,68 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
+import org.apache.lucene.util.AttributeImpl;
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedbackEventHandler.ACTION;
+
+public class AqpFeedbackImpl extends AttributeImpl implements AqpFeedback {
+
+ private static final long serialVersionUID = 5178148416076100953L;
+
+ private List events = new ArrayList();
+ private List handlers = new ArrayList();
+
+ @Override
+ public void clear() {
+ events.clear();
+ }
+
+ @Override
+ public void copyTo(AttributeImpl target) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void registerEventHandler(AqpFeedbackEventHandler handler) {
+ handlers.add(handler);
+ }
+
+ public AqpFeedbackEvent createEvent(TYPE level,
+ Class extends QueryNodeProcessor> qnClass, QueryNode node, String msg,
+ Object... args) {
+ return new AqpFeedbackEventImpl(level, qnClass, node, msg, args);
+ }
+
+ public void sendEvent(AqpFeedbackEvent event) {
+ for (AqpFeedbackEventHandler handler : handlers) {
+ ACTION r = handler.handle(event);
+ if (r == ACTION.STOP) {
+ return;
+ } else if (r == ACTION.SAVE_EVENT) {
+ if (!events.contains(event)) {
+ events.add(event);
+ }
+ }
+ }
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEvent.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEvent.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEvent.java (revision 0)
@@ -0,0 +1,19 @@
+package org.apache.lucene.queryparser.flexible.aqp.config;
+
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+
+public interface AqpFeedbackEvent extends Attribute {
+
+ public AqpFeedback.TYPE getType();
+
+ public Class extends QueryNodeProcessor> getCaller();
+
+ public QueryNode getNode();
+
+ public String getMessage();
+
+ public Object[] getArgs();
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEventImpl.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEventImpl.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/config/AqpFeedbackEventImpl.java (revision 0)
@@ -0,0 +1,46 @@
+package org.apache.lucene.queryparser.flexible.aqp.config;
+
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedback.TYPE;
+
+public class AqpFeedbackEventImpl implements AqpFeedbackEvent {
+
+ private AqpFeedback.TYPE type = null;
+ private Class extends QueryNodeProcessor> caller = null;
+ private QueryNode node = null;
+ private String message = null;
+ private Object[] args = null;
+
+ AqpFeedbackEventImpl(AqpFeedback.TYPE type,
+ Class extends QueryNodeProcessor> processorClass, QueryNode node,
+ String message, Object... args) {
+
+ this.type = type;
+ this.caller = processorClass;
+ this.node = node;
+ this.message = message;
+ this.args = args;
+
+ }
+
+ public TYPE getType() {
+ return type;
+ }
+
+ public Class extends QueryNodeProcessor> getCaller() {
+ return caller;
+ }
+
+ public QueryNode getNode() {
+ return node;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public Object[] getArgs() {
+ return args;
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/SlowFuzzyQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/SlowFuzzyQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/SlowFuzzyQueryNode.java (revision 0)
@@ -0,0 +1,18 @@
+package org.apache.lucene.queryparser.flexible.aqp.nodes;
+
+import org.apache.lucene.queryparser.flexible.core.nodes.FuzzyQueryNode;
+
+/**
+ * Exactly the same as FuzzyQueryNode but it will be transformed into a
+ * SlowFuzzyQuery
+ *
+ *
+ */
+public class SlowFuzzyQueryNode extends FuzzyQueryNode {
+
+ public SlowFuzzyQueryNode(CharSequence field, CharSequence term,
+ float minSimilarity, int begin, int end) {
+ super(field, term, minSimilarity, begin, end);
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpANTLRNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpANTLRNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpANTLRNode.java (revision 0)
@@ -0,0 +1,249 @@
+package org.apache.lucene.queryparser.flexible.aqp.nodes;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.antlr.runtime.CommonToken;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryparser.flexible.aqp.util.AqpCommonTree;
+
+/**
+ * When Aqp parser starts processing the AST (abstract syntax tree)
+ * every node in the tree is made of {@link AqpANTLRNode} and it wraps
+ * the {@link AqpCommonTree} through which you can access information
+ * about the string, its position, type etc... these are courtesy of
+ * ANTLR.
+ *
+ * We provide a few utility methods for setting different attributes
+ * of the original ANTLR object.
+ *
+ */
+public class AqpANTLRNode extends QueryNodeImpl {
+
+ private static final long serialVersionUID = 5128762709928473351L;
+
+ private AqpCommonTree tree;
+
+ private int tokenType;
+
+ private String tokenLabel;
+
+ private String tokenName;
+
+ private String tokenInput = null;
+
+ /**
+ * @param node
+ * - AST node
+ */
+ public AqpANTLRNode(AqpCommonTree node) {
+
+ tree = node;
+ String input = node.getTokenInput();
+
+ if (input != null) {
+ setTokenInput(input);
+ }
+
+ setTokenLabel(node.getTokenLabel());
+
+ setTokenType(node.getTokenType());
+
+ setTokenName(node.getTypeLabel());
+
+ if (node.getChildCount() > 0) {
+ setLeaf(false);
+ allocate();
+ }
+ }
+
+ public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+ if (getTokenInput() != null) {
+ return "(" + getTokenLabel() + ":" + getTokenInput() + ")";
+ } else {
+ return getTokenLabel();
+ }
+ }
+
+ public String toStringNodeOnly() {
+ if (getTokenInput() != null) {
+ return "";
+ } else {
+ return "";
+ }
+ }
+
+ public String toString() {
+ return toString(0);
+ }
+
+ public String toString(int level) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("\n");
+ for (int i = 0; i < level; i++) {
+ buf.append(" ");
+ }
+
+ buf.append(" children = this.getChildren();
+
+ if (children != null) {
+ buf.append(">");
+ for (QueryNode child : children) {
+ if (child instanceof AqpANTLRNode) {
+ buf.append(((AqpANTLRNode) child).toString(level + 4));
+ } else {
+ buf.append(child.toString());
+ }
+ }
+ }
+
+ if (isLeaf()) {
+ buf.append("/>");
+ } else {
+ buf.append("\n");
+ for (int i = 0; i < level; i++) {
+ buf.append(" ");
+ }
+ buf.append("");
+ }
+
+ return buf.toString();
+ }
+
+ public int getTokenType() {
+ return tokenType;
+ }
+
+ public void setTokenType(int tokenType) {
+ this.tokenType = tokenType;
+ }
+
+ /**
+ * Label is what is displayed in the AST tree, for example and, And, AND will
+ * all have label=AND
+ *
+ * (But their internal name is an 'OPERATOR')
+ *
+ * @return
+ */
+ public String getTokenLabel() {
+ return tokenLabel;
+ }
+
+ public void setTokenLabel(String tokenLabel) {
+ this.tokenLabel = tokenLabel;
+ }
+
+ public String getTokenName() {
+ return tokenName;
+ }
+
+ /**
+ * Name is the name of the group, ie. 'AND' is an OPERATOR (but its label
+ * says: 'AND')
+ *
+ * @param tokenName
+ */
+ public void setTokenName(String tokenName) {
+ this.tokenName = tokenName;
+ }
+
+ public String getTokenInput() {
+ return tokenInput;
+ }
+
+ public void setTokenInput(String tokenInput) {
+ this.tokenInput = tokenInput;
+ }
+
+ public int getTokenStart() {
+ return tree.getStartIndex();
+ }
+
+ public int getTokenEnd() {
+ return tree.getStopIndex();
+ }
+
+ public AqpCommonTree getTree() {
+ return tree;
+ }
+
+ public int getInputTokenStart() {
+ return ((CommonToken) tree.getToken()).getCharPositionInLine();// getStartIndex();
+ }
+
+ public int getInputTokenEnd() {
+ return ((CommonToken) tree.getToken()).getStopIndex();
+ }
+
+ public void setInputTokenEnd(int stop) {
+ ((CommonToken) tree.getToken()).setStopIndex(stop);
+ }
+
+ public void setInputTokenStart(int start) {
+ ((CommonToken) tree.getToken()).setStartIndex(start);
+ }
+
+ public AqpANTLRNode getChild(String tokenLabel) {
+ List children = getChildren();
+ if (children != null) {
+ for (QueryNode child : children) {
+ AqpANTLRNode n = (AqpANTLRNode) child;
+ if (n.getTokenLabel().equals(tokenLabel)) {
+ return n;
+ }
+ }
+
+ }
+ return null;
+ }
+
+ public AqpANTLRNode findChild(String tokenLabel) {
+ ArrayList lst = new ArrayList();
+ findChild(this, tokenLabel, lst);
+
+ if (lst.size() == 1) {
+ return (AqpANTLRNode) lst.get(0);
+ } else if (lst.size() > 1) {
+ throw new RuntimeException(
+ "This method is not meant to search for n>1 nodes");
+ }
+ return null;
+ }
+
+ private void findChild(QueryNode node, String tokenLabel,
+ ArrayList lst) {
+ if (((AqpANTLRNode) node).getTokenLabel().equals(tokenLabel)) {
+ lst.add(node);
+ } else {
+ if (!node.isLeaf()) {
+ for (QueryNode child : node.getChildren()) {
+ findChild(child, tokenLabel, lst);
+ }
+ }
+ }
+ }
+
+ public Float getTokenInputFloat() {
+ if (this.tokenInput != null) {
+ return Float.valueOf(this.tokenInput);
+ }
+ return null;
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpDefopQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpDefopQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpDefopQueryNode.java (revision 0)
@@ -0,0 +1,67 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler;
+
+/**
+ * A {@link AqpDefopQueryNode} represents the default boolean operation
+ * performed on a list of nodes.
+ *
+ * This behaves the same way as any AqpBooleanQueryNode but we have the
+ * advantage of knowing which tokens were marked by the DEFOP operator and later
+ * on we can look at them and process specially (in the logic that explicit AND
+ * is stronger than implicit AND)
+ *
+ * @see AqpBooleanQueryNode
+ * @see StandardQueryConfigHandler.Operator
+ */
+public class AqpDefopQueryNode extends AqpBooleanQueryNode {
+
+ /**
+ * @param clauses
+ * - the query nodes to be joined
+ */
+ public AqpDefopQueryNode(List clauses,
+ StandardQueryConfigHandler.Operator op) {
+ super(clauses);
+
+ if ((clauses == null) || (clauses.size() == 0)) {
+ throw new IllegalArgumentException(
+ "DEFOP query must have at least one clause");
+ }
+
+ if (op.equals(StandardQueryConfigHandler.Operator.AND)) {
+ operator = "AND";
+ applyModifier(clauses, Modifier.MOD_REQ);
+ } else if (op.equals(StandardQueryConfigHandler.Operator.OR)) {
+ operator = "OR";
+ applyModifier(clauses, Modifier.MOD_NONE);
+ }
+
+ // unfortunately we have to do it like this (when subclassing from
+ // BooleanQueryNode)
+ set(clauses);
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpBooleanQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpBooleanQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpBooleanQueryNode.java (revision 0)
@@ -0,0 +1,114 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.BooleanQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.GroupQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link AqpBooleanQueryNode} represents base boolean operation performed on
+ * a list of nodes. It will apply the @{link ModifierQueryNode} to the clauses.
+ * The normal behaviour is not to override the ModifierQueryNode values, if
+ * already present.
+ */
+public class AqpBooleanQueryNode extends BooleanQueryNode {
+
+ private static final long serialVersionUID = -5974910790857168198L;
+
+ protected String operator = "DEFOP";
+ protected boolean overrideModifiers = false;
+
+ /**
+ * @param clauses
+ * - the query nodes to be op'ed
+ */
+ public AqpBooleanQueryNode(List clauses) {
+ super(clauses);
+
+ }
+
+ @Override
+ 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();
+ }
+
+ @Override
+ 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 = " " + operator + " ";
+ }
+
+ // in case is root or the parent is a group node avoid parenthesis
+ if ((getParent() != null && getParent() instanceof GroupQueryNode)
+ || isRoot())
+ return sb.toString();
+ else
+ return "( " + sb.toString() + " )";
+ }
+
+ public void applyModifier(List clauses, Modifier mod) {
+ for (int i = 0; i < clauses.size(); i++) {
+ QueryNode child = clauses.get(i);
+
+ if (child instanceof ModifierQueryNode || child instanceof GroupQueryNode) {
+ if (overrideModifiers) {
+ clauses
+ .set(i,
+ new ModifierQueryNode(((ModifierQueryNode) child).getChild(),
+ mod));
+ }
+ } else {
+ clauses.set(i, new ModifierQueryNode(child, mod));
+ }
+ }
+ }
+
+ public void setOverrideModifiers(boolean val) {
+ this.overrideModifiers = val;
+ }
+
+ public void setOperator(String op) {
+ operator = op;
+ }
+
+ public String getOperator() {
+ return operator;
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpOrQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpOrQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpOrQueryNode.java (revision 0)
@@ -0,0 +1,51 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.QueryNode;
+
+/**
+ * A {@link AqpOrQueryNode} represents an OR boolean operation performed on a
+ * list of nodes.
+ *
+ * @see AqpBooleanQueryNode
+ */
+public class AqpOrQueryNode extends AqpBooleanQueryNode {
+
+ private static final long serialVersionUID = 8472252510866053747L;
+
+ /**
+ * @param clauses
+ * - the query nodes to be or'ed
+ */
+ public AqpOrQueryNode(List clauses) {
+ super(clauses);
+
+ operator = "OR";
+
+ // applyModifier(clauses, Modifier.MOD_NONE);
+
+ // unfortunately we have to do it like this (when subclassing from
+ // BooleanQueryNode)
+ set(clauses);
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNotQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNotQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNotQueryNode.java (revision 0)
@@ -0,0 +1,72 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+
+/**
+ * A {@link AqpNotQueryNode} represents an NOT boolean operation performed on a
+ * list of nodes.
+ *
+ *
+ *
+ * The first node is set to be required
+ * {@link ModifierQueryNode.Modifier#MOD_REQ} and the rest of the clauses will
+ * have a {@link ModifierQueryNode.Modifier#MOD_NOT}
+ *
+ * @see AqpBooleanQueryNode
+ */
+public class AqpNotQueryNode extends AqpBooleanQueryNode {
+
+ private static final long serialVersionUID = 4054514488434283069L;
+
+ /**
+ * @param clauses
+ * - the query nodes to be and'ed
+ */
+ public AqpNotQueryNode(List clauses) {
+ super(clauses);
+
+ operator = "NOT";
+
+ if ((clauses == null) || (clauses.size() < 2)) {
+ throw new IllegalArgumentException(
+ "NOT query must have at least two clauses");
+ }
+
+ QueryNode firstNode = clauses.get(0);
+ applyModifier(clauses, Modifier.MOD_NOT);
+ // reset the first node (if it was wrapped, ie not already having user
+ // specified MODIFIER)
+ if (!firstNode.equals(clauses.get(0))) {
+ clauses
+ .set(
+ 0,
+ new ModifierQueryNode(((ModifierQueryNode) clauses.get(0))
+ .getChild(), Modifier.MOD_REQ));
+ }
+
+ set(clauses);
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpFuzzyModifierNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpFuzzyModifierNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpFuzzyModifierNode.java (revision 0)
@@ -0,0 +1,69 @@
+package org.apache.lucene.queryparser.flexible.aqp.nodes;
+
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpFuzzyModifierProcessor;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeError;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.ModifierQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+
+/**
+ * {@link AqpFuzzyModifierNode} is consumed by the {@link AqpFuzzyModifierProcessor}
+ * which will decide what is the appropriate operation for '~' operator. E.g.
+ *
+ *
+ *
+ * "foo bar"~5 == slop query node
+ * "foo"~5 == fuzzy search for 'foo'
+ *
+ */
+public class AqpFuzzyModifierNode extends QueryNodeImpl implements QueryNode {
+
+ private static final long serialVersionUID = -3059874057254791689L;
+ private Float fuzzy;
+
+ public AqpFuzzyModifierNode(QueryNode query, Float fuzzy) {
+ if (query == null) {
+ throw new QueryNodeError(new MessageImpl(
+ QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "query", "null"));
+ }
+
+ allocate();
+ setLeaf(false);
+ add(query);
+ this.fuzzy = fuzzy;
+ }
+
+ public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+ if (getChild() == null)
+ return "";
+
+ String leftParenthensis = "";
+ String rightParenthensis = "";
+
+ if (getChild() != null && getChild() instanceof ModifierQueryNode) {
+ leftParenthensis = "(";
+ rightParenthensis = ")";
+ }
+
+ return leftParenthensis + getChild().toQueryString(escapeSyntaxParser)
+ + rightParenthensis + "~" + this.fuzzy.toString();
+
+ }
+
+ public String toString() {
+ return "" + "\n"
+ + getChild().toString() + "\n";
+ }
+
+ public QueryNode getChild() {
+ return getChildren().get(0);
+ }
+
+ public Float getFuzzyValue() {
+ return fuzzy;
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAndQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAndQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAndQueryNode.java (revision 0)
@@ -0,0 +1,57 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+
+/**
+ * A {@link AqpAndQueryNode} represents an AND boolean operation performed on a
+ * list of nodes.
+ *
+ * @see AqpBooleanQueryNode
+ */
+public class AqpAndQueryNode extends AqpBooleanQueryNode {
+
+ private static final long serialVersionUID = -4148186404006404927L;
+
+ /**
+ * @param clauses
+ * - the query nodes to be and'ed
+ */
+ public AqpAndQueryNode(List clauses) {
+ super(clauses);
+
+ operator = "AND";
+
+ if ((clauses == null) || (clauses.size() == 0)) {
+ throw new IllegalArgumentException(
+ "AND query must have at least one clause");
+ }
+
+ applyModifier(clauses, Modifier.MOD_REQ);
+
+ // unfortunately we have to do it like this (when subclassing from
+ // BooleanQueryNode)
+ set(clauses);
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNonAnalyzedQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNonAnalyzedQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNonAnalyzedQueryNode.java (revision 0)
@@ -0,0 +1,66 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QuotedFieldQueryNode;
+
+/**
+ * A {@link NonAnalyzedQueryNode} represents a query that will not be processed
+ * by an analyzer. It will be served to the search engine as it is
+ *
+ * Example: e(+)
+ */
+public class AqpNonAnalyzedQueryNode extends QuotedFieldQueryNode {
+
+ private static final long serialVersionUID = 6921391439471630844L;
+
+ /**
+ * @param field
+ * - field name
+ * @param text
+ * - the query
+ * @param begin
+ * - position in the query string
+ * @param end
+ * - position in the query string
+ */
+ public AqpNonAnalyzedQueryNode(CharSequence field, CharSequence text,
+ int begin, int end) {
+ super(field, text, begin, end);
+ }
+
+ public AqpNonAnalyzedQueryNode(FieldQueryNode fqn) {
+ this(fqn.getField(), fqn.getText(), fqn.getBegin(), fqn.getEnd());
+ }
+
+ @Override
+ public String toString() {
+ return "";
+ }
+
+ @Override
+ public AqpNonAnalyzedQueryNode cloneTree() throws CloneNotSupportedException {
+ AqpNonAnalyzedQueryNode clone = (AqpNonAnalyzedQueryNode) super.cloneTree();
+
+ // nothing to do here
+
+ return clone;
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNearQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNearQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpNearQueryNode.java (revision 0)
@@ -0,0 +1,89 @@
+package org.apache.lucene.queryparser.flexible.aqp.nodes;
+
+import java.util.List;
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpOPERATORProcessor;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeError;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+
+/**
+ * For nodes connected through proximity operators, eg.
+ *
+ *
+ * foo NEAR bar
+ *
+ *
+ * @see AqpOPERATORProcessor
+ *
+ */
+public class AqpNearQueryNode extends QueryNodeImpl implements QueryNode {
+
+ private static final long serialVersionUID = 8806759327487974314L;
+ private Integer slop = null;
+ private boolean inOrder = true;
+
+ public AqpNearQueryNode(List children, int proximity) {
+ if (children == null) {
+ throw new QueryNodeError(
+ new MessageImpl(QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED,
+ "children", "null"));
+ }
+ allocate();
+ setLeaf(false);
+ add(children);
+ this.slop = proximity;
+ }
+
+ public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+ if (getChild() == null)
+ return "";
+
+ String leftParenthensis = "";
+ String rightParenthensis = "";
+
+ if (getChild() != null && getChild() instanceof AqpNearQueryNode) {
+ leftParenthensis = "(";
+ rightParenthensis = ")";
+ }
+
+ return leftParenthensis + "#"
+ + getChild().toQueryString(escapeSyntaxParser) + rightParenthensis;
+
+ }
+
+ public String toString() {
+ StringBuffer bo = new StringBuffer();
+ bo.append("\n");
+ for (QueryNode child : this.getChildren()) {
+ bo.append(child.toString());
+ bo.append("\n");
+ }
+ bo.append("\n");
+ return bo.toString();
+ }
+
+ public QueryNode getChild() {
+ return getChildren().get(0);
+ }
+
+ public Integer getSlop() {
+ return slop;
+ }
+
+ public void setSlop(Integer prox) {
+ slop = prox;
+ }
+
+ public boolean getInOrder() {
+ return inOrder;
+ }
+
+ public void setInOrder(boolean order) {
+ inOrder = order;
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAnalyzedQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAnalyzedQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAnalyzedQueryNode.java (revision 0)
@@ -0,0 +1,63 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.aqp.processors.AqpAnalyzerQueryNodeProcessor;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link NonAnalyzedQueryNode} represents a query that was already be
+ * processed by an analyzer. The child (typically only one) is the result of a
+ * call to another analyzer.
+ *
+ * @see AqpAnalyzerQueryNodeProcessor
+ */
+public class AqpAnalyzedQueryNode extends QueryNodeImpl {
+
+ /**
+ * @param node
+ * - query node
+ */
+ public AqpAnalyzedQueryNode(QueryNode node) {
+ allocate();
+ setLeaf(false);
+ this.add(node);
+ }
+
+ @Override
+ public String toString() {
+ return "" + this.getChild() + "";
+ }
+
+ @Override
+ public AqpAnalyzedQueryNode cloneTree() throws CloneNotSupportedException {
+ AqpAnalyzedQueryNode clone = (AqpAnalyzedQueryNode) super.cloneTree();
+ // nothing to do here
+ return clone;
+ }
+
+ public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+ return this.getChildren().get(0).toQueryString(escapeSyntaxParser);
+ }
+
+ public QueryNode getChild() {
+ return this.getChildren().get(0);
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAdsabsRegexQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAdsabsRegexQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpAdsabsRegexQueryNode.java (revision 0)
@@ -0,0 +1,41 @@
+package org.apache.lucene.queryparser.flexible.aqp.nodes;
+
+import org.apache.lucene.queryparser.flexible.aqp.builders.AqpFieldQueryNodeRegexBuilder;
+import org.apache.lucene.queryparser.flexible.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.search.RegexpQuery;
+
+/**
+ * This node will be turned into the {@link RegexpQuery} by
+ * {@link AqpFieldQueryNodeRegexBuilder}. But the appropriate
+ * builder must be configured.
+ *
+ * @see instances of {@link QueryTreeBuilder}
+ *
+ */
+public class AqpAdsabsRegexQueryNode extends AqpNonAnalyzedQueryNode {
+
+ public AqpAdsabsRegexQueryNode(CharSequence field, CharSequence text,
+ int begin, int end) {
+ super(field, text, begin, end);
+ }
+
+ public AqpAdsabsRegexQueryNode(FieldQueryNode fqn) {
+ this(fqn.getField(), fqn.getText(), fqn.getBegin(), fqn.getEnd());
+ }
+
+ @Override
+ public String toString() {
+ return "";
+ }
+
+ @Override
+ public AqpAdsabsRegexQueryNode cloneTree() throws CloneNotSupportedException {
+ AqpAdsabsRegexQueryNode clone = (AqpAdsabsRegexQueryNode) super.cloneTree();
+
+ // nothing to do here
+
+ return clone;
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpDisjunctionQueryNode.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpDisjunctionQueryNode.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/nodes/AqpDisjunctionQueryNode.java (revision 0)
@@ -0,0 +1,68 @@
+package org.apache.lucene.queryparser.flexible.aqp.nodes;
+
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.core.QueryNodeError;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNodeImpl;
+import org.apache.lucene.queryparser.flexible.core.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+
+public class AqpDisjunctionQueryNode extends QueryNodeImpl {
+
+ private Float tieBreaker = null;
+
+ public AqpDisjunctionQueryNode(List children, float tieBreaker) {
+ if (children == null) {
+ throw new QueryNodeError(
+ new MessageImpl(QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED,
+ "children", "null"));
+ }
+ allocate();
+ setLeaf(false);
+ add(children);
+ this.tieBreaker = tieBreaker;
+ }
+
+ public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+ if (getChildren().size() == 0)
+ return "";
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ boolean notFirst = false;
+ for (QueryNode child : getChildren()) {
+ if (notFirst) {
+ sb.append(" | ");
+ }
+ sb.append(child.toQueryString(escapeSyntaxParser));
+ notFirst = true;
+ }
+ sb.append(")");
+ return sb.toString();
+
+ }
+
+ public String toString() {
+ StringBuffer bo = new StringBuffer();
+ bo.append("\n");
+ for (QueryNode child : this.getChildren()) {
+ bo.append(child.toString());
+ bo.append("\n");
+ }
+ bo.append("\n");
+ return bo.toString();
+ }
+
+ public Float getTieBreaker() {
+ return tieBreaker;
+ }
+
+ public void setTieBreaker(Float tieBreaker) {
+ this.tieBreaker = tieBreaker;
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpNearQueryNodeBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpNearQueryNodeBuilder.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpNearQueryNodeBuilder.java (revision 0)
@@ -0,0 +1,213 @@
+package org.apache.lucene.queryparser.flexible.aqp.builders;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.builders.QueryBuilder;
+import org.apache.lucene.queryparser.flexible.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.aqp.nodes.AqpNearQueryNode;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.PrefixQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
+import org.apache.lucene.search.spans.SpanNearQuery;
+import org.apache.lucene.search.spans.SpanNotQuery;
+import org.apache.lucene.search.spans.SpanOrQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+import org.apache.lucene.search.spans.SpanTermQuery;
+
+/**
+ * The builder for the {@link AqpNearQueryNode}, example query:
+ *
+ *
+ * dog NEAR/5 cat
+ *
+ *
+ *
+ * After the AST tree was parsed, and synonyms were found,
+ * we may have the following tree:
+ *
+ *
+ *
+ * AqpNearQueryNode(5)
+ * |
+ * ------------------------------
+ * / \
+ * OR QueryNode(cat)
+ * |
+ * -----------------
+ * / \
+ * QueryNode(dog) QueryNode(canin)
+ *
+ *
+ *
+ *
+ *
+ * Since Lucene cannot handle these queries, the flex builder
+ * must rewrite them, effectively producing
+ *
+ *
+ * SpanNear(SpanOr(dog | cat), SpanTerm(cat), 5)
+ *
+ *
+ *
+ * This builder does not know (yet) how to handle cases of
+ * mixed boolean operators, eg.
+ *
+ *
+ * (dog AND (cat OR fat)) NEAR/5 batman
+ *
+ *
+ * @see QueryNodeProcessorPipeline
+ * @see AqpNearQueryNode
+ *
+ */
+public class AqpNearQueryNodeBuilder implements QueryBuilder {
+
+ public AqpNearQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public Object build(QueryNode queryNode) throws QueryNodeException {
+ AqpNearQueryNode nearNode = (AqpNearQueryNode) queryNode;
+
+ List children = nearNode.getChildren();
+
+ if (children != null) {
+ SpanQuery[] clauses = new SpanQuery[children.size()];
+
+ int i = 0;
+ for (QueryNode child : children) {
+ Object obj = child.getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+ if (obj != null) {
+ clauses[i++] = getSpanQuery(obj, nearNode);
+ } else {
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR,
+ "One of the clauses inside AqpNearQueryNode is null"));
+ }
+ }
+
+ return new SpanNearQuery(clauses, nearNode.getSlop(),
+ nearNode.getInOrder());
+ }
+
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR,
+ "Illegal state for: " + nearNode.toString()));
+ }
+
+ protected SpanQuery getSpanQuery(Object obj, AqpNearQueryNode nearNode)
+ throws QueryNodeException {
+ Query q = (Query) obj;
+ if (q instanceof SpanQuery) {
+ return (SpanQuery) q;
+ } else if (q instanceof TermQuery) {
+ return new SpanTermQuery(((TermQuery) q).getTerm());
+ } else if (q instanceof WildcardQuery) {
+ return new SpanMultiTermQueryWrapper((WildcardQuery) q);
+ } else if (q instanceof PrefixQuery) {
+ return new SpanMultiTermQueryWrapper((PrefixQuery) q);
+ } else if (q instanceof BooleanQuery) {
+ return convertBooleanToSpan((BooleanQuery) q, nearNode);
+ } else {
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, q.toString(),
+ "(yet) Unsupported clause inside span query: "
+ + q.getClass().getName()));
+ }
+ }
+
+ /*
+ * Silly convertor for now it can handle only boolean queries of the same type
+ * (ie not mixed cases). To do that, I have to build a graph (tree) and maybe
+ * of only pairs (?)
+ */
+ protected SpanQuery convertBooleanToSpan(BooleanQuery q,
+ AqpNearQueryNode nearNode) throws QueryNodeException {
+ BooleanClause[] clauses = q.getClauses();
+ SpanQuery[] spanClauses = new SpanQuery[clauses.length];
+ Occur o = null;
+ int i = 0;
+ for (BooleanClause c : clauses) {
+ if (o != null && !o.equals(c.getOccur())) {
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, q.toString(),
+ "(yet) Unsupported clause inside span query: "
+ + q.getClass().getName()));
+ }
+ o = c.getOccur();
+ spanClauses[i] = getSpanQuery(c.getQuery(), nearNode);
+ i++;
+ }
+
+ if (o.equals(Occur.MUST)) {
+ return new SpanNearQuery(spanClauses, nearNode.getSlop(),
+ nearNode.getInOrder());
+ } else if (o.equals(Occur.SHOULD)) {
+ return new SpanOrQuery(spanClauses);
+ } else if (o.equals(Occur.MUST_NOT)) {
+ SpanQuery[] exclude = new SpanQuery[spanClauses.length - 1];
+ for (int j = 1; j < spanClauses.length; j++) {
+ exclude[j - 1] = spanClauses[j];
+ }
+ return new SpanNotQuery(spanClauses[0], new SpanOrQuery(exclude));
+ }
+
+ throw new QueryNodeException(new MessageImpl(
+ QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, q.toString(),
+ "Congratulations! You have hit (yet) unsupported case: "
+ + q.getClass().getName()));
+ }
+
+ class Leaf {
+ public List members = new ArrayList();
+ public BooleanClause left;
+ public Leaf right;
+
+ public Leaf(BooleanClause left, Leaf right) {
+ this.left = left;
+ this.right = right;
+ }
+ }
+
+ /*
+ * Creates a tree of the clauses, according to operator precedence:
+ *
+ * Thus: D +C -A -B becomes:
+ *
+ * - / \ A - / \ B + / \ C D
+ */
+ private Leaf constructTree(BooleanClause[] clauses) {
+ List toProcess = Arrays.asList(clauses);
+ Leaf leaf = new Leaf(null, null);
+ leaf.members = toProcess;
+
+ // from highest priority
+ // findNots(leaf);
+ // findAnds(leaf);
+ // findOrs(leaf);
+ return leaf;
+ }
+
+ private void findNots(Leaf leaf) {
+
+ for (BooleanClause m : leaf.members) {
+ if (m.getOccur().equals(Occur.MUST_NOT)) {
+ leaf.members.remove(m);
+ leaf.left = m;
+ }
+ }
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpQueryTreeBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpQueryTreeBuilder.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpQueryTreeBuilder.java (revision 0)
@@ -0,0 +1,113 @@
+package org.apache.lucene.queryparser.flexible.aqp.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.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.builders.QueryBuilder;
+import org.apache.lucene.queryparser.flexible.core.builders.QueryTreeBuilder;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.standard.builders.StandardQueryBuilder;
+import org.apache.lucene.queryparser.flexible.standard.processors.StandardQueryNodeProcessorPipeline;
+import org.apache.lucene.search.Query;
+
+/**
+ * This query tree builder only defines the necessary methods for
+ * debugging.
+ *
+ * @see QueryTreeBuilder
+ * @see StandardQueryNodeProcessorPipeline
+ */
+public class AqpQueryTreeBuilder extends QueryTreeBuilder implements
+ StandardQueryBuilder {
+
+ private boolean debug = false;
+ private int counter = 0;
+
+ public AqpQueryTreeBuilder(boolean debug) {
+ this.setDebug(debug);
+ init();
+ }
+
+ public AqpQueryTreeBuilder() {
+ init();
+ }
+
+ public void setDebug(boolean val) {
+ if (val != debug) {
+ debug = val;
+ init();
+ }
+ debug = val;
+ }
+
+ public boolean isInDebugMode() {
+ return debug;
+ }
+
+ public void init() {
+ throw new IllegalAccessError("AqpQueryTreeBuilder must be subclassed and has the init() method");
+ }
+
+ @Override
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ this.counter = 0;
+ return (Query) super.build(queryNode);
+ }
+
+
+ public void setBuilder(Class extends QueryNode> queryNodeClass,
+ QueryBuilder builder) {
+ if (this.debug) {
+ super.setBuilder(queryNodeClass, new DebuggingNodeBuilder(queryNodeClass,
+ builder));
+ } else {
+ super.setBuilder(queryNodeClass, builder);
+ }
+ }
+
+ class DebuggingNodeBuilder implements QueryBuilder {
+ private Class extends QueryNode> clazz = null;
+ private QueryBuilder realBuilder = null;
+
+ DebuggingNodeBuilder(Class extends QueryNode> queryNodeClass,
+ QueryBuilder builder) {
+ clazz = queryNodeClass;
+ realBuilder = builder;
+ }
+
+ public Object build(QueryNode queryNode) throws QueryNodeException {
+ System.out.println("--------------------------------------------");
+ System.out.println("step " + counter++ + ".");
+ System.out.println("builder: " + realBuilder.getClass().getName());
+ System.out.println("node: " + clazz.getName());
+ System.out.println(queryNode.toString());
+ System.out.println(" -->");
+ Object result = realBuilder.build(queryNode);
+ if (result != null) {
+ System.out.println(((Query) result).toString() + " <"
+ + result.getClass().getName() + ">");
+ } else {
+ System.out.println("null");
+ }
+ System.out.println("--------------------------------------------");
+ return result;
+ }
+
+ };
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpSlowFuzzyQueryNodeBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpSlowFuzzyQueryNodeBuilder.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpSlowFuzzyQueryNodeBuilder.java (revision 0)
@@ -0,0 +1,26 @@
+package org.apache.lucene.queryparser.flexible.aqp.builders;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.flexible.aqp.nodes.SlowFuzzyQueryNode;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.standard.builders.StandardQueryBuilder;
+import org.apache.lucene.sandbox.queries.SlowFuzzyQuery;
+
+@SuppressWarnings("deprecation")
+public class AqpSlowFuzzyQueryNodeBuilder implements StandardQueryBuilder {
+
+ public AqpSlowFuzzyQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public SlowFuzzyQuery build(QueryNode queryNode) throws QueryNodeException {
+ SlowFuzzyQueryNode fuzzyNode = (SlowFuzzyQueryNode) queryNode;
+
+ return new SlowFuzzyQuery(new Term(fuzzyNode.getFieldAsString(),
+ fuzzyNode.getTextAsString()), fuzzyNode.getSimilarity(),
+ fuzzyNode.getPrefixLength());
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpFieldQueryNodeRegexBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpFieldQueryNodeRegexBuilder.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpFieldQueryNodeRegexBuilder.java (revision 0)
@@ -0,0 +1,26 @@
+package org.apache.lucene.queryparser.flexible.aqp.builders;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.standard.builders.StandardQueryBuilder;
+import org.apache.lucene.search.Query;
+//import org.apache.lucene.sandbox.queries.regex.RegexQuery;
+import org.apache.lucene.search.RegexpQuery;
+
+public class AqpFieldQueryNodeRegexBuilder implements StandardQueryBuilder {
+
+ public AqpFieldQueryNodeRegexBuilder() {
+ // empty constructor
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ FieldQueryNode fieldNode = (FieldQueryNode) queryNode;
+
+ return new RegexpQuery(new Term(fieldNode.getFieldAsString(),
+ fieldNode.getTextAsString()));
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpFieldQueryNodeBuilder.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpFieldQueryNodeBuilder.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/builders/AqpFieldQueryNodeBuilder.java (revision 0)
@@ -0,0 +1,31 @@
+package org.apache.lucene.queryparser.flexible.aqp.builders;
+
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeException;
+import org.apache.lucene.queryparser.flexible.core.nodes.FieldQueryNode;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+import org.apache.lucene.queryparser.flexible.standard.builders.StandardQueryBuilder;
+import org.apache.lucene.search.MatchAllDocsQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.TermQuery;
+
+public class AqpFieldQueryNodeBuilder implements StandardQueryBuilder {
+
+ public AqpFieldQueryNodeBuilder() {
+ // empty constructor
+ }
+
+ public Query build(QueryNode queryNode) throws QueryNodeException {
+ FieldQueryNode fieldNode = (FieldQueryNode) queryNode;
+
+ if (fieldNode.getFieldAsString().equals("*")
+ && fieldNode.getTextAsString().equals("*")) {
+ return new MatchAllDocsQuery();
+ }
+
+ return new TermQuery(new Term(fieldNode.getFieldAsString(),
+ fieldNode.getTextAsString()));
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParserAbstract.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParserAbstract.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParserAbstract.java (revision 0)
@@ -0,0 +1,35 @@
+package org.apache.lucene.queryparser.flexible.aqp;
+
+import org.antlr.runtime.TokenStream;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+
+/**
+ * All ANTLR parsers should subclass {@link AqpSyntaxParser} and
+ * provide two methods:
+ *
+ * {@link AqpSyntaxParser}{@link #getTokenStream(CharSequence)}
+ * {@link AqpSyntaxParser}{@link #parseTokenStream(TokenStream, CharSequence, CharSequence)
+ *
+ * Optionally, the new class can also override
+ *
+ * {@link AqpSyntaxParser}{@link #initializeGrammar(String)
+ *
+ * The default implementation is using reflection and is able
+ * to instantiate any grammar provided that the top parse rule
+ * is called mainQ and that the grammar is producing
+ * AST tree.
+ *
+ */
+public abstract class AqpSyntaxParserAbstract implements AqpSyntaxParser {
+
+ /**
+ * Parse the query and return the {@link QueryNode}. ANTLR will
+ * do the parsing and we return AST.
+ */
+ public QueryNode parse(CharSequence query, CharSequence field)
+ throws QueryNodeParseException {
+ TokenStream tokens = getTokenStream(query);
+ return parseTokenStream(tokens, query, field);
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParserLoadableImpl.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParserLoadableImpl.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/AqpSyntaxParserLoadableImpl.java (revision 0)
@@ -0,0 +1,180 @@
+package org.apache.lucene.queryparser.flexible.aqp;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.Lexer;
+import org.antlr.runtime.Parser;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.TokenSource;
+import org.antlr.runtime.TokenStream;
+import org.antlr.runtime.tree.TreeAdaptor;
+import org.apache.lucene.queryparser.flexible.messages.Message;
+import org.apache.lucene.queryparser.flexible.messages.MessageImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.core.messages.QueryParserMessages;
+import org.apache.lucene.queryparser.flexible.core.nodes.QueryNode;
+
+import org.apache.lucene.queryparser.flexible.aqp.parser.AqpStandardLuceneParser;
+import org.apache.lucene.queryparser.flexible.aqp.util.AqpCommonTree;
+import org.apache.lucene.queryparser.flexible.aqp.util.AqpCommonTreeAdaptor;
+
+/**
+ * This implementation can load any AST grammar from the repository of grammars
+ * without a need to provide a Java implementation. It uses reflection, so it
+ * might be slower than a dedicated parsing class.
+ *
+ * Every grammar must have a top-level rule called mainQ
+ *
+ * And every grammar must return AST.
+ *
+ * If you know that you are going to instantiate specific parser, then
+ * you should not use this generic class.
+ *
+ * @see AqpSyntaxParserAbstract
+ * @see AqpStandardLuceneParser#init()
+ *
+ */
+public class AqpSyntaxParserLoadableImpl extends AqpSyntaxParserAbstract {
+
+ @SuppressWarnings("rawtypes")
+ private Class clsLexer;
+ @SuppressWarnings("rawtypes")
+ private Class clsParser;
+
+ private Object iLexer;
+ private Object iParser;
+
+ private Method invokeMainQ;
+ private Method getTreeMethod;
+ private Method getNumberOfSyntaxErrorsMethod;
+
+ private Lexer lexer;
+ private Parser parser;
+
+ private String[] tokenNames;
+
+ public AqpSyntaxParserLoadableImpl() {
+ // empty constructor
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public AqpSyntaxParser initializeGrammar(String grammarName)
+ throws QueryNodeParseException {
+
+ try {
+ // get the Classes
+ clsLexer = Class
+ .forName("org.apache.lucene.queryparser.flexible.aqp.parser."
+ + grammarName + "Lexer");
+ clsParser = Class
+ .forName("org.apache.lucene.queryparser.flexible.aqp.parser."
+ + grammarName + "Parser");
+
+ // instantiate lexer with no parameter
+ Class partypes[] = new Class[0];
+ // partypes[0] = CharStream.class;
+ Constructor ctLexer = clsLexer.getConstructor(partypes);
+ Object arglist[] = new Object[0];
+ iLexer = ctLexer.newInstance(arglist);
+
+ // instantiate parser using no parameters
+ // ANTLRStringStream fakeInput = new ANTLRStringStream("none");
+ CommonTokenStream fakeTokens = new CommonTokenStream(
+ (TokenSource) clsLexer.cast(iLexer));
+ Class partypes2[] = new Class[1];
+ partypes2[0] = TokenStream.class;
+ Constructor ct = clsParser.getConstructor(partypes2);
+ iParser = ct.newInstance(fakeTokens);
+
+ parser = (Parser) iParser;
+ lexer = (Lexer) iLexer;
+
+ // get tokenNames
+ Method getTokenNames = clsParser.getDeclaredMethod("getTokenNames");
+ tokenNames = (String[]) getTokenNames.invoke(iParser);
+
+ // create adaptor
+ AqpCommonTreeAdaptor adaptor = new AqpCommonTreeAdaptor(tokenNames);
+
+ // set adaptor
+ Method setTreeAdaptor = clsParser.getDeclaredMethod("setTreeAdaptor",
+ TreeAdaptor.class);
+ setTreeAdaptor.invoke(iParser, adaptor);
+
+ // get the mainQ parser rule & return value
+ invokeMainQ = clsParser.getDeclaredMethod("mainQ");
+ getTreeMethod = invokeMainQ.getReturnType().getMethod("getTree");
+ getNumberOfSyntaxErrorsMethod = clsParser
+ .getMethod("getNumberOfSyntaxErrors");
+
+ // AqpCommonTree ast = parseTest("hey:joe");
+
+ return this;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new QueryNodeParseException(e);
+ }
+
+ }
+
+ public TokenStream getTokenStream(CharSequence query) {
+ ANTLRStringStream input = new ANTLRStringStream(query.toString());
+ lexer.setCharStream(input);
+
+ // get tokens
+ CommonTokenStream tokens = new CommonTokenStream(
+ (TokenSource) clsLexer.cast(iLexer));
+ return tokens;
+ }
+
+ public QueryNode parseTokenStream(TokenStream tokens, CharSequence query,
+ CharSequence field) throws QueryNodeParseException {
+
+ // set tokens
+ parser.setTokenStream(tokens);
+
+ // get tree back
+ Object retVal;
+ AqpCommonTree astTree;
+
+ try {
+ retVal = invokeMainQ.invoke(iParser);
+ astTree = (AqpCommonTree) (getTreeMethod.invoke(retVal));
+
+ // this prevents parser from recovering, however it can also interfere
+ // with custom error handling (if present inside the grammar)
+ Object errNo = getNumberOfSyntaxErrorsMethod.invoke(iParser);
+
+ if (errNo instanceof Integer && ((Integer) errNo > 0)) {
+ throw new Error(
+ "The parser reported a syntax error, antlrqueryparser hates errors!");
+ }
+ } catch (Error e) {
+ Message message = new MessageImpl(
+ QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query,
+ e.getMessage());
+ QueryNodeParseException ee = new QueryNodeParseException(e);
+ ee.setQuery(query);
+ ee.setNonLocalizedMessage(message);
+ throw ee;
+ } catch (Exception e) { // TODO: these exceptions are from the code, should
+ // not be printed
+ // e.printStackTrace();
+ QueryNodeParseException ee = new QueryNodeParseException(e);
+ throw ee;
+ }
+
+ try {
+ return astTree.toQueryNodeTree();
+ } catch (RecognitionException e) {
+ throw new QueryNodeParseException(new MessageImpl(query + " >> "
+ + parser.getErrorMessage(e, parser.getTokenNames())));
+ }
+
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/NestedParseException.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/NestedParseException.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/NestedParseException.java (revision 0)
@@ -0,0 +1,32 @@
+package org.apache.lucene.queryparser.flexible.aqp;
+
+/**
+ * This class is used explicitly (and only) for exceptions that happen inside a
+ * QueryParser (AQP). We want to have a mechanism to raise and exception that is
+ * not interfering with existing interfaces. But which is caught by the
+ * {@link AqpAdsabsQueryParser}
+ *
+ *
+ */
+
+public class NestedParseException extends RuntimeException {
+
+ private static final long serialVersionUID = -3943145526662562552L;
+
+ public NestedParseException() {
+ super();
+ }
+
+ public NestedParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public NestedParseException(String string) {
+ super(string);
+ }
+
+ public NestedParseException(Throwable cause) {
+ super(cause);
+ }
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/UnforgivingParser.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/UnforgivingParser.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/UnforgivingParser.java (revision 0)
@@ -0,0 +1,33 @@
+package org.apache.lucene.queryparser.flexible.aqp.parser;
+
+import org.antlr.runtime.BitSet;
+import org.antlr.runtime.IntStream;
+import org.antlr.runtime.MismatchedTokenException;
+import org.antlr.runtime.Parser;
+import org.antlr.runtime.RecognitionException;
+import org.antlr.runtime.RecognizerSharedState;
+import org.antlr.runtime.TokenStream;
+
+public class UnforgivingParser extends Parser {
+
+ public UnforgivingParser(TokenStream input) {
+ super(input);
+ // TODO Auto-generated constructor stub
+ }
+
+ public UnforgivingParser(TokenStream input, RecognizerSharedState state) {
+ super(input, state);
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow)
+ throws RecognitionException
+ {
+ //do not try to recover
+ MismatchedTokenException e = new MismatchedTokenException(ttype, input);
+ throw e;
+ }
+
+
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/AqpStandardLuceneParser.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/AqpStandardLuceneParser.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/AqpStandardLuceneParser.java (revision 0)
@@ -0,0 +1,60 @@
+package org.apache.lucene.queryparser.flexible.aqp.parser;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryparser.flexible.aqp.AqpQueryParser;
+import org.apache.lucene.queryparser.flexible.aqp.AqpSyntaxParserLoadableImpl;
+import org.apache.lucene.queryparser.flexible.core.QueryNodeParseException;
+import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser;
+
+public class AqpStandardLuceneParser {
+
+ /**
+ * Constructs a {@link StandardQueryParser} object. The default grammar used
+ * is "LuceneGrammar" {@see AqpQueryParser#AqpQueryParser(String)}
+ *
+ * @throws Exception
+ */
+
+ public static AqpQueryParser init(String grammarName)
+ throws QueryNodeParseException {
+ return new AqpQueryParser(new AqpStandardQueryConfigHandler(),
+ new AqpSyntaxParserLoadableImpl().initializeGrammar(grammarName),
+ new AqpStandardQueryNodeProcessorPipeline(null),
+ new AqpStandardQueryTreeBuilder());
+ }
+
+ /**
+ * Instantiates {@link StandardLuceneGrammarSyntaxParser}, this method
+ * is using a dedicated parser class, instead of loading the parser
+ * by its grammar name
+ *
+ * @return
+ * @throws QueryNodeParseException
+ */
+ public static AqpQueryParser init() throws QueryNodeParseException {
+ return new AqpQueryParser(new AqpStandardQueryConfigHandler(),
+ new StandardLuceneGrammarSyntaxParser(),
+ new AqpStandardQueryNodeProcessorPipeline(null),
+ new AqpStandardQueryTreeBuilder());
+
+ }
+
+ /**
+ * Constructs a {@link StandardQueryParser} object and sets an
+ * {@link Analyzer} to it. The same as:
+ *
+ *
+ * StandardQueryParser qp = new StandardQueryParser();
+ * qp.getQueryConfigHandler().setAnalyzer(analyzer);
+ *
+ *
+ * @param analyzer
+ * the analyzer to be used by this query parser helper
+ * @throws Exception
+ */
+ public AqpQueryParser init(Analyzer analyzer) throws Exception {
+ AqpQueryParser p = AqpStandardLuceneParser.init("StandardLuceneGrammar");
+ p.setAnalyzer(analyzer);
+ return p;
+ }
+}
Index: lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/AqpStandardQueryConfigHandler.java
===================================================================
--- lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/AqpStandardQueryConfigHandler.java (revision 0)
+++ lucene/queryparser/src/java/org/apache/lucene/queryparser/flexible/aqp/parser/AqpStandardQueryConfigHandler.java (revision 0)
@@ -0,0 +1,126 @@
+package org.apache.lucene.queryparser.flexible.aqp.parser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.queryparser.flexible.core.config.ConfigurationKey;
+import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.standard.config.StandardQueryConfigHandler;
+import org.apache.lucene.queryparser.flexible.standard.processors.PhraseSlopQueryNodeProcessor;
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedback;
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedbackEvent;
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedbackEventHandler;
+import org.apache.lucene.queryparser.flexible.aqp.config.AqpFeedbackImpl;
+import org.apache.lucene.queryparser.flexible.aqp.nodes.AqpFuzzyModifierNode;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpBOOSTProcessor;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpDEFOPProcessor;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpFUZZYProcessor;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpFuzzyModifierProcessor;
+import org.apache.lucene.queryparser.flexible.aqp.processors.AqpQNORMALProcessor;
+
+public class AqpStandardQueryConfigHandler extends StandardQueryConfigHandler {
+
+ final public static class ConfigurationKeys {
+
+ /**
+ * This attribute is used by {@link AqpQNORMALProcessor} processor and must
+ * be defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor what is the default field when no field is defined in a phrase.
+ *
+ */
+ final public static ConfigurationKey DEFAULT_FIELD = ConfigurationKey
+ .newInstance();
+
+ /**
+ * 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.
+ *
+ */
+ final public static ConfigurationKey DEFAULT_PROXIMITY = ConfigurationKey
+ .newInstance();
+
+ /**
+ * This attribute is used by {@link AqpDEFOPProcessor} processor and must be
+ * defined in the {@link QueryConfigHandler}. This attribute tells the
+ * processor what are the allowed values when user submits them.
+ *
+ */
+ final public static ConfigurationKey ALLOWED_PROXIMITY_RANGE = ConfigurationKey
+ .newInstance();
+
+ /**
+ * Value of the default boost, to be used when user specified '^' without a
+ * value
+ *
+ * @see AqpBOOSTProcessor
+ */
+ final public static ConfigurationKey IMPLICIT_BOOST = ConfigurationKey
+ .newInstance();
+
+ /**
+ * This attribute is used to collect feedback messages and suggestions from
+ * the query parser
+ *
+ * @see AqpFeedback#registerEventHandler(AqpFeedbackEventHandler)
+ * @see AqpFeedback#sendEvent(AqpFeedbackEvent)
+ */
+ final public static ConfigurationKey FEEDBACK = ConfigurationKey
+ .newInstance();
+
+ /**
+ * Default fuzzy value when user specified only 'term~'
+ *
+ * @see AqpFUZZYProcessor
+ * @see AqpFuzzyModifierNode
+ * @see AqpFuzzyModifierProcessor
+ */
+ final public static ConfigurationKey IMPLICIT_FUZZY = ConfigurationKey
+ .newInstance();
+
+ /**
+ * Allow to use the old-style 0.0-1.0f fuzzy value and let it be handled by
+ * the SlowFuzzyQuery
+ *
+ * @see AqpFuzzyModifierProcessor
+ *
+ */
+ final public static ConfigurationKey ALLOW_SLOW_FUZZY = ConfigurationKey
+ .newInstance();
+
+ /**
+ * Translation mapping for index names
+ */
+ final public static ConfigurationKey