Index: src/java/org/apache/lucene/queryParser/QueryParser.jj
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.jj	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/QueryParser.jj	(working copy)
@@ -119,7 +119,10 @@
  * use a different method for date conversion.
  * </p>
  *
- * <p>Note that QueryParser is <em>not</em> thread-safe.</p>
+ * <p>Note that QueryParser is <em>not</em> thread-safe.</p> 
+ *
+ * @deprecated use new the flexible query parser instead
+ *
  */
 public class QueryParser {
 
Index: src/java/org/apache/lucene/queryParser/ParseException.java
===================================================================
--- src/java/org/apache/lucene/queryParser/ParseException.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/ParseException.java	(working copy)
@@ -10,6 +10,9 @@
  *
  * You can modify this class to customize your error reporting
  * mechanisms so long as you retain the public fields.
+ * 
+ * @deprecated use new the flexible query parser instead: {@link org.apache.lucene.queryParser.original.parser.ParseException}
+ * 
  */
 public class ParseException extends Exception {
 
Index: src/java/org/apache/lucene/queryParser/QueryParserConstants.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParserConstants.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/QueryParserConstants.java	(working copy)
@@ -5,6 +5,9 @@
 /**
  * Token literal values and constants.
  * Generated by org.javacc.parser.OtherFilesGen#start()
+ *
+ * @deprecated use new the flexible query parser instead: {@link org.apache.lucene.queryParser.original.parser.QueryParserConstants}
+ * 
  */
 public interface QueryParserConstants {
 
Index: src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/ComplexPhraseQueryParser.java	(working copy)
@@ -53,8 +53,8 @@
  * 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/*<ComplexPhraseQuery>*/complexPhrases = null;
Index: src/java/org/apache/lucene/queryParser/TokenMgrError.java
===================================================================
--- src/java/org/apache/lucene/queryParser/TokenMgrError.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/TokenMgrError.java	(working copy)
@@ -2,7 +2,11 @@
 /* JavaCCOptions: */
 package org.apache.lucene.queryParser;
 
-/** Token Manager Error. */
+/** Token Manager Error. 
+ *
+ * @deprecated use new the flexible query parser instead: {@link org.apache.lucene.queryParser.original.parser.TokenMgrError}
+ *
+ */
 public class TokenMgrError extends Error
 {
 
Index: src/java/org/apache/lucene/queryParser/Token.java
===================================================================
--- src/java/org/apache/lucene/queryParser/Token.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/Token.java	(working copy)
@@ -4,6 +4,9 @@
 
 /**
  * Describes the input token stream.
+ * 
+ * @deprecated use new the flexible query parser instead: {@link org.apache.lucene.queryParser.original.parser.Token}
+ * 
  */
 
 public class Token {
Index: src/java/org/apache/lucene/queryParser/CharStream.java
===================================================================
--- src/java/org/apache/lucene/queryParser/CharStream.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/CharStream.java	(working copy)
@@ -15,6 +15,8 @@
  * 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 {
Index: src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java	(working copy)
@@ -33,7 +33,11 @@
 import org.apache.lucene.search.WildcardQuery;
 import org.apache.lucene.util.Parameter;
 
-/** Token Manager. */
+/** Token Manager. 
+ *
+ * @deprecated use new the flexible query parser instead
+ * 
+ */
 public class QueryParserTokenManager implements QueryParserConstants
 {
 
Index: src/java/org/apache/lucene/queryParser/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/package.html	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/package.html	(working copy)
@@ -20,6 +20,8 @@
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 </head>
 <body>
+NOTE: Please look into lucene contrib/queryparser for the new flexible queryparser api.
+
 A simple query parser implemented with JavaCC.
 <p>Note that JavaCC defines lots of public classes, methods and fields
 that do not need to be public.&nbsp; These clutter the documentation.&nbsp;
Index: src/java/org/apache/lucene/queryParser/FastCharStream.java
===================================================================
--- src/java/org/apache/lucene/queryParser/FastCharStream.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/FastCharStream.java	(working copy)
@@ -16,6 +16,7 @@
  * 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 @@
 /** An efficient implementation of JavaCC's CharStream interface.  <p>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;
 
Index: src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java	(working copy)
@@ -20,7 +20,6 @@
 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;
@@ -31,7 +30,13 @@
 
 /**
  * A QueryParser which constructs queries to search multiple fields.
- *
+ * 
+ * @deprecated This class will be removed in Lucene 3.0, {@link LuceneQueryParserHelper} should be used instead, 
+ * 				which is currently in queryparser contrib. The static methods can be found in {@link QueryParserUtil} class.
+ * 
+ * @see LuceneQueryParserHelper
+ * @see LuceneQueryConfigHandler#setMultiFields(CharSequence[])
+ * @see LuceneQueryConfigHandler#setFieldsBoost(Map)
  *
  * @version $Revision$
  */
Index: src/java/org/apache/lucene/queryParser/QueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.java	(revision 797318)
+++ src/java/org/apache/lucene/queryParser/QueryParser.java	(working copy)
@@ -96,6 +96,9 @@
  * </p>
  *
  * <p>Note that QueryParser is <em>not</em> thread-safe.</p>
+ * 
+ * @deprecated This class will be removed in Lucene 3.0, {@link LuceneQueryParserHelper} should be used instead, 
+ * 				which is currently in queryparser contrib. The method {@link #escape(String)} was moved to {@link QueryParserUtil} class.
  */
 public class QueryParser implements QueryParserConstants {
 
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/config/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/config/package.html	(revision 0)
@@ -0,0 +1,48 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Query Configuration Interfaces</h2>
+<p>
+The package <tt>org.apache.lucene.queryParser.config</tt> contains query configuration handler
+abstract class that all config handlers should extend.
+</p>
+<p>
+See {@link org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler} for a reference
+implementation.
+</p>
+<p>
+{@link org.apache.lucene.queryParser.config.FieldConfig} and {@link org.apache.lucene.queryParser.config.Queryconfig}
+ should use {@link org.apache.lucene.util.Attribute} to store all attributes
+required by the config implementation. See <tt>org.apache.lucene.queryParser.original.config.*Attribute</tt>
+for reference implementation.
+</p>
+<p>
+The {@link org.apache.lucene.queryParser.config.QueryConfigHandler}, {@link org.apache.lucene.queryParser.config.FieldConfig},
+ and {@link org.apache.lucene.util.Attribute}s are used in the processors to access config
+information in a flexible and independent way.
+See {@link org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor} for a 
+reference implementation.
+</p>
+</body>
+</html
+

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java	(revision 0)
@@ -0,0 +1,55 @@
+package org.apache.lucene.queryParser.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.processors.QueryNodeProcessor;
+import org.apache.lucene.util.Attribute;
+import org.apache.lucene.util.AttributeSource;
+
+/**
+ * {@link QueryConfigHandler} should be implemented by classes that intends to
+ * provide configuration to {@link QueryNodeProcessor} objects.
+ * 
+ * This class extends {@link AttributeSource}, so {@link Attribute}s can be
+ * attached to it.
+ * 
+ * The class that implements this class should also provides {@link FieldConfig}
+ * objects for each collection field.
+ * 
+ * @see Attribute
+ * @see FieldConfig
+ * @see FieldConfigListener
+ */
+public abstract class QueryConfigHandler extends AttributeSource {
+
+  /**
+   * The class that implements this method should return an implementation of
+   * {@link FieldConfig} for a specific field name. If the implemented
+   * {@link QueryConfigHandler} does not know a specific field name, it may
+   * return <code>null</code>, indicating there is no configuration for that
+   * field.
+   * 
+   * @param fieldName
+   *          the field name
+   * @return a {@link FieldConfig} object containing the field name
+   *         configuration or <code>null</code>, if the implemented
+   *         {@link QueryConfigHandler} has no configuration for that field
+   */
+  public abstract FieldConfig getFieldConfig(CharSequence fieldName);
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfig.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfig.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfig.java	(revision 0)
@@ -0,0 +1,60 @@
+package org.apache.lucene.queryParser.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.util.AttributeSource;
+
+/**
+ * This class represents a field configuration. Every configuration should be
+ * set using the methods inherited from {@link AttributeSource}.
+ * 
+ * @see QueryConfigHandler
+ * @see org.apache.lucene.util.Attribute
+ */
+public class FieldConfig extends AttributeSource {
+
+  private CharSequence fieldName;
+
+  /**
+   * Constructs a {@link FieldConfig}
+   * 
+   * @param fieldName
+   *          the field name, it cannot be null
+   * @throws IllegalArgumentException
+   *           if the field name is null
+   */
+  public FieldConfig(CharSequence fieldName) {
+
+    if (fieldName == null) {
+      throw new IllegalArgumentException("field name should not be null!");
+    }
+
+    this.fieldName = fieldName;
+
+  }
+
+  /**
+   * Returns the field name this configuration represents.
+   * 
+   * @return the field name
+   */
+  public CharSequence getFieldName() {
+    return this.fieldName;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfig.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfigListener.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfigListener.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfigListener.java	(revision 0)
@@ -0,0 +1,21 @@
+package org.apache.lucene.queryParser.config;
+
+/**
+ * This interface should be implemented by classes that wants to listen for
+ * field configuration requests. The implementation receives a
+ * {@link FieldConfig} object and may add/change its attributes.
+ * 
+ * @see FieldConfig
+ * @see QueryConfigHandler
+ */
+public interface FieldConfigListener {
+
+  /**
+   * This method is called ever time a field configuration is requested.
+   * 
+   * @param fieldConfig
+   *          the field configuration requested, should never be null
+   */
+  void getQueryConfig(FieldConfig fieldConfig);
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/FieldConfigListener.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/DefaultQueryConfigHandler.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/config/DefaultQueryConfigHandler.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/config/DefaultQueryConfigHandler.java	(revision 0)
@@ -0,0 +1,42 @@
+package org.apache.lucene.queryParser.config;
+
+import java.util.LinkedList;
+
+/**
+ * This class can be used to hold any query configuration and no field
+ * configuration. For field configuration, it creates a empty
+ * {@link FieldConfig} object and delegate it to field config listeners, they
+ * are responsible for setting up all the field configuration.
+ * 
+ * @see FieldConfigListener
+ * @see FieldConfig
+ * @see QueryConfigHandler
+ */
+public class DefaultQueryConfigHandler extends QueryConfigHandler {
+
+  private LinkedList<FieldConfigListener> listeners = new LinkedList<FieldConfigListener>();;
+
+  @Override
+  public FieldConfig getFieldConfig(CharSequence fieldName) {
+    FieldConfig fieldConfig = new FieldConfig(fieldName);
+
+    for (FieldConfigListener listener : this.listeners) {
+      listener.getQueryConfig(fieldConfig);
+    }
+
+    return fieldConfig;
+
+  }
+
+  /**
+   * Adds a listener. The added listeners are called in the order they are
+   * added.
+   * 
+   * @param listener
+   *          the listener to be added
+   */
+  public void addFieldConfigListener(FieldConfigListener listener) {
+    this.listeners.add(listener);
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/config/DefaultQueryConfigHandler.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html	(revision 0)
@@ -0,0 +1,129 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Flexible Query Parser</h2>
+<p>
+Features:
+    <ol>
+        <li>Full support for lucene 2.4.2 syntax</li>
+        <li>Full support for boolean logic (not enabled)</li>
+        <li>QueryNode Trees - support for several syntaxes, 
+            that are convert into similar syntax QueryNode trees.</li>
+        <li>QueryNode Processors - Optimize, validate, rewrite the 
+            QueryNode trees</li>
+		<li>Processors Pipelines - Select your favorite Processor
+		    and build a processor pipeline, to implement the features you need</li>
+        <li>Config Interfaces - Allow the consumer of the Query Parser to implement
+            a diff Config Handler Objects to suite their needs.</li>
+        <li>Original Lucene Builders - convert queries into several lucene 
+            representations. supported conversion is using a 2.4 compatible logic</li>                       
+    </ol>
+</p>
+
+<tt>
+<p>
+This new query parser was designed to have very generic
+architecture, so that this query parser can be easily used for different
+products with varying query syntaxes. This code is much more 
+flexible and extensible than the current Lucene query parser.
+</p>
+<p>
+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.
+</p>
+<p>
+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':
+</p>
+<p>
+  AND<br/>
+ /   \<br/>
+A     B<br/>
+</p>
+<p>
+The three layers are:<br/>
+1. QueryParser<br/>
+2. QueryNodeProcessor<br/>
+3. QueryBuilder<br/>
+</p>
+<p>
+1. The upper layer is the text parsing layer which simply transforms the
+query text string into a {@link org.apache.lucene.queryParser.nodes.QueryNode} tree. Every text parser
+must implement the interface {@link org.apache.lucene.queryParser.parser.Parser}, Lucene default implementations
+implements it using JavaCC.
+</p>
+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.
+</p>
+<p>
+3. The third layer is a configurable map of builders, which map {@link QueryNode} types to its specific 
+builder that will transform the QueryNode into Lucene Query object.
+</p>
+<p>
+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.
+</p>
+<p>
+This design allows to develop different query syntaxes very quickly.
+</p>
+<p>
+A Lucene-compatible syntax is implemented using this new query parser
+API and is located under org.apache.lucene.queryParser.original.
+<p>
+To make it simpler to use the new query parser, specially for people that does not
+want to extend it, the class {@link org.apache.lucene.queryParser.original.LuceneQueryParserHelper} 
+may be helpful. 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.LuceneQueryParserHelper} usage:
+<ul>
+LuceneQueryParserHelper qpHelper = new LuceneQueryParserHelper();
+
+<br/><br/>
+LuceneQueryConfigHandler config =  qpHelper.getQueryConfigHandler();
+<br/><br/>
+config.setAllowLeadingWildcard(true);
+<br/><br/>
+config.setAnalyzer(new WhitespaceAnalyzer());
+<br/><br/>
+Query query = qpHelper.parse("apache AND lucene", "defaultField");
+</ul>
+To make it easy for people who are using current Lucene's query parser to switch to
+the new one, there is a QueryParserWrapper under org.apache.lucene.queryParser.original
+that keeps the old query parser interface, but uses the new query parser features.
+</p>
+</p>
+</tt>
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeError.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeError.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeError.java	(revision 0)
@@ -0,0 +1,75 @@
+package org.apache.lucene.queryParser;
+
+/**
+ * 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.NLSException;
+
+/**
+ * Error class with NLS support
+ * 
+ * @see org.apache.lucene.messages.NLS
+ * @see org.apache.lucene.messages.Message
+ */
+public class QueryNodeError extends Error implements NLSException {
+
+  private static final long serialVersionUID = 1804855832182710327L;
+  private Message message;
+
+  /**
+   * @param message
+   *          - NLS Message Object
+   */
+  public QueryNodeError(Message message) {
+    super(message.getKey());
+
+    this.message = message;
+
+  }
+
+  /**
+   * @param throwable
+   *          - @see java.lang.Error
+   */
+  public QueryNodeError(Throwable throwable) {
+    super(throwable);
+  }
+
+  /**
+   * @param message
+   *          - NLS Message Object
+   * @param throwable
+   *          - @see java.lang.Error
+   */
+  public QueryNodeError(Message message, Throwable throwable) {
+    super(message.getKey(), throwable);
+
+    this.message = message;
+
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.lucene.messages.NLSException#getMessageObject()
+   */
+  public Message getMessageObject() {
+    return this.message;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeError.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryParserHelper.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryParserHelper.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryParserHelper.java	(revision 0)
@@ -0,0 +1,261 @@
+package org.apache.lucene.queryParser;
+
+/**
+ * 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.builders.QueryBuilder;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.parser.Parser;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessor;
+
+/**
+ * <p>
+ * This class is a helper for the query parser framework, it does all the three
+ * query parser phrases at once: text parsing, query processing and query
+ * building.
+ * </p>
+ * <p>
+ * It contains methods that allows the user to change the implementation used on
+ * the three phases.
+ * </p>
+ * 
+ * @see QueryNodeProcessor
+ * @see Parser
+ * @see QueryBuilder
+ * @see QueryConfigHandler
+ */
+public class QueryParserHelper<C extends QueryConfigHandler, T extends Parser, P extends QueryNodeProcessor, B extends QueryBuilder> {
+
+  private P processor;
+
+  private T textParser;
+
+  private B queryBuilder;
+
+  private C config;
+
+  /**
+   * Creates a query parser helper object using the specified configuration,
+   * text parser, processor and builder.
+   * 
+   * @param queryConfigHandler
+   *          the query configuration handler that will be initially set to this
+   *          helper
+   * @param textParser
+   *          the text parser that will be initially set to this helper
+   * @param processor
+   *          the query processor that will be initially set to this helper
+   * @param builder
+   *          the query builder that will be initially set to this helper
+   * 
+   * @see QueryNodeProcessor
+   * @see Parser
+   * @see QueryBuilder
+   * @see QueryConfigHandler
+   */
+  public QueryParserHelper(C queryConfigHandler, T textParser, P processor,
+      B builder) {
+    this.textParser = textParser;
+    this.config = queryConfigHandler;
+    this.processor = processor;
+    this.queryBuilder = builder;
+
+    if (processor != null) {
+      processor.setQueryConfigHandler(queryConfigHandler);
+    }
+
+  }
+
+  /**
+   * Returns the processor object used to process the query node tree, it
+   * returns <code>null</code> if no processor is used.
+   * 
+   * @return the actual processor used to process the query node tree,
+   *         <code>null</code> if no processor is used
+   * 
+   * @see QueryNodeProcessor
+   * @see #setQueryNodeProcessor(QueryNodeProcessor)
+   */
+  public P getQueryNodeProcessor() {
+    return processor;
+  }
+
+  /**
+   * Sets the processor that will be used to process the query node tree. If
+   * there is any {@link QueryConfigHandler} returned by
+   * {@link #getQueryConfigHandler()}, it will be set on the processor. The
+   * argument can be <code>null</code>, which means that no processor will be
+   * used to process the query node tree.
+   * 
+   * @param processor
+   *          the processor that will be used to process the query node tree,
+   *          this argument can be <code>null</code>
+   * 
+   * @see #getQueryNodeProcessor()
+   * @see QueryNodeProcessor
+   */
+  public void setQueryNodeProcessor(P processor) {
+    this.processor = processor;
+    this.processor.setQueryConfigHandler(getQueryConfigHandler());
+
+  }
+
+  /**
+   * Sets the text parser that will be used to parse the query string, it cannot
+   * be <code>null</code>.
+   * 
+   * @param textParser
+   *          the text parser that will be used to parse the query string
+   * 
+   * @see #getTextParser()
+   * @see Parser
+   */
+  public void setTextParser(T textParser) {
+
+    if (textParser == null) {
+      throw new IllegalArgumentException("textParser should not be null!");
+    }
+
+    this.textParser = textParser;
+
+  }
+
+  /**
+   * The query builder that will be used to build an object from the query node
+   * tree. It cannot be <code>null</code>.
+   * 
+   * @param queryBuilder
+   *          the query builder used to build something from the query node tree
+   * 
+   * @see #getQueryBuilder()
+   * @see QueryBuilder
+   */
+  public void setQueryBuilder(B queryBuilder) {
+
+    if (queryBuilder == null) {
+      throw new IllegalArgumentException("queryBuilder should not be null!");
+    }
+
+    this.queryBuilder = queryBuilder;
+
+  }
+
+  /**
+   * Returns the query configuration handler, which is used during the query
+   * node tree processing. It can be <code>null</code>.
+   * 
+   * @return the query configuration handler used on the query processing,
+   *         <code>null</code> if not query configuration handler is defined
+   * 
+   * @see QueryConfigHandler
+   * @see #setQueryConfigHandler(QueryConfigHandler)
+   */
+  public C getQueryConfigHandler() {
+    return config;
+  }
+
+  /**
+   * Returns the query builder used to build a object from the query node tree.
+   * The object produced by this builder is returned by
+   * {@link #parse(String, String)}.
+   * 
+   * @return the query builder
+   * 
+   * @see #setQueryBuilder(QueryBuilder)
+   * @see QueryBuilder
+   */
+  public B getQueryBuilder() {
+    return this.queryBuilder;
+  }
+
+  /**
+   * Returns the text parser used to build a query node tree from a query
+   * string. The default text parser instance returned by this method is a
+   * {@link Parser}.
+   * 
+   * @return the text parse used to build query node trees.
+   * 
+   * @see Parser
+   * @see #setTextParser(Parser)
+   */
+  public T getTextParser() {
+    return this.textParser;
+  }
+
+  /**
+   * Sets the query configuration handler that will be used during query
+   * processing. It can be <code>null</code>. It's also set to the processor
+   * returned by {@link #getQueryNodeProcessor()}.
+   * 
+   * @param config
+   *          the query configuration handler used during query processing, it
+   *          can be <code>null</code>
+   * 
+   * @see #getQueryConfigHandler()
+   * @see QueryConfigHandler
+   */
+  public void setQueryConfigHandler(C config) {
+    this.config = config;
+    QueryNodeProcessor processor = getQueryNodeProcessor();
+
+    if (processor != null) {
+      processor.setQueryConfigHandler(config);
+    }
+
+  }
+
+  /**
+   * Parses a query string to an object, usually some query object. <br/>
+   * <br/>
+   * In this method the three phases are executed: <br/>
+   * <br/>
+   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1st - the query string is parsed using the
+   * text parser returned by {@link #getTextParser()}, the result is a query
+   * node tree <br/>
+   * <br/>
+   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2nd - the query node tree is processed by the
+   * processor returned by {@link #getQueryNodeProcessor()} <br/>
+   * <br/>
+   * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3th - a object is built from the query node
+   * tree using the builder returned by {@link #getQueryBuilder()}
+   * 
+   * @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
+   */
+  public Object parse(String query, String defaultField)
+      throws QueryNodeException {
+    QueryNode queryTree = getTextParser().parse(query, defaultField);
+
+    QueryNodeProcessor processor = getQueryNodeProcessor();
+
+    if (processor != null) {
+      queryTree = processor.process(queryTree);
+    }
+
+    return getQueryBuilder().build(queryTree);
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryParserHelper.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties	(revision 0)
@@ -0,0 +1,45 @@
+# This resource bundle contains Flexible Query Parser messages.
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+#  <REPLACEMENT arg="{0}" value="detailed_message"/>
+INVALID_SYNTAX = Syntax Error: {0}
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+#  <REPLACEMENT arg="{0}" value="invalid_query"/>
+#  <REPLACEMENT arg="{1}" value="detailed_message"/>
+INVALID_SYNTAX_CANNOT_PARSE = Syntax Error, cannot parse {0}: {1} 
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+INVALID_SYNTAX_FUZZY_LIMITS = The similarity value for a fuzzy search must be between 0.0 and 1.0.
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION = Truncated unicode escape sequence.
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+INVALID_SYNTAX_ESCAPE_CHARACTER = Term can not end with escape character.
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE = None-hex character in unicode escape sequence: {0}
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+NODE_ACTION_NOT_SUPPORTED = This node does not support this action.
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+PARAMETER_VALUE_NOT_SUPPORTED = Parameter {1} with value {0} not supported.
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+#  <REPLACEMENT arg="{0}" value="query"/>
+#  <REPLACEMENT arg="{1}" value="error/class"/>
+LUCENE_QUERY_CONVERSION_ERROR = Cannot convert query to lucene syntax: {0} error: {1}
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+EMPTY_MESSAGE = 
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+WILDCARD_NOT_SUPPORTED = Wildcard is not supported for query: {0} 
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+TOO_MANY_BOOLEAN_CLAUSES = Too many boolean clauses, the maximum supported is {0}: {1}
+
+#<CREATEDBY>Apache Lucene Community</CREATEDBY>
+LEADING_WILDCARD_NOT_ALLOWED = Leading wildcard is not allowed: {0}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java	(revision 0)
@@ -0,0 +1,54 @@
+package org.apache.lucene.queryParser.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 org.apache.lucene.messages.NLS;
+
+/**
+ * Flexible Query Parser message bundle class
+ */
+public class QueryParserMessages extends NLS {
+
+  private static final String BUNDLE_NAME = QueryParserMessages.class.getName();
+
+  private QueryParserMessages() {
+    // Do not instantiate
+  }
+
+  static {
+    // register all string ids with NLS class and initialize static string
+    // values
+    NLS.initializeMessages(BUNDLE_NAME, QueryParserMessages.class);
+  }
+
+  // static string must match the strings in the property files.
+  public static String INVALID_SYNTAX;
+  public static String INVALID_SYNTAX_CANNOT_PARSE;
+  public static String INVALID_SYNTAX_FUZZY_LIMITS;
+  public static String INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION;
+  public static String INVALID_SYNTAX_ESCAPE_CHARACTER;
+  public static String INVALID_SYNTAX_ESCAPE_NONE_HEX_UNICODE;
+  public static String NODE_ACTION_NOT_SUPPORTED;
+  public static String PARAMETER_VALUE_NOT_SUPPORTED;
+  public static String LUCENE_QUERY_CONVERSION_ERROR;
+  public static String EMPTY_MESSAGE;
+  public static String WILDCARD_NOT_SUPPORTED;
+  public static String TOO_MANY_BOOLEAN_CLAUSES;
+  public static String LEADING_WILDCARD_NOT_ALLOWED;
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/package.html	(revision 0)
@@ -0,0 +1,25 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+Messages for the Flexible Query Parser, they use <tt>org.apache.lucene.messages.NLS</tt> API.
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/messages/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java	(revision 0)
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * This interface is used by implementors classes that builds some kind of
+ * object from a query tree.
+ * 
+ * @see QueryTreeBuilder
+ */
+public interface QueryBuilder {
+
+  /**
+   * Builds some kind of object from a query tree.
+   * 
+   * @param queryNode
+   *          the query tree root node
+   * 
+   * @return some object generated from the query tree
+   * 
+   * @throws QueryNodeException
+   */
+  Object build(QueryNode queryNode) throws QueryNodeException;
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/package.html	(revision 0)
@@ -0,0 +1,33 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Query Parser Builders</h2>
+<p>
+The package <tt>org.apache.lucene.queryParser.builders</tt> contains the interface that
+builders must implement, it also contain a utility {@link org.apache.lucene.queryParser.builders.QueryTreeBuilder}, which walks the tree
+and call the Builder for each node in the tree.
+</p>
+<p>
+</p>
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java	(revision 0)
@@ -0,0 +1,222 @@
+package org.apache.lucene.queryParser.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.HashMap;
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.FieldableNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+
+/**
+ * This class should be used when there is a builder for each type of node.
+ * 
+ * The type of node may be defined in 2 different ways: - by the field name,
+ * when the node implements the {@link FieldableNode} interface - by its class,
+ * it keeps checking the class and all the interfaces and classes this class
+ * implements/extends until it finds a builder for that class/interface
+ * 
+ * This class always check if there is a builder for the field name before it
+ * checks for the node class. So, field name builders have precedence over class
+ * builders.
+ * 
+ * When a builder is found for a node, it's called and the node is passed to the
+ * builder. If the returned built object is not <code>null</code>, it's tagged
+ * on the node using the tag {@link QueryTreeBuilder#QUERY_TREE_BUILDER_TAGID}.
+ * 
+ * The children are usually built before the parent node. However, if a builder
+ * associated to a node is an instance of {@link QueryTreeBuilder}, the node is
+ * delegated to this builder and it's responsible to build the node and its
+ * children.
+ * 
+ * @see QueryBuilder
+ */
+public class QueryTreeBuilder implements QueryBuilder {
+
+  /**
+   * This tag is used to tag the nodes in a query tree with the built objects
+   * produced from their own associated builder.
+   */
+  public static final String QUERY_TREE_BUILDER_TAGID = QueryTreeBuilder.class
+      .getName();
+
+  private HashMap<Class<? extends QueryNode>, QueryBuilder> queryNodeBuilders;
+
+  private HashMap<CharSequence, QueryBuilder> fieldNameBuilders;
+
+  /**
+   * {@link QueryTreeBuilder} constructor.
+   */
+  public QueryTreeBuilder() {
+    // empty constructor
+  }
+
+  /**
+   * Associates a field name with a builder.
+   * 
+   * @param fieldName
+   *          the field name
+   * @param builder
+   *          the builder to be associated
+   */
+  public void setBuilder(CharSequence fieldName, QueryBuilder builder) {
+
+    if (this.fieldNameBuilders == null) {
+      this.fieldNameBuilders = new HashMap<CharSequence, QueryBuilder>();
+    }
+
+    this.fieldNameBuilders.put(fieldName, builder);
+
+  }
+
+  /**
+   * Associates a class with a builder
+   * 
+   * @param queryNodeClass
+   *          the class
+   * @param builder
+   *          the builder to be associated
+   */
+  public void setBuilder(Class<? extends QueryNode> queryNodeClass,
+      QueryBuilder builder) {
+
+    if (this.queryNodeBuilders == null) {
+      this.queryNodeBuilders = new HashMap<Class<? extends QueryNode>, QueryBuilder>();
+    }
+
+    this.queryNodeBuilders.put(queryNodeClass, builder);
+
+  }
+
+  private void process(QueryNode node) throws QueryNodeException {
+
+    if (node != null) {
+      QueryBuilder builder = getBuilder(node);
+
+      if (!(builder instanceof QueryTreeBuilder)) {
+        List<QueryNode> children = node.getChildren();
+
+        if (children != null) {
+
+          for (QueryNode child : children) {
+            process(child);
+          }
+
+        }
+
+      }
+
+      processNode(node, builder);
+
+    }
+
+  }
+
+  private QueryBuilder getBuilder(QueryNode node) {
+    QueryBuilder builder = null;
+
+    if (this.fieldNameBuilders != null && node instanceof FieldableNode) {
+
+      builder = this.fieldNameBuilders.get(((FieldableNode) node).getField());
+
+    }
+
+    if (builder == null && this.queryNodeBuilders != null) {
+
+      Class<?> clazz = node.getClass();
+
+      do {
+        builder = getQueryBuilder(clazz);
+
+        if (builder == null) {
+          Class<?>[] classes = node.getClass().getInterfaces();
+
+          for (Class<?> actualClass : classes) {
+            builder = getQueryBuilder(actualClass);
+
+            if (builder != null) {
+              break;
+            }
+
+          }
+
+        }
+
+      } while (builder == null && (clazz = clazz.getSuperclass()) != null);
+
+    }
+
+    return builder;
+
+  }
+
+  private void processNode(QueryNode node, QueryBuilder builder)
+      throws QueryNodeException {
+
+    if (builder == null) {
+
+      throw new QueryNodeException(new MessageImpl(
+          QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, node
+              .toQueryString(new EscapeQuerySyntaxImpl()), node.getClass()
+              .getName()));
+
+    }
+
+    Object obj = builder.build(node);
+
+    if (obj != null) {
+      node.setTag(QUERY_TREE_BUILDER_TAGID, obj);
+    }
+
+  }
+
+  private QueryBuilder getQueryBuilder(Class<?> clazz) {
+
+    if (QueryNode.class.isAssignableFrom(clazz)) {
+      return this.queryNodeBuilders.get(clazz);
+    }
+
+    return null;
+
+  }
+
+  /**
+   * Builds some kind of object from a query tree. Each node in the query tree
+   * is built using an specific builder associated to it.
+   * 
+   * @param queryNode
+   *          the query tree root node
+   * 
+   * @return the built object
+   * 
+   * @throws QueryNodeException
+   *           if some node builder throws a {@link QueryNodeException} or if
+   *           there is a node which had no builder associated to it
+   */
+  public Object build(QueryNode queryNode) throws QueryNodeException {
+    process(queryNode);
+
+    return queryNode.getTag(QUERY_TREE_BUILDER_TAGID);
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeParseException.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeParseException.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeParseException.java	(revision 0)
@@ -0,0 +1,121 @@
+package org.apache.lucene.queryParser;
+
+/**
+ * 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.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.parser.Parser;
+
+/**
+ * This should be thrown when an exception happens during the query parsing from
+ * string to the query node tree.
+ * 
+ * @see QueryNodeException
+ * @see Parser
+ * @see QueryNode
+ */
+public class QueryNodeParseException extends QueryNodeException {
+
+  private static final long serialVersionUID = 8197535103538766773L;
+
+  private CharSequence query;
+
+  private int beginColumn = -1;
+
+  private int beginLine = -1;
+
+  private String errorToken = "";
+
+  public QueryNodeParseException(Message message) {
+    super(message);
+  }
+
+  public QueryNodeParseException(Throwable throwable) {
+    super(throwable);
+  }
+
+  public QueryNodeParseException(Message message, Throwable throwable) {
+    super(message, throwable);
+  }
+
+  public void setQuery(CharSequence query) {
+    this.query = query;
+    this.message = new MessageImpl(
+        QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, "");
+  }
+
+  public CharSequence getQuery() {
+    return this.query;
+  }
+
+  /**
+   * @param errorToken
+   *          the errorToken in the query
+   */
+  protected void setErrorToken(String errorToken) {
+    this.errorToken = errorToken;
+  }
+
+  public String getErrorToken() {
+    return this.errorToken;
+  }
+
+  public void setNonLocalizedMessage(Message message) {
+    this.message = message;
+  }
+
+  /**
+   * For EndOfLine and EndOfFile ("<EOF>") parsing problems the last char in the
+   * string is returned For the case where the parser is not able to figure out
+   * the line and column number -1 will be returned
+   * 
+   * @return line where the problem was found
+   */
+  public int getBeginLine() {
+    return this.beginLine;
+  }
+
+  /**
+   * For EndOfLine and EndOfFile ("<EOF>") parsing problems the last char in the
+   * string is returned For the case where the parser is not able to figure out
+   * the line and column number -1 will be returned
+   * 
+   * @return column of the first char where the problem was found
+   */
+  public int getBeginColumn() {
+    return this.beginColumn;
+  }
+
+  /**
+   * @param beginLine
+   *          the beginLine to set
+   */
+  protected void setBeginLine(int beginLine) {
+    this.beginLine = beginLine;
+  }
+
+  /**
+   * @param beginColumn
+   *          the beginColumn to set
+   */
+  protected void setBeginColumn(int beginColumn) {
+    this.beginColumn = beginColumn;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeParseException.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java	(revision 0)
@@ -0,0 +1,141 @@
+package org.apache.lucene.queryParser.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();
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/util/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/util/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/util/package.html	(revision 0)
@@ -0,0 +1,25 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+<p>Utility classes to used with the Query Parser</p>
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/util/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/util/QueryNodeOperation.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/util/QueryNodeOperation.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/util/QueryNodeOperation.java	(revision 0)
@@ -0,0 +1,94 @@
+package org.apache.lucene.queryParser.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.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * Allow joining 2 QueryNode Trees, into one.
+ */
+public final class QueryNodeOperation {
+  private QueryNodeOperation() {
+    // Exists only to defeat instantiation.
+  }
+
+  private enum ANDOperation {
+    BOTH, Q1, Q2, NONE
+  }
+
+  /**
+   * perform a logical and of 2 QueryNode trees. if q1 and q2 are ANDQueryNode
+   * nodes it uses head Node from q1 and adds the children of q2 to q1 if q1 is
+   * a AND node and q2 is not, add q2 as a child of the head node of q1 if q2 is
+   * a AND node and q1 is not, add q1 as a child of the head node of q2 if q1
+   * and q2 are not ANDQueryNode nodes, create a AND node and make q1 and q2
+   * children of that node if q1 or q2 is null it returns the not null node if
+   * q1 = q2 = null it returns null
+   */
+  public final static QueryNode logicalAnd(QueryNode q1, QueryNode q2) {
+    if (q1 == null)
+      return q2;
+    if (q2 == null)
+      return q1;
+
+    ANDOperation op = null;
+    if (q1 instanceof AndQueryNode && q2 instanceof AndQueryNode)
+      op = ANDOperation.BOTH;
+    else if (q1 instanceof AndQueryNode)
+      op = ANDOperation.Q1;
+    else if (q1 instanceof AndQueryNode)
+      op = ANDOperation.Q2;
+    else
+      op = ANDOperation.NONE;
+
+    try {
+      QueryNode result = null;
+      switch (op) {
+      case NONE:
+        List<QueryNode> children = new ArrayList<QueryNode>();
+        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;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/util/QueryNodeOperation.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java	(revision 0)
@@ -0,0 +1,129 @@
+package org.apache.lucene.queryParser.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 org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * A {@link QueryNodeProcessorPipeline} class should be used to build a query
+ * node processor pipeline.
+ * 
+ * When a query node tree is processed using this class, it passes the query
+ * node tree to each processor on the pipeline and the result from each
+ * processor is passed to the next one, always following the order the
+ * processors were on the pipeline.
+ * 
+ * When a {@link QueryConfigHandler} object is set on a
+ * {@link QueryNodeProcessorPipeline}, it takes care of also setting this
+ * {@link QueryConfigHandler} on all processor on pipeline.
+ * 
+ */
+public class QueryNodeProcessorPipeline implements QueryNodeProcessor {
+
+  private LinkedList<QueryNodeProcessor> processors = new LinkedList<QueryNodeProcessor>();
+
+  private QueryConfigHandler queryConfig;
+
+  /**
+   * Constructs an empty query node processor pipeline.
+   */
+  public QueryNodeProcessorPipeline() {
+    // empty constructor
+  }
+
+  /**
+   * Constructs with a {@link QueryConfigHandler} object.
+   */
+  public QueryNodeProcessorPipeline(QueryConfigHandler queryConfigHandler) {
+    this.queryConfig = queryConfigHandler;
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#getQueryConfigHandler()}.
+   * 
+   * @param queryConfigHandler
+   *          the query configuration handler to be set.
+   * 
+   * @see QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)
+   * @see QueryConfigHandler
+   */
+  public QueryConfigHandler getQueryConfigHandler() {
+    return this.queryConfig;
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#process(QueryNode)}.
+   * 
+   * @param queryTree
+   *          the query node tree to be processed
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   * 
+   * @see QueryNode
+   */
+  public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+
+    for (QueryNodeProcessor processor : this.processors) {
+      queryTree = processor.process(queryTree);
+    }
+
+    return queryTree;
+
+  }
+
+  /**
+   * Adds a processor to the pipeline, it's always added to the end of the
+   * pipeline.
+   * 
+   * @param processor
+   *          the processor to be added
+   */
+  public void addProcessor(QueryNodeProcessor processor) {
+    this.processors.add(processor);
+
+    processor.setQueryConfigHandler(this.queryConfig);
+
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)}.
+   * 
+   * @param queryConfigHandler
+   *          the query configuration handler to be set.
+   * 
+   * @see QueryNodeProcessor#getQueryConfigHandler()
+   * @see QueryConfigHandler
+   */
+  public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
+    this.queryConfig = queryConfigHandler;
+
+    for (QueryNodeProcessor processor : this.processors) {
+      processor.setQueryConfigHandler(this.queryConfig);
+    }
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/NoChildOptimizationQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/NoChildOptimizationQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/NoChildOptimizationQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,90 @@
+package org.apache.lucene.queryParser.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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.nodes.DeletedQueryNode;
+import org.apache.lucene.queryParser.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+
+/**
+ * <p>
+ * A {@link NoChildOptimizationQueryNodeProcessor} removes every
+ * BooleanQueryNode, BoostQueryNode, TokenizedPhraseQueryNode or
+ * ModifierQueryNode that do not have a valid children.
+ * </p>
+ * <p>
+ * Example: When the children of these nodes are removed for any reason then the
+ * nodes may become invalid.
+ * </p>
+ */
+public class NoChildOptimizationQueryNodeProcessor extends
+    QueryNodeProcessorImpl {
+
+  public NoChildOptimizationQueryNodeProcessor() {
+    // empty constructor
+  }
+
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+    if (node instanceof BooleanQueryNode || node instanceof BoostQueryNode
+        || node instanceof TokenizedPhraseQueryNode
+        || node instanceof ModifierQueryNode) {
+
+      List<QueryNode> children = node.getChildren();
+
+      if (children != null && children.size() > 0) {
+
+        for (QueryNode child : children) {
+
+          if (!(child instanceof DeletedQueryNode)) {
+            return node;
+          }
+
+        }
+
+      }
+
+      return new MatchNoDocsQueryNode();
+
+    }
+
+    return node;
+
+  }
+
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+    return node;
+
+  }
+
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/NoChildOptimizationQueryNodeProcessor.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java	(revision 0)
@@ -0,0 +1,254 @@
+package org.apache.lucene.queryParser.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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * <p>
+ * This is a default implementation for the {@link QueryNodeProcessor}
+ * interface, it's an abstract class, so it should be extended by classes that
+ * want to process a {@link QueryNode} tree.
+ * </p>
+ * <p>
+ * This class process {@link QueryNode}s from left to right in the tree. While
+ * it's walking down the tree, for every node,
+ * {@link #preProcessNode(QueryNode)} is invoked. After a node's children are
+ * processed, {@link #postProcessNode(QueryNode)} is invoked for that node.
+ * {@link #setChildrenOrder(List)} is invoked before
+ * {@link #postProcessNode(QueryNode)} only if the node has at least one child,
+ * in {@link #setChildrenOrder(List)} the implementor might redefine the
+ * children order or remove any children from the children list.
+ * </p>
+ * <p>
+ * Here is an example about how it process the nodes:
+ * </p>
+ * 
+ * <pre>
+ *      a
+ *     / \
+ *    b   e
+ *   / \
+ *  c   d
+ * </pre>
+ * 
+ * Here is the order the methods would be invoked for the tree described above:
+ * 
+ * <pre>
+ *      preProcessNode( a );
+ *      preProcessNode( b );
+ *      preProcessNode( c );
+ *      postProcessNode( c );
+ *      preProcessNode( d );
+ *      postProcessNode( d );
+ *      setChildrenOrder( bChildrenList );
+ *      postProcessNode( b );
+ *      preProcessNode( e );
+ *      postProcessNode( e );
+ *      setChildrenOrder( aChildrenList );
+ *      postProcessNode( a )
+ * </pre>
+ * 
+ * @see org.apache.lucene.queryParser.processors.QueryNodeProcessor
+ */
+public abstract class QueryNodeProcessorImpl implements QueryNodeProcessor {
+
+  private ArrayList<ChildrenList> childrenListPool = new ArrayList<ChildrenList>();
+
+  private QueryConfigHandler queryConfig;
+
+  public QueryNodeProcessorImpl() {
+    // empty constructor
+  }
+
+  public QueryNodeProcessorImpl(QueryConfigHandler queryConfigHandler) {
+    this.queryConfig = queryConfigHandler;
+  }
+
+  public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+    return processIteration(queryTree);
+  }
+
+  private QueryNode processIteration(QueryNode queryTree)
+      throws QueryNodeException {
+    queryTree = preProcessNode(queryTree);
+
+    processChildren(queryTree);
+
+    queryTree = postProcessNode(queryTree);
+
+    return queryTree;
+
+  }
+
+  /**
+   * This method is called every time a child is processed.
+   * 
+   * @param queryTree
+   *          the query node child to be processed
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  protected void processChildren(QueryNode queryTree) throws QueryNodeException {
+
+    List<QueryNode> children = queryTree.getChildren();
+    ChildrenList newChildren;
+
+    if (children != null && children.size() > 0) {
+
+      newChildren = allocateChildrenList();
+
+      try {
+
+        for (QueryNode child : children) {
+          child = processIteration(child);
+
+          if (child == null) {
+            throw new NullPointerException();
+
+          }
+
+          newChildren.add(child);
+
+        }
+
+        List<QueryNode> orderedChildrenList = setChildrenOrder(newChildren);
+
+        queryTree.set(orderedChildrenList);
+
+      } finally {
+        newChildren.beingUsed = false;
+      }
+
+    }
+
+  }
+
+  private ChildrenList allocateChildrenList() {
+    ChildrenList list = null;
+
+    for (ChildrenList auxList : this.childrenListPool) {
+
+      if (!auxList.beingUsed) {
+        list = auxList;
+        list.clear();
+
+        break;
+
+      }
+
+    }
+
+    if (list == null) {
+      list = new ChildrenList();
+      this.childrenListPool.add(list);
+
+    }
+
+    list.beingUsed = true;
+
+    return list;
+
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)}.
+   * 
+   * @param queryConfigHandler
+   *          the query configuration handler to be set.
+   * 
+   * @see QueryNodeProcessor#getQueryConfigHandler()
+   * @see QueryConfigHandler
+   */
+  public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
+    this.queryConfig = queryConfigHandler;
+  }
+
+  /**
+   * For reference about this method check:
+   * {@link QueryNodeProcessor#getQueryConfigHandler()}.
+   * 
+   * @param queryConfigHandler
+   *          the query configuration handler to be set.
+   * 
+   * @see QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)
+   * @see QueryConfigHandler
+   */
+  public QueryConfigHandler getQueryConfigHandler() {
+    return this.queryConfig;
+  }
+
+  /**
+   * This method is invoked for every node when walking down the tree.
+   * 
+   * @param node
+   *          the query node to be pre-processed
+   * 
+   * @return a query node
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  abstract protected QueryNode preProcessNode(QueryNode node)
+      throws QueryNodeException;
+
+  /**
+   * This method is invoked for every node when walking up the tree.
+   * 
+   * @param node
+   *          node the query node to be post-processed
+   * 
+   * @return a query node
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  abstract protected QueryNode postProcessNode(QueryNode node)
+      throws QueryNodeException;
+
+  /**
+   * This method is invoked for every node that has at least on child. It's
+   * invoked right before {@link #postProcessNode(QueryNode)} is invoked.
+   * 
+   * @param children
+   *          the list containing all current node's children
+   * 
+   * @return a new list containing all children that should be set to the
+   *         current node
+   * 
+   * @throws QueryNodeException
+   *           if something goes wrong during the query node processing
+   */
+  abstract protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException;
+
+  private static class ChildrenList extends ArrayList<QueryNode> {
+
+    private static final long serialVersionUID = -2613518456949297135L;
+
+    boolean beingUsed;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java	(revision 0)
@@ -0,0 +1,109 @@
+package org.apache.lucene.queryParser.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.Iterator;
+import java.util.List;
+
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.DeletedQueryNode;
+import org.apache.lucene.queryParser.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * A {@link QueryNodeProcessorPipeline} class removes every instance of
+ * {@link DeletedQueryNode} from a query node tree. If the resulting root node
+ * is a {@link DeletedQueryNode}, {@link MatchNoDocsQueryNode} is returned.
+ * 
+ */
+public class RemoveDeletedQueryNodesProcessor extends QueryNodeProcessorImpl {
+
+  public RemoveDeletedQueryNodesProcessor() {
+    // empty constructor
+  }
+
+  public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+    queryTree = super.process(queryTree);
+
+    if (queryTree instanceof DeletedQueryNode
+        && !(queryTree instanceof MatchNoDocsQueryNode)) {
+
+      return new MatchNoDocsQueryNode();
+
+    }
+
+    return queryTree;
+
+  }
+
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+    if (!node.isLeaf()) {
+      List<QueryNode> children = node.getChildren();
+      boolean removeBoolean = false;
+
+      if (children == null || children.size() == 0) {
+        removeBoolean = true;
+
+      } else {
+        removeBoolean = true;
+
+        for (Iterator<QueryNode> it = children.iterator(); it.hasNext();) {
+
+          if (!(it.next() instanceof DeletedQueryNode)) {
+            removeBoolean = false;
+            break;
+
+          }
+
+        }
+
+      }
+
+      if (removeBoolean) {
+        return new DeletedQueryNode();
+      }
+
+    }
+
+    return node;
+
+  }
+
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    for (int i = 0; i < children.size(); i++) {
+
+      if (children.get(i) instanceof DeletedQueryNode) {
+        children.remove(i--);
+      }
+
+    }
+
+    return children;
+
+  }
+
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+    return node;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,79 @@
+package org.apache.lucene.queryParser.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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * <p>
+ * A {@link QueryNodeProcessor} is an interface for classes that process a
+ * {@link QueryNode} tree.
+ * <p>
+ * </p>
+ * The implementor of this class should perform some operation on a query node
+ * tree and return the same or another query node tree.
+ * <p>
+ * </p>
+ * It also may carry a {@link QueryConfigHandler} object that contains
+ * configuration about the query represented by the query tree or the
+ * collection/index where it's intended to be executed.
+ * <p>
+ * </p>
+ * In case there is any {@link QueryConfigHandler} associated to the query tree
+ * to be processed, it should be set using
+ * {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)} before
+ * {@link QueryNodeProcessor#process(QueryNode)} is invoked.
+ * 
+ * @see QueryNode
+ * @see QueryNodeProcessor
+ * @see QueryConfigHandler
+ */
+public interface QueryNodeProcessor {
+
+  /**
+   * Processes a query node tree. It may return the same or another query tree.
+   * I should never return <code>null</code>.
+   * 
+   * @param queryTree
+   *          tree root node
+   * 
+   * @return the processed query tree
+   * 
+   * @throws QueryNodeException
+   */
+  public QueryNode process(QueryNode queryTree) throws QueryNodeException;
+
+  /**
+   * Sets the {@link QueryConfigHandler} associated to the query tree.
+   * 
+   * @param queryConfigHandler
+   */
+  public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler);
+
+  /**
+   * Returns the {@link QueryConfigHandler} associated to the query tree if any,
+   * otherwise it returns <code>null</code>
+   * 
+   * @return the {@link QueryConfigHandler} associated to the query tree if any,
+   *         otherwise it returns <code>null</code>
+   */
+  public QueryConfigHandler getQueryConfigHandler();
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java	(revision 0)
@@ -0,0 +1,468 @@
+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.List;
+import java.util.Locale;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryBuilder;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.ConstantScoreRewriteAttribute;
+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.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.original.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessor;
+import org.apache.lucene.search.FuzzyQuery;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.util.Parameter;
+
+/**
+ * This class extends {@link QueryParserWrapper} and overrides every method. It
+ * performs the query parsing using the new query parser instead of the old one. <br/>
+ * <br/>
+ * 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. <br/>
+ * 
+ * @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 QueryParser#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 <code>\</code>.
+   */
+  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 org.apache.lucene.queryParser.original.parser.TextParser luceneQueryParser = new org.apache.lucene.queryParser.original.parser.TextParser();
+
+  private LuceneQueryConfigHandler config;
+
+  private QueryNodeProcessor processorPipeline;
+
+  private LuceneQueryBuilder builder = new LuceneQueryTreeBuilder();
+
+  private String defaultField;
+
+  public QueryParserWrapper(String defaultField, Analyzer analyzer) {
+    this.defaultField = defaultField;
+    this.config = new LuceneQueryConfigHandler();
+
+    this.config.setAnalyzer(analyzer);
+
+    this.processorPipeline = new LuceneQueryNodeProcessorPipeline(this.config);
+
+  }
+
+  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 LuceneQueryBuilder} used to generate a {@link Query} object
+   * from the parsed and processed query node tree.
+   * 
+   * @param builder
+   *          the builder
+   * @see QueryParserWrapper#setQueryProcessor(QueryNodeProcessor)
+   */
+  public void setQueryBuilder(LuceneQueryBuilder 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.QueryParser}, the
+   * {@link QueryConfigHandler} already set to this object is automatically set
+   * to the new processor.
+   * 
+   * @param processor
+   *          the processor
+   * @see QueryParserWrapper#setQueryBuilder(LuceneQueryBuilder)
+   * @see QueryParserWrapper#setQueryConfig(LuceneQueryConfigHandler)
+   */
+  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
+   * @see QueryParserWrapper#setQueryProcessor(QueryNodeProcessor)
+   */
+  public void setQueryConfig(LuceneQueryConfigHandler 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.QueryParser}.
+   * 
+   * @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 boolean getConstantScoreRewrite() {
+
+    if (this.config != null
+        && this.config.hasAttribute(ConstantScoreRewriteAttribute.class)) {
+      return ((ConstantScoreRewriteAttribute) this.config
+          .getAttribute(ConstantScoreRewriteAttribute.class))
+          .isConstantScoreRewrite();
+    }
+
+    return true;
+
+  }
+
+  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() {
+    return !getConstantScoreRewrite();
+  }
+
+  public Query parse(String query) throws ParseException {
+
+    try {
+      QueryNode queryTree = this.luceneQueryParser.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.config.setAllowLeadingWildcard(allowLeadingWildcard);
+  }
+
+  public void setConstantScoreRewrite(boolean constantScoreRewrite) {
+    this.config.setConstantScoreRewrite(constantScoreRewrite);
+  }
+
+  public void setDateResolution(Resolution dateResolution) {
+    this.config.setDateResolution(dateResolution);
+  }
+
+  public void setDateResolution(String fieldName, Resolution dateResolution) {
+    this.config.setDateResolution(fieldName, dateResolution);
+  }
+
+  public void setDefaultOperator(Operator op) {
+
+    this.config
+        .setDefaultOperator(OR_OPERATOR.equals(op) ? org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator.OR
+            : org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.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.LuceneQueryConfigHandler.Operator.AND) ? AND_OPERATOR
+          : OR_OPERATOR;
+
+    }
+
+    return OR_OPERATOR;
+
+  }
+
+  public void setEnablePositionIncrements(boolean enable) {
+    this.config.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.config.setLocale(locale);
+  }
+
+  public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+    this.config.setLowercaseExpandedTerms(lowercaseExpandedTerms);
+  }
+
+  public void setPhraseSlop(int phraseSlop) {
+    this.config.setDefaultPhraseSlop(phraseSlop);
+  }
+
+  public void setRangeCollator(Collator rc) {
+    this.config.setRangeCollator(rc);
+  }
+
+  public void setUseOldRangeQuery(boolean useOldRangeQuery) {
+    setConstantScoreRewrite(!useOldRangeQuery);
+  }
+
+  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();
+  }
+
+  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();
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserWrapper.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java	(revision 0)
@@ -0,0 +1,270 @@
+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.queryParser.original.config.LuceneQueryConfigHandler;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Query;
+
+/**
+ * This class behaves as the {@link MultiFieldQueryParser}, but uses the new
+ * query parser interface instead of the old one. <br/>
+ * <br/>
+ * 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. <br/>
+ * 
+ * @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.
+   * 
+   * <p>
+   * 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
+   * <code>title</code> and <code>body</code>):
+   * </p>
+   * 
+   * <code>
+     * (title:term1 body:term1) (title:term2 body:term2)
+     * </code>
+   * 
+   * <p>
+   * When setDefaultOperator(AND_OPERATOR) is set, the result will be:
+   * </p>
+   * 
+   * <code>
+     * +(title:term1 body:term1) +(title:term2 body:term2)
+     * </code>
+   * 
+   * <p>
+   * When you pass a boost (title=>5 body=>10) you can get
+   * </p>
+   * 
+   * <code>
+     * +(title:term1^5.0 body:term1^10.0) +(title:term2^5.0 body:term2^10.0)
+     * </code>
+   * 
+   * <p>
+   * In other words, all the query's terms must appear, but it doesn't matter in
+   * what fields they appear.
+   * </p>
+   */
+  public MultiFieldQueryParserWrapper(String[] fields, Analyzer analyzer,
+      Map boosts) {
+    this(fields, analyzer);
+    LuceneQueryConfigHandler config = (LuceneQueryConfigHandler) getQueryConfigHandler();
+
+    config.setMultiFields(fields);
+    config.setFieldsBoost(boosts);
+
+  }
+
+  /**
+   * Creates a MultiFieldQueryParser.
+   * 
+   * <p>
+   * 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
+   * <code>title</code> and <code>body</code>):
+   * </p>
+   * 
+   * <code>
+     * (title:term1 body:term1) (title:term2 body:term2)
+     * </code>
+   * 
+   * <p>
+   * When setDefaultOperator(AND_OPERATOR) is set, the result will be:
+   * </p>
+   * 
+   * <code>
+     * +(title:term1 body:term1) +(title:term2 body:term2)
+     * </code>
+   * 
+   * <p>
+   * In other words, all the query's terms must appear, but it doesn't matter in
+   * what fields they appear.
+   * </p>
+   */
+  public MultiFieldQueryParserWrapper(String[] fields, Analyzer analyzer) {
+    super(null, analyzer);
+
+    LuceneQueryConfigHandler config = (LuceneQueryConfigHandler) getQueryConfigHandler();
+    config.setAnalyzer(analyzer);
+
+    config.setMultiFields(fields);
+  }
+
+  /**
+   * Parses a query which searches on the fields specified.
+   * <p>
+   * If x fields are specified, this effectively constructs:
+   * 
+   * <pre>
+   * &lt;code&gt;
+   * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
+   * &lt;/code&gt;
+   * </pre>
+   * 
+   * @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.
+   * <p>
+   * 
+   * <pre>
+   * Usage:
+   * &lt;code&gt;
+   * String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};
+   * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+   *                BooleanClause.Occur.MUST,
+   *                BooleanClause.Occur.MUST_NOT};
+   * MultiFieldQueryParser.parse(&quot;query&quot;, fields, flags, analyzer);
+   * &lt;/code&gt;
+   * </pre>
+   *<p>
+   * The code above would construct a query:
+   * 
+   * <pre>
+   * &lt;code&gt;
+   * (filename:query) +(contents:query) -(description:query)
+   * &lt;/code&gt;
+   * </pre>
+   * 
+   * @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.
+   * <p>
+   * 
+   * <pre>
+   * Usage:
+   * &lt;code&gt;
+   * String[] query = {&quot;query1&quot;, &quot;query2&quot;, &quot;query3&quot;};
+   * String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};
+   * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+   *                BooleanClause.Occur.MUST,
+   *                BooleanClause.Occur.MUST_NOT};
+   * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+   * &lt;/code&gt;
+   * </pre>
+   *<p>
+   * The code above would construct a query:
+   * 
+   * <pre>
+   * &lt;code&gt;
+   * (filename:query1) +(contents:query2) -(description:query3)
+   * &lt;/code&gt;
+   * </pre>
+   * 
+   * @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;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/MultiFieldQueryParserWrapper.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html	(revision 0)
@@ -0,0 +1,48 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Lucene Flexible Query Parser</h2>
+<p>
+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.
+</p>
+<p>
+The classes contained in the package org.apache.lucene.queryParser.original
+are used to reproduce the same behaviour as the old query parser.
+</p>
+
+<p>
+Check <tt>org.apache.lucene.queryParser.original.LuceneQueryParserHelper</tt> to quick start using the Lucene query parser. 
+</p>
+
+<p>
+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.  
+</p>
+
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java	(revision 0)
@@ -0,0 +1,189 @@
+package org.apache.lucene.queryParser.original;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.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.
+   * <p>
+   * If x fields are specified, this effectively constructs:
+   * 
+   * <pre>
+   * &lt;code&gt;
+   * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
+   * &lt;/code&gt;
+   * </pre>
+   * 
+   * @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();
+
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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.
+   * <p>
+   * 
+   * <pre>
+   * Usage:
+   * &lt;code&gt;
+   * String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};
+   * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+   *                BooleanClause.Occur.MUST,
+   *                BooleanClause.Occur.MUST_NOT};
+   * MultiFieldQueryParser.parse(&quot;query&quot;, fields, flags, analyzer);
+   * &lt;/code&gt;
+   * </pre>
+   *<p>
+   * The code above would construct a query:
+   * 
+   * <pre>
+   * &lt;code&gt;
+   * (filename:query) +(contents:query) -(description:query)
+   * &lt;/code&gt;
+   * </pre>
+   * 
+   * @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();
+
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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.
+   * <p>
+   * 
+   * <pre>
+   * Usage:
+   * &lt;code&gt;
+   * String[] query = {&quot;query1&quot;, &quot;query2&quot;, &quot;query3&quot;};
+   * String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};
+   * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+   *                BooleanClause.Occur.MUST,
+   *                BooleanClause.Occur.MUST_NOT};
+   * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+   * &lt;/code&gt;
+   * </pre>
+   *<p>
+   * The code above would construct a query:
+   * 
+   * <pre>
+   * &lt;code&gt;
+   * (filename:query1) +(contents:query2) -(description:query3)
+   * &lt;/code&gt;
+   * </pre>
+   * 
+   * @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();
+
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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 <code>\</code>.
+   */
+  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();
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/QueryParserUtil.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BoostQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BoostQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BoostQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BooleanQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BooleanQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/BooleanQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.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. <br/>
+ * <br/>
+ * It takes in consideration if the children is a {@link ModifierQueryNode} to
+ * define the {@link BooleanClause}.
+ */
+public class BooleanQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public BooleanQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+    BooleanQueryNode booleanNode = (BooleanQueryNode) queryNode;
+
+    BooleanQuery bQuery = new BooleanQuery();
+    List<QueryNode> 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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/ModifierQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/ModifierQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/ModifierQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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);
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneQueryTreeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneQueryTreeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneQueryTreeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.nodes.LuceneBooleanQueryNode;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+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 LuceneQueryNodeProcessorPipeline}. <br/>
+ * 
+ * @see QueryTreeBuilder
+ * @see LuceneQueryNodeProcessorPipeline
+ */
+public class LuceneQueryTreeBuilder extends QueryTreeBuilder implements
+    LuceneQueryBuilder {
+
+  public LuceneQueryTreeBuilder() {
+    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(LuceneBooleanQueryNode.class,
+        new LuceneBooleanQueryNodeBuilder());
+    setBuilder(MultiPhraseQueryNode.class, new MultiPhraseQueryNodeBuilder());
+    setBuilder(MatchAllDocsQueryNode.class, new MatchAllDocsQueryNodeBuilder());
+
+  }
+
+  public Query build(QueryNode queryNode) throws QueryNodeException {
+    return (Query) super.build(queryNode);
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MultiPhraseQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MultiPhraseQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MultiPhraseQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  public MultiPhraseQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public MultiPhraseQuery build(QueryNode queryNode) throws QueryNodeException {
+    MultiPhraseQueryNode phraseNode = (MultiPhraseQueryNode) queryNode;
+
+    MultiPhraseQuery phraseQuery = new MultiPhraseQuery();
+
+    List<QueryNode> children = phraseNode.getChildren();
+
+    if (children != null) {
+      TreeMap<Integer, List<Term>> positionTermMap = new TreeMap<Integer, List<Term>>();
+
+      for (QueryNode child : children) {
+        FieldQueryNode termNode = (FieldQueryNode) child;
+        TermQuery termQuery = (TermQuery) termNode
+            .getTag(QueryTreeBuilder.QUERY_TREE_BUILDER_TAGID);
+        List<Term> termList = positionTermMap.get(termNode
+            .getPositionIncrement());
+
+        if (termList == null) {
+          termList = new LinkedList<Term>();
+          positionTermMap.put(termNode.getPositionIncrement(), termList);
+
+        }
+
+        termList.add(termQuery.getTerm());
+
+      }
+
+      for (int positionIncrement : positionTermMap.keySet()) {
+        List<Term> termList = positionTermMap.get(positionIncrement);
+
+        phraseQuery.add(termList.toArray(new Term[termList.size()]),
+            positionIncrement);
+
+      }
+
+    }
+
+    return phraseQuery;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/WildcardQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/WildcardQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/WildcardQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.search.WildcardQuery;
+
+/**
+ * Builds a {@link WildcardQuery} object from a {@link WildcardQueryNode}
+ * object.
+ */
+public class WildcardQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public WildcardQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public WildcardQuery build(QueryNode queryNode) throws QueryNodeException {
+    WildcardQueryNode wildcardNode = (WildcardQueryNode) queryNode;
+
+    return new WildcardQuery(new Term(wildcardNode.getFieldAsString(),
+        wildcardNode.getTextAsString()));
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/SlopQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/SlopQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/SlopQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/GroupQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/GroupQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/GroupQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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);
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/package.html	(revision 0)
@@ -0,0 +1,35 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Original Lucene Query Node Builders</h2>
+<p>
+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.LuceneQueryNodeProcessorPipeline}.
+</p>
+<p>
+{@link org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder} is a builder that already contains a defined map that maps each QueryNode object
+with its respective builder.
+</p>
+</body>
+</html>
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneQueryBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneQueryBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneQueryBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryBuilder;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.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. <br/>
+ * 
+ * @see QueryBuilder
+ * @see QueryTreeBuilder
+ */
+public interface LuceneQueryBuilder extends QueryBuilder {
+
+  public Query build(QueryNode queryNode) throws QueryNodeException;
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FuzzyQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FuzzyQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FuzzyQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.search.FuzzyQuery;
+
+/**
+ * Builds a {@link FuzzyQuery} object from a {@link FuzzyQueryNode} object.
+ */
+public class FuzzyQueryNodeBuilder implements LuceneQueryBuilder {
+
+  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());
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PhraseQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PhraseQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PhraseQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  public PhraseQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public PhraseQuery build(QueryNode queryNode) throws QueryNodeException {
+    TokenizedPhraseQueryNode phraseNode = (TokenizedPhraseQueryNode) queryNode;
+
+    PhraseQuery phraseQuery = new PhraseQuery();
+
+    List<QueryNode> 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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchNoDocsQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchNoDocsQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchNoDocsQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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();
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PrefixWildcardQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PrefixWildcardQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/PrefixWildcardQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.search.PrefixQuery;
+
+/**
+ * Builds a {@link PrefixQuery} object from a {@link PrefixWildcardQueryNode}
+ * object.
+ */
+public class PrefixWildcardQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public PrefixWildcardQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public PrefixQuery build(QueryNode queryNode) throws QueryNodeException {
+    PrefixWildcardQueryNode wildcardNode = (PrefixWildcardQueryNode) queryNode;
+
+    return new PrefixQuery(new Term(wildcardNode.getFieldAsString(),
+        wildcardNode.getTextAsString()));
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchAllDocsQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchAllDocsQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/MatchAllDocsQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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();
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FieldQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FieldQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/FieldQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.search.TermQuery;
+
+/**
+ * Builds a {@link TermQuery} object from a {@link FieldQueryNode} object.
+ */
+public class FieldQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public FieldQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public TermQuery build(QueryNode queryNode) throws QueryNodeException {
+    FieldQueryNode fieldNode = (FieldQueryNode) queryNode;
+
+    return new TermQuery(new Term(fieldNode.getFieldAsString(), fieldNode
+        .getTextAsString()));
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/RangeQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/RangeQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/RangeQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  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.setConstantScoreRewrite(rangeNode.isConstantScoreRewrite());
+
+    return rangeQuery;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneBooleanQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneBooleanQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/LuceneBooleanQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryParser.original.nodes.LuceneBooleanQueryNode;
+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. <br/>
+ * 
+ * @see BooleanQueryNodeBuilder
+ * @see BooleanQuery
+ * @see Similarity#coord(int, int)
+ */
+public class LuceneBooleanQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public LuceneBooleanQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+    LuceneBooleanQueryNode booleanNode = (LuceneBooleanQueryNode) queryNode;
+
+    BooleanQuery bQuery = new BooleanQuery(booleanNode.isDisableCoord());
+    List<QueryNode> 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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/AnyQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/AnyQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/builders/AnyQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.AnyQueryNode;
+import org.apache.lucene.queryParser.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 LuceneQueryBuilder {
+
+  public AnyQueryNodeBuilder() {
+    // empty constructor
+  }
+
+  public BooleanQuery build(QueryNode queryNode) throws QueryNodeException {
+    AnyQueryNode andNode = (AnyQueryNode) queryNode;
+
+    BooleanQuery bQuery = new BooleanQuery();
+    List<QueryNode> 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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/package.html	(revision 0)
@@ -0,0 +1,33 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Lucene Query Parser</h2>
+<p>
+The package org.apache.lucene.queryParser.original.parser contains the query parser.
+</p>
+<p>
+This query parser only performs the syntax validation and create an QueryNode tree
+from a query string.
+</p>
+</body>
+</html>
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TextParser.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TextParser.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TextParser.java	(revision 0)
@@ -0,0 +1,1086 @@
+/* Generated By:JavaCC: Do not edit this line. TextParser.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.Vector;
+
+import org.apache.lucene.messages.Message;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeParseException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.QuotedFieldQueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.parser.Parser;
+
+@SuppressWarnings("all")
+public class TextParser implements Parser, QueryParserConstants {
+
+  private static final int CONJ_NONE = 0;
+  private static final int CONJ_AND = 2;
+  private static final int CONJ_OR = 2;
+
+  // query parser constructor
+  public TextParser() {
+    this(new StringReader(""));
+  }
+
+  /**
+   * Parses a query string, returning a
+   * {@link org.apache.lucene.queryParser.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 ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" 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) {
+          fms = defaultMinSimilarity;
+        }
+        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 QueryParserTokenManager 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 TextParser(java.io.InputStream stream) {
+    this(stream, null);
+  }
+
+  /** Constructor with InputStream and supplied encoding */
+  public TextParser(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 QueryParserTokenManager(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 TextParser(java.io.Reader stream) {
+    jj_input_stream = new JavaCharStream(stream, 1, 1);
+    token_source = new QueryParserTokenManager(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 TextParser(QueryParserTokenManager 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(QueryParserTokenManager 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<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+  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 << j)) != 0) {
+            la1tokens[j] = true;
+          }
+          if ((jj_la1_1[i] & (1 << j)) != 0) {
+            la1tokens[32 + j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 34; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    jj_endpos = 0;
+    jj_rescan_token();
+    jj_add_error_token(0, 0);
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+  private void jj_rescan_token() {
+    jj_rescan = true;
+    for (int i = 0; i < 1; i++) {
+      try {
+        JJCalls p = jj_2_rtns[i];
+        do {
+          if (p.gen > 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;
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/Token.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/Token.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/Token.java	(revision 0)
@@ -0,0 +1,143 @@
+/* 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;
+
+/**
+ * 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.
+ */
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class. Increment only if the
+   * <i>serialized</i> 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=c7458f48213af7d4c6a887e945d19ece (do not edit this
+ * line)
+ */
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/QueryParserConstants.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/QueryParserConstants.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/QueryParserConstants.java	(revision 0)
@@ -0,0 +1,112 @@
+/* Generated By:JavaCC: Do not edit this line. QueryParserConstants.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 literal values and constants. Generated by
+ * org.javacc.parser.OtherFilesGen#start()
+ */
+public interface QueryParserConstants {
+
+  /** 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 = { "<EOF>", "<_NUM_CHAR>", "<_ESCAPED_CHAR>",
+      "<_TERM_START_CHAR>", "<_TERM_CHAR>", "<_WHITESPACE>", "<_QUOTED_CHAR>",
+      "<token of kind 7>", "<AND>", "<OR>", "<NOT>", "\"+\"", "\"-\"", "\"(\"",
+      "\")\"", "\":\"", "\"*\"", "\"^\"", "<QUOTED>", "<TERM>", "<FUZZY_SLOP>",
+      "<PREFIXTERM>", "<WILDTERM>", "\"[\"", "\"{\"", "<NUMBER>", "\"TO\"",
+      "\"]\"", "<RANGEIN_QUOTED>", "<RANGEIN_GOOP>", "\"TO\"", "\"}\"",
+      "<RANGEEX_QUOTED>", "<RANGEEX_GOOP>", };
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/QueryParserTokenManager.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/QueryParserTokenManager.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/QueryParserTokenManager.java	(revision 0)
@@ -0,0 +1,1171 @@
+/* Generated By:JavaCC: Do not edit this line. QueryParserTokenManager.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. */
+public class QueryParserTokenManager implements QueryParserConstants {
+
+  /** 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;
+    }
+  }
+
+  @SuppressWarnings("unused")
+  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);
+  }
+
+  @SuppressWarnings("unused")
+  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 QueryParserTokenManager(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 QueryParserTokenManager(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);
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TextParser.jj
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TextParser.jj	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TextParser.jj	(revision 0)
@@ -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(TextParser)
+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.QueryNodeError;
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.QueryNodeParseException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.OpaqueQueryNode;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.ProximityQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNodeImpl;
+import org.apache.lucene.queryParser.nodes.QuotedFieldQueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.parser.Parser;
+
+@SuppressWarnings("all")
+public class TextParser implements Parser {
+
+	private static final int CONJ_NONE =0;
+	private static final int CONJ_AND =2;
+	private static final int CONJ_OR =2;
+
+ 
+   // query parser constructor
+   public TextParser() {
+   	this(new StringReader(""));
+  }
+     /** Parses a query string, returning a {@link org.apache.lucene.queryParser.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(TextParser)
+
+/* ***************** */
+/* 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> ) >
+}
+
+<DEFAULT, RangeIn, RangeEx> SKIP : {
+  < <_WHITESPACE>>
+}
+
+<DEFAULT> TOKEN : {
+  <AND:       ("AND" | "&&") >
+| <OR:        ("OR" | "||") >
+| <NOT:       ("NOT" | "!") >
+| <PLUS:      "+" >
+| <MINUS:     "-" >
+| <LPAREN:    "(" >
+| <RPAREN:    ")" >
+| <COLON:     ":" >
+| <STAR:      "*" >
+| <CARAT:     "^" > : Boost
+| <QUOTED:     "\"" (<_QUOTED_CHAR>)* "\"">
+| <TERM:      <_TERM_START_CHAR> (<_TERM_CHAR>)*  >
+| <FUZZY_SLOP:     "~" ( (<_NUM_CHAR>)+ ( "." (<_NUM_CHAR>)+ )? )? >
+| <PREFIXTERM:  ("*") | ( <_TERM_START_CHAR> (<_TERM_CHAR>)* "*" ) >
+| <WILDTERM:  (<_TERM_START_CHAR> | [ "*", "?" ]) (<_TERM_CHAR> | ( [ "*", "?" ] ))* >
+| <RANGEIN_START: "[" > : RangeIn
+| <RANGEEX_START: "{" > : RangeEx
+}
+
+<Boost> TOKEN : {
+<NUMBER:    (<_NUM_CHAR>)+ ( "." (<_NUM_CHAR>)+ )? > : DEFAULT
+}
+
+<RangeIn> TOKEN : {
+<RANGEIN_TO: "TO">
+| <RANGEIN_END: "]"> : DEFAULT
+| <RANGEIN_QUOTED: "\"" (~["\""] | "\\\"")+ "\"">
+| <RANGEIN_GOOP: (~[ " ", "]" ])+ >
+}
+
+<RangeEx> TOKEN : {
+<RANGEEX_TO: "TO">
+| <RANGEEX_END: "}"> : DEFAULT
+| <RANGEEX_QUOTED: "\"" (~["\""] | "\\\"")+ "\"">
+| <RANGEEX_GOOP: (~[ " ", "}" ])+ >
+}
+
+// *   Query  ::= ( Clause )*
+// *   Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" )
+
+int Conjunction() : {
+  int ret = CONJ_NONE;
+}
+{
+  [
+    <AND> { ret = CONJ_AND; }
+    | <OR>  { ret = CONJ_OR; }
+  ]
+  { return ret; }
+}
+
+ModifierQueryNode.Modifier Modifiers() : {
+  ModifierQueryNode.Modifier ret = ModifierQueryNode.Modifier.MOD_NONE;
+}
+{
+  [
+     <PLUS> { ret = ModifierQueryNode.Modifier.MOD_REQ; }
+     | <MINUS> { ret = ModifierQueryNode.Modifier.MOD_NOT; }
+     | <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) <EOF>
+	{
+		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)
+  (
+   <OR> 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)
+  (
+   <AND> 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=<TERM> <COLON> {field=EscapeQuerySyntaxImpl.discardEscapeChar(fieldToken.image);}
+    | <STAR> <COLON> {field="*";}
+    )
+  ]
+
+  (
+   q=Term(field)
+   | <LPAREN> q=Query(field) <RPAREN> (<CARAT> boost=<NUMBER>)? {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=<TERM> { q = new FieldQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+	   | term=<STAR> { wildcard=true; q = new WildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+	   | term=<PREFIXTERM> { prefix=true; q = new PrefixWildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+	   | term=<WILDTERM> { wildcard=true; q = new WildcardQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image), term.beginColumn, term.endColumn); }
+       | term=<NUMBER>
+     )
+     [ fuzzySlop=<FUZZY_SLOP> { fuzzy=true; } ]
+     [ <CARAT> boost=<NUMBER> [ fuzzySlop=<FUZZY_SLOP> { 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);
+       }
+     }
+     | ( <RANGEIN_START> ( goop1=<RANGEIN_GOOP>|goop1=<RANGEIN_QUOTED> )
+         [ <RANGEIN_TO> ] ( goop2=<RANGEIN_GOOP>|goop2=<RANGEIN_QUOTED> )
+         <RANGEIN_END> )
+       [ <CARAT> boost=<NUMBER> ]
+        {
+          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);
+        }
+     | ( <RANGEEX_START> ( goop1=<RANGEEX_GOOP>|goop1=<RANGEEX_QUOTED> )
+         [ <RANGEEX_TO> ] ( goop2=<RANGEEX_GOOP>|goop2=<RANGEEX_QUOTED> )
+         <RANGEEX_END> )
+       [ <CARAT> boost=<NUMBER> ]
+        {
+          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=<QUOTED> {q = new QuotedFieldQueryNode(field, EscapeQuerySyntaxImpl.discardEscapeChar(term.image.substring(1, term.image.length()-1)), term.beginColumn + 1, term.endColumn - 1);}
+       [ fuzzySlop=<FUZZY_SLOP> ]
+       [ <CARAT> boost=<NUMBER> ]
+       {       
+         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;
+  }
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/ParseException.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/ParseException.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/ParseException.java	(revision 0)
@@ -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.QueryNodeParseException;
+import org.apache.lucene.queryParser.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
+   * <i>serialized</i> 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)
+ */
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/EscapeQuerySyntaxImpl.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/EscapeQuerySyntaxImpl.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/EscapeQuerySyntaxImpl.java	(revision 0)
@@ -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.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryParser.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 <code>A</code> to
+   * <code>A</code>.
+   * 
+   */
+  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));
+    }
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TokenMgrError.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TokenMgrError.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/TokenMgrError.java	(revision 0)
@@ -0,0 +1,168 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
+/* JavaCCOptions: */
+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 Error. */
+public class TokenMgrError extends Error {
+
+  /**
+   * The version identifier for this Serializable class. Increment only if the
+   * <i>serialized</i> 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 ? "<EOF> "
+            : ("\"" + 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=300228b3ff2a8227a4e823b29d23ad93 (do not edit this
+ * line)
+ */
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/JavaCharStream.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/JavaCharStream.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/parser/JavaCharStream.java	(revision 0)
@@ -0,0 +1,591 @@
+/* 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;
+
+/**
+ * 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.
+ */
+
+/**
+ * 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=e61bd5c730f749861216d7199a74d372 (do not edit this
+ * line)
+ */
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/RangeQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/RangeQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/RangeQueryNode.java	(revision 0)
@@ -0,0 +1,78 @@
+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.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricRangeQueryNode;
+
+/**
+ * This query node represents a Lucene range query. It also holds which collator
+ * will be used by the range query and if the constant score rewrite is enabled. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setConstantScoreRewrite(boolean)
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setRangeCollator(Collator)
+ * @see org.apache.lucene.search.RangeQuery
+ */
+public class RangeQueryNode extends ParametricRangeQueryNode {
+
+  private static final long serialVersionUID = 7400866652044314657L;
+
+  private Collator collator;
+
+  private boolean constantScoreRewrite;
+
+  /**
+   * @param lower
+   * @param upper
+   */
+  public RangeQueryNode(ParametricQueryNode lower, ParametricQueryNode upper,
+      Collator collator, boolean constantScoreRewrite) {
+    super(lower, upper);
+
+    this.constantScoreRewrite = constantScoreRewrite;
+    this.collator = collator;
+
+  }
+
+  public String toString() {
+    StringBuilder sb = new StringBuilder("<range>\n\t");
+    sb.append(this.getUpperBound()).append("\n\t");
+    sb.append(this.getLowerBound()).append("\n");
+    sb.append("</range>\n");
+
+    return sb.toString();
+
+  }
+
+  /**
+   * @return the collator
+   */
+  public Collator getCollator() {
+    return this.collator;
+  }
+
+  /**
+   * @return the constantScoreRewrite
+   */
+  public boolean isConstantScoreRewrite() {
+    return this.constantScoreRewrite;
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/MultiPhraseQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/MultiPhraseQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/MultiPhraseQueryNode.java	(revision 0)
@@ -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.nodes.FieldableNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNodeImpl;
+import org.apache.lucene.queryParser.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 "<multiPhrase/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<multiPhrase>");
+    for (QueryNode child : getChildren()) {
+      sb.append("\n");
+      sb.append(child.toString());
+    }
+    sb.append("\n</multiPhrase>");
+    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<QueryNode> children = getChildren();
+
+    if (children == null || children.size() == 0) {
+      return null;
+
+    } else {
+      return ((FieldableNode) children.get(0)).getField();
+    }
+
+  }
+
+  public void setField(CharSequence fieldName) {
+    List<QueryNode> children = getChildren();
+
+    if (children != null) {
+
+      for (QueryNode child : children) {
+
+        if (child instanceof FieldableNode) {
+          ((FieldableNode) child).setField(fieldName);
+        }
+
+      }
+
+    }
+
+  }
+
+} // end class MultitermQueryNode
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/package.html	(revision 0)
@@ -0,0 +1,31 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Original Lucene Query Nodes</h2>
+<p>
+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.
+</p>
+</body>
+</html>
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/BooleanModifierNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/BooleanModifierNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/BooleanModifierNode.java	(revision 0)
@@ -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.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.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. <br/>
+ * 
+ * @see ModifierQueryNode
+ */
+public class BooleanModifierNode extends ModifierQueryNode {
+
+  private static final long serialVersionUID = -557816496416587068L;
+
+  public BooleanModifierNode(QueryNode node, Modifier mod) {
+    super(node, mod);
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/LuceneBooleanQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/LuceneBooleanQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/nodes/LuceneBooleanQueryNode.java	(revision 0)
@@ -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.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.Similarity;
+
+/**
+ * A {@link LuceneBooleanQueryNode} has the same behavior as
+ * {@link BooleanQueryNode}. It only indicates if the coord should be enabled or
+ * not for this boolean query. <br/>
+ * 
+ * @see Similarity#coord(int, int)
+ * @see BooleanQuery
+ */
+public class LuceneBooleanQueryNode extends BooleanQueryNode {
+
+  private static final long serialVersionUID = 1938287817191138787L;
+
+  private boolean disableCoord;
+
+  /**
+   * @param clauses
+   */
+  public LuceneBooleanQueryNode(List<QueryNode> clauses, boolean disableCoord) {
+    super(clauses);
+
+    this.disableCoord = disableCoord;
+
+  }
+
+  public boolean isDisableCoord() {
+    return this.disableCoord;
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/LuceneQueryParserHelper.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/LuceneQueryParserHelper.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/LuceneQueryParserHelper.java	(revision 0)
@@ -0,0 +1,154 @@
+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 org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.QueryParserHelper;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.search.Query;
+
+/**
+ * <p>
+ * This class is a helper that enables users to easily use the Lucene query
+ * parser.
+ * </p>
+ * <p>
+ * To construct a Query object from a query string, use the
+ * {@link #parse(String, String)} method:
+ * <ul>
+ * LuceneQueryParserHelper queryParserHelper = new LuceneQueryParserHelper(); <br/>
+ * Query query = queryParserHelper.parse("a AND b", "defaultField");
+ * </ul>
+ * <p>
+ * To change any configuration before parsing the query string do, for example:
+ * <p/>
+ * <ul>
+ * // the query config handler returned by {@link LuceneQueryParserHelper} is a
+ * {@link LuceneQueryConfigHandler} <br/>
+ * queryParserHelper.getQueryConfigHandler().setAnalyzer(new
+ * WhitespaceAnalyzer());
+ * </ul>
+ * <p>
+ * The syntax for query strings is as follows (copied from the old QueryParser
+ * javadoc):
+ * <ul>
+ * A Query is a series of clauses. A clause may be prefixed by:
+ * <ul>
+ * <li>a plus (<code>+</code>) or a minus (<code>-</code>) sign, indicating that
+ * the clause is required or prohibited respectively; or
+ * <li>a term followed by a colon, indicating the field to be searched. This
+ * enables one to construct queries which search multiple fields.
+ * </ul>
+ * 
+ * A clause may be either:
+ * <ul>
+ * <li>a term, indicating all the documents that contain this term; or
+ * <li>a nested query, enclosed in parentheses. Note that this may be used with
+ * a <code>+</code>/<code>-</code> prefix to require any of a set of terms.
+ * </ul>
+ * 
+ * Thus, in BNF, the query grammar is:
+ * 
+ * <pre>
+ *   Query  ::= ( Clause )*
+ *   Clause ::= [&quot;+&quot;, &quot;-&quot;] [&lt;TERM&gt; &quot;:&quot;] ( &lt;TERM&gt; | &quot;(&quot; Query &quot;)&quot; )
+ * </pre>
+ * 
+ * <p>
+ * Examples of appropriately formatted queries can be found in the <a
+ * href="../../../../../../queryparsersyntax.html">query syntax
+ * documentation</a>.
+ * </p>
+ * </ul>
+ * <p>
+ * The text parser used by this helper is a {@link TextParser}.
+ * <p/>
+ * <p>
+ * The query node processor used by this helper is a
+ * {@link LuceneQueryNodeProcessorPipeline}.
+ * <p/>
+ * <p>
+ * The builder used by this helper is a {@link LuceneQueryTreeBuilder}.
+ * <p/>
+ * 
+ * @see QueryParserHelper
+ * @see LuceneQueryConfigHandler
+ * @see TextParser
+ * @see LuceneQueryNodeProcessorPipeline
+ * @see LuceneQueryTreeBuilder
+ */
+public class LuceneQueryParserHelper
+    extends
+    QueryParserHelper<LuceneQueryConfigHandler, TextParser, LuceneQueryNodeProcessorPipeline, LuceneQueryTreeBuilder> {
+
+  /**
+   * Constructs a {@link LuceneQueryParserHelper} object.
+   */
+  public LuceneQueryParserHelper() {
+    super(new LuceneQueryConfigHandler(), new TextParser(),
+        new LuceneQueryNodeProcessorPipeline(null),
+        new LuceneQueryTreeBuilder());
+  }
+
+  /**
+   * Constructs a {@link LuceneQueryParserHelper} object and sets an
+   * {@link Analyzer} to it. The same as:
+   * 
+   * <ul>
+   * LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+   * qp.getQueryConfigHandler().setAnalyzer(analyzer);
+   * </ul>
+   * 
+   * @param analyzer
+   *          the analyzer to be used by this query parser helper
+   */
+  public LuceneQueryParserHelper(Analyzer analyzer) {
+    this();
+
+    getQueryConfigHandler().setAnalyzer(analyzer);
+
+  }
+
+  /**
+   * 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);
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/LuceneQueryParserHelper.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LuceneQueryNodeProcessorPipeline.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LuceneQueryNodeProcessorPipeline.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LuceneQueryNodeProcessorPipeline.java	(revision 0)
@@ -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.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.processors.NoChildOptimizationQueryNodeProcessor;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.processors.RemoveDeletedQueryNodesProcessor;
+import org.apache.lucene.search.Query;
+
+/**
+ * This pipeline has all the processors needed to process a query node tree,
+ * generated by {@link TextParser}, already assembled. <br/>
+ * <br/>
+ * The order they are assembled affects the results. <br/>
+ * <br/>
+ * This processor pipeline was designed to work with
+ * {@link LuceneQueryConfigHandler}. <br/>
+ * <br/>
+ * The result query node tree can be used to build a {@link Query} object using
+ * {@link LuceneQueryTreeBuilder}. <br/>
+ * 
+ * @see LuceneQueryTreeBuilder
+ * @see LuceneQueryConfigHandler
+ * @see TextParser
+ */
+public class LuceneQueryNodeProcessorPipeline extends
+    QueryNodeProcessorPipeline {
+
+  public LuceneQueryNodeProcessorPipeline(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());
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LowercaseExpandedTermsQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LowercaseExpandedTermsQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/LowercaseExpandedTermsQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,96 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.LowercaseExpandedTermsAttribute;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * This processor verifies if the attribute
+ * {@link LowercaseExpandedTermsAttribute} is defined in the
+ * {@link QueryConfigHandler}. If it is and the expanded terms should be
+ * lowercased, it looks for every {@link WildcardQueryNode},
+ * {@link FuzzyQueryNode} and {@link ParametricQueryNode} and lowercase its
+ * term. <br/>
+ * 
+ * @see QueryParserWrapper#setLowercaseExpandedTerms(boolean)
+ * @see LowercaseExpandedTermsAttribute
+ */
+@SuppressWarnings("deprecation")
+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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AllowLeadingWildcardProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AllowLeadingWildcardProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AllowLeadingWildcardProcessor.java	(revision 0)
@@ -0,0 +1,101 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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 '?'). <br/>
+ * 
+ * @see QueryParserWrapper#setAllowLeadingWildcard(boolean)
+ * @see AllowLeadingWildcardAttribute
+ */
+@SuppressWarnings("deprecation")
+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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/RemoveEmptyNonLeafQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/RemoveEmptyNonLeafQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/RemoveEmptyNonLeafQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.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. <br/>
+ * <br/>
+ * 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. <br/>
+ * 
+ * @see QueryNode
+ * @see MatchNoDocsQueryNode
+ */
+public class RemoveEmptyNonLeafQueryNodeProcessor extends
+    QueryNodeProcessorImpl {
+
+  private LinkedList<QueryNode> childrenBuffer = new LinkedList<QueryNode>();
+
+  public RemoveEmptyNonLeafQueryNodeProcessor() {
+    // empty constructor
+  }
+
+  public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+    queryTree = super.process(queryTree);
+
+    if (!queryTree.isLeaf()) {
+
+      List<QueryNode> 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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    try {
+
+      for (QueryNode child : children) {
+
+        if (!child.isLeaf()) {
+
+          List<QueryNode> 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;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BoostQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BoostQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BoostQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldableNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.config.BoostAttribute;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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}. <br/>
+ * 
+ * @see BoostAttribute
+ * @see QueryConfigHandler
+ * @see FieldableNode
+ */
+public class BoostQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+  @Override
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+    if (node 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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PhraseSlopQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PhraseSlopQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PhraseSlopQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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}. <br/>
+ * 
+ * @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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/FuzzyQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/FuzzyQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/FuzzyQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.config.FuzzyAttribute;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+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}. <br/>
+ * 
+ * @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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MatchAllDocsQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MatchAllDocsQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MatchAllDocsQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AnalyzerQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AnalyzerQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/AnalyzerQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.NoTokenFoundQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.TextableQueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.original.nodes.LuceneBooleanQueryNode;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * This processor verifies if the attribute {@link AnalyzerQueryNodeProcessor}
+ * is defined in the {@link QueryConfigHandler}. If it is and the analyzer is
+ * not <code>null</code>, 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. <br/>
+ * <br/>
+ * If the analyzer return only one term, the returned term is set to the
+ * {@link FieldQueryNode} and it's returned. <br/>
+ * <br/>
+ * 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. <br/>
+ * <br/>
+ * If no term is returned by the analyzer a {@link NoTokenFoundQueryNode} object
+ * is returned. <br/>
+ * 
+ * @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<QueryNode> children = new LinkedList<QueryNode>();
+
+          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 LuceneBooleanQueryNode(children, true));
+
+        } else {
+          // phrase query:
+          MultiPhraseQueryNode mpq = new MultiPhraseQueryNode();
+
+          List<FieldQueryNode> multiTerms = new ArrayList<FieldQueryNode>();
+          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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/ParametricRangeQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/ParametricRangeQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/ParametricRangeQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,187 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricRangeQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.ParametricQueryNode.CompareOperator;
+import org.apache.lucene.queryParser.original.config.ConstantScoreRewriteAttribute;
+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.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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. <br/>
+ * <br/>
+ * 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. <br/>
+ * <br/>
+ * If a {@link DateResolutionAttribute} is defined and the {@link Resolution} is
+ * not <code>null</code> it will also be used to parse the date value. <br/>
+ * <br/>
+ * 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 <code>null</code>, it's set on the
+ * {@link RangeQueryNode}. <br/>
+ * 
+ * @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(
+          ConstantScoreRewriteAttribute.class)) {
+        throw new IllegalArgumentException(
+            "ConstantScoreRewriteAttribute should be set on the QueryConfigHandler");
+      }
+
+      boolean constantScoreRewrite = ((ConstantScoreRewriteAttribute) getQueryConfigHandler()
+          .getAttribute(ConstantScoreRewriteAttribute.class))
+          .isConstantScoreRewrite();
+
+      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, constantScoreRewrite);
+
+    }
+
+    return node;
+
+  }
+
+  protected QueryNode preProcessNode(QueryNode node) throws QueryNodeException {
+
+    return node;
+
+  }
+
+  protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/DefaultPhraseSlopQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/DefaultPhraseSlopQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/DefaultPhraseSlopQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,118 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.DefaultPhraseSlopAttribute;
+import org.apache.lucene.queryParser.original.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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. <br/>
+ * 
+ * @see SlopQueryNode
+ * @see DefaultPhraseSlopAttribute
+ * @see QueryParserWrapper#setPhraseSlop(int)
+ */
+@SuppressWarnings("deprecation")
+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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/package.html	(revision 0)
@@ -0,0 +1,33 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Lucene Query Node Processors</h2>
+<p>
+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.
+</p>
+<p>
+This processors are already assembled correctly in the LuceneQueryNodeProcessorPipeline. 
+</p>
+</body>
+</html>
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/GroupQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/GroupQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/GroupQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,220 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.DefaultOperatorAttribute;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator;
+import org.apache.lucene.queryParser.original.nodes.BooleanModifierNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessor;
+
+/**
+ * The {@link org.apache.lucene.queryParser.original.parser.TextParser}
+ * 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. <br/>
+ * <br/>
+ * 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 QueryParserWrapper
+ */
+@SuppressWarnings("deprecation")
+public class GroupQueryNodeProcessor implements QueryNodeProcessor {
+
+  private ArrayList<QueryNode> 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<QueryNode>();
+    this.latestNodeVerified = false;
+    readTree(queryTree);
+
+    List<QueryNode> 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<QueryNode> 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;
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode.Modifier;
+import org.apache.lucene.queryParser.original.nodes.BooleanModifierNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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} <br/>
+ * 
+ * @see ModifierQueryNode
+ */
+public class BooleanSingleChildOptimizationQueryNodeProcessor extends
+    QueryNodeProcessorImpl {
+
+  public BooleanSingleChildOptimizationQueryNodeProcessor() {
+    // empty constructor
+  }
+
+  protected QueryNode postProcessNode(QueryNode node) throws QueryNodeException {
+
+    if (node instanceof BooleanQueryNode) {
+      List<QueryNode> 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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MultiFieldQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MultiFieldQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/MultiFieldQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,134 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldableNode;
+import org.apache.lucene.queryParser.nodes.GroupQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.MultiFieldQueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.MultiFieldAttribute;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+/**
+ * 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. <br/>
+ * <br/>
+ * 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. <br/>
+ * 
+ * @see MultiFieldAttribute
+ * @see MultiFieldQueryParserWrapper
+ */
+@SuppressWarnings("deprecation")
+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<QueryNode> children = new LinkedList<QueryNode>();
+            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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PrefixWildcardQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PrefixWildcardQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/processors/PrefixWildcardQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.search.PrefixQuery;
+
+/**
+ * The {@link TextParser} 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. <br/>
+ * 
+ * @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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/PositionIncrementsAttribute.java	(revision 0)
@@ -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.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setEnablePositionIncrements(boolean)
+ */
+public class PositionIncrementsAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2804763012793049527L;
+
+  private boolean positionIncrementsEnabled = true;
+
+  public PositionIncrementsAttribute() {
+    // empty constructor
+  }
+
+  void setPositionIncrementsEnabled(boolean positionIncrementsEnabled) {
+    this.positionIncrementsEnabled = positionIncrementsEnabled;
+  }
+
+  public boolean isPositionIncrementsEnabled() {
+    return this.positionIncrementsEnabled;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof PositionIncrementsAttribute
+        && other != null
+        && ((PositionIncrementsAttribute) other).positionIncrementsEnabled == this.positionIncrementsEnabled) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return this.positionIncrementsEnabled ? -1 : Integer.MAX_VALUE;
+  }
+
+  public String toString() {
+    return "<positionIncrements positionIncrementsEnabled="
+        + this.positionIncrementsEnabled + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AllowLeadingWildcardAttribute.java	(revision 0)
@@ -0,0 +1,79 @@
+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.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setAllowLeadingWildcard(boolean)
+ */
+public class AllowLeadingWildcardAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2804763012723049527L;
+
+  private boolean allowLeadingWildcard = true;
+
+  public AllowLeadingWildcardAttribute() {
+    // empty constructor
+  }
+
+  public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
+    this.allowLeadingWildcard = allowLeadingWildcard;
+  }
+
+  public boolean isAllowLeadingWildcard() {
+    return this.allowLeadingWildcard;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof AllowLeadingWildcardAttribute
+        && ((AllowLeadingWildcardAttribute) other).allowLeadingWildcard == this.allowLeadingWildcard) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return this.allowLeadingWildcard ? -1 : Integer.MAX_VALUE;
+  }
+
+  public String toString() {
+    return "<allowLeadingWildcard allowLeadingWildcard="
+        + this.allowLeadingWildcard + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DateResolutionAttribute.java	(revision 0)
@@ -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 org.apache.lucene.document.DateTools;
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setDateResolution(DateTools.Resolution)
+ */
+public class DateResolutionAttribute extends Attribute {
+
+  private static final long serialVersionUID = -6804360312723049526L;
+
+  private DateTools.Resolution dateResolution;
+
+  public DateResolutionAttribute() {
+    // empty constructor
+  }
+
+  void setDateResolution(DateTools.Resolution dateResolution) {
+    this.dateResolution = dateResolution;
+  }
+
+  public DateTools.Resolution getDateResolution() {
+    return this.dateResolution;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof DateResolutionAttribute) {
+      DateResolutionAttribute dateResAttr = (DateResolutionAttribute) 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 "<dateResolutionAttribute dateResolution='" + this.dateResolution
+        + "'/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/MultiFieldAttribute.java	(revision 0)
@@ -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 java.util.Arrays;
+
+import org.apache.lucene.queryParser.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.MultiFieldQueryParserWrapper
+ */
+public class MultiFieldAttribute extends Attribute {
+
+  private static final long serialVersionUID = -6809760312720049526L;
+
+  private CharSequence[] fields;
+
+  public MultiFieldAttribute() {
+    // empty constructor
+  }
+
+  void setFields(CharSequence[] fields) {
+    this.fields = fields;
+  }
+
+  public CharSequence[] getFields() {
+    return this.fields;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof MultiFieldAttribute) {
+      MultiFieldAttribute fieldsAttr = (MultiFieldAttribute) other;
+
+      return Arrays.equals(this.fields, fieldsAttr.fields);
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return Arrays.hashCode(this.fields);
+  }
+
+  public String toString() {
+    return "<fieldsAttribute fields=" + Arrays.toString(this.fields) + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/package.html	(revision 0)
@@ -0,0 +1,34 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+
+<h2>Original Lucene Query Configuration</h2>
+<p>
+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.
+</p>
+<p>
+LuceneQueryConfigHandler is the class that should be used to configure the LuceneQueryNodeProcessorPipeline.
+</p>
+</body>
+</html>
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostConfigListener.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostConfigListener.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FieldBoostConfigListener.java	(revision 0)
@@ -0,0 +1,77 @@
+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.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.FieldConfigListener;
+
+/**
+ * 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
+ * 
+ * @see BoostAttribute
+ * @see Map
+ * @see FieldConfig
+ * @see FieldConfigListener
+ */
+public class FieldBoostConfigListener extends HashMap<String, Float> implements
+    FieldConfigListener {
+
+  private static final long serialVersionUID = -5929802948798314067L;
+
+  public FieldBoostConfigListener() {
+    // empty constructor
+  }
+
+  public FieldBoostConfigListener(
+      Map<? extends String, ? extends Float> boostMap) {
+    super(boostMap);
+  }
+
+  public void getQueryConfig(FieldConfig fieldConfig) {
+    CharSequence fieldName = fieldConfig.getFieldName();
+
+    if (fieldName != null) {
+
+      Float boost = get(fieldName.toString());
+      BoostAttribute boostAttr;
+
+      if (boost != null) {
+
+        if (fieldConfig.hasAttribute(BoostAttribute.class)) {
+          boostAttr = (BoostAttribute) fieldConfig
+              .getAttribute(BoostAttribute.class);
+
+        } else {
+          boostAttr = (BoostAttribute) fieldConfig
+              .addAttribute(BoostAttribute.class);
+        }
+
+        boostAttr.setBoost(boost.floatValue());
+
+      }
+
+    }
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/AnalyzerAttribute.java	(revision 0)
@@ -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 org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.queryParser.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#getAnalyzer()
+ */
+public class AnalyzerAttribute extends Attribute {
+
+  private static final long serialVersionUID = -6804760312723049526L;
+
+  private Analyzer analyzer;
+
+  public AnalyzerAttribute() {
+    // empty constructor
+  }
+
+  void setAnalyzer(Analyzer analyzer) {
+    this.analyzer = analyzer;
+  }
+
+  public Analyzer getAnalyzer() {
+    return this.analyzer;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof AnalyzerAttribute) {
+      AnalyzerAttribute analyzerAttr = (AnalyzerAttribute) 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 "<analyzerAttribute analyzer='" + this.analyzer + "'/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LuceneQueryConfigHandler.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LuceneQueryConfigHandler.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LuceneQueryConfigHandler.java	(revision 0)
@@ -0,0 +1,425 @@
+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 java.util.HashMap;
+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.QueryParser;
+import org.apache.lucene.queryParser.config.DefaultQueryConfigHandler;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.FieldConfigListener;
+import org.apache.lucene.queryParser.original.nodes.RangeQueryNode;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.search.FuzzyQuery;
+
+/**
+ * This query configuration handler is used for almost every processor defined
+ * in the {@link LuceneQueryNodeProcessorPipeline} processor pipeline. It holds
+ * attributes that reproduces the configuration that could be set on the old
+ * query parser: {@link QueryParser}. <br/>
+ * 
+ * @see LuceneQueryNodeProcessorPipeline
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper
+ */
+public class LuceneQueryConfigHandler extends DefaultQueryConfigHandler
+    implements FieldConfigListener {
+
+  public static enum Operator {
+    AND, OR;
+  }
+
+  private Map<CharSequence, Float> boosts;
+
+  private LowercaseExpandedTermsAttribute lowercaseExpandedTermsAttr;
+
+  private DefaultOperatorAttribute defaultOperatorAttribute;
+
+  private AllowLeadingWildcardAttribute allowLeadingWildcardAttribute;
+
+  private DefaultPhraseSlopAttribute defaultPhraseSlopAttribute;
+
+  private PositionIncrementsAttribute positionIncrementsAttribute;
+
+  private ConstantScoreRewriteAttribute constantScoreRewriteAttribute;
+
+  private RangeCollatorAttribute rangeCollatorAttribute;
+
+  private DateTools.Resolution defaultDateResolution;
+
+  private AnalyzerAttribute analyzerAttr;
+
+  private LocaleAttribute localeAttribute;
+
+  private FuzzyAttribute fuzzyAttribute;
+
+  private HashMap<CharSequence, DateTools.Resolution> dateResolutions;
+
+  public LuceneQueryConfigHandler() {
+    addFieldConfigListener(this);
+
+    // setting the old QueryParser default values
+    Collator collator = null;
+    Locale locale = Locale.getDefault();
+    int defaultPhraseSlop = 0;
+    boolean lowercaseExpandedTerms = true;
+    boolean allowLeadingWildcard = true;
+    boolean constantScoreRewrite = true;
+    boolean positionIncrementsEnabled = false;
+    this.defaultDateResolution = null;
+
+    this.rangeCollatorAttribute = ((RangeCollatorAttribute) addAttribute(RangeCollatorAttribute.class));
+    this.rangeCollatorAttribute.setDateResolution(collator);
+
+    this.defaultOperatorAttribute = ((DefaultOperatorAttribute) addAttribute(DefaultOperatorAttribute.class));
+
+    this.analyzerAttr = ((AnalyzerAttribute) addAttribute(AnalyzerAttribute.class));
+    this.analyzerAttr.setAnalyzer(null);
+
+    this.fuzzyAttribute = ((FuzzyAttribute) addAttribute(FuzzyAttribute.class));
+
+    this.lowercaseExpandedTermsAttr = ((LowercaseExpandedTermsAttribute) addAttribute(LowercaseExpandedTermsAttribute.class));
+    this.lowercaseExpandedTermsAttr
+        .setLowercaseExpandedTerms(lowercaseExpandedTerms);
+
+    this.constantScoreRewriteAttribute = ((ConstantScoreRewriteAttribute) addAttribute(ConstantScoreRewriteAttribute.class));
+    this.constantScoreRewriteAttribute
+        .setConstantScoreRewrite(constantScoreRewrite);
+
+    this.allowLeadingWildcardAttribute = ((AllowLeadingWildcardAttribute) addAttribute(AllowLeadingWildcardAttribute.class));
+    this.allowLeadingWildcardAttribute
+        .setAllowLeadingWildcard(allowLeadingWildcard);
+
+    this.positionIncrementsAttribute = ((PositionIncrementsAttribute) addAttribute(PositionIncrementsAttribute.class));
+    this.positionIncrementsAttribute
+        .setPositionIncrementsEnabled(positionIncrementsEnabled);
+
+    this.localeAttribute = ((LocaleAttribute) addAttribute(LocaleAttribute.class));
+    this.localeAttribute.setLocale(locale);
+
+    this.defaultPhraseSlopAttribute = ((DefaultPhraseSlopAttribute) addAttribute(DefaultPhraseSlopAttribute.class));
+    this.defaultPhraseSlopAttribute.setDefaultPhraseSlop(defaultPhraseSlop);
+
+  }
+
+  /**
+   * Gets implicit operator setting, which will be either {@link Operator#AND}
+   * or {@link Operator#OR}.
+   */
+  public Operator getDefaultOperator() {
+    return this.defaultOperatorAttribute.getOperator();
+  }
+
+  /**
+   * Sets the collator used to determine index term inclusion in ranges for
+   * RangeQuerys.
+   * <p/>
+   * <strong>WARNING:</strong> 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) {
+    this.rangeCollatorAttribute.setDateResolution(collator);
+  }
+
+  /**
+   * @return the collator used to determine index term inclusion in ranges for
+   *         RangeQuerys.
+   */
+  public Collator getRangeCollator() {
+    return this.rangeCollatorAttribute.getRangeCollator();
+  }
+
+  /**
+   * Sets the boolean operator of the QueryParser. In default mode (
+   * {@link Operator#OR}) terms without any modifiers are considered optional:
+   * for example <code>capital of Hungary</code> is equal to
+   * <code>capital OR of OR Hungary</code>.<br/>
+   * In {@link Operator#AND} mode terms are considered to be in conjunction: the
+   * above mentioned query is parsed as <code>capital AND of AND Hungary</code>
+   */
+  public void setDefaultOperator(Operator operator) {
+    this.defaultOperatorAttribute.setOperator(operator);
+  }
+
+  /**
+   * Set to <code>true</code> to allow leading wildcard characters.
+   * <p>
+   * When set, <code>*</code> or <code>?</code> are allowed as the first
+   * character of a PrefixQuery and WildcardQuery. Note that this can produce
+   * very slow queries on big indexes.
+   * <p>
+   * Default: false.
+   */
+  public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+    this.lowercaseExpandedTermsAttr
+        .setLowercaseExpandedTerms(lowercaseExpandedTerms);
+  }
+
+  /**
+   * @see #setLowercaseExpandedTerms(boolean)
+   */
+  public boolean getLowercaseExpandedTerms() {
+    return this.lowercaseExpandedTermsAttr.isLowercaseExpandedTerms();
+  }
+
+  /**
+   * Set to <code>true</code> to allow leading wildcard characters.
+   * <p>
+   * When set, <code>*</code> or <code>?</code> are allowed as the first
+   * character of a PrefixQuery and WildcardQuery. Note that this can produce
+   * very slow queries on big indexes.
+   * <p>
+   * Default: false.
+   */
+  public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
+    this.allowLeadingWildcardAttribute
+        .setAllowLeadingWildcard(allowLeadingWildcard);
+  }
+
+  /**
+   * Set to <code>true</code> to enable position increments in result query.
+   * <p>
+   * 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.
+   * <p>
+   * Default: false.
+   */
+  public void setEnablePositionIncrements(boolean enabled) {
+    this.positionIncrementsAttribute.setPositionIncrementsEnabled(enabled);
+  }
+
+  /**
+   * @see #setEnablePositionIncrements(boolean)
+   */
+  public boolean getEnablePositionIncrements() {
+    return this.positionIncrementsAttribute.isPositionIncrementsEnabled();
+  }
+
+  /**
+   * By default, it uses constant-score rewriting 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 set
+   * this option to <code>true</code> Default is <code>false</code>.
+   */
+  public void setConstantScoreRewrite(boolean constantScoreRewrite) {
+    this.constantScoreRewriteAttribute
+        .setConstantScoreRewrite(constantScoreRewrite);
+  }
+
+  /**
+   * @see #setConstantScoreRewrite(boolean)
+   */
+  public boolean getConstantScoreRewrite() {
+    return this.constantScoreRewriteAttribute.isConstantScoreRewrite();
+  }
+
+  public void setFieldsBoost(Map<CharSequence, Float> boosts) {
+    this.boosts = boosts;
+  }
+
+  public void setMultiFields(CharSequence[] fields) {
+
+    if (fields == null) {
+      fields = new CharSequence[0];
+    }
+
+    MultiFieldAttribute multiFieldAttr = (MultiFieldAttribute) addAttribute(MultiFieldAttribute.class);
+    multiFieldAttr.setFields(fields);
+
+  }
+
+  /**
+   * Returns the date resolution that is used by {@link RangeQueryNode}s for the
+   * given field. Returns <code>null</code>, if no default or field specific
+   * date resolution has been set for the given field.
+   * 
+   */
+  public DateTools.Resolution getDateResolution(String fieldName) {
+    if (fieldName == null) {
+      throw new IllegalArgumentException("Field cannot be null.");
+    }
+
+    if (this.dateResolutions == null) {
+      // no field specific date resolutions set; return default date
+      // resolution instead
+      return this.defaultDateResolution;
+    }
+
+    DateTools.Resolution resolution = (DateTools.Resolution) this.dateResolutions
+        .get(fieldName);
+    if (resolution == null) {
+      // no date resolutions set for the given field; return default date
+      // resolution instead
+      resolution = this.defaultDateResolution;
+    }
+
+    return resolution;
+  }
+
+  /**
+   * 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
+   * {@link #setDateResolution(String, DateTools.Resolution)}.
+   * 
+   * @param dateResolution
+   *          the default date resolution to set
+   */
+  public void setDateResolution(DateTools.Resolution dateResolution) {
+    this.defaultDateResolution = dateResolution;
+  }
+
+  /**
+   * Set the prefix length for fuzzy queries. Default is 0.
+   * 
+   * @param fuzzyPrefixLength
+   *          The fuzzyPrefixLength to set.
+   */
+  public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
+    this.fuzzyAttribute.setPrefixLength(fuzzyPrefixLength);
+  }
+
+  /**
+   * Set locale used by date range parsing.
+   */
+  public void setLocale(Locale locale) {
+    this.localeAttribute.setLocale(locale);
+  }
+
+  /**
+   * Returns current locale, allowing access by subclasses.
+   */
+  public Locale getLocale() {
+    return this.localeAttribute.getLocale();
+  }
+
+  /**
+   * Sets the default slop for phrases. If zero, then exact phrase matches are
+   * required. Default value is zero.
+   */
+  public void setDefaultPhraseSlop(int defaultPhraseSlop) {
+    this.defaultPhraseSlopAttribute.setDefaultPhraseSlop(defaultPhraseSlop);
+  }
+
+  public void setAnalyzer(Analyzer analyzer) {
+    this.analyzerAttr.setAnalyzer(analyzer);
+  }
+
+  /**
+   * 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
+   * {@link #setDateResolution(String, DateTools.Resolution)}.
+   * 
+   * @param dateResolution
+   *          the default date resolution to set
+   */
+  public void setDateResolution(String fieldName,
+      DateTools.Resolution dateResolution) {
+
+    if (this.dateResolutions == null) {
+      this.dateResolutions = new HashMap<CharSequence, DateTools.Resolution>();
+    }
+
+    if (fieldName != null) {
+      this.dateResolutions.put(fieldName.toString(), dateResolution);
+    }
+
+  }
+
+  /**
+   * @see #setAllowLeadingWildcard(boolean)
+   */
+  public boolean getAllowLeadingWildcard() {
+    return this.allowLeadingWildcardAttribute.isAllowLeadingWildcard();
+  }
+
+  /**
+   * Get the minimal similarity for fuzzy queries.
+   */
+  public float getFuzzyMinSim() {
+    return this.fuzzyAttribute.getFuzzyMinSimilarity();
+  }
+
+  /**
+   * Get the prefix length for fuzzy queries.
+   * 
+   * @return Returns the fuzzyPrefixLength.
+   */
+  public int getFuzzyPrefixLength() {
+    return this.fuzzyAttribute.getPrefixLength();
+  }
+
+  /**
+   * Gets the default slop for phrases.
+   */
+  public int getPhraseSlop() {
+    return this.defaultPhraseSlopAttribute.getDefaultPhraseSlop();
+  }
+
+  /**
+   * Set the minimum similarity for fuzzy queries. Default is defined on
+   * {@link FuzzyQuery#defaultMinSimilarity}.
+   */
+  public void setFuzzyMinSim(float fuzzyMinSim) {
+    this.fuzzyAttribute.setFuzzyMinSimilarity(fuzzyMinSim);
+  }
+
+  public void getQueryConfig(FieldConfig fieldConfig) {
+    DateResolutionAttribute dateResolutionAttr = (DateResolutionAttribute) fieldConfig
+        .addAttribute(DateResolutionAttribute.class);
+    DateTools.Resolution dateRes = null;
+
+    if (this.dateResolutions != null) {
+      dateRes = this.dateResolutions.get(fieldConfig.getFieldName().toString());
+    }
+
+    if (dateRes == null) {
+      dateRes = this.defaultDateResolution;
+    }
+
+    dateResolutionAttr.setDateResolution(dateRes);
+
+    if (this.boosts != null) {
+      BoostAttribute boostAttr = (BoostAttribute) fieldConfig
+          .addAttribute(BoostAttribute.class);
+      Float boost = this.boosts.get(fieldConfig.getFieldName());
+
+      if (boost != null) {
+        boostAttr.setBoost(boost.floatValue());
+      }
+
+    }
+
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/BoostAttribute.java	(revision 0)
@@ -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.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. <br/>
+ * <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.MultiFieldQueryParserWrapper
+ */
+public class BoostAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2104763012523049527L;
+
+  private float boost = 1.0f;
+
+  public BoostAttribute() {
+    // empty constructor
+  }
+
+  void setBoost(float boost) {
+    this.boost = boost;
+  }
+
+  public float getBoost() {
+    return this.boost;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof BoostAttribute && other != null
+        && ((BoostAttribute) other).boost == this.boost) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return Float.valueOf(this.boost).hashCode();
+  }
+
+  public String toString() {
+    return "<boost boost=" + this.boost + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/RangeCollatorAttribute.java	(revision 0)
@@ -0,0 +1,88 @@
+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.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} <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setRangeCollator(Collator)
+ */
+public class RangeCollatorAttribute extends Attribute {
+
+  private static final long serialVersionUID = -6804360312723049526L;
+
+  private Collator rangeCollator;
+
+  public RangeCollatorAttribute() {
+    // empty constructor
+  }
+
+  void setDateResolution(Collator rangeCollator) {
+    this.rangeCollator = rangeCollator;
+  }
+
+  public Collator getRangeCollator() {
+    return this.rangeCollator;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof RangeCollatorAttribute) {
+      RangeCollatorAttribute rangeCollatorAttr = (RangeCollatorAttribute) 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 "<rangeCollatorAttribute rangeCollator='" + this.rangeCollator
+        + "'/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LocaleAttribute.java	(revision 0)
@@ -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.Locale;
+
+import org.apache.lucene.queryParser.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setLocale(Locale)
+ */
+public class LocaleAttribute extends Attribute {
+
+  private static final long serialVersionUID = -6804760312720049526L;
+
+  private Locale locale = Locale.getDefault();
+
+  public LocaleAttribute() {
+    // empty constructor
+  }
+
+  void setLocale(Locale locale) {
+    this.locale = locale;
+  }
+
+  public Locale getLocale() {
+    return this.locale;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof LocaleAttribute) {
+      LocaleAttribute localeAttr = (LocaleAttribute) 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 "<localeAttribute locale=" + this.locale + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultPhraseSlopAttribute.java	(revision 0)
@@ -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.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setPhraseSlop(int)
+ */
+public class DefaultPhraseSlopAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2104763012527049527L;
+
+  private int defaultPhraseSlop = 1;
+
+  public DefaultPhraseSlopAttribute() {
+    // empty constructor
+  }
+
+  void setDefaultPhraseSlop(int defaultPhraseSlop) {
+    this.defaultPhraseSlop = defaultPhraseSlop;
+  }
+
+  public int getDefaultPhraseSlop() {
+    return this.defaultPhraseSlop;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof DefaultPhraseSlopAttribute
+        && other != null
+        && ((DefaultPhraseSlopAttribute) other).defaultPhraseSlop == this.defaultPhraseSlop) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return Integer.valueOf(this.defaultPhraseSlop).hashCode();
+  }
+
+  public String toString() {
+    return "<defaultPhraseSlop defaultPhraseSlop=" + this.defaultPhraseSlop
+        + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/ConstantScoreRewriteAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/ConstantScoreRewriteAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/ConstantScoreRewriteAttribute.java	(revision 0)
@@ -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.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.ParametricRangeQueryNodeProcessor;
+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 if the constant score rewrite is
+ * enabled. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setConstantScoreRewrite(boolean)
+ */
+public class ConstantScoreRewriteAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2104763012723049527L;
+
+  private boolean constantScoreRewrite = true;
+
+  public ConstantScoreRewriteAttribute() {
+    // empty constructor
+  }
+
+  void setConstantScoreRewrite(boolean constantScoreRewrite) {
+    this.constantScoreRewrite = constantScoreRewrite;
+  }
+
+  public boolean isConstantScoreRewrite() {
+    return this.constantScoreRewrite;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof ConstantScoreRewriteAttribute
+        && ((ConstantScoreRewriteAttribute) other).constantScoreRewrite == this.constantScoreRewrite) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return this.constantScoreRewrite ? -1 : Integer.MAX_VALUE;
+  }
+
+  public String toString() {
+    return "<constantScoreRewrite constantScoreRewrite="
+        + this.constantScoreRewrite + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/FuzzyAttribute.java	(revision 0)
@@ -0,0 +1,90 @@
+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.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.processors.PhraseSlopQueryNodeProcessor;
+import org.apache.lucene.search.FuzzyQuery;
+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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setPhraseSlop(int)
+ */
+public class FuzzyAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2104763012527049527L;
+
+  private int prefixLength = FuzzyQuery.defaultPrefixLength;
+
+  private float minSimilarity = FuzzyQuery.defaultMinSimilarity;
+
+  public FuzzyAttribute() {
+    // empty constructor
+  }
+
+  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(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof FuzzyAttribute && other != null
+        && ((FuzzyAttribute) other).prefixLength == this.prefixLength) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return Integer.valueOf(this.prefixLength).hashCode();
+  }
+
+  public String toString() {
+    return "<fuzzyAttribute prefixLength=" + this.prefixLength + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/DefaultOperatorAttribute.java	(revision 0)
@@ -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.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator;
+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. <br/>
+ * 
+ * @see QueryParserWrapper#setDefaultOperator(org.apache.lucene.queryParser.QueryParser.Operator)
+ */
+@SuppressWarnings("deprecation")
+public class DefaultOperatorAttribute extends Attribute {
+
+  private static final long serialVersionUID = -6804760312723049526L;
+
+  private Operator operator = Operator.OR;
+
+  public DefaultOperatorAttribute() {
+    // 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(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof DefaultOperatorAttribute) {
+      DefaultOperatorAttribute defaultOperatorAttr = (DefaultOperatorAttribute) other;
+
+      if (defaultOperatorAttr.getOperator() == this.getOperator()) {
+        return true;
+
+      }
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return getOperator().hashCode() * 31;
+  }
+
+  public String toString() {
+    return "<defaultOperatorAttribute operator=" + this.operator.name() + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttribute.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttribute.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/original/config/LowercaseExpandedTermsAttribute.java	(revision 0)
@@ -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.Locale;
+
+import org.apache.lucene.queryParser.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. <br/>
+ * 
+ * @see org.apache.lucene.queryParser.original.QueryParserWrapper#setLowercaseExpandedTerms(boolean)
+ */
+public class LowercaseExpandedTermsAttribute extends Attribute {
+
+  private static final long serialVersionUID = -2804760312723049527L;
+
+  private boolean lowercaseExpandedTerms = true;
+
+  public LowercaseExpandedTermsAttribute() {
+    // empty constructor
+  }
+
+  void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+    this.lowercaseExpandedTerms = lowercaseExpandedTerms;
+  }
+
+  public boolean isLowercaseExpandedTerms() {
+    return this.lowercaseExpandedTerms;
+  }
+
+  public void clear() {
+    throw new UnsupportedOperationException();
+  }
+
+  public void copyTo(Attribute target) {
+    throw new UnsupportedOperationException();
+  }
+
+  public boolean equals(Object other) {
+
+    if (other instanceof LowercaseExpandedTermsAttribute
+        && ((LowercaseExpandedTermsAttribute) other).lowercaseExpandedTerms == this.lowercaseExpandedTerms) {
+
+      return true;
+
+    }
+
+    return false;
+
+  }
+
+  public int hashCode() {
+    return this.lowercaseExpandedTerms ? -1 : Integer.MAX_VALUE;
+  }
+
+  public String toString() {
+    return "<lowercaseExpandedTerms lowercaseExpandedTerms="
+        + this.lowercaseExpandedTerms + "/>";
+  }
+
+}
Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/Parser.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/Parser.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/Parser.java	(revision 0)
@@ -0,0 +1,36 @@
+package org.apache.lucene.queryParser.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.queryParser.QueryNodeParseException;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * A parser needs to implement {@link Parser} interface
+ */
+public interface Parser {
+  /**
+   * @param query
+   *          - query data to be parsed
+   * @param field
+   *          - default field name
+   * @return QueryNode tree
+   */
+  public QueryNode parse(CharSequence query, CharSequence field)
+      throws QueryNodeParseException;
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/Parser.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java	(revision 0)
@@ -0,0 +1,41 @@
+package org.apache.lucene.queryParser.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;
+
+/**
+ * A parser needs to implement {@link EscapeQuerySyntax} to allow the QueryNode
+ * to escape the queries, when the toQueryString method is called.
+ */
+public interface EscapeQuerySyntax {
+  public enum Type {
+    STRING, NORMAL;
+  }
+
+  /**
+   * @param text
+   *          - text to be escaped
+   * @param locale
+   *          - locale for the current query
+   * @param type
+   *          - select the type of escape operation to use
+   * @return escaped text
+   */
+  CharSequence escape(CharSequence text, Locale locale, Type type);
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/package.html	(revision 0)
@@ -0,0 +1,41 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+<h2>Parser</h2>
+<p>
+The package <tt>org.apache.lucene.queryParser.parser</tt> contains interfaces
+that should be implemented by the parsers.
+
+Parsers produce QueryNode Trees from a string object.
+These package still needs some work to add support to for multiple parsers.
+
+Features that should be supported for the future, related with the parser:
+- QueryNode tree should be able convertible to any parser syntax.
+- The query syntax should support calling other parsers.
+- QueryNode tree created by multiple parsers.
+
+</p>
+<p>
+
+</p>
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/parser/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeException.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeException.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeException.java	(revision 0)
@@ -0,0 +1,87 @@
+package org.apache.lucene.queryParser;
+
+/**
+ * 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.Message;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.messages.NLS;
+import org.apache.lucene.messages.NLSException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * <p>
+ * This exception should be thrown if something wrong happens when dealing with
+ * {@link QueryNode}s.
+ * </p>
+ * <p>
+ * It also supports NLS messages.
+ * </p>
+ * 
+ * @see Message
+ * @see NLS
+ * @see NLSException
+ * @see QueryNode
+ */
+public class QueryNodeException extends Exception implements NLSException {
+
+  private static final long serialVersionUID = -5962648855261624214L;
+
+  protected Message message = new MessageImpl(QueryParserMessages.EMPTY_MESSAGE);
+
+  public QueryNodeException(Message message) {
+    super(message.getKey());
+
+    this.message = message;
+
+  }
+
+  public QueryNodeException(Throwable throwable) {
+    super(throwable);
+  }
+
+  public QueryNodeException(Message message, Throwable throwable) {
+    super(message.getKey(), throwable);
+
+    this.message = message;
+
+  }
+
+  public Message getMessageObject() {
+    return this.message;
+  }
+
+  public String getMessage() {
+    return getLocalizedMessage();
+  }
+
+  public String getLocalizedMessage() {
+    return getLocalizedMessage(Locale.getDefault());
+  }
+
+  public String getLocalizedMessage(Locale locale) {
+    return this.message.getLocalizedMessage(locale);
+  }
+
+  public String toString() {
+    return this.message.getKey() + ": " + getLocalizedMessage();
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/QueryNodeException.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchNoDocsQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchNoDocsQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchNoDocsQueryNode.java	(revision 0)
@@ -0,0 +1,37 @@
+package org.apache.lucene.queryParser.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.
+ */
+
+/**
+ * A {@link MatchNoDocsQueryNode} indicates that a query node tree or subtree
+ * will not match any documents if executed in the index.
+ * 
+ */
+public class MatchNoDocsQueryNode extends DeletedQueryNode {
+
+  private static final long serialVersionUID = 8081805751679581497L;
+
+  public MatchNoDocsQueryNode() {
+    // empty constructor
+  }
+
+  public String toString() {
+    return "<matchNoDocsQueryNode/>";
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchNoDocsQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OpaqueQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OpaqueQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OpaqueQueryNode.java	(revision 0)
@@ -0,0 +1,80 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link OpaqueQueryNode} is used for specify values that are not supposed to
+ * be parsed by the parser. For example: and XPATH query in the middle of a
+ * query string a b @xpath:'/bookstore/book[1]/title' c d
+ */
+public class OpaqueQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = 0L;
+
+  private CharSequence schema = null;
+
+  private CharSequence value = null;
+
+  /**
+   * @param schema
+   *          - schema identifier
+   * @param value
+   *          - value that was not parsed
+   */
+  public OpaqueQueryNode(CharSequence schema, CharSequence value) {
+    this.setLeaf(true);
+
+    this.schema = schema;
+    this.value = value;
+
+  }
+
+  public String toString() {
+    return "<opaque schema='" + this.schema + "' value='" + this.value + "'/>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    return "@" + this.schema + ":'" + this.value + "'";
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    OpaqueQueryNode clone = (OpaqueQueryNode) super.cloneTree();
+
+    clone.schema = this.schema;
+    clone.value = this.value;
+
+    return clone;
+  }
+
+  /**
+   * @return the schema
+   */
+  public CharSequence getSchema() {
+    return this.schema;
+  }
+
+  /**
+   * @return the value
+   */
+  public CharSequence getValue() {
+    return this.value;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OpaqueQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchAllDocsQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchAllDocsQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchAllDocsQueryNode.java	(revision 0)
@@ -0,0 +1,49 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link MatchAllDocsQueryNode} indicates that a query node tree or subtree
+ * will match all documents if executed in the index.
+ */
+public class MatchAllDocsQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -7050381275423477809L;
+
+  public MatchAllDocsQueryNode() {
+    // empty constructor
+  }
+
+  public String toString() {
+    return "<matchAllDocs field='*' term='*'>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    return "*:*";
+  }
+
+  public MatchAllDocsQueryNode cloneTree() throws CloneNotSupportedException {
+    MatchAllDocsQueryNode clone = (MatchAllDocsQueryNode) super.cloneTree();
+
+    // nothing to clone
+
+    return clone;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/MatchAllDocsQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java	(revision 0)
@@ -0,0 +1,143 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link AnyQueryNode} represents an ANY operator performed on a list of
+ * nodes.
+ */
+public class AnyQueryNode extends AndQueryNode {
+  private static final long serialVersionUID = 1000791433562954187L;
+
+  private CharSequence field = null;
+  private int minimumMatchingmElements = 0;
+
+  /**
+   * @param clauses
+   *          - the query nodes to be or'ed
+   */
+  public AnyQueryNode(List<QueryNode> clauses, CharSequence field,
+      int minimumMatchingElements) {
+    super(clauses);
+    this.field = field;
+    this.minimumMatchingmElements = minimumMatchingElements;
+
+    if (clauses != null) {
+
+      for (QueryNode clause : clauses) {
+
+        if (clause instanceof FieldQueryNode) {
+
+          if (clause instanceof QueryNodeImpl) {
+            ((QueryNodeImpl) clause).toQueryStringIgnoreFields = true;
+          }
+
+          if (clause instanceof FieldableNode) {
+            ((FieldableNode) clause).setField(field);
+          }
+
+        }
+      }
+
+    }
+
+  }
+
+  public int getMinimumMatchingElements() {
+    return this.minimumMatchingmElements;
+  }
+
+  /**
+   * returns null if the field was not specified
+   * 
+   * @return the field
+   */
+  public CharSequence getField() {
+    return this.field;
+  }
+
+  /**
+   * returns - null if the field was not specified
+   * 
+   * @return the field as a String
+   */
+  public String getFieldAsString() {
+    if (this.field == null)
+      return null;
+    else
+      return this.field.toString();
+  }
+
+  /**
+   * @param field
+   *          - the field to set
+   */
+  public void setField(CharSequence field) {
+    this.field = field;
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    AnyQueryNode clone = (AnyQueryNode) super.cloneTree();
+
+    clone.field = this.field;
+    clone.minimumMatchingmElements = this.minimumMatchingmElements;
+
+    return clone;
+  }
+
+  public String toString() {
+    if (getChildren() == null || getChildren().size() == 0)
+      return "<any field='" + this.field + "'  matchelements="
+          + this.minimumMatchingmElements + "/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<any field='" + this.field + "'  matchelements="
+        + this.minimumMatchingmElements + ">");
+    for (QueryNode clause : getChildren()) {
+      sb.append("\n");
+      sb.append(clause.toString());
+    }
+    sb.append("\n</any>");
+    return sb.toString();
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    String anySTR = "ANY " + this.minimumMatchingmElements;
+
+    StringBuilder sb = new StringBuilder();
+    if (getChildren() == null || getChildren().size() == 0) {
+      // no childs case
+    } else {
+      String filler = "";
+      for (QueryNode clause : getChildren()) {
+        sb.append(filler).append(clause.toQueryString(escapeSyntaxParser));
+        filler = " ";
+      }
+    }
+
+    if (isDefaultField(this.field)) {
+      return "( " + sb.toString() + " ) " + anySTR;
+    } else {
+      return this.field + ":(( " + sb.toString() + " ) " + anySTR + ")";
+    }
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/package.html
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/package.html	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/package.html	(revision 0)
@@ -0,0 +1,86 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+<h2>QueryNodes</h2>
+<p>
+The package <tt>org.apache.lucene.queryParser.nodes</tt> contains all the basic query nodes. The interface 
+that represents a query node is {@link org.apache.lucene.queryParser.nodes.QueryNode}. Every query node must be serializable.
+</p>
+<p>
+{@link org.apache.lucene.queryParser.nodes.QueryNode}s are used by the text parser to create a syntax tree.
+These nodes are designed to be used by UI or other text parsers.
+The default Lucene text parser is {@link org.apache.lucene.queryParser.original.parser.TextParser},
+it implements original syntax.
+</p>
+<p>
+{@link org.apache.lucene.queryParser.nodes.QueryNode} interface should be implemented by all query nodes, 
+the class {@link org.apache.lucene.queryParser.nodes.QueryNodeImpl} implements {@link org.apache.lucene.queryParser.nodes.QueryNode} and is extended
+by all current query node implementations.
+</p>
+<p>
+A query node tree can be printed to the a stream, and it generates a pseudo XML representation
+with all the nodes.
+</p>
+<p>
+A query node tree can also generate a query string that can be parsed back by the original text parser,
+at this point only the original lucene syntax is supported.
+</p>
+<p>
+Grouping nodes:
+<ul>
+<li>AndQueryNode - used for AND operator</li>
+<li>AnyQueryNode - used for ANY operator</li>
+<li>OrQueryNode - used for OR operator</li>
+<li>BooleanQueryNode - used when no operator is specified</li>
+<li>ModifierQueryNode - used for modifier operator</li>
+<li>GroupQueryNode - used for parenthesis</li>
+<li>BoostQueryNode - used for boost operator</li>
+<li>SlopQueryNode - phrase slop</li>
+<li>FuzzyQueryNode - fuzzy node</li>
+<li>ParametricRangeQueryNode - used for parametric field:[low_value TO high_value]</li>
+<li>ProximityQueryNode - used for proximity search</li>
+<li>TokenizedPhraseQueryNode - used by tokenizers/lemmatizers/analizers for phrases/autophrases</li>
+</ul>
+</p>
+<p>
+Leaf Nodes:
+<ul>
+<li>FieldQueryNode - field/value node</li>
+<li>PathQueryNode - {@link org.apache.lucene.queryParser.nodes.QueryNode} object used with path-like queries</li>
+<li>OpaqueQueryNode - Used as for part of the query that can be parsed by other parsers. schema/value</li> 
+<li>ParametricQueryNode - used for parametric field [>=|<=|=|<|>] value</li>
+<li>PrefixWildcardQueryNode - non-phrase wildcard query</li>
+<li>QuotedFieldQUeryNode - regular phrase node</li>
+<li>WildcardQueryNode - non-phrase wildcard query</li>
+</ul>
+</p>
+<p>
+Utility Nodes:
+<ul>
+<li>DeletedQueryNode - used by processors on optimizations</li>
+<li>MatchAllDocsQueryNode - used by processors on optimizations</li>
+<li>MatchNoDocsQueryNode - used by processors on optimizations</li>
+<li>NoTokenFoundQueryNode - used by tokenizers/lemmatizers/analizers</li>
+</ul>
+</p>
+</body>
+</html>

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/package.html
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java	(revision 0)
@@ -0,0 +1,64 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link QuotedFieldQueryNode} represents phrase query. Example:
+ * "life is great"
+ */
+public class QuotedFieldQueryNode extends FieldQueryNode {
+
+  private static final long serialVersionUID = -6675157780051428987L;
+
+  /**
+   * @param field
+   *          - field name
+   * @param text
+   *          - value
+   * @param begin
+   *          - position in the query string
+   * @param end
+   *          - position in the query string
+   */
+  public QuotedFieldQueryNode(CharSequence field, CharSequence text, int begin,
+      int end) {
+    super(field, text, begin, end);
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    if (isDefaultField(this.field)) {
+      return "\"" + getTermEscapeQuoted(escaper) + "\"";
+    } else {
+      return this.field + ":" + "\"" + getTermEscapeQuoted(escaper) + "\"";
+    }
+  }
+
+  public String toString() {
+    return "<quotedfield start='" + this.begin + "' end='" + this.end
+        + "' field='" + this.field + "' term='" + this.text + "'/>";
+  }
+
+  public QuotedFieldQueryNode cloneTree() throws CloneNotSupportedException {
+    QuotedFieldQueryNode clone = (QuotedFieldQueryNode) super.cloneTree();
+    // nothing to do here
+    return clone;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java	(revision 0)
@@ -0,0 +1,120 @@
+package org.apache.lucene.queryParser.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.nodes.ParametricQueryNode.CompareOperator;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link ParametricRangeQueryNode} represents LE, LT, GE, GT, EQ, NE query.
+ * Example: date >= "2009-10-10" OR price = 200
+ */
+public class ParametricRangeQueryNode extends QueryNodeImpl implements
+    FieldableNode {
+
+  private static final long serialVersionUID = 7120958816535573935L;
+
+  public ParametricRangeQueryNode(ParametricQueryNode lowerBound,
+      ParametricQueryNode upperBound) {
+
+    if (upperBound.getOperator() != CompareOperator.LE
+        && upperBound.getOperator() != CompareOperator.LT) {
+      throw new IllegalArgumentException("upper bound should have "
+          + CompareOperator.LE + " or " + CompareOperator.LT);
+    }
+
+    if (lowerBound.getOperator() != CompareOperator.GE
+        && lowerBound.getOperator() != CompareOperator.GT) {
+      throw new IllegalArgumentException("lower bound should have "
+          + CompareOperator.GE + " or " + CompareOperator.GT);
+    }
+
+    if (upperBound.getField() != lowerBound.getField()
+        || (upperBound.getField() != null && !upperBound.getField().equals(
+            lowerBound.getField()))) {
+
+      throw new IllegalArgumentException(
+          "lower and upper bounds should have the same field name!");
+
+    }
+
+    allocate();
+    setLeaf(false);
+
+    add(lowerBound);
+    add(upperBound);
+
+  }
+
+  public ParametricQueryNode getUpperBound() {
+    return (ParametricQueryNode) getChildren().get(1);
+  }
+
+  public ParametricQueryNode getLowerBound() {
+    return (ParametricQueryNode) getChildren().get(0);
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    return getLowerBound().toQueryString(escapeSyntaxParser) + " AND "
+        + getUpperBound().toQueryString(escapeSyntaxParser);
+  }
+
+  public CharSequence getField() {
+    return getLowerBound().getField();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("<parametricRange>\n\t");
+    sb.append(getUpperBound()).append("\n\t");
+    sb.append(getLowerBound()).append("\n");
+    sb.append("</parametricRange>\n");
+
+    return sb.toString();
+
+  }
+
+  public ParametricRangeQueryNode cloneTree() throws CloneNotSupportedException {
+    ParametricRangeQueryNode clone = (ParametricRangeQueryNode) super
+        .cloneTree();
+
+    // nothing to do here
+
+    return clone;
+  }
+
+  public void setField(CharSequence fieldName) {
+    List<QueryNode> children = getChildren();
+
+    if (children != null) {
+
+      for (QueryNode child : getChildren()) {
+
+        if (child instanceof FieldableNode) {
+          ((FieldableNode) child).setField(fieldName);
+        }
+
+      }
+
+    }
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java	(revision 0)
@@ -0,0 +1,225 @@
+package org.apache.lucene.queryParser.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.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import org.apache.lucene.messages.NLS;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+
+/**
+ * A {@link QueryNodeImpl} is the default implementation of the interface
+ * {@link QueryNode}
+ */
+public abstract class QueryNodeImpl implements QueryNode, Cloneable {
+
+  private static final long serialVersionUID = 5569870883474845989L;
+
+  /* index default field */
+  // TODO remove PLAINTEXT_FIELD_NAME replacing it with configuration APIs
+  public static final String PLAINTEXT_FIELD_NAME = "_plain";
+
+  private boolean isLeaf = true;
+
+  private Hashtable<CharSequence, Object> tags = new Hashtable<CharSequence, Object>();
+
+  private List<QueryNode> clauses = null;
+
+  protected void allocate() {
+
+    if (this.clauses == null) {
+      this.clauses = new ArrayList<QueryNode>();
+
+    } else {
+      this.clauses.clear();
+    }
+
+  }
+
+  public final void add(QueryNode child) {
+
+    if (isLeaf() || this.clauses == null || child == null) {
+      throw new IllegalArgumentException(NLS
+          .getLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+    }
+
+    this.clauses.add(child);
+    ((QueryNodeImpl) child).setParent(this);
+
+  }
+
+  public final void add(List<QueryNode> children) {
+
+    if (isLeaf() || this.clauses == null) {
+      throw new IllegalArgumentException(NLS
+          .getLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+    }
+
+    for (QueryNode child : getChildren()) {
+      add(child);
+    }
+
+  }
+
+  public boolean isLeaf() {
+    return this.isLeaf;
+  }
+
+  public final void set(List<QueryNode> children) {
+
+    if (isLeaf() || this.clauses == null) {
+      ResourceBundle bundle = ResourceBundle
+          .getBundle("org.apache.lucene.queryParser.messages.QueryParserMessages");
+      String message = bundle.getObject("Q0008E.NODE_ACTION_NOT_SUPPORTED")
+          .toString();
+
+      throw new IllegalArgumentException(message);
+
+    }
+
+    // reset parent value
+    for (QueryNode child : children) {
+
+      ((QueryNodeImpl) child).setParent(null);
+
+    }
+
+    // allocate new children list
+    allocate();
+
+    // add new childs and set parent
+    for (QueryNode child : children) {
+      add(child);
+    }
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    QueryNodeImpl clone = (QueryNodeImpl) super.clone();
+    clone.isLeaf = this.isLeaf;
+
+    // Reset all tags
+    clone.tags = new Hashtable<CharSequence, Object>();
+
+    // copy children
+    if (this.clauses != null) {
+      List<QueryNode> localClauses = new ArrayList<QueryNode>();
+      for (QueryNode clause : this.clauses) {
+        localClauses.add(clause.cloneTree());
+      }
+      clone.clauses = localClauses;
+    }
+
+    return clone;
+  }
+
+  public Object clone() throws CloneNotSupportedException {
+    return cloneTree();
+  }
+
+  protected void setLeaf(boolean isLeaf) {
+    this.isLeaf = isLeaf;
+  }
+
+  /**
+   * @return a List for QueryNode object. Returns null, for nodes that do not
+   *         contain children. All leaf Nodes return null.
+   */
+  public final List<QueryNode> getChildren() {
+    if (isLeaf() || this.clauses == null) {
+      return null;
+    }
+    return this.clauses;
+  }
+
+  public void setTag(CharSequence tagName, Object value) {
+    this.tags.put(tagName.toString().toLowerCase(), value);
+  }
+
+  public void unsetTag(CharSequence tagName) {
+    this.tags.remove(tagName.toString().toLowerCase());
+  }
+
+  public boolean containsTag(CharSequence tagName) {
+    return this.tags.containsKey(tagName.toString().toLowerCase());
+  }
+
+  public Object getTag(CharSequence tagName) {
+    return this.tags.get(tagName.toString().toLowerCase());
+  }
+
+  private QueryNode parent = null;
+
+  private void setParent(QueryNode parent) {
+    this.parent = parent;
+  }
+
+  public QueryNode getParent() {
+    return this.parent;
+  }
+
+  protected boolean isRoot() {
+    return getParent() == null;
+  }
+
+  /**
+   * If set to true the the method toQueryString will not write field names
+   */
+  protected boolean toQueryStringIgnoreFields = false;
+
+  /**
+   * This method is use toQueryString to detect if fld is the default field
+   * 
+   * @param fld
+   *          - field name
+   * @return true if fld is the default field
+   */
+  protected boolean isDefaultField(CharSequence fld) {
+    if (this.toQueryStringIgnoreFields)
+      return true;
+    if (fld == null)
+      return true;
+    if (QueryNodeImpl.PLAINTEXT_FIELD_NAME.equals(fld.toString()))
+      return true;
+    return false;
+  }
+
+  /**
+   * Every implementation of this class should return pseudo xml like this:
+   * 
+   * For FieldQueryNode: <field start='1' end='2' field='subject' text='foo'/>
+   * 
+   * @see org.apache.lucene.queryParser.nodes.QueryNode#toString()
+   */
+  public String toString() {
+    return super.toString();
+  }
+
+  /**
+   * @see org.apache.lucene.queryParser.nodes.QueryNode#getTag(CharSequence)
+   * @return a Map with all tags for this QueryNode
+   */
+  @SuppressWarnings( { "unchecked" })
+  public Map<CharSequence, Object> getTags() {
+    return (Map<CharSequence, Object>) this.tags.clone();
+  }
+
+} // end class QueryNodeImpl

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java	(revision 0)
@@ -0,0 +1,83 @@
+package org.apache.lucene.queryParser.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.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link GroupQueryNode} represents a location where the original user typed
+ * real parenthesis on the query string. This class is useful for queries like:
+ * a) a AND b OR c b) ( a AND b) OR c
+ * 
+ * Parenthesis might be used to define the boolean operation precedence.
+ */
+public class GroupQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -9204673493869114999L;
+
+  /**
+   * This QueryNode is used to identify parenthesis on the original query string
+   */
+  public GroupQueryNode(QueryNode query) {
+    if (query == null) {
+      throw new QueryNodeError(new MessageImpl(
+          QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "query", "null"));
+    }
+
+    allocate();
+    setLeaf(false);
+    add(query);
+  }
+
+  public QueryNode getChild() {
+    return getChildren().get(0);
+  }
+
+  public String toString() {
+    return "<group>" + "\n" + getChild().toString() + "\n</group>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (getChild() == null)
+      return "";
+
+    return "( " + getChild().toQueryString(escapeSyntaxParser) + " )";
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    GroupQueryNode clone = (GroupQueryNode) super.cloneTree();
+
+    return clone;
+  }
+
+  /**
+   * @param child
+   */
+  public void setChild(QueryNode child) {
+    List<QueryNode> list = new ArrayList<QueryNode>();
+    list.add(child);
+    this.set(list);
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TextableQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TextableQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TextableQueryNode.java	(revision 0)
@@ -0,0 +1,26 @@
+package org.apache.lucene.queryParser.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.
+ */
+
+public interface TextableQueryNode {
+
+  CharSequence getText();
+
+  void setText(CharSequence text);
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TextableQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java	(revision 0)
@@ -0,0 +1,251 @@
+package org.apache.lucene.queryParser.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.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link ProximityQueryNode} represents a query where the terms should meet
+ * specific distance conditions. (a b c) WITHIN [SENTENCE|PARAGRAPH|NUMBER]
+ * [INORDER] ("a" "b" "c") WITHIN [SENTENCE|PARAGRAPH|NUMBER] [INORDER]
+ * 
+ * TODO: Add this to the future original Lucene parser/processor/builder
+ */
+public class ProximityQueryNode extends BooleanQueryNode {
+
+  private static final long serialVersionUID = 9018220596680832916L;
+
+  public enum Type {
+    PARAGRAPH, SENTENCE, NUMBER;
+
+    CharSequence toQueryString() {
+      switch (this) {
+      case PARAGRAPH:
+        return "WITHIN PARAGRAPH";
+      case SENTENCE:
+        return "WITHIN SENTENCE";
+      case NUMBER:
+        return "WITHIN";
+      default:
+        return "WITHIN SENTENCE";
+      }
+    }
+
+    public String toString() {
+      switch (this) {
+      case PARAGRAPH:
+        return "PARAGRAPH";
+      case SENTENCE:
+        return "SENTENCE";
+      case NUMBER:
+        return "NUMBER";
+      default:
+        return "NUMBER";
+      }
+    }
+  }
+
+  // utility class
+  static public class ProximityType {
+    int pDistance = 0;
+
+    Type pType = null;
+
+    public ProximityType(Type type) {
+      this(type, 0);
+    }
+
+    public ProximityType(Type type, int distance) {
+      this.pType = type;
+      this.pDistance = distance;
+    }
+  }
+
+  private Type proximityType = Type.SENTENCE;
+  private int distance = -1;
+  private boolean inorder = false;
+  private CharSequence field = null;
+
+  /**
+   * @param clauses
+   *          - QueryNode children
+   * @param field
+   *          - field name
+   * @param type
+   *          - type of proximity query
+   * @param distance
+   *          - positive integer that specifies the distance
+   * @param inorder
+   *          - true, if the tokens should be matched in the order of the
+   *          clauses
+   */
+  public ProximityQueryNode(List<QueryNode> clauses, CharSequence field,
+      Type type, int distance, boolean inorder) {
+    super(clauses);
+    setLeaf(false);
+    this.proximityType = type;
+    this.inorder = inorder;
+    this.field = field;
+    if (type == Type.NUMBER) {
+      if (distance <= 0) {
+        throw new QueryNodeError(new MessageImpl(
+            QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "distance",
+            distance));
+
+      } else {
+        this.distance = distance;
+      }
+
+    }
+    clearFields(clauses, field);
+  }
+
+  /**
+   * @param clauses
+   *          - QueryNode children
+   * @param field
+   *          - field name
+   * @param type
+   *          - type of proximity query
+   * @param inorder
+   *          - true, if the tokens should be matched in the order of the
+   *          clauses
+   */
+  public ProximityQueryNode(List<QueryNode> clauses, CharSequence field,
+      Type type, boolean inorder) {
+    this(clauses, field, type, -1, inorder);
+  }
+
+  static private void clearFields(List<QueryNode> nodes, CharSequence field) {
+    if (nodes == null || nodes.size() == 0)
+      return;
+
+    for (QueryNode clause : nodes) {
+
+      if (clause instanceof FieldQueryNode) {
+        ((FieldQueryNode) clause).toQueryStringIgnoreFields = true;
+        ((FieldQueryNode) clause).setField(field);
+      }
+    }
+  }
+
+  public Type getProximityType() {
+    return this.proximityType;
+  }
+
+  public String toString() {
+    String distanceSTR = ((this.distance == -1) ? ("")
+        : (" distance='" + this.distance) + "'");
+
+    if (getChildren() == null || getChildren().size() == 0)
+      return "<proximity field='" + this.field + "' inorder='" + this.inorder
+          + "' type='" + this.proximityType.toString() + "'" + distanceSTR
+          + "/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<proximity field='" + this.field + "' inorder='" + this.inorder
+        + "' type='" + this.proximityType.toString() + "'" + distanceSTR + ">");
+    for (QueryNode child : getChildren()) {
+      sb.append("\n");
+      sb.append(child.toString());
+    }
+    sb.append("\n</proximity>");
+    return sb.toString();
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    String withinSTR = this.proximityType.toQueryString()
+        + ((this.distance == -1) ? ("") : (" " + this.distance))
+        + ((this.inorder) ? (" INORDER") : (""));
+
+    StringBuilder sb = new StringBuilder();
+    if (getChildren() == null || getChildren().size() == 0) {
+      // no children case
+    } else {
+      String filler = "";
+      for (QueryNode child : getChildren()) {
+        sb.append(filler).append(child.toQueryString(escapeSyntaxParser));
+        filler = " ";
+      }
+    }
+
+    if (isDefaultField(this.field)) {
+      return "( " + sb.toString() + " ) " + withinSTR;
+    } else {
+      return this.field + ":(( " + sb.toString() + " ) " + withinSTR + ")";
+    }
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    ProximityQueryNode clone = (ProximityQueryNode) super.cloneTree();
+
+    clone.proximityType = this.proximityType;
+    clone.distance = this.distance;
+    clone.field = this.field;
+
+    return clone;
+  }
+
+  /**
+   * @return the distance
+   */
+  public int getDistance() {
+    return this.distance;
+  }
+
+  /**
+   * returns null if the field was not specified in the query string
+   * 
+   * @return the field
+   */
+  public CharSequence getField() {
+    return this.field;
+  }
+
+  /**
+   * returns null if the field was not specified in the query string
+   * 
+   * @return the field
+   */
+  public String getFieldAsString() {
+    if (this.field == null)
+      return null;
+    else
+      return this.field.toString();
+  }
+
+  /**
+   * @param field
+   *          the field to set
+   */
+  public void setField(CharSequence field) {
+    this.field = field;
+  }
+
+  /**
+   * @return terms must be matched in the specified order
+   */
+  public boolean isInOrder() {
+    return this.inorder;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.java	(revision 0)
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.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.Iterator;
+import java.util.List;
+
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link OrQueryNode} represents an OR boolean operation performed on a list
+ * of nodes.
+ * 
+ */
+public class OrQueryNode extends BooleanQueryNode {
+
+  private static final long serialVersionUID = -3692323307688017852L;
+
+  /**
+   * @param clauses
+   *          - the query nodes to be or'ed
+   */
+  public OrQueryNode(List<QueryNode> clauses) {
+    super(clauses);
+    if ((clauses == null) || (clauses.size() == 0)) {
+      throw new IllegalArgumentException(
+          "OR query must have at least one clause");
+    }
+  }
+
+  public String toString() {
+    if (getChildren() == null || getChildren().size() == 0)
+      return "<boolean operation='or'/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<boolean operation='or'>");
+    for (QueryNode child : getChildren()) {
+      sb.append("\n");
+      sb.append(child.toString());
+
+    }
+    sb.append("\n</boolean>");
+    return sb.toString();
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (getChildren() == null || getChildren().size() == 0)
+      return "";
+
+    StringBuilder sb = new StringBuilder();
+    String filler = "";
+    for (Iterator<QueryNode> it = getChildren().iterator(); it.hasNext();) {
+      sb.append(filler).append(it.next().toQueryString(escapeSyntaxParser));
+      filler = " OR ";
+    }
+
+    // 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() + " )";
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PathQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PathQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PathQueryNode.java	(revision 0)
@@ -0,0 +1,214 @@
+package org.apache.lucene.queryParser.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.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax.Type;
+
+/**
+ * A {@link PathQueryNode} is used for to store queries like
+ * /company/USA/California /product/shoes/brown QueryText are objects that
+ * contain the text, begin position and end position in the query.
+ * 
+ * Example how the text parser creates these objects:
+ * 
+ * List values = ArrayList(); values.add(new PathQueryNode.QueryText("company",
+ * 1, 7)); values.add(new PathQueryNode.QueryText("USA", 9, 12)); values.add(new
+ * PathQueryNode.QueryText("California", 14, 23)); QueryNode q = new
+ * PathQueryNode(values);
+ * 
+ */
+public class PathQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -8325921322405804789L;
+
+  public static class QueryText implements Cloneable {
+    CharSequence value = null;
+    /**
+     * != null The term's begin position.
+     */
+    int begin;
+
+    /**
+     * The term's end position.
+     */
+    int end;
+
+    /**
+     * @param value
+     *          - text value
+     * @param begin
+     *          - position in the query string
+     * @param end
+     *          - position in the query string
+     */
+    public QueryText(CharSequence value, int begin, int end) {
+      super();
+      this.value = value;
+      this.begin = begin;
+      this.end = end;
+    }
+
+    public QueryText clone() throws CloneNotSupportedException {
+      QueryText clone = (QueryText) super.clone();
+      clone.value = this.value;
+      clone.begin = this.begin;
+      clone.end = this.end;
+      return clone;
+    }
+
+    /**
+     * @return the value
+     */
+    public CharSequence getValue() {
+      return value;
+    }
+
+    /**
+     * @return the begin
+     */
+    public int getBegin() {
+      return begin;
+    }
+
+    /**
+     * @return the end
+     */
+    public int getEnd() {
+      return end;
+    }
+
+    public String toString() {
+      return value + ", " + begin + ", " + end;
+    }
+  }
+
+  private List<QueryText> values = null;
+
+  /**
+   * @param pathElements
+   *          - List of QueryText objects
+   */
+  public PathQueryNode(List<QueryText> pathElements) {
+    this.values = pathElements;
+    if (pathElements.size() <= 1) {
+      // this should not happen
+      throw new RuntimeException(
+          "PathQuerynode requires more 2 or more path elements.");
+    }
+  }
+
+  /**
+   * Returns the a List with all QueryText elements
+   * 
+   * @return QueryText List size
+   */
+  public List<QueryText> getPathElements() {
+    return values;
+  }
+
+  /**
+   * Returns the a List with all QueryText elements
+   */
+  public void setPathElements(List<QueryText> elements) {
+    this.values = elements;
+  }
+
+  /**
+   * Returns the a specific QueryText element
+   * 
+   * @return QueryText List size
+   */
+  public QueryText getPathElement(int index) {
+    return values.get(index);
+  }
+
+  /**
+   * Returns the CharSequence value of a specific QueryText element
+   * 
+   * @return the CharSequence for a specific QueryText element
+   */
+  public CharSequence getFirstPathElement() {
+    return values.get(0).value;
+  }
+
+  /**
+   * Returns a List QueryText element from position startIndex
+   * 
+   * @return a List QueryText element from position startIndex
+   */
+  public List<QueryText> getPathElements(int startIndex) {
+    List<PathQueryNode.QueryText> rValues = new ArrayList<PathQueryNode.QueryText>();
+    for (int i = startIndex; i < this.values.size(); i++) {
+      try {
+        rValues.add(this.values.get(i).clone());
+      } catch (CloneNotSupportedException e) {
+        // this will not happen
+      }
+    }
+    return rValues;
+  }
+
+  private CharSequence getPathString() {
+    StringBuffer path = new StringBuffer();
+
+    for (QueryText pathelement : values) {
+      path.append("/").append(pathelement.value);
+    }
+    return path.toString();
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    StringBuffer path = new StringBuffer();
+    path.append("/").append(getFirstPathElement());
+
+    for (QueryText pathelement : getPathElements(1)) {
+      CharSequence value = escaper.escape(pathelement.value, Locale
+          .getDefault(), Type.STRING);
+      path.append("/\"").append(value).append("\"");
+    }
+    return path.toString();
+  }
+
+  public String toString() {
+    QueryText text = this.values.get(0);
+
+    return "<path start='" + text.begin + "' end='" + text.end + "' path='"
+        + getPathString() + "'/>";
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    PathQueryNode clone = (PathQueryNode) super.cloneTree();
+
+    // copy children
+    if (this.values != null) {
+      List<QueryText> localValues = new ArrayList<QueryText>();
+      for (QueryText value : this.values) {
+        localValues.add(value.clone());
+      }
+      clone.values = localValues;
+    }
+
+    return clone;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PathQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.java	(revision 0)
@@ -0,0 +1,98 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link FuzzyQueryNode} represents a element that contains
+ * field/text/similarity tuple
+ */
+public class FuzzyQueryNode extends FieldQueryNode {
+
+  private static final long serialVersionUID = -1794537213032589441L;
+
+  private float similarity;
+
+  private int prefixLength;
+
+  /**
+   * @param field
+   *          Name of the field query will use.
+   * @param termStr
+   *          Term token to use for building term for the query
+   */
+  /**
+   * @param field
+   *          - Field name
+   * @param term
+   *          - Value
+   * @param minSimilarity
+   *          - similarity value
+   * @param begin
+   *          - position in the query string
+   * @param end
+   *          - position in the query string
+   */
+  public FuzzyQueryNode(CharSequence field, CharSequence term,
+      float minSimilarity, int begin, int end) {
+    super(field, term, begin, end);
+    this.similarity = minSimilarity;
+    setLeaf(true);
+  }
+
+  public void setPrefixLength(int prefixLength) {
+    this.prefixLength = prefixLength;
+  }
+
+  public int getPrefixLength() {
+    return this.prefixLength;
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    if (isDefaultField(this.field)) {
+      return getTermEscaped(escaper) + "~" + this.similarity;
+    } else {
+      return this.field + ":" + getTermEscaped(escaper) + "~" + this.similarity;
+    }
+  }
+
+  public String toString() {
+    return "<fuzzy field='" + this.field + "' similarity='" + this.similarity
+        + "' term='" + this.text + "'/>";
+  }
+
+  public void setSimilarity(float similarity) {
+    this.similarity = similarity;
+  }
+
+  public FuzzyQueryNode cloneTree() throws CloneNotSupportedException {
+    FuzzyQueryNode clone = (FuzzyQueryNode) super.cloneTree();
+
+    clone.similarity = this.similarity;
+
+    return clone;
+  }
+
+  /**
+   * @return the similarity
+   */
+  public float getSimilarity() {
+    return this.similarity;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.java	(revision 0)
@@ -0,0 +1,100 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link ParametricQueryNode} represents LE, LT, GE, GT, EQ, NE query.
+ * Example: date >= "2009-10-10" OR price = 200
+ */
+public class ParametricQueryNode extends FieldQueryNode {
+
+  private static final long serialVersionUID = -5770038129741218116L;
+
+  private CompareOperator operator;
+
+  public enum CompareOperator {
+    LE, LT, GE, GT, EQ, NE;
+
+    public String toString() {
+      if (LE.equals(this)) {
+        return "<=";
+      } else if (LT.equals(this)) {
+        return "<";
+      } else if (GE.equals(this)) {
+        return ">=";
+      } else if (GT.equals(this)) {
+        return ">";
+      } else if (EQ.equals(this)) {
+        return "=";
+      } else if (NE.equals(this)) {
+        return "!=";
+      } else {
+        throw new IllegalArgumentException("Unknown operator");
+      }
+    }
+  }
+
+  /**
+   * @param field
+   *          - field name
+   * @param comp
+   *          - CompareOperator
+   * @param value
+   *          - text value
+   * @param begin
+   *          - position in the query string
+   * @param end
+   *          - position in the query string
+   */
+  public ParametricQueryNode(CharSequence field, CompareOperator comp,
+      CharSequence value, int begin, int end) {
+    super(field, value, begin, end);
+    this.operator = comp;
+    setLeaf(true);
+  }
+
+  public CharSequence getOperand() {
+    return getText();
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    return this.field + "" + this.operator.toString() + "\"" + this.text + "\"";
+  }
+
+  public String toString() {
+    return "<parametric field='" + this.field + "' operator='"
+        + this.operator.toString() + "' text='" + this.text + "'/>";
+  }
+
+  public ParametricQueryNode cloneTree() throws CloneNotSupportedException {
+    ParametricQueryNode clone = (ParametricQueryNode) super.cloneTree();
+
+    clone.operator = this.operator;
+
+    return clone;
+  }
+
+  /**
+   * @return the operator
+   */
+  public CompareOperator getOperator() {
+    return this.operator;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java	(revision 0)
@@ -0,0 +1,57 @@
+package org.apache.lucene.queryParser.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.
+ */
+
+/**
+ * A {@link PrefixWildcardQueryNode} represents wildcardquery that matches abc*
+ * or *. This does not apply to phrases, this is a special case on the original
+ * lucene parser. TODO: refactor the code to remove this special case from the
+ * parser. and probably do it on a Processor
+ */
+public class PrefixWildcardQueryNode extends WildcardQueryNode {
+
+  private static final long serialVersionUID = 6851557641826407515L;
+
+  /**
+   * @param field
+   *          - field name
+   * @param text
+   *          - value including the wildcard
+   * @param begin
+   *          - position in the query string
+   * @param end
+   *          - position in the query string
+   */
+  public PrefixWildcardQueryNode(CharSequence field, CharSequence text,
+      int begin, int end) {
+    super(field, text, begin, end);
+  }
+
+  public String toString() {
+    return "<prefixWildcard field='" + this.field + "' term='" + this.text
+        + "'/>";
+  }
+
+  public PrefixWildcardQueryNode cloneTree() throws CloneNotSupportedException {
+    PrefixWildcardQueryNode clone = (PrefixWildcardQueryNode) super.cloneTree();
+
+    // nothing to do here
+
+    return clone;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PhraseSlopQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PhraseSlopQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PhraseSlopQueryNode.java	(revision 0)
@@ -0,0 +1,108 @@
+package org.apache.lucene.queryParser.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.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+public class PhraseSlopQueryNode extends QueryNodeImpl implements FieldableNode {
+
+  private static final long serialVersionUID = 0L;
+
+  private int value = 0;
+
+  /**
+   * @throws QueryNodeException
+   * @throws QueryNodeParseException
+   * @exception QueryNodeParseException
+   *              throw in overridden method to disallow
+   */
+  public PhraseSlopQueryNode(QueryNode query, int value)
+      throws QueryNodeException {
+    if (query == null) {
+      throw new QueryNodeError(new MessageImpl(
+          QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
+    }
+
+    this.value = value;
+    setLeaf(false);
+    allocate();
+    add(query);
+  }
+
+  public QueryNode getChild() {
+    return getChildren().get(0);
+  }
+
+  public int getValue() {
+    return this.value;
+  }
+
+  private CharSequence getValueString() {
+    Float f = new Float(this.value);
+    if (f == f.longValue())
+      return "" + f.longValue();
+    else
+      return "" + f;
+
+  }
+
+  public String toString() {
+    return "<phraseslop value='" + getValueString() + "'>" + "\n"
+        + getChild().toString() + "\n</phraseslop>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (getChild() == null)
+      return "";
+    return getChild().toQueryString(escapeSyntaxParser) + "~"
+        + getValueString();
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    PhraseSlopQueryNode clone = (PhraseSlopQueryNode) super.cloneTree();
+
+    clone.value = this.value;
+
+    return clone;
+  }
+
+  public CharSequence getField() {
+    QueryNode child = getChild();
+
+    if (child instanceof FieldableNode) {
+      return ((FieldableNode) child).getField();
+    }
+
+    return null;
+
+  }
+
+  public void setField(CharSequence fieldName) {
+    QueryNode child = getChild();
+
+    if (child instanceof FieldableNode) {
+      ((FieldableNode) child).setField(fieldName);
+    }
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/PhraseSlopQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TokenizedPhraseQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TokenizedPhraseQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TokenizedPhraseQueryNode.java	(revision 0)
@@ -0,0 +1,104 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link TokenizedPhraseQueryNode} represents a node created by a code that
+ * tokenizes/lemmatizes/analizes.
+ */
+public class TokenizedPhraseQueryNode extends QueryNodeImpl implements
+    FieldableNode {
+
+  private static final long serialVersionUID = -7185108320787917541L;
+
+  public TokenizedPhraseQueryNode() {
+    setLeaf(false);
+    allocate();
+  }
+
+  public String toString() {
+    if (getChildren() == null || getChildren().size() == 0)
+      return "<tokenizedphrase/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<tokenizedtphrase>");
+    for (QueryNode child : getChildren()) {
+      sb.append("\n");
+      sb.append(child.toString());
+    }
+    sb.append("\n</tokenizedphrase>");
+    return sb.toString();
+  }
+
+  // This text representation is not re-parseable
+  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 "[TP[" + sb.toString() + "]]";
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    TokenizedPhraseQueryNode clone = (TokenizedPhraseQueryNode) super
+        .cloneTree();
+
+    // nothing to do
+
+    return clone;
+  }
+
+  public CharSequence getField() {
+    List<QueryNode> children = getChildren();
+
+    if (children == null || children.size() == 0) {
+      return null;
+
+    } else {
+      return ((FieldableNode) children.get(0)).getField();
+    }
+
+  }
+
+  public void setField(CharSequence fieldName) {
+    List<QueryNode> children = getChildren();
+
+    if (children != null) {
+
+      for (QueryNode child : getChildren()) {
+
+        if (child instanceof FieldableNode) {
+          ((FieldableNode) child).setField(fieldName);
+        }
+
+      }
+
+    }
+
+  }
+
+} // end class MultitermQueryNode

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/TokenizedPhraseQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/DeletedQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/DeletedQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/DeletedQueryNode.java	(revision 0)
@@ -0,0 +1,51 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryParser.processors.RemoveDeletedQueryNodesProcessor;
+
+/**
+ * A {@link DeletedQueryNode} represents a node that was deleted from the query
+ * node tree. It can be removed from the tree using the
+ * {@link RemoveDeletedQueryNodesProcessor} processor.
+ */
+public class DeletedQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -9151675506000425293L;
+
+  public DeletedQueryNode() {
+    // empty constructor
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    return "[DELETEDCHILD]";
+  }
+
+  public String toString() {
+    return "<deleted/>";
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    DeletedQueryNode clone = (DeletedQueryNode) super.cloneTree();
+
+    return clone;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/DeletedQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNode.java	(revision 0)
@@ -0,0 +1,95 @@
+package org.apache.lucene.queryParser.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.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link QueryNode} is a interface implemented by all nodes on a QueryNode
+ * tree.
+ */
+public interface QueryNode extends Serializable {
+
+  /** convert to a query string understood by the query parser */
+  // TODO: this interface might be changed in the future
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser);
+
+  /** for printing */
+  public String toString();
+
+  /** get Children nodes */
+  public List<QueryNode> getChildren();
+
+  /** verify if a node is a Leaf node */
+  public boolean isLeaf();
+
+  /** verify if a node contains a tag */
+  public boolean containsTag(CharSequence tagName);
+
+  /**
+   * @param tagName
+   * @return of stored on under that tag name
+   */
+  public Object getTag(CharSequence tagName);
+
+  public QueryNode getParent();
+
+  /**
+   * Recursive clone the QueryNode tree The tags are not copied to the new tree
+   * when you call the cloneTree() method
+   * 
+   * @return the cloned tree
+   * @throws CloneNotSupportedException
+   */
+  public QueryNode cloneTree() throws CloneNotSupportedException;
+
+  // Below are the methods that can change state of a QueryNode
+  // Write Operations (not Thread Safe)
+
+  // add a new child to a non Leaf node
+  public void add(QueryNode child);
+
+  public void add(List<QueryNode> children);
+
+  // reset the children of a node
+  public void set(List<QueryNode> children);
+
+  /**
+   * Associate the specified value with the specified tagName. If the tagName
+   * already exists, the old value is replaced. The tagName and value cannot be
+   * null. tagName will be converted to lowercase.
+   * 
+   * @param tagName
+   * @param value
+   */
+  public void setTag(CharSequence tagName, Object value);
+
+  /**
+   * Unset a tag. tagName will be converted to lowercase.
+   * 
+   * @param tagName
+   */
+  public void unsetTag(CharSequence tagName);
+
+  public Map<CharSequence, Object> getTags();
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/QueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java	(revision 0)
@@ -0,0 +1,184 @@
+package org.apache.lucene.queryParser.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.Locale;
+
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax.Type;
+
+/**
+ * A {@link FieldQueryNode} represents a element that contains field/text tuple
+ */
+public class FieldQueryNode extends QueryNodeImpl implements TextableQueryNode,
+    FieldableNode {
+
+  private static final long serialVersionUID = 3634521145130758265L;
+
+  /**
+   * The term's field
+   */
+  protected CharSequence field;
+
+  /**
+   * The term's text.
+   */
+  protected CharSequence text;
+
+  /**
+   * The term's begin position.
+   */
+  protected int begin;
+
+  /**
+   * The term's end position.
+   */
+  protected int end;
+
+  /**
+   * The term's position increment.
+   */
+  protected int positionIncrement;
+
+  /**
+   * @param field
+   *          - field name
+   * @param text
+   *          - value
+   * @param begin
+   *          - position in the query string
+   * @param end
+   *          - position in the query string
+   */
+  public FieldQueryNode(CharSequence field, CharSequence text, int begin,
+      int end) {
+    this.field = field;
+    this.text = text;
+    this.begin = begin;
+    this.end = end;
+    this.setLeaf(true);
+
+  }
+
+  CharSequence getTermEscaped(EscapeQuerySyntax escaper) {
+    return escaper.escape(this.text, Locale.getDefault(), Type.NORMAL);
+  }
+
+  CharSequence getTermEscapeQuoted(EscapeQuerySyntax escaper) {
+    return escaper.escape(this.text, Locale.getDefault(), Type.STRING);
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    if (isDefaultField(this.field)) {
+      return getTermEscaped(escaper);
+    } else {
+      return this.field + ":" + getTermEscaped(escaper);
+    }
+  }
+
+  public String toString() {
+    return "<field start='" + this.begin + "' end='" + this.end + "' field='"
+        + this.field + "' text='" + this.text + "'/>";
+  }
+
+  /**
+   * @return the term
+   */
+  public String getTextAsString() {
+    if (this.text == null)
+      return null;
+    else
+      return this.text.toString();
+  }
+
+  /**
+   * returns null if the field was not specified in the query string
+   * 
+   * @return the field
+   */
+  public String getFieldAsString() {
+    if (this.field == null)
+      return null;
+    else
+      return this.field.toString();
+  }
+
+  public int getBegin() {
+    return this.begin;
+  }
+
+  public void setBegin(int begin) {
+    this.begin = begin;
+  }
+
+  public int getEnd() {
+    return this.end;
+  }
+
+  public void setEnd(int end) {
+    this.end = end;
+  }
+
+  public CharSequence getField() {
+    return this.field;
+  }
+
+  public void setField(CharSequence field) {
+    this.field = field;
+  }
+
+  public int getPositionIncrement() {
+    return this.positionIncrement;
+  }
+
+  public void setPositionIncrement(int pi) {
+    this.positionIncrement = pi;
+  }
+
+  /**
+   * Returns the term.
+   * 
+   * @return The "original" form of the term.
+   */
+  public CharSequence getText() {
+    return this.text;
+  }
+
+  /**
+   * @param text
+   *          the text to set
+   */
+  public void setText(CharSequence text) {
+    this.text = text;
+  }
+
+  @Override
+  public FieldQueryNode cloneTree() throws CloneNotSupportedException {
+    FieldQueryNode fqn = (FieldQueryNode) super.cloneTree();
+    fqn.begin = this.begin;
+    fqn.end = this.end;
+    fqn.field = this.field;
+    fqn.text = this.text;
+    fqn.positionIncrement = this.positionIncrement;
+    fqn.toQueryStringIgnoreFields = this.toQueryStringIgnoreFields;
+
+    return fqn;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java	(revision 0)
@@ -0,0 +1,122 @@
+package org.apache.lucene.queryParser.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.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link BoostQueryNode} boosts the QueryNode tree which is under this node.
+ * So, it must only and always have one child.
+ * 
+ * The boost value may vary from 0.0 to 1.0.
+ * 
+ */
+public class BoostQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -3929082630855807593L;
+
+  private float value = 0;
+
+  /**
+   * Constructs a boost node
+   * 
+   * @param query
+   *          the query to be boosted
+   * @param value
+   *          the boost value, it may vary from 0.0 to 1.0
+   * 
+   * @throws QueryNodeException
+   */
+  public BoostQueryNode(QueryNode query, float value) throws QueryNodeException {
+    if (query == null) {
+      throw new QueryNodeError(new MessageImpl(
+          QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
+    }
+
+    this.value = value;
+    setLeaf(false);
+    allocate();
+    add(query);
+  }
+
+  /**
+   * Returns the single child which this node boosts.
+   * 
+   * @return the single child which this node boosts
+   */
+  public QueryNode getChild() {
+    List<QueryNode> children = getChildren();
+
+    if (children == null || children.size() == 0) {
+      return null;
+    }
+
+    return children.get(0);
+
+  }
+
+  /**
+   * Returns the boost value. It may vary from 0.0 to 1.0.
+   * 
+   * @return the boost value
+   */
+  public float getValue() {
+    return this.value;
+  }
+
+  /**
+   * Returns the boost value parsed to a string.
+   * 
+   * @return the parsed value
+   */
+  private CharSequence getValueString() {
+    Float f = new Float(this.value);
+    if (f == f.longValue())
+      return "" + f.longValue();
+    else
+      return "" + f;
+
+  }
+
+  public String toString() {
+    return "<boost value='" + getValueString() + "'>" + "\n"
+        + getChild().toString() + "\n</boost>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (getChild() == null)
+      return "";
+    return getChild().toQueryString(escapeSyntaxParser) + "^"
+        + getValueString();
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    BoostQueryNode clone = (BoostQueryNode) super.cloneTree();
+
+    clone.value = this.value;
+
+    return clone;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java	(revision 0)
@@ -0,0 +1,116 @@
+package org.apache.lucene.queryParser.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.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link SlopQueryNode} represents phrase query with a slop.
+ * 
+ * From Lucene FAQ: Is there a way to use a proximity operator (like near or
+ * within) with Lucene? There is a variable called slop that allows you to
+ * perform NEAR/WITHIN-like queries. By default, slop is set to 0 so that only
+ * exact phrases will match. When using TextParser you can use this syntax to
+ * specify the slop: "doug cutting"~2 will find documents that contain
+ * "doug cutting" as well as ones that contain "cutting doug".
+ */
+public class SlopQueryNode extends QueryNodeImpl implements FieldableNode {
+
+  private static final long serialVersionUID = 0L;
+
+  private int value = 0;
+
+  /**
+   * @param query
+   *          - QueryNode Tree with the phrase
+   * @param value
+   *          - slop value
+   */
+  public SlopQueryNode(QueryNode query, int value) {
+    if (query == null) {
+      throw new QueryNodeError(new MessageImpl(
+          QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
+    }
+
+    this.value = value;
+    setLeaf(false);
+    allocate();
+    add(query);
+  }
+
+  public QueryNode getChild() {
+    return getChildren().get(0);
+  }
+
+  public int getValue() {
+    return this.value;
+  }
+
+  private CharSequence getValueString() {
+    Float f = new Float(this.value);
+    if (f == f.longValue())
+      return "" + f.longValue();
+    else
+      return "" + f;
+
+  }
+
+  public String toString() {
+    return "<slop value='" + getValueString() + "'>" + "\n"
+        + getChild().toString() + "\n</slop>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (getChild() == null)
+      return "";
+    return getChild().toQueryString(escapeSyntaxParser) + "~"
+        + getValueString();
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    SlopQueryNode clone = (SlopQueryNode) super.cloneTree();
+
+    clone.value = this.value;
+
+    return clone;
+  }
+
+  public CharSequence getField() {
+    QueryNode child = getChild();
+
+    if (child instanceof FieldableNode) {
+      return ((FieldableNode) child).getField();
+    }
+
+    return null;
+
+  }
+
+  public void setField(CharSequence fieldName) {
+    QueryNode child = getChild();
+
+    if (child instanceof FieldableNode) {
+      ((FieldableNode) child).setField(fieldName);
+    }
+
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java	(revision 0)
@@ -0,0 +1,77 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link AndQueryNode} represents an AND boolean operation performed on a
+ * list of nodes.
+ */
+public class AndQueryNode extends BooleanQueryNode {
+
+  private static final long serialVersionUID = 118496077529151825L;
+
+  /**
+   * @param clauses
+   *          - the query nodes to be and'ed
+   */
+  public AndQueryNode(List<QueryNode> clauses) {
+    super(clauses);
+    if ((clauses == null) || (clauses.size() == 0)) {
+      throw new IllegalArgumentException(
+          "AND query must have at least one clause");
+    }
+  }
+
+  public String toString() {
+    if (getChildren() == null || getChildren().size() == 0)
+      return "<boolean operation='and'/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<boolean operation='and'>");
+    for (QueryNode child : getChildren()) {
+      sb.append("\n");
+      sb.append(child.toString());
+
+    }
+    sb.append("\n</boolean>");
+    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 = " AND ";
+    }
+
+    // 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() + " )";
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java	(revision 0)
@@ -0,0 +1,83 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link BooleanQueryNode} represents a list of elements which do not have an
+ * explicit boolean operator defined between them. It can be used to express a
+ * boolean query that intends to use the default boolean operator.
+ */
+public class BooleanQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -2206623652088638072L;
+
+  /**
+   * @param clauses
+   *          - the query nodes to be and'ed
+   */
+  public BooleanQueryNode(List<QueryNode> clauses) {
+    setLeaf(false);
+    allocate();
+    set(clauses);
+  }
+
+  public String toString() {
+    if (getChildren() == null || getChildren().size() == 0)
+      return "<boolean operation='default'/>";
+    StringBuilder sb = new StringBuilder();
+    sb.append("<boolean operation='default'>");
+    for (QueryNode child : getChildren()) {
+      sb.append("\n");
+      sb.append(child.toString());
+    }
+    sb.append("\n</boolean>");
+    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 = " ";
+    }
+
+    // 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 QueryNode cloneTree() throws CloneNotSupportedException {
+    BooleanQueryNode clone = (BooleanQueryNode) super.cloneTree();
+
+    // nothing to do here
+
+    return clone;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java	(revision 0)
@@ -0,0 +1,45 @@
+package org.apache.lucene.queryParser.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.
+ */
+
+/**
+ * A query node implements {@link FieldableNode} interface to indicate that its
+ * children and itself are associated to a specific field.
+ * 
+ * If it has any children which also implements this interface, it must ensure
+ * the children are associated to the same field.
+ * 
+ */
+public interface FieldableNode extends QueryNode {
+
+  /**
+   * Returns the field associated to the node and every node under it.
+   * 
+   * @return the field name
+   */
+  CharSequence getField();
+
+  /**
+   * Associates the node to a field.
+   * 
+   * @param fieldName
+   *          the field name
+   */
+  void setField(CharSequence fieldName);
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java	(revision 0)
@@ -0,0 +1,156 @@
+package org.apache.lucene.queryParser.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.ArrayList;
+import java.util.List;
+
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.queryParser.QueryNodeError;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link ModifierQueryNode} indicates the modifier value (+,-,?,NONE) for
+ * each term on the query string for example "+t1 -t2 t3" will have a tree of
+ * <BooleanQueryNode> <ModifierQueryNode modifier="MOD_REQ"> <t1/>
+ * </ModifierQueryNode> <ModifierQueryNode modifier="MOD_NOT"> <t2/>
+ * </ModifierQueryNode> <t3/> </BooleanQueryNode>
+ * 
+ */
+public class ModifierQueryNode extends QueryNodeImpl {
+
+  private static final long serialVersionUID = -391209837953928169L;
+
+  public enum Modifier {
+    MOD_NONE, MOD_NOT, MOD_REQ;
+
+    public String toString() {
+      switch (this) {
+      case MOD_NONE:
+        return "MOD_NONE";
+      case MOD_NOT:
+        return "MOD_NOT";
+      case MOD_REQ:
+        return "MOD_REQ";
+      }
+      // this code is never executed
+      return "MOD_DEFAULT";
+    }
+
+    public String toDigitString() {
+      switch (this) {
+      case MOD_NONE:
+        return "";
+      case MOD_NOT:
+        return "-";
+      case MOD_REQ:
+        return "+";
+      }
+      // this code is never executed
+      return "";
+    }
+
+    public String toLargeString() {
+      switch (this) {
+      case MOD_NONE:
+        return "";
+      case MOD_NOT:
+        return "NOT ";
+      case MOD_REQ:
+        return "+";
+      }
+      // this code is never executed
+      return "";
+    }
+  }
+
+  private Modifier modifier = Modifier.MOD_NONE;
+
+  /**
+   * Used to store the modifier value on the original query string
+   * 
+   * @param query
+   *          - QueryNode subtree
+   * @param mod
+   *          - Modifier Value
+   */
+  public ModifierQueryNode(QueryNode query, Modifier mod) {
+    if (query == null) {
+      throw new QueryNodeError(new MessageImpl(
+          QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "query", "null"));
+    }
+
+    allocate();
+    setLeaf(false);
+    add(query);
+    this.modifier = mod;
+  }
+
+  public QueryNode getChild() {
+    return getChildren().get(0);
+  }
+
+  public Modifier getModifier() {
+    return this.modifier;
+  }
+
+  public String toString() {
+    return "<modifier operation='" + this.modifier.toString() + "'>" + "\n"
+        + getChild().toString() + "\n</modifier>";
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escapeSyntaxParser) {
+    if (getChild() == null)
+      return "";
+
+    String leftParenthensis = "";
+    String rightParenthensis = "";
+
+    if (getChild() != null && getChild() instanceof ModifierQueryNode) {
+      leftParenthensis = "(";
+      rightParenthensis = ")";
+    }
+
+    if (getChild() instanceof BooleanQueryNode) {
+      return this.modifier.toLargeString() + leftParenthensis
+          + getChild().toQueryString(escapeSyntaxParser) + rightParenthensis;
+    } else {
+      return this.modifier.toDigitString() + leftParenthensis
+          + getChild().toQueryString(escapeSyntaxParser) + rightParenthensis;
+    }
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    ModifierQueryNode clone = (ModifierQueryNode) super.cloneTree();
+
+    clone.modifier = this.modifier;
+
+    return clone;
+  }
+
+  /**
+   * @param child
+   */
+  public void setChild(QueryNode child) {
+    List<QueryNode> list = new ArrayList<QueryNode>();
+    list.add(child);
+    this.set(list);
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java	(revision 0)
@@ -0,0 +1,63 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link WildcardQueryNode} represents wildcard query This does not apply to
+ * phrases. Examples: a*b*c Fl?w? m?ke*g
+ */
+public class WildcardQueryNode extends FieldQueryNode {
+  private static final long serialVersionUID = 0L;
+
+  /**
+   * @param field
+   *          - field name
+   * @param text
+   *          - value that contains one or more wild card characters (? or *)
+   * @param begin
+   *          - position in the query string
+   * @param end
+   *          - position in the query string
+   */
+  public WildcardQueryNode(CharSequence field, CharSequence text, int begin,
+      int end) {
+    super(field, text, begin, end);
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    if (isDefaultField(this.field)) {
+      return getTermEscaped(escaper);
+    } else {
+      return this.field + ":" + getTermEscaped(escaper);
+    }
+  }
+
+  public String toString() {
+    return "<wildcard field='" + this.field + "' term='" + this.text + "'/>";
+  }
+
+  public WildcardQueryNode cloneTree() throws CloneNotSupportedException {
+    WildcardQueryNode clone = (WildcardQueryNode) super.cloneTree();
+
+    // nothing to do here
+
+    return clone;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/NoTokenFoundQueryNode.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/NoTokenFoundQueryNode.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/NoTokenFoundQueryNode.java	(revision 0)
@@ -0,0 +1,49 @@
+package org.apache.lucene.queryParser.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.parser.EscapeQuerySyntax;
+
+/**
+ * A {@link NoTokenFoundQueryNode} is used if a term is convert into no tokens
+ * by the tokenizer/lemmatizer/analyzer (null).
+ */
+public class NoTokenFoundQueryNode extends DeletedQueryNode {
+
+  private static final long serialVersionUID = 7332975497586993833L;
+
+  public NoTokenFoundQueryNode() {
+    super();
+  }
+
+  public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+    return "[NTF]";
+  }
+
+  public String toString() {
+    return "<notokenfound/>";
+  }
+
+  public QueryNode cloneTree() throws CloneNotSupportedException {
+    NoTokenFoundQueryNode clone = (NoTokenFoundQueryNode) super.cloneTree();
+
+    // nothing to do here
+
+    return clone;
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/queryParser/nodes/NoTokenFoundQueryNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/messages/MessageImpl.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/messages/MessageImpl.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/messages/MessageImpl.java	(revision 0)
@@ -0,0 +1,70 @@
+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;
+
+/**
+ * For Native Language Support (NLS), system of software internationalization.
+ */
+public class MessageImpl implements Message {
+
+  private static final long serialVersionUID = -3077643314630884523L;
+
+  private String key;
+
+  private Object[] arguments = new Object[0];
+
+  public MessageImpl(String key) {
+    this.key = key;
+
+  }
+
+  public MessageImpl(String key, Object... args) {
+    this(key);
+    this.arguments = args;
+  }
+
+  public Object[] getArguments() {
+    return this.arguments;
+  }
+
+  public String getKey() {
+    return this.key;
+  }
+
+  public String getLocalizedMessage() {
+    return getLocalizedMessage(Locale.getDefault());
+  }
+
+  public String getLocalizedMessage(Locale locale) {
+    return NLS.getLocalizedMessage(getKey(), locale, getArguments());
+  }
+
+  public String toString() {
+    Object[] args = getArguments();
+    String argsString = "";
+    if (args != null) {
+      for (int i = 0; i < args.length; i++) {
+        argsString += args[i] + (i < args.length ? "" : ", ");
+      }
+    }
+    return getKey() + " " + argsString;
+  }
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/messages/MessageImpl.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/messages/NLS.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/messages/NLS.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/messages/NLS.java	(revision 0)
@@ -0,0 +1,206 @@
+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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * For Native Language Support (NLS), system of software internationalization.
+ * This interface is similar to the NLS class in eclipse.osgi.util.NLS class -
+ * initializeMessages() method resets the values of all static strings, should
+ * only be called by classes that extend from NLS (see TestMessages.java for
+ * reference) - performs validation of all message in a bundle, at class load
+ * time - performs per message validation at runtime - see NLSTest.java for
+ * usage reference
+ * 
+ * Client may subclass this type.
+ */
+public class NLS {
+
+  private static Map<String, Class<Object>> bundles = new HashMap<String, Class<Object>>(
+      0);
+
+  protected NLS() {
+    // Do not instantiate
+  }
+
+  public static String getLocalizedMessage(String key) {
+    return getLocalizedMessage(key, Locale.getDefault());
+  }
+
+  public static String getLocalizedMessage(String key, Locale locale) {
+    Object message = getResourceBundleObject(key, locale);
+    if (message == null) {
+      return "Message with key:" + key + " and locale: " + locale
+          + " not found.";
+    }
+    return message.toString();
+  }
+
+  public static String getLocalizedMessage(String key, Locale locale,
+      Object... args) {
+    String str = getLocalizedMessage(key, locale);
+
+    if (args.length > 0) {
+      str = MessageFormat.format(str, args);
+    }
+
+    return str;
+  }
+
+  public static String getLocalizedMessage(String key, Object... args) {
+    return getLocalizedMessage(key, Locale.getDefault(), args);
+  }
+
+  /**
+   * Initialize a given class with the message bundle Keys Should be called from
+   * a class that extends NLS in a static block at class load time.
+   * 
+   * @param bundleName
+   *          Property file with that contains the message bundle
+   * @param clazz
+   *          where constants will reside
+   */
+  @SuppressWarnings("unchecked")
+  protected static void initializeMessages(String bundleName, Class clazz) {
+    try {
+      load(clazz);
+      if (!bundles.containsKey(bundleName))
+        bundles.put(bundleName, clazz);
+    } catch (Throwable e) {
+      // ignore all errors and exceptions
+      // because this function is supposed to be called at class load time.
+    }
+  }
+
+  private static Object getResourceBundleObject(String messageKey, Locale locale) {
+
+    // slow resource checking
+    // need to loop thru all registered resource bundles
+    for (Iterator<String> it = bundles.keySet().iterator(); it.hasNext();) {
+      Class<Object> clazz = bundles.get(it.next());
+      ResourceBundle resourceBundle = ResourceBundle.getBundle(clazz.getName(),
+          locale);
+      if (resourceBundle != null) {
+        try {
+          Object obj = resourceBundle.getObject(messageKey);
+          if (obj != null)
+            return obj;
+        } catch (MissingResourceException e) {
+          // just continue it might be on the next resource bundle
+        }
+      }
+    }
+    // if resource is not found
+    return null;
+  }
+
+  /**
+   * @param bundleName
+   * @param clazz
+   */
+  private static void load(Class<Object> clazz) {
+    final Field[] fieldArray = clazz.getDeclaredFields();
+
+    boolean isFieldAccessible = (clazz.getModifiers() & Modifier.PUBLIC) != 0;
+
+    // build a map of field names to Field objects
+    final int len = fieldArray.length;
+    Map<String, Field> fields = new HashMap<String, Field>(len * 2);
+    for (int i = 0; i < len; i++) {
+      fields.put(fieldArray[i].getName(), fieldArray[i]);
+      loadfieldValue(fieldArray[i], isFieldAccessible, clazz);
+    }
+  }
+
+  /**
+   * @param field
+   * @param isFieldAccessible
+   */
+  private static void loadfieldValue(Field field, boolean isFieldAccessible,
+      Class<Object> clazz) {
+    int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
+    int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
+    if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
+      return;
+
+    // Set a value for this empty field.
+    if (!isFieldAccessible)
+      makeAccessible(field);
+    try {
+      field.set(null, field.getName());
+      validateMessage(field.getName(), clazz);
+    } catch (IllegalArgumentException e) {
+      // should not happen
+    } catch (IllegalAccessException e) {
+      // should not happen
+    }
+  }
+
+  /**
+   * @param key
+   *          - Message Key
+   */
+  private static void validateMessage(String key, Class<Object> clazz) {
+    // Test if the message is present in the resource bundle
+    try {
+      ResourceBundle resourceBundle = ResourceBundle.getBundle(clazz.getName(),
+          Locale.getDefault());
+      if (resourceBundle != null) {
+        Object obj = resourceBundle.getObject(key);
+        if (obj == null)
+          System.err.println("WARN: Message with key:" + key + " and locale: "
+              + Locale.getDefault() + " not found.");
+      }
+    } catch (MissingResourceException e) {
+      System.err.println("WARN: Message with key:" + key + " and locale: "
+          + Locale.getDefault() + " not found.");
+    } catch (Throwable e) {
+      // ignore all other errors and exceptions
+      // since this code is just a test to see if the message is present on the
+      // system
+    }
+  }
+
+  /*
+   * Make a class field accessible
+   */
+  @SuppressWarnings("unchecked")
+  private static void makeAccessible(final Field field) {
+    if (System.getSecurityManager() == null) {
+      field.setAccessible(true);
+    } else {
+      AccessController.doPrivileged(new PrivilegedAction() {
+        public Object run() {
+          field.setAccessible(true);
+          return null;
+        }
+      });
+    }
+  }
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/messages/NLS.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/messages/NLSException.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/messages/NLSException.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/messages/NLSException.java	(revision 0)
@@ -0,0 +1,31 @@
+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.
+ */
+
+/**
+ * For Native Language Support (NLS), system of software internationalization.
+ * This Interface should be implemented by all exceptions that require
+ * translation
+ * 
+ */
+public interface NLSException {
+  /**
+   * @return a instance of a class that implements the Message interface
+   */
+  public Message getMessageObject();
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/messages/NLSException.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/java/org/apache/lucene/messages/Message.java
===================================================================
--- contrib/queryparser/src/java/org/apache/lucene/messages/Message.java	(revision 0)
+++ contrib/queryparser/src/java/org/apache/lucene/messages/Message.java	(revision 0)
@@ -0,0 +1,36 @@
+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.io.Serializable;
+import java.util.Locale;
+
+/**
+ * For Native Language Support (NLS), system of software internationalization.
+ */
+public interface Message extends Serializable {
+
+  public String getKey();
+
+  public Object[] getArguments();
+
+  public String getLocalizedMessage();
+
+  public String getLocalizedMessage(Locale locale);
+
+}

Property changes on: contrib/queryparser/src/java/org/apache/lucene/messages/Message.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java	(revision 0)
@@ -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);
+  }
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/messages/TestNLS.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java	(revision 0)
@@ -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;
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties	(revision 0)
@@ -0,0 +1,3 @@
+Q0001E_INVALID_SYNTAX = Syntax Error: {0}
+
+Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION = Truncated unicode escape sequence.

Property changes on: contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle.properties
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties	(revision 0)
@@ -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

Property changes on: contrib/queryparser/src/test/org/apache/lucene/messages/MessagesTestBundle_ja.properties
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java	(revision 0)
@@ -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.config.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+
+/**
+ * This query config handler only adds the {@link UniqueFieldAttribute} to it.<br/>
+ * <br/>
+ * 
+ * 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;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java	(revision 0)
@@ -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.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.parser.Parser;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+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.<br/>
+ * <br/>
+ * 
+ * It tests queries likes "term", "field:term" "term1 term2" "term1 OR term2",
+ * which are all already supported by the current syntax parser (
+ * {@link TextParser}).<br/>
+ * <br/>
+ * 
+ * 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}.<br/>
+ * <br/>
+ * 
+ * Another functionality that will be added is the ability to convert every
+ * field defined in the query to an unique specific field.<br/>
+ * <br/>
+ * 
+ * The query generation is divided in three different steps: parsing (syntax),
+ * processing (semantic) and building.<br/>
+ * <br/>
+ * 
+ * The parsing phase, as already mentioned will be performed by the current
+ * query parser: {@link TextParser}.<br/>
+ * <br/>
+ * 
+ * The processing phase will be performed by a processor pipeline which is
+ * compound by 2 processors: {@link SpansValidatorQueryNodeProcessor} and
+ * {@link UniqueFieldQueryNodeProcessor}.
+ * 
+ * <pre>
+ * 
+ *   {@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 &quot;unique field&quot; from the configuration and convert every field defined
+ *   in every pair to this &quot;unique field&quot;. For that, a {@link SpansQueryConfigHandler} is
+ *   used, which has the {@link UniqueFieldAttribute} defined in it.
+ * </pre>
+ * 
+ * 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.<br/>
+ * <br/>
+ * 
+ * @see TestSpanQueryParser for a more advanced example
+ * 
+ * @see SpansQueryConfigHandler
+ * @see SpansQueryTreeBuilder
+ * @see SpansValidatorQueryNodeProcessor
+ * @see SpanOrQueryNodeBuilder
+ * @see SpanTermQueryNodeBuilder
+ * @see TextParser
+ * @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 {
+    Parser queryParser = new TextParser();
+
+    // 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");
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java	(revision 0)
@@ -0,0 +1,92 @@
+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.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}.<br/>
+ * <br/>
+ * 
+ * @see UniqueFieldQueryNodeProcessor
+ */
+public class UniqueFieldAttribute extends Attribute {
+
+  private static final long serialVersionUID = 8553318595851064232L;
+
+  private CharSequence uniqueField;
+
+  public UniqueFieldAttribute() {
+    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(Attribute target) {
+
+    if (!(target instanceof UniqueFieldAttribute)) {
+      throw new IllegalArgumentException(
+          "cannot copy the values from attribute UniqueFieldAttribute to an instance of "
+              + target.getClass().getName());
+    }
+
+    UniqueFieldAttribute uniqueFieldAttr = (UniqueFieldAttribute) target;
+    uniqueFieldAttr.uniqueField = uniqueField.toString();
+
+  }
+
+  @Override
+  public boolean equals(Object other) {
+
+    if (other instanceof UniqueFieldAttribute) {
+
+      return ((UniqueFieldAttribute) other).uniqueField
+          .equals(this.uniqueField);
+
+    }
+
+    return false;
+
+  }
+
+  @Override
+  public int hashCode() {
+    return this.uniqueField.hashCode();
+  }
+
+  @Override
+  public String toString() {
+    return "<uniqueField uniqueField='" + this.uniqueField + "'/>";
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryBuilder;
+import org.apache.lucene.search.spans.SpanTermQuery;
+
+/**
+ * This builder creates {@link SpanTermQuery}s from a {@link FieldQueryNode}
+ * object.
+ */
+public class SpanTermQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public SpanTermQuery build(QueryNode node) throws QueryNodeException {
+    FieldQueryNode fieldQueryNode = (FieldQueryNode) node;
+
+    return new SpanTermQuery(new Term(fieldQueryNode.getFieldAsString(),
+        fieldQueryNode.getTextAsString()));
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.nodes.FieldableNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.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.<br/>
+ * <br/>
+ * 
+ * @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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java	(revision 0)
@@ -0,0 +1,232 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+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.<br/>
+ * <br/>
+ * 
+ * It tests queries likes "term", "field:term" "term1 term2" "term1 OR term2",
+ * which are all already supported by the current syntax parser (
+ * {@link TextParser}).<br/>
+ * <br/>
+ * 
+ * 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}.<br/>
+ * <br/>
+ * 
+ * Another functionality that will be added is the ability to convert every
+ * field defined in the query to an unique specific field.<br/>
+ * <br/>
+ * 
+ * The query generation is divided in three different steps: parsing (syntax),
+ * processing (semantic) and building.<br/>
+ * <br/>
+ * 
+ * The parsing phase, as already mentioned will be performed by the current
+ * query parser: {@link TextParser}.<br/>
+ * <br/>
+ * 
+ * The processing phase will be performed by a processor pipeline which is
+ * compound by 2 processors: {@link SpansValidatorQueryNodeProcessor} and
+ * {@link UniqueFieldQueryNodeProcessor}.
+ * 
+ * <pre>
+ * 
+ *   {@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 &quot;unique field&quot; from the configuration and convert every field defined
+ *   in every pair to this &quot;unique field&quot;. For that, a {@link SpansQueryConfigHandler} is
+ *   used, which has the {@link UniqueFieldAttribute} defined in it.
+ * </pre>
+ * 
+ * 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.<br/>
+ * <br/>
+ * 
+ * @see SpansQueryConfigHandler
+ * @see SpansQueryTreeBuilder
+ * @see SpansValidatorQueryNodeProcessor
+ * @see SpanOrQueryNodeBuilder
+ * @see SpanTermQueryNodeBuilder
+ * @see TextParser
+ * @see UniqueFieldQueryNodeProcessor
+ * @see UniqueFieldAttribute
+ */
+public class TestSpanQueryParser extends TestCase {
+
+  private QueryNodeProcessorPipeline spanProcessorPipeline;
+
+  private SpansQueryConfigHandler spanQueryConfigHandler;
+
+  private SpansQueryTreeBuilder spansQueryTreeBuilder;
+
+  private TextParser queryParser = new TextParser();
+
+  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
+    }
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryBuilder;
+import org.apache.lucene.search.spans.SpanQuery;
+
+/**
+ * Sets up a query tree builder to build a span query tree from a query node
+ * tree.<br/>
+ * <br/>
+ * 
+ * The defined map is:<br/>
+ * - every BooleanQueryNode instance is delegated to the SpanOrQueryNodeBuilder<br/>
+ * - every FieldQueryNode instance is delegated to the SpanTermQueryNodeBuilder <br/>
+ * 
+ */
+public class SpansQueryTreeBuilder extends QueryTreeBuilder implements
+    LuceneQueryBuilder {
+
+  public SpansQueryTreeBuilder() {
+    setBuilder(BooleanQueryNode.class, new SpanOrQueryNodeBuilder());
+    setBuilder(FieldQueryNode.class, new SpanTermQueryNodeBuilder());
+
+  }
+
+  public SpanQuery build(QueryNode queryTree) throws QueryNodeException {
+    return (SpanQuery) super.build(queryTree);
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.builders.QueryTreeBuilder;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryBuilder;
+import org.apache.lucene.search.spans.SpanOrQuery;
+import org.apache.lucene.search.spans.SpanQuery;
+
+/**
+ * This builder creates {@link SpanOrQuery}s from a {@link BooleanQueryNode}.<br/>
+ * <br/>
+ * 
+ * It assumes that the {@link BooleanQueryNode} instance has at least one child.
+ */
+public class SpanOrQueryNodeBuilder implements LuceneQueryBuilder {
+
+  public SpanOrQuery build(QueryNode node) throws QueryNodeException {
+
+    // validates node
+    BooleanQueryNode booleanNode = (BooleanQueryNode) node;
+
+    List<QueryNode> 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);
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.AndQueryNode;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.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. <br/>
+ * <br/>
+ * 
+ * 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<QueryNode> setChildrenOrder(List<QueryNode> children)
+      throws QueryNodeException {
+
+    return children;
+
+  }
+
+}

Property changes on: contrib/queryparser/src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQPHelper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQPHelper.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQPHelper.java	(revision 0)
@@ -0,0 +1,369 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.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 };
+    TestQueryParser.QPTestAnalyzer a = new TestQueryParser.QPTestAnalyzer();
+    LuceneQueryParserHelper mfqp = new LuceneQueryParserHelper();
+    mfqp.getQueryConfigHandler().setMultiFields(fields);
+    mfqp.getQueryConfigHandler().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" };
+    LuceneQueryParserHelper mfqp = new LuceneQueryParserHelper();
+    mfqp.getQueryConfigHandler().setMultiFields(fields);
+    mfqp.getQueryConfigHandler().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: LuceneQueryParserHelper 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.getQueryConfigHandler().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" };
+    LuceneQueryParserHelper mfqp = new LuceneQueryParserHelper();
+    mfqp.getQueryConfigHandler().setMultiFields(fields);
+    mfqp.getQueryConfigHandler().setFieldsBoost(boosts);
+    mfqp.getQueryConfigHandler().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[]).
+    TestQueryParser.QPTestAnalyzer stopA = new TestQueryParser.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" };
+    // int[] flags = {LuceneQueryParserHelper.REQUIRED_FIELD,
+    // LuceneQueryParserHelper.PROHIBITED_FIELD};
+    BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+        BooleanClause.Occur.MUST_NOT };
+    LuceneQueryParserHelper parser = new LuceneQueryParserHelper();
+    parser.getQueryConfigHandler().setMultiFields(fields);
+    parser.getQueryConfigHandler().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" };
+    LuceneQueryParserHelper parser = new LuceneQueryParserHelper();
+    parser.getQueryConfigHandler().setMultiFields(fields);
+    parser.getQueryConfigHandler().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();
+
+    LuceneQueryParserHelper mfqp = new LuceneQueryParserHelper();
+
+    mfqp.getQueryConfigHandler().setMultiFields(new String[] { "body" });
+    mfqp.getQueryConfigHandler().setAnalyzer(analyzer);
+    mfqp.getQueryConfigHandler().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;
+      }
+    }
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzer.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzer.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzer.java	(revision 0)
@@ -0,0 +1,347 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * This test case is a copy of the core Lucene query parser test, it was adapted
+ * to use the new query parser instead of the old one.
+ * 
+ * Test TextParser's ability to deal with Analyzers that return more than one
+ * token per position or that return tokens with a position increment &gt; 1.
+ */
+public class TestMultiAnalyzer extends LuceneTestCase {
+
+  private static int multiToken = 0;
+
+  private String parse(LuceneQueryConfigHandler config, String queryString)
+      throws QueryNodeException {
+
+    TextParser textParser = new TextParser();
+    QueryNode queryTree = textParser.parse(queryString, "");
+
+    LuceneQueryNodeProcessorPipeline processor = new LuceneQueryNodeProcessorPipeline(
+        config);
+    queryTree = processor.process(queryTree);
+
+    LuceneQueryTreeBuilder builder = new LuceneQueryTreeBuilder();
+
+    return builder.build(queryTree).toString();
+
+  }
+
+  public void testMultiAnalyzer() throws QueryNodeException {
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setAnalyzer(new MultiAnalyzer());
+
+    // trivial, no multiple tokens:
+    assertEquals("foo", parse(config, "foo").toString());
+    assertEquals("foo", parse(config, "\"foo\"").toString());
+    assertEquals("foo foobar", parse(config, "foo foobar".toString()));
+    assertEquals("\"foo foobar\"", parse(config, "\"foo foobar\"".toString()));
+    assertEquals("\"foo foobar blah\"", parse(config, "\"foo foobar blah\""
+        .toString()));
+
+    // two tokens at the same position:
+    assertEquals("(multi multi2) foo", parse(config, "multi foo".toString()));
+    assertEquals("foo (multi multi2)", parse(config, "foo multi".toString()));
+    assertEquals("(multi multi2) (multi multi2)", parse(config, "multi multi"
+        .toString()));
+    assertEquals("+(foo (multi multi2)) +(bar (multi multi2))", parse(config,
+        "+(foo multi) +(bar multi)".toString()));
+    assertEquals("+(foo (multi multi2)) field:\"bar (multi multi2)\"", parse(
+        config, "+(foo multi) field:\"bar multi\"".toString()));
+
+    // phrases:
+    assertEquals("\"(multi multi2) foo\"", parse(config, "\"multi foo\""
+        .toString()));
+    assertEquals("\"foo (multi multi2)\"", parse(config, "\"foo multi\""
+        .toString()));
+    assertEquals("\"foo (multi multi2) foobar (multi multi2)\"", parse(config,
+        "\"foo multi foobar multi\"".toString()));
+
+    // fields:
+    assertEquals("(field:multi field:multi2) field:foo", parse(config,
+        "field:multi field:foo").toString());
+    assertEquals("field:\"(multi multi2) foo\"", parse(config,
+        "field:\"multi foo\"").toString());
+
+    // three tokens at one position:
+    assertEquals("triplemulti multi3 multi2", parse(config, "triplemulti")
+        .toString());
+    assertEquals("foo (triplemulti multi3 multi2) foobar", parse(config,
+        "foo triplemulti foobar").toString());
+
+    // phrase with non-default slop:
+    assertEquals("\"(multi multi2) foo\"~10", parse(config, "\"multi foo\"~10")
+        .toString());
+
+    // phrase with non-default boost:
+    assertEquals("\"(multi multi2) foo\"^2.0", parse(config, "\"multi foo\"^2")
+        .toString());
+
+    // phrase after changing default slop
+    config.setDefaultPhraseSlop(99);
+
+    assertEquals("\"(multi multi2) foo\"~99 bar", parse(config,
+        "\"multi foo\" bar").toString());
+    assertEquals("\"(multi multi2) foo\"~99 \"foo bar\"~2", parse(config,
+        "\"multi foo\" \"foo bar\"~2").toString());
+    config.setDefaultPhraseSlop(0);
+
+    // non-default operator:
+    config.setDefaultOperator(Operator.AND);
+    assertEquals("+(multi multi2) +foo", parse(config, "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 {
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setAnalyzer(new PosIncrementAnalyzer());
+
+    assertEquals("quick brown", parse(config, "the quick brown").toString());
+    assertEquals("\"quick brown\"", parse(config, "\"the quick brown\"")
+        .toString());
+    assertEquals("quick brown fox", parse(config, "the quick brown fox")
+        .toString());
+    assertEquals("\"quick brown fox\"",
+        parse(config, "\"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;
+    }
+
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParser.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParser.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParser.java	(revision 0)
@@ -0,0 +1,501 @@
+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.SimpleAnalyzer;
+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.QueryNodeException;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+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 the new query parser instead of the old one.
+ * 
+ * Tests QueryParser.
+ */
+public class TestMultiFieldQueryParser 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 };
+    TestQueryParser.QPTestAnalyzer a = new TestQueryParser.QPTestAnalyzer();
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setMultiFields(fields);
+    config.setAnalyzer(a);
+
+    Query q = getQuery(config, qtxt);
+    assertEquals(expectedRes, q.toString());
+
+    q = parse(qtxt, fields, occur, a);
+    assertEquals(expectedRes, q.toString());
+  }
+
+  private static Query getQuery(LuceneQueryConfigHandler config,
+      String defaultField, String query) throws QueryNodeException {
+
+    TextParser textParser = new TextParser();
+
+    if (((AnalyzerAttribute) config.getAttribute(AnalyzerAttribute.class))
+        .getAnalyzer() == null) {
+      config.setAnalyzer(new SimpleAnalyzer());
+    }
+
+    QueryNode queryTree = textParser.parse(query, null);
+
+    QueryNodeProcessorPipeline processor = new LuceneQueryNodeProcessorPipeline(
+        config);
+    queryTree = processor.process(queryTree);
+
+    LuceneQueryTreeBuilder builder = new LuceneQueryTreeBuilder();
+
+    return builder.build(queryTree);
+
+  }
+
+  private static Query getQuery(LuceneQueryConfigHandler config, String query)
+      throws QueryNodeException {
+    return getQuery(config, "", query);
+  }
+
+  public void testSimple() throws Exception {
+    String[] fields = { "b", "t" };
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setMultiFields(fields);
+    config.setAnalyzer(new StandardAnalyzer());
+
+    Query q = getQuery(config, "one");
+    assertEquals("b:one t:one", q.toString());
+
+    q = getQuery(config, "one two");
+    assertEquals("(b:one t:one) (b:two t:two)", q.toString());
+
+    q = getQuery(config, "+one +two");
+    assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+
+    q = getQuery(config, "+one -two -three");
+    assertEquals("+(b:one t:one) -(b:two t:two) -(b:three t:three)", q
+        .toString());
+
+    q = getQuery(config, "one^2 two");
+    assertEquals("((b:one t:one)^2.0) (b:two t:two)", q.toString());
+
+    q = getQuery(config, "one~ two");
+    assertEquals("(b:one~0.5 t:one~0.5) (b:two t:two)", q.toString());
+
+    q = getQuery(config, "one~0.8 two^2");
+    assertEquals("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)", q.toString());
+
+    q = getQuery(config, "one* two*");
+    assertEquals("(b:one* t:one*) (b:two* t:two*)", q.toString());
+
+    q = getQuery(config, "[a TO c] two");
+    assertEquals("(b:[a TO c] t:[a TO c]) (b:two t:two)", q.toString());
+
+    q = getQuery(config, "w?ldcard");
+    assertEquals("b:w?ldcard t:w?ldcard", q.toString());
+
+    q = getQuery(config, "\"foo bar\"");
+    assertEquals("b:\"foo bar\" t:\"foo bar\"", q.toString());
+
+    q = getQuery(config, "\"aa bb cc\" \"dd ee\"");
+    assertEquals("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")", q
+        .toString());
+
+    q = getQuery(config, "\"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 = getQuery(config, "b:\"foo bar\"~4");
+    assertEquals("b:\"foo bar\"~4", q.toString());
+
+    // make sure that terms which have a field are not touched:
+    q = getQuery(config, "one f:two");
+    assertEquals("(b:one t:one) f:two", q.toString());
+
+    // AND mode:
+    config.setDefaultOperator(Operator.AND);
+    q = getQuery(config, "one two");
+    assertEquals("+(b:one t:one) +(b:two t:two)", q.toString());
+    q = getQuery(config, "\"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" };
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setMultiFields(fields);
+    config.setFieldsBoost(boosts);
+    config.setAnalyzer(new StandardAnalyzer());
+
+    // Check for simple
+    Query q = getQuery(config, "one");
+    assertEquals("b:one^5.0 t:one^10.0", q.toString());
+
+    // Check for AND
+    q = getQuery(config, "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 = getQuery(config, "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 = getQuery(config, "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 = getQuery(config, "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 QueryNodeException {
+    String[] fields = { "b", "t" };
+    String[] queries = { "one", "two" };
+
+    Query q = parse(queries, fields, new StandardAnalyzer());
+    assertEquals("b:one t:two", q.toString());
+
+    String[] queries2 = { "+one", "+two" };
+    q = parse(queries2, fields, new StandardAnalyzer());
+    assertEquals("(+b:one) (+t:two)", q.toString());
+
+    String[] queries3 = { "one", "+two" };
+    q = parse(queries3, fields, new StandardAnalyzer());
+    assertEquals("b:one (+t:two)", q.toString());
+
+    String[] queries4 = { "one +more", "+two" };
+    q = parse(queries4, fields, new StandardAnalyzer());
+    assertEquals("(b:one +b:more) (+t:two)", q.toString());
+
+    String[] queries5 = { "blah" };
+    try {
+      q = 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[]).
+    TestQueryParser.QPTestAnalyzer stopA = new TestQueryParser.QPTestAnalyzer();
+
+    String[] queries6 = { "((+stop))", "+((stop))" };
+    q = parse(queries6, fields, stopA);
+    assertEquals("", q.toString());
+
+    String[] queries7 = { "one ((+stop)) +more", "+((stop)) +two" };
+    q = 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 = parse("one", fields, flags, new StandardAnalyzer());
+    assertEquals("+b:one -t:one", q.toString());
+
+    q = 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 = parse("blah", fields, flags2, new StandardAnalyzer());
+      fail();
+    } catch (IllegalArgumentException e) {
+      // expected exception, array length differs
+    }
+  }
+
+  public void testStaticMethod2Old() throws QueryNodeException {
+    String[] fields = { "b", "t" };
+    // int[] flags = {MultiFieldQueryParserWrapper.REQUIRED_FIELD,
+    // MultiFieldQueryParserWrapper.PROHIBITED_FIELD};
+    BooleanClause.Occur[] flags = { BooleanClause.Occur.MUST,
+        BooleanClause.Occur.MUST_NOT };
+
+    Query q = parse("one", fields, flags, new StandardAnalyzer());// ,
+    // fields,
+    // flags,
+    // new
+    // StandardAnalyzer());
+    assertEquals("+b:one -t:one", q.toString());
+
+    q = 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 = 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 = parse(queries, fields, flags, new StandardAnalyzer());
+    assertEquals("+f1:one -f2:two f3:three", q.toString());
+
+    try {
+      BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+      q = 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 = parse(queries, fields, flags, new StandardAnalyzer());
+    assertEquals("+b:one -t:two", q.toString());
+
+    try {
+      BooleanClause.Occur[] flags2 = { BooleanClause.Occur.MUST };
+      q = 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" };
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setMultiFields(fields);
+    config.setAnalyzer(new AnalyzerReturningNull());
+
+    Query q = getQuery(config, "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 = getQuery(config, "bla*");
+    assertEquals("f1:bla* f2:bla* f3:bla*", q.toString());
+    q = getQuery(config, "bla~");
+    assertEquals("f1:bla~0.5 f2:bla~0.5 f3:bla~0.5", q.toString());
+    q = getQuery(config, "[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();
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setMultiFields(new String[] { "body" });
+    config.setAnalyzer(analyzer);
+    config.setDefaultOperator(Operator.AND);
+
+    Query q = getQuery(config, "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;
+      }
+    }
+  }
+
+  public static Query parse(String[] queries, String[] fields, Analyzer analyzer)
+      throws QueryNodeException {
+
+    TextParser textParser = new TextParser();
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    LuceneQueryTreeBuilder builder = new LuceneQueryTreeBuilder();
+    LuceneQueryNodeProcessorPipeline processor = new LuceneQueryNodeProcessorPipeline(
+        config);
+
+    if (analyzer == null) {
+      analyzer = new SimpleAnalyzer();
+    }
+
+    config.setAnalyzer(analyzer);
+
+    if (queries.length != fields.length)
+      throw new IllegalArgumentException("queries.length != fields.length");
+    BooleanQuery bQuery = new BooleanQuery();
+    for (int i = 0; i < fields.length; i++) {
+      QueryNode queryTree = textParser.parse(queries[i], fields[i]);
+
+      queryTree = processor.process(queryTree);
+      Query q = builder.build(queryTree);
+
+      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;
+  }
+
+  public static Query parse(String query, String[] fields,
+      BooleanClause.Occur[] flags, Analyzer analyzer) throws QueryNodeException {
+
+    TextParser textParser = new TextParser();
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    LuceneQueryTreeBuilder builder = new LuceneQueryTreeBuilder();
+    LuceneQueryNodeProcessorPipeline processor = new LuceneQueryNodeProcessorPipeline(
+        config);
+
+    if (analyzer == null) {
+      analyzer = new SimpleAnalyzer();
+    }
+
+    config.setAnalyzer(analyzer);
+
+    if (fields.length != flags.length)
+      throw new IllegalArgumentException("fields.length != flags.length");
+    BooleanQuery bQuery = new BooleanQuery();
+    for (int i = 0; i < fields.length; i++) {
+      QueryNode queryTree = textParser.parse(query, fields[i]);
+
+      queryTree = processor.process(queryTree);
+      Query q = builder.build(queryTree);
+
+      if (q != null && // q never null, just being defensive
+          (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+        bQuery.add(q, flags[i]);
+      }
+    }
+    return bQuery;
+  }
+
+  public static Query parse(String[] queries, String[] fields,
+      BooleanClause.Occur[] flags, Analyzer analyzer) throws QueryNodeException {
+
+    TextParser textParser = new TextParser();
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    LuceneQueryTreeBuilder builder = new LuceneQueryTreeBuilder();
+    LuceneQueryNodeProcessorPipeline processor = new LuceneQueryNodeProcessorPipeline(
+        config);
+
+    if (analyzer == null) {
+      analyzer = new SimpleAnalyzer();
+    }
+
+    config.setAnalyzer(analyzer);
+
+    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++) {
+      QueryNode queryTree = textParser.parse(queries[i], fields[i]);
+
+      queryTree = processor.process(queryTree);
+      Query q = builder.build(queryTree);
+
+      if (q != null && // q never null, just being defensive
+          (!(q instanceof BooleanQuery) || ((BooleanQuery) q).getClauses().length > 0)) {
+        bQuery.add(q, flags[i]);
+      }
+    }
+    return bQuery;
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQPHelper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQPHelper.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQPHelper.java	(revision 0)
@@ -0,0 +1,1128 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.LuceneQueryParserHelper;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+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.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 LuceneQueryParserHelper {
+    public QPTestParser(Analyzer a) {
+      getQueryNodeProcessor()
+          .addProcessor(new QPTestParserQueryNodeProcessor());
+      getQueryConfigHandler().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<QueryNode> setChildrenOrder(List<QueryNode> children)
+          throws QueryNodeException {
+
+        return children;
+
+      }
+
+    }
+
+  }
+
+  private int originalMaxClauses;
+
+  public void setUp() throws Exception {
+    super.setUp();
+    originalMaxClauses = BooleanQuery.getMaxClauseCount();
+  }
+
+  public LuceneQueryParserHelper getParser(Analyzer a) throws Exception {
+    if (a == null)
+      a = new SimpleAnalyzer();
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().setAnalyzer(a);
+
+    qp.getQueryConfigHandler().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(LuceneQueryParserHelper 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 = 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 {
+    LuceneQueryParserHelper qp = getParser(null);
+    qp.getQueryConfigHandler().setLowercaseExpandedTerms(lowercase);
+    qp.getQueryConfigHandler().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 {
+    LuceneQueryParserHelper 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();
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().setAnalyzer(a);
+    qp.getQueryConfigHandler().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 {
+    LuceneQueryParserHelper qp = getParser(null);
+    qp.getQueryConfigHandler().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]");
+    assertTrue(((TermRangeQuery) getQuery("[ a TO z]", null))
+        .getConstantScoreRewrite());
+
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().setConstantScoreRewrite(false);
+
+    assertFalse(((TermRangeQuery) qp.parse("[ a TO z]", "field"))
+        .getConstantScoreRewrite());
+
+    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);
+
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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.getQueryConfigHandler().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.getQueryConfigHandler().setConstantScoreRewrite(true);
+    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.getQueryConfigHandler().setConstantScoreRewrite(false);
+    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";
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+
+    // 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.getQueryConfigHandler().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.getQueryConfigHandler().setDateResolution(
+        DateTools.Resolution.MILLISECOND);
+
+    // set second field specific date resolution
+    qp.getQueryConfigHandler().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(LuceneQueryParserHelper 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" });
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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);
+
+    LuceneQueryParserHelper qp2 = new LuceneQueryParserHelper();
+    qp2.getQueryConfigHandler().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 {
+      LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+      qp.getQueryConfigHandler().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 {
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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];
+    // QueryParser qp = new LuceneQueryParserHelper("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 {
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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 {
+      LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+      qp.getQueryConfigHandler().setAnalyzer(
+          new StopAnalyzer(new String[] { "the", "in", "are", "this" }));
+
+      qp.getQueryConfigHandler().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 {
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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 {
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().setAnalyzer(new WhitespaceAnalyzer());
+    qp.getQueryConfigHandler().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);
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerWrapper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerWrapper.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerWrapper.java	(revision 0)
@@ -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 &gt; 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;
+    }
+
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParser.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParser.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParser.java	(revision 0)
@@ -0,0 +1,1148 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.original.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.Operator;
+import org.apache.lucene.queryParser.original.parser.EscapeQuerySyntaxImpl;
+import org.apache.lucene.queryParser.original.parser.TextParser;
+import org.apache.lucene.queryParser.original.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+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.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 the new query parser instead of the old one.
+ * 
+ * Tests QueryParser.
+ */
+public class TestQueryParser 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));
+    }
+  }
+
+  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<QueryNode> setChildrenOrder(List<QueryNode> children)
+        throws QueryNodeException {
+
+      return children;
+
+    }
+
+  }
+
+  private int originalMaxClauses;
+
+  public void setUp() throws Exception {
+    super.setUp();
+    originalMaxClauses = BooleanQuery.getMaxClauseCount();
+  }
+
+  public Query getQuery(String query, Analyzer a) throws Exception {
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+
+    if (a == null) {
+      a = new SimpleAnalyzer();
+    }
+
+    config.setAnalyzer(a);
+
+    return getQuery(config, query);
+
+  }
+
+  private Query getQuery(LuceneQueryConfigHandler config, String query)
+      throws Exception {
+    return getQuery(config, query, "field");
+  }
+
+  private Query getQuery(LuceneQueryConfigHandler config, String query,
+      CharSequence field) throws Exception {
+    TextParser textParser = new TextParser();
+
+    if (((AnalyzerAttribute) config.getAttribute(AnalyzerAttribute.class))
+        .getAnalyzer() == null) {
+      config.setAnalyzer(new SimpleAnalyzer());
+    }
+
+    QueryNode queryTree = textParser.parse(query, field);
+
+    LuceneQueryNodeProcessorPipeline processor = new LuceneQueryNodeProcessorPipeline(
+        config);
+    queryTree = processor.process(queryTree);
+
+    LuceneQueryTreeBuilder builder = new LuceneQueryTreeBuilder();
+
+    return builder.build(queryTree);
+
+  }
+
+  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(LuceneQueryConfigHandler config, String field,
+      String query, String result) throws Exception {
+    Query q = getQuery(config, 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 {
+    QueryNode queryTree = new FieldQueryNode(null, query, 0, 0);
+    CharSequence escapedQuery = queryTree
+        .toQueryString(new EscapeQuerySyntaxImpl());
+
+    if (!escapedQuery.toString().equals(result)) {
+      fail("Query /" + query + "/ yielded /" + escapedQuery + "/, expecting /"
+          + result + "/");
+    }
+  }
+
+  public void assertWildcardQueryEquals(String query, boolean lowercase,
+      String result, boolean allowLeadingWildcard) throws Exception {
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+
+    config.setLowercaseExpandedTerms(lowercase);
+    config.setAllowLeadingWildcard(allowLeadingWildcard);
+    Query q = getQuery(config, 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 {
+
+    Query q = getQuery(query, null);
+    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 {
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setAnalyzer(new SimpleAnalyzer());
+    config.setDefaultOperator(Operator.AND);
+
+    return getQuery(config, 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\"");
+
+  }
+
+  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 {
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setAllowLeadingWildcard(true);
+
+    assertEquals(WildcardQuery.class, getQuery(config, "t*erm*").getClass());
+    assertEquals(WildcardQuery.class, getQuery(config, "?term*").getClass());
+    assertEquals(WildcardQuery.class, getQuery(config, "*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]");
+    assertTrue(((TermRangeQuery) getQuery("[ a TO z]", null))
+        .getConstantScoreRewrite());
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+
+    config.setConstantScoreRewrite(false);
+    assertFalse(((TermRangeQuery) getQuery(config, "[ a TO z]"))
+        .getConstantScoreRewrite());
+
+    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("field", "\u0633\u0627\u0628", Field.Store.YES,
+        Field.Index.UN_TOKENIZED));
+    iw.addDocument(doc);
+    iw.close();
+    IndexSearcher is = new IndexSearcher(ramDir);
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.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"));
+    config.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
+    config.setConstantScoreRewrite(true);
+    ScoreDoc[] result = is.search(getQuery(config, "[ \u062F TO \u0698 ]",
+        "field"), null, 1000).scoreDocs;
+    assertEquals("The index Term should not be included.", 0, result.length);
+
+    result = is.search(getQuery(config, "[ \u0633 TO \u0638 ]", "field"), null,
+        1000).scoreDocs;
+    assertEquals("The index Term should be included.", 1, result.length);
+
+    // Test RangeQuery
+    config.setConstantScoreRewrite(false);
+    result = is.search(getQuery(config, "[ \u062F TO \u0698 ]", "field"), null,
+        1000).scoreDocs;
+    assertEquals("The index Term should not be included.", 0, result.length);
+
+    result = is.search(getQuery(config, "[ \u0633 TO \u0638 ]", "field"), 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";
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+
+    // Don't set any date resolution and verify if DateField is used
+    assertDateRangeQueryEquals(config, defaultField, startDate, endDate,
+        endDateExpected.getTime(), null);
+
+    // set a field specific date resolution
+    config.setDateResolution(monthField, DateTools.Resolution.MONTH);
+
+    // DateField should still be used for defaultField
+    assertDateRangeQueryEquals(config, defaultField, startDate, endDate,
+        endDateExpected.getTime(), null);
+
+    // set default date resolution to MILLISECOND
+    config.setDateResolution(DateTools.Resolution.MILLISECOND);
+
+    // set second field specific date resolution
+    config.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(config, defaultField, startDate, endDate,
+        endDateExpected.getTime(), DateTools.Resolution.MILLISECOND);
+
+    // verify if field specific date resolutions are used for these two
+    // fields
+    assertDateRangeQueryEquals(config, monthField, startDate, endDate,
+        endDateExpected.getTime(), DateTools.Resolution.MONTH);
+
+    assertDateRangeQueryEquals(config, hourField, startDate, endDate,
+        endDateExpected.getTime(), DateTools.Resolution.HOUR);
+  }
+
+  public void assertDateRangeQueryEquals(LuceneQueryConfigHandler config,
+      String field, String startDate, String endDate, Date endDateInclusive,
+      DateTools.Resolution resolution) throws Exception {
+    assertQueryEquals(config, field, field + ":[" + startDate + " TO "
+        + endDate + "]", "[" + getDate(startDate, resolution) + " TO "
+        + getDate(endDateInclusive, resolution) + "]");
+    assertQueryEquals(config, 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 TextParser
+    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" });
+
+    Query q = getQuery("on^1.0", oneStopAnalyzer);
+    assertNotNull(q);
+    q = getQuery("\"hello\"^2.0", oneStopAnalyzer);
+    assertNotNull(q);
+    assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
+    q = getQuery("hello^2.0", oneStopAnalyzer);
+    assertNotNull(q);
+    assertEquals(q.getBoost(), (float) 2.0, (float) 0.5);
+    q = getQuery("\"on\"^1.0", oneStopAnalyzer);
+    assertNotNull(q);
+
+    StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
+
+    q = getQuery("the^3", standardAnalyzer);
+    // "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 testCustomProcessor() {
+    QPTestParserQueryNodeProcessor processor = new QPTestParserQueryNodeProcessor();
+    TextParser textParser = new TextParser();
+
+    try {
+      QueryNode queryTree = textParser.parse("a?t", "contents");
+      processor.process(queryTree);
+
+      fail("Wildcard queries should not be allowed");
+    } catch (QueryNodeException expected) {
+      // expected exception
+    }
+
+    try {
+      QueryNode queryTree = textParser.parse("xunit~", "contents");
+      processor.process(queryTree);
+
+      fail("Fuzzy queries should not be allowed");
+    } catch (QueryNodeException expected) {
+      // expected exception
+    }
+
+  }
+
+  public void testCustomQueryParserFuzzy() throws Exception {
+
+  }
+
+  /**
+   * This test differs from TestPrecedenceQueryParser
+   */
+  public void testPrecedence() throws Exception {
+    Analyzer wAnalyzer = new WhitespaceAnalyzer();
+
+    Query query1 = getQuery("A AND B OR C AND D", wAnalyzer);
+    Query query2 = getQuery("+A +B +C +D", wAnalyzer);
+
+    assertEquals(query1, query2);
+  }
+
+  public void testLocalDateFormat() throws Exception {
+
+    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();
+  }
+
+  // TODO: fix this test
+  // public void testStarParsing() throws Exception {
+  // final int[] type = new int[1];
+  // TextParser 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 {
+    Analyzer analyzer = new StopAnalyzer(new String[] { "the", "foo" });
+
+    Query result = getQuery("field:the OR field:foo", analyzer);
+    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 = getQuery("field:woo OR field:the", analyzer);
+    assertNotNull("result is null and it shouldn't be", result);
+    assertTrue("result is not a TermQuery", result instanceof TermQuery);
+    result = getQuery(
+        "(fieldX:xxxxx OR fieldy:xxxxxxxx)^2 AND (fieldx:the OR fieldy:foo)",
+        analyzer);
+    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 {
+      LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+      Analyzer analyzer = new StopAnalyzer(new String[] { "the", "in", "are",
+          "this" });
+      config.setAnalyzer(analyzer);
+      config.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) getQuery(config, 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 {
+    Analyzer wAnalyzer = new WhitespaceAnalyzer();
+
+    assertEquals(new MatchAllDocsQuery(), getQuery("*:*", wAnalyzer));
+    assertEquals(new MatchAllDocsQuery(), getQuery("(*:*)", wAnalyzer));
+    BooleanQuery bq = (BooleanQuery) getQuery("+*:* -*:*", wAnalyzer);
+    assertTrue(bq.getClauses()[0].getQuery() instanceof MatchAllDocsQuery);
+    assertTrue(bq.getClauses()[1].getQuery() instanceof MatchAllDocsQuery);
+  }
+
+  private void assertHits(int expected, String query, IndexSearcher is)
+      throws Exception {
+
+    LuceneQueryConfigHandler config = new LuceneQueryConfigHandler();
+    config.setAnalyzer(new WhitespaceAnalyzer());
+    config.setLocale(Locale.ENGLISH);
+    Query q = getQuery(config, 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);
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParserWrapper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParserWrapper.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestQueryParserWrapper.java	(revision 0)
@@ -0,0 +1,1123 @@
+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.QueryNodeException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+import org.apache.lucene.queryParser.nodes.FuzzyQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.queryParser.original.QueryParserWrapper;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.ParseException;
+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.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 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<QueryNode> setChildrenOrder(List<QueryNode> 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]");
+    assertTrue(((TermRangeQuery) getQuery("[ a TO z]", null))
+        .getConstantScoreRewrite());
+
+    QueryParserWrapper qp = new QueryParserWrapper("field",
+        new SimpleAnalyzer());
+    qp.setConstantScoreRewrite(false);
+    assertFalse(((TermRangeQuery) qp.parse("[ a TO z]"))
+        .getConstantScoreRewrite());
+
+    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.setConstantScoreRewrite(true);
+    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.setConstantScoreRewrite(false);
+    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);
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerQPHelper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerQPHelper.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiAnalyzerQPHelper.java	(revision 0)
@@ -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.QueryNodeException;
+import org.apache.lucene.queryParser.original.LuceneQueryParserHelper;
+import org.apache.lucene.queryParser.original.config.LuceneQueryConfigHandler.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 &gt; 1.
+ */
+public class TestMultiAnalyzerQPHelper extends LuceneTestCase {
+
+  private static int multiToken = 0;
+
+  public void testMultiAnalyzer() throws QueryNodeException {
+
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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.getQueryConfigHandler().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.getQueryConfigHandler().setDefaultPhraseSlop(0);
+
+    // non-default operator:
+    qp.getQueryConfigHandler().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 {
+    LuceneQueryParserHelper qp = new LuceneQueryParserHelper();
+    qp.getQueryConfigHandler().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;
+    }
+
+  }
+
+}
Index: contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParserWrapper.java
===================================================================
--- contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParserWrapper.java	(revision 0)
+++ contrib/queryparser/src/test/org/apache/lucene/queryParser/original/TestMultiFieldQueryParserWrapper.java	(revision 0)
@@ -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 QueryParser.
+ */
+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 };
+    TestQueryParser.QPTestAnalyzer a = new TestQueryParser.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[]).
+    TestQueryParser.QPTestAnalyzer stopA = new TestQueryParser.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;
+      }
+    }
+  }
+
+}
