Index: src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java
===================================================================
--- src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/parser/EscapeQuerySyntax.java	(revision 0)
@@ -0,0 +1,39 @@
+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);
+}
Index: src/java/org/apache/lucene/queryParser/parser/Parser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/parser/Parser.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/parser/Parser.java	(revision 0)
@@ -0,0 +1,33 @@
+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;
+}
Index: src/java/org/apache/lucene/queryParser/parser/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/parser/package.html	(revision 0)
+++ 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>
Index: src/java/org/apache/lucene/queryParser/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/package.html	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/package.html	(working copy)
@@ -1,31 +0,0 @@
-<!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">
-   <meta name="Author" content="Doug Cutting">
-</head>
-<body>
-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;
-Sorry.
-<p>Note that because JavaCC defines a class named <tt>Token</tt>, <tt>org.apache.lucene.analysis.Token</tt>
-must always be fully qualified in source code in this package.
-</body>
-</html>
Index: src/java/org/apache/lucene/queryParser/TokenMgrError.java
===================================================================
--- src/java/org/apache/lucene/queryParser/TokenMgrError.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/TokenMgrError.java	(working copy)
@@ -1,140 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
-/* JavaCCOptions: */
-package org.apache.lucene.queryParser;
-
-/** Token Manager Error. */
-public class TokenMgrError extends Error
-{
-
-   /*
-    * 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=55cddb2336a66b376c0bb59d916b326d (do not edit this line) */
Index: src/java/org/apache/lucene/queryParser/QueryNodeException.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryNodeException.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/QueryNodeException.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 java.util.Locale;
+
+import org.apache.lucene.messages.Message;
+import org.apache.lucene.messages.MessageImpl;
+import org.apache.lucene.messages.NLSException;
+import org.apache.lucene.queryParser.messages.QueryParserMessages;
+
+
+/**
+ * 
+ */
+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();
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/QueryParser.jj
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.jj	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/QueryParser.jj	(working copy)
@@ -1,1480 +0,0 @@
-/**
- * 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.
- */
-
-options {
-  STATIC=false;
-  JAVA_UNICODE_ESCAPE=true;
-  USER_CHAR_STREAM=true;
-}
-
-PARSER_BEGIN(QueryParser)
-
-package org.apache.lucene.queryParser;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.text.Collator;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Vector;
-
-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.document.DateField;
-import org.apache.lucene.document.DateTools;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.ConstantScoreRangeQuery;
-import org.apache.lucene.search.FuzzyQuery;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.MultiPhraseQuery;
-import org.apache.lucene.search.PhraseQuery;
-import org.apache.lucene.search.PrefixQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.RangeQuery;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.WildcardQuery;
-import org.apache.lucene.util.Parameter;
-
-/**
- * This class is generated by JavaCC.  The most important method is
- * {@link #parse(String)}.
- *
- * The syntax for query strings is as follows:
- * 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 ::= ["+", "-"] [&lt;TERM&gt; ":"] ( &lt;TERM&gt; | "(" Query ")" )
- * </pre>
- *
- * <p>
- * Examples of appropriately formatted queries can be found in the <a
- * href="../../../../../../queryparsersyntax.html">query syntax
- * documentation</a>.
- * </p>
- *
- * <p>
- * In {@link RangeQuery}s, QueryParser tries to detect date values, e.g.
- * <tt>date:[6/1/2005 TO 6/4/2005]</tt> produces a range query that searches
- * for "date" fields between 2005-06-01 and 2005-06-04. Note that the format
- * of the accepted input depends on {@link #setLocale(Locale) the locale}.
- * By default a date is converted into a search term using the deprecated
- * {@link DateField} for compatibility reasons.
- * To use the new {@link DateTools} to convert dates, a
- * {@link org.apache.lucene.document.DateTools.Resolution} has to be set.
- * </p>
- * <p>
- * The date resolution that shall be used for RangeQueries can be set
- * using {@link #setDateResolution(DateTools.Resolution)}
- * or {@link #setDateResolution(String, DateTools.Resolution)}. The former
- * sets the default date resolution for all fields, whereas the latter can
- * be used to set field specific date resolutions. Field specific date
- * resolutions take, if set, precedence over the default date resolution.
- * </p>
- * <p>
- * If you use neither {@link DateField} nor {@link DateTools} in your
- * index, you can create your own
- * query parser that inherits QueryParser and overwrites
- * {@link #getRangeQuery(String, String, String, boolean)} to
- * use a different method for date conversion.
- * </p>
- *
- * <p>Note that QueryParser is <em>not</em> thread-safe.</p>
- */
-public class QueryParser {
-
-  private static final int CONJ_NONE   = 0;
-  private static final int CONJ_AND    = 1;
-  private static final int CONJ_OR     = 2;
-
-  private static final int MOD_NONE    = 0;
-  private static final int MOD_NOT     = 10;
-  private static final int MOD_REQ     = 11;
-
-  // make it possible to call setDefaultOperator() without accessing 
-  // 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;
-
-  /** The actual operator that parser uses to combine query terms */
-  private Operator operator = OR_OPERATOR;
-
-  boolean lowercaseExpandedTerms = true;
-  boolean constantScoreRewrite= true;
-  boolean allowLeadingWildcard = false;
-  boolean enablePositionIncrements = false;
-
-  Analyzer analyzer;
-  String field;
-  int phraseSlop = 0;
-  float fuzzyMinSim = FuzzyQuery.defaultMinSimilarity;
-  int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
-  Locale locale = Locale.getDefault();
-
-  // the default date resolution
-  DateTools.Resolution dateResolution = null;
-  // maps field names to date resolutions
-  Map fieldToDateResolution = null;
-
-  // The collator to use when determining range inclusion,
-  // for use when constructing RangeQuerys.
-  Collator rangeCollator = null;
-
-  /** The default operator for parsing queries. 
-   * Use {@link QueryParser#setDefaultOperator} to change it.
-   */
-  static public final class Operator extends Parameter {
-    private Operator(String name) {
-      super(name);
-    }
-    static public final Operator OR = new Operator("OR");
-    static public final Operator AND = new Operator("AND");
-  }
-
-
-  /** Constructs a query parser.
-   *  @param f  the default field for query terms.
-   *  @param a   used to find terms in the query text.
-   */
-  public QueryParser(String f, Analyzer a) {
-    this(new FastCharStream(new StringReader("")));
-    analyzer = a;
-    field = f;
-  }
-
-  /** Parses a query string, returning a {@link org.apache.lucene.search.Query}.
-   *  @param query  the query string to be parsed.
-   *  @throws ParseException if the parsing fails
-   */
-  public Query parse(String query) throws ParseException {
-    ReInit(new FastCharStream(new StringReader(query)));
-    try {
-      // TopLevelQuery is a Query followed by the end-of-input (EOF)
-      Query res = TopLevelQuery(field);
-      return res!=null ? res : newBooleanQuery(false);
-    }
-    catch (ParseException tme) {
-      // rethrow to include the original query:
-      throw new ParseException("Cannot parse '" +query+ "': " + tme.getMessage());
-    }
-    catch (TokenMgrError tme) {
-      throw new ParseException("Cannot parse '" +query+ "': " + tme.getMessage());
-    }
-    catch (BooleanQuery.TooManyClauses tmc) {
-      throw new ParseException("Cannot parse '" +query+ "': too many boolean clauses");
-    }
-  }
-
-   /**
-   * @return Returns the analyzer.
-   */
-  public Analyzer getAnalyzer() {
-    return analyzer;
-  }
-
-  /**
-   * @return Returns the field.
-   */
-  public String getField() {
-    return field;
-  }
-
-   /**
-   * Get the minimal similarity for fuzzy queries.
-   */
-  public float getFuzzyMinSim() {
-      return fuzzyMinSim;
-  }
-
-  /**
-   * Set the minimum similarity for fuzzy queries.
-   * Default is 0.5f.
-   */
-  public void setFuzzyMinSim(float fuzzyMinSim) {
-      this.fuzzyMinSim = fuzzyMinSim;
-  }
-
-   /**
-   * Get the prefix length for fuzzy queries. 
-   * @return Returns the fuzzyPrefixLength.
-   */
-  public int getFuzzyPrefixLength() {
-    return fuzzyPrefixLength;
-  }
-
-  /**
-   * Set the prefix length for fuzzy queries. Default is 0.
-   * @param fuzzyPrefixLength The fuzzyPrefixLength to set.
-   */
-  public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
-    this.fuzzyPrefixLength = fuzzyPrefixLength;
-  }
-
-  /**
-   * Sets the default slop for phrases.  If zero, then exact phrase matches
-   * are required.  Default value is zero.
-   */
-  public void setPhraseSlop(int phraseSlop) {
-    this.phraseSlop = phraseSlop;
-  }
-
-  /**
-   * Gets the default slop for phrases.
-   */
-  public int getPhraseSlop() {
-    return phraseSlop;
-  }
-
-
-  /**
-   * 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.allowLeadingWildcard = allowLeadingWildcard;
-  }
-
-  /**
-   * @see #setAllowLeadingWildcard(boolean)
-   */
-  public boolean getAllowLeadingWildcard() {
-    return 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 enable) {
-    this.enablePositionIncrements = enable;
-  }
-
-  /**
-   * @see #setEnablePositionIncrements(boolean)
-   */
-  public boolean getEnablePositionIncrements() {
-    return enablePositionIncrements;
-  }
-
-  /**
-   * Sets the boolean operator of the QueryParser.
-   * In default mode (<code>OR_OPERATOR</code>) 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 <code>AND_OPERATOR</code> 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 op) {
-    this.operator = op;
-  }
-
-
-  /**
-   * Gets implicit operator setting, which will be either AND_OPERATOR
-   * or OR_OPERATOR.
-   */
-  public Operator getDefaultOperator() {
-    return operator;
-  }
-
-
-  /**
-   * Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically
-   * lower-cased or not.  Default is <code>true</code>.
-   */
-  public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
-    this.lowercaseExpandedTerms = lowercaseExpandedTerms;
-  }
-
-
-  /**
-   * @see #setLowercaseExpandedTerms(boolean)
-   */
-  public boolean getLowercaseExpandedTerms() {
-    return lowercaseExpandedTerms;
-  }
-
-  /**
-   * @deprecated Please use {@link #setConstantScoreRewrite} instead.
-   */
-  public void setUseOldRangeQuery(boolean useOldRangeQuery) {
-    constantScoreRewrite = !useOldRangeQuery;
-  }
-
-
-  /**
-   * @deprecated Please use {@link #getConstantScoreRewrite} instead.
-   */
-  public boolean getUseOldRangeQuery() {
-    return !constantScoreRewrite;
-  }
-
-  /**
-   * By default QueryParser uses constant-score rewriting
-   * when creating a PrefixQuery, WildcardQuery or RangeQuery. This implementation is generally preferable because it 
-   * a) Runs faster b) Does not have the scarcity of terms unduly influence score 
-   * c) avoids any "TooManyBooleanClauses" exception.
-   * However, if your application really needs to use the
-   * old-fashioned BooleanQuery 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 v) {
-    constantScoreRewrite = v;
-  }
-
-
-  /**
-   * @see #setConstantScoreRewrite(boolean)
-   */
-  public boolean getConstantScoreRewrite() {
-    return constantScoreRewrite;
-  }
-
-  /**
-   * Set locale used by date range parsing.
-   */
-  public void setLocale(Locale locale) {
-    this.locale = locale;
-  }
-
-  /**
-   * Returns current locale, allowing access by subclasses.
-   */
-  public Locale getLocale() {
-    return locale;
-  }
-
-  /**
-   * Sets the default date resolution used by RangeQueries 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.dateResolution = dateResolution;
-  }
-
-  /**
-   * Sets the date resolution used by RangeQueries for a specific field.
-   *  
-   * @param fieldName field for which the date resolution is to be set 
-   * @param dateResolution date resolution to set
-   */
-  public void setDateResolution(String fieldName, DateTools.Resolution dateResolution) {
-    if (fieldName == null) {
-      throw new IllegalArgumentException("Field cannot be null.");
-    }
-
-    if (fieldToDateResolution == null) {
-      // lazily initialize HashMap
-      fieldToDateResolution = new HashMap();
-    }
-
-    fieldToDateResolution.put(fieldName, dateResolution);
-  }
-
-  /**
-   * Returns the date resolution that is used by RangeQueries for the given field. 
-   * Returns null, 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 (fieldToDateResolution == null) {
-      // no field specific date resolutions set; return default date resolution instead
-      return this.dateResolution;
-    }
-
-    DateTools.Resolution resolution = (DateTools.Resolution) fieldToDateResolution.get(fieldName);
-    if (resolution == null) {
-      // no date resolutions set for the given field; return default date resolution instead
-      resolution = this.dateResolution;
-    }
-
-    return resolution;
-  }
-  
-  /** 
-   * 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 rc  the collator to use when constructing RangeQuerys
-   */
-  public void setRangeCollator(Collator rc) {
-    rangeCollator = rc;
-  }
-  
-  /**
-   * @return the collator used to determine index term inclusion in ranges
-   * for RangeQuerys.
-   */
-  public Collator getRangeCollator() {
-    return rangeCollator;
-  }
-
-  /**
-   * @deprecated use {@link #addClause(List, int, int, Query)} instead.
-   */
-  protected void addClause(Vector clauses, int conj, int mods, Query q) {
-    addClause((List) clauses, conj, mods, q);
-  }
-
-  protected void addClause(List clauses, int conj, int mods, Query q) {
-    boolean required, prohibited;
-
-    // If this term is introduced by AND, make the preceding term required,
-    // unless it's already prohibited
-    if (clauses.size() > 0 && conj == CONJ_AND) {
-      BooleanClause c = (BooleanClause) clauses.get(clauses.size()-1);
-      if (!c.isProhibited())
-        c.setOccur(BooleanClause.Occur.MUST);
-    }
-
-    if (clauses.size() > 0 && operator == AND_OPERATOR && conj == CONJ_OR) {
-      // If this term is introduced by OR, make the preceding term optional,
-      // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b)
-      // notice if the input is a OR b, first term is parsed as required; without
-      // this modification a OR b would parsed as +a OR b
-      BooleanClause c = (BooleanClause) clauses.get(clauses.size()-1);
-      if (!c.isProhibited())
-        c.setOccur(BooleanClause.Occur.SHOULD);
-    }
-
-    // We might have been passed a null query; the term might have been
-    // filtered away by the analyzer.
-    if (q == null)
-      return;
-
-    if (operator == OR_OPERATOR) {
-      // We set REQUIRED if we're introduced by AND or +; PROHIBITED if
-      // introduced by NOT or -; make sure not to set both.
-      prohibited = (mods == MOD_NOT);
-      required = (mods == MOD_REQ);
-      if (conj == CONJ_AND && !prohibited) {
-        required = true;
-      }
-    } else {
-      // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED
-      // if not PROHIBITED and not introduced by OR
-      prohibited = (mods == MOD_NOT);
-      required   = (!prohibited && conj != CONJ_OR);
-    }
-    if (required && !prohibited)
-      clauses.add(newBooleanClause(q, BooleanClause.Occur.MUST));
-    else if (!required && !prohibited)
-      clauses.add(newBooleanClause(q, BooleanClause.Occur.SHOULD));
-    else if (!required && prohibited)
-      clauses.add(newBooleanClause(q, BooleanClause.Occur.MUST_NOT));
-    else
-      throw new RuntimeException("Clause cannot be both required and prohibited");
-  }
-
-
-  /**
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getFieldQuery(String field, String queryText)  throws ParseException {
-    // Use the analyzer to get all the tokens, and then build a TermQuery,
-    // PhraseQuery, or nothing based on the term count
-
-    TokenStream source = analyzer.tokenStream(field, new StringReader(queryText));
-    CachingTokenFilter buffer = new CachingTokenFilter(source);
-    TermAttribute termAtt = null;
-    PositionIncrementAttribute posIncrAtt = null;
-    int numTokens = 0;
-
-    org.apache.lucene.analysis.Token reusableToken = null;
-    org.apache.lucene.analysis.Token nextToken = null;
-
-    
-    boolean useNewAPI = TokenStream.useNewAPIDefault();
-    
-    if (useNewAPI) {
-      boolean success = false;
-      try {
-        buffer.reset();
-        success = true;
-      } catch (IOException e) {
-        // success==false if we hit an exception
-      }
-      if (success) {
-    	if (buffer.hasAttribute(TermAttribute.class)) {
-    	  termAtt = (TermAttribute) buffer.getAttribute(TermAttribute.class);
-    	}
-        if (buffer.hasAttribute(PositionIncrementAttribute.class)) {
-          posIncrAtt = (PositionIncrementAttribute) buffer.getAttribute(PositionIncrementAttribute.class);
-        }
-      }
-    } else {
-      reusableToken = new org.apache.lucene.analysis.Token();      
-    }
-    
-    int positionCount = 0;
-    boolean severalTokensAtSamePosition = false;
-
-    if (useNewAPI) {
-      if (termAtt != null) {
-        try {
-          while (buffer.incrementToken()) {
-            numTokens++;
-            int positionIncrement = (posIncrAtt != null) ? posIncrAtt.getPositionIncrement() : 1;
-            if (positionIncrement != 0) {
-              positionCount += positionIncrement;
-            } else {
-              severalTokensAtSamePosition = true;
-            }
-          }
-        } catch (IOException e) {
-          // ignore
-        }
-      }
-    } else {
-      while (true) {
-        try {
-          nextToken = buffer.next(reusableToken);
-        }
-        catch (IOException e) {
-          nextToken = null;
-        }
-        if (nextToken == null)
-          break;
-        numTokens++;
-        if (nextToken.getPositionIncrement() != 0)
-          positionCount += nextToken.getPositionIncrement();
-        else
-          severalTokensAtSamePosition = true;
-      }      
-    }
-    try {
-      // rewind the buffer stream
-      buffer.reset();
-
-      // close original stream - all tokens buffered
-      source.close();
-    }
-    catch (IOException e) {
-      // ignore
-    }
-    
-    if (numTokens == 0)
-      return null;
-    else if (numTokens == 1) {
-      String term = null;
-      try {
-
-        if (useNewAPI) {
-          boolean hasNext = buffer.incrementToken();
-          assert hasNext == true;
-          term = termAtt.term();
-        } else {
-          nextToken = buffer.next(reusableToken);
-          assert nextToken != null;
-          term = nextToken.term();
-        }
-      } catch (IOException e) {
-        // safe to ignore, because we know the number of tokens
-      }
-      return newTermQuery(new Term(field, term));
-    } else {
-      if (severalTokensAtSamePosition) {
-        if (positionCount == 1) {
-          // no phrase query:
-          BooleanQuery q = newBooleanQuery(true);
-          for (int i = 0; i < numTokens; i++) {
-            String term = null;
-            try {
-              if (useNewAPI) {
-                boolean hasNext = buffer.incrementToken();
-                assert hasNext == true;
-                term = termAtt.term();
-              } else {
-                nextToken = buffer.next(reusableToken);
-                assert nextToken != null;
-                term = nextToken.term();
-              }            
-            } catch (IOException e) {
-              // safe to ignore, because we know the number of tokens
-            }
-            
-            Query currentQuery = newTermQuery(
-                new Term(field, term));
-            q.add(currentQuery, BooleanClause.Occur.SHOULD);
-          }
-          return q;
-        }
-        else {
-          // phrase query:
-          MultiPhraseQuery mpq = newMultiPhraseQuery();
-          mpq.setSlop(phraseSlop);
-          List multiTerms = new ArrayList();
-          int position = -1;
-          for (int i = 0; i < numTokens; i++) {
-            String term = null;
-            int positionIncrement = 1;
-            try {
-              if (useNewAPI) {
-                boolean hasNext = buffer.incrementToken();
-                assert hasNext == true;
-                term = termAtt.term();
-                if (posIncrAtt != null) {
-                  positionIncrement = posIncrAtt.getPositionIncrement();
-                }
-              } else {
-                nextToken = buffer.next(reusableToken);
-                assert nextToken != null;
-                term = nextToken.term();
-                positionIncrement = nextToken.getPositionIncrement();
-              }
-            } catch (IOException e) {
-              // safe to ignore, because we know the number of tokens
-            }
-
-            if (positionIncrement > 0 && multiTerms.size() > 0) {
-              if (enablePositionIncrements) {
-                mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
-              } else {
-                mpq.add((Term[])multiTerms.toArray(new Term[0]));
-              }
-              multiTerms.clear();
-            }
-            position += positionIncrement;
-            multiTerms.add(new Term(field, term));
-          }
-          if (enablePositionIncrements) {
-            mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
-          } else {
-            mpq.add((Term[])multiTerms.toArray(new Term[0]));
-          }
-          return mpq;
-        }
-      }
-      else {
-        PhraseQuery pq = newPhraseQuery();
-        pq.setSlop(phraseSlop);
-        int position = -1;
-        
-        
-        for (int i = 0; i < numTokens; i++) {
-          String term = null;
-          int positionIncrement = 1;
-
-          try {  
-            if (useNewAPI) {
-              
-              boolean hasNext = buffer.incrementToken();
-              assert hasNext == true;
-              term = termAtt.term();
-              if (posIncrAtt != null) {
-                positionIncrement = posIncrAtt.getPositionIncrement();
-              }
-            } else {
-              nextToken = buffer.next(reusableToken);
-              assert nextToken != null;
-              term = nextToken.term();
-              positionIncrement = nextToken.getPositionIncrement();
-            }
-          } catch (IOException e) {
-            // safe to ignore, because we know the number of tokens
-          }
-
-          if (enablePositionIncrements) {
-            position += positionIncrement;
-            pq.add(new Term(field, term),position);
-          } else {
-            pq.add(new Term(field, term));
-          }
-        }
-        return pq;
-      }
-    }
-  }
-
-
-
-  /**
-   * 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 {
-    Query query = getFieldQuery(field, queryText);
-
-    if (query instanceof PhraseQuery) {
-      ((PhraseQuery) query).setSlop(slop);
-    }
-    if (query instanceof MultiPhraseQuery) {
-      ((MultiPhraseQuery) query).setSlop(slop);
-    }
-
-    return query;
-  }
-
-
-  /**
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getRangeQuery(String field,
-                                String part1,
-                                String part2,
-                                boolean inclusive) throws ParseException
-  {
-    if (lowercaseExpandedTerms) {
-      part1 = part1.toLowerCase();
-      part2 = part2.toLowerCase();
-    }
-    try {
-      DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
-      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();
-      }
-      DateTools.Resolution resolution = getDateResolution(field);
-      if (resolution == 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, resolution);
-        part2 = DateTools.dateToString(d2, resolution);
-      }
-    }
-    catch (Exception e) { }
-
-    return newRangeQuery(field, part1, part2, inclusive);
-  }
-
- /**
-  * Builds a new BooleanQuery instance
-  * @param disableCoord disable coord
-  * @return new BooleanQuery instance
-  */
-  protected BooleanQuery newBooleanQuery(boolean disableCoord) {
-    return new BooleanQuery(disableCoord); 
-  }
-
- /**
-  * Builds a new BooleanClause instance
-  * @param q sub query
-  * @param occur how this clause should occur when matching documents
-  * @return new BooleanClause instance
-  */
-  protected BooleanClause newBooleanClause(Query q, BooleanClause.Occur occur) {
-    return new BooleanClause(q, occur);
-  }
- 
-  /**
-   * Builds a new TermQuery instance
-   * @param term term
-   * @return new TermQuery instance
-   */
-  protected Query newTermQuery(Term term){
-    return new TermQuery(term);
-  }
- 
-  /**
-   * Builds a new PhraseQuery instance
-   * @return new PhraseQuery instance
-   */
-  protected PhraseQuery newPhraseQuery(){
-    return new PhraseQuery();
-  }
- 
-  /**
-   * Builds a new MultiPhraseQuery instance
-   * @return new MultiPhraseQuery instance
-   */
-  protected MultiPhraseQuery newMultiPhraseQuery(){
-    return new MultiPhraseQuery();
-  }
- 
-  /**
-   * Builds a new PrefixQuery instance
-   * @param prefix Prefix term
-   * @return new PrefixQuery instance
-   */
-  protected Query newPrefixQuery(Term prefix){
-    PrefixQuery query = new PrefixQuery(prefix);
-    query.setConstantScoreRewrite(constantScoreRewrite);
-    return query;
-  }
- 
-  /**
-   * Builds a new FuzzyQuery instance
-   * @param term Term
-   * @param minimumSimilarity minimum similarity
-   * @param prefixLength prefix length
-   * @return new FuzzyQuery Instance
-   */
-  protected Query newFuzzyQuery(Term term, float minimumSimilarity, int prefixLength) {
-    // FuzzyQuery doesn't yet allow constant score rewrite
-    return new FuzzyQuery(term,minimumSimilarity,prefixLength);
-  }
-
-  /**
-   * Builds a new RangeQuery instance
-   * @param field Field
-   * @param part1 min
-   * @param part2 max
-   * @param inclusive true if range is inclusive
-   * @return new RangeQuery instance
-   */
-  protected Query newRangeQuery(String field, String part1, String part2, boolean inclusive) {
-    RangeQuery query;  
-  
-    if (constantScoreRewrite) {
-      // TODO: remove in Lucene 3.0
-      query = new ConstantScoreRangeQuery(field, part1, part2, inclusive, inclusive, rangeCollator);
-    } else {
-      query = new RangeQuery(field, part1, part2, inclusive, inclusive, rangeCollator);
-    }
-    query.setConstantScoreRewrite(constantScoreRewrite);
-    return query;
-  }
-  
-  /**
-   * Builds a new MatchAllDocsQuery instance
-   * @return new MatchAllDocsQuery instance
-   */
-  protected Query newMatchAllDocsQuery() {
-    return new MatchAllDocsQuery(); 
-  }
-
-  /**
-   * Builds a new WildcardQuery instance
-   * @param t wildcard term
-   * @return new WildcardQuery instance
-   */
-  protected Query newWildcardQuery(Term t) {
-    WildcardQuery query = new WildcardQuery(t);
-    query.setConstantScoreRewrite(constantScoreRewrite);
-    return query;
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   * @deprecated use {@link #getBooleanQuery(List)} instead
-   */
-  protected Query getBooleanQuery(Vector clauses) throws ParseException {
-    return getBooleanQuery((List) clauses, false);
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getBooleanQuery(List clauses) throws ParseException {
-    return getBooleanQuery(clauses, false);
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   * @param disableCoord true if coord scoring should be disabled.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   * @deprecated use {@link #getBooleanQuery(List, boolean)} instead
-   */
-  protected Query getBooleanQuery(Vector clauses, boolean disableCoord)
-    throws ParseException
-  {
-    return getBooleanQuery((List) clauses, disableCoord);
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   * @param disableCoord true if coord scoring should be disabled.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getBooleanQuery(List clauses, boolean disableCoord)
-    throws ParseException
-  {
-    if (clauses.size()==0) {
-      return null; // all clause words were filtered away by the analyzer.
-    }
-    BooleanQuery query = newBooleanQuery(disableCoord);
-    for (int i = 0; i < clauses.size(); i++) {
-      query.add((BooleanClause)clauses.get(i));
-    }
-    return query;
-  }
-
-  /**
-   * Factory method for generating a query. Called when parser
-   * parses an input term token that contains one or more wildcard
-   * characters (? and *), but is not a prefix term token (one
-   * that has just a single * character at the end)
-   *<p>
-   * Depending on settings, prefix term may be lower-cased
-   * automatically. It will not go through the default Analyzer,
-   * however, since normal Analyzers are unlikely to work properly
-   * with wildcard templates.
-   *<p>
-   * Can be overridden by extending classes, to provide custom handling for
-   * wildcard queries, which may be necessary due to missing analyzer calls.
-   *
-   * @param field Name of the field query will use.
-   * @param termStr Term token that contains one or more wild card
-   *   characters (? or *), but is not simple prefix term
-   *
-   * @return Resulting {@link Query} built for the term
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getWildcardQuery(String field, String termStr) throws ParseException
-  {
-    if ("*".equals(field)) {
-      if ("*".equals(termStr)) return newMatchAllDocsQuery();
-    }
-    if (!allowLeadingWildcard && (termStr.startsWith("*") || termStr.startsWith("?")))
-      throw new ParseException("'*' or '?' not allowed as first character in WildcardQuery");
-    if (lowercaseExpandedTerms) {
-      termStr = termStr.toLowerCase();
-    }
-    Term t = new Term(field, termStr);
-    return newWildcardQuery(t);
-  }
-
-  /**
-   * Factory method for generating a query (similar to
-   * {@link #getWildcardQuery}). Called when parser parses an input term
-   * token that uses prefix notation; that is, contains a single '*' wildcard
-   * character as its last character. Since this is a special case
-   * of generic wildcard term, and such a query can be optimized easily,
-   * this usually results in a different query object.
-   *<p>
-   * Depending on settings, a prefix term may be lower-cased
-   * automatically. It will not go through the default Analyzer,
-   * however, since normal Analyzers are unlikely to work properly
-   * with wildcard templates.
-   *<p>
-   * Can be overridden by extending classes, to provide custom handling for
-   * wild card queries, which may be necessary due to missing analyzer calls.
-   *
-   * @param field Name of the field query will use.
-   * @param termStr Term token to use for building term for the query
-   *    (<b>without</b> trailing '*' character!)
-   *
-   * @return Resulting {@link Query} built for the term
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getPrefixQuery(String field, String termStr) throws ParseException
-  {
-    if (!allowLeadingWildcard && termStr.startsWith("*"))
-      throw new ParseException("'*' not allowed as first character in PrefixQuery");
-    if (lowercaseExpandedTerms) {
-      termStr = termStr.toLowerCase();
-    }
-    Term t = new Term(field, termStr);
-    return newPrefixQuery(t);
-  }
-
-   /**
-   * Factory method for generating a query (similar to
-   * {@link #getWildcardQuery}). Called when parser parses
-   * an input term token that has the fuzzy suffix (~) appended.
-   *
-   * @param field Name of the field query will use.
-   * @param termStr Term token to use for building term for the query
-   *
-   * @return Resulting {@link Query} built for the term
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException
-  {
-    if (lowercaseExpandedTerms) {
-      termStr = termStr.toLowerCase();
-    }
-    Term t = new Term(field, termStr);
-    return newFuzzyQuery(t, minSimilarity, fuzzyPrefixLength);
-  }
-
-  /**
-   * 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>\\u0041</code> to <code>A</code>.
-   * 
-   */
-  private String discardEscapeChar(String input) throws ParseException {
-    // Create char array to hold unescaped char sequence
-    char[] output = new char[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;
-          length++;
-        }
-        lastCharWasEscapeChar = false;
-      } else {
-        if (curChar == '\\') {
-          lastCharWasEscapeChar = true;
-        } else {
-          output[length] = curChar;
-          length++;
-        }
-      }
-    }
-
-    if (codePointMultiplier > 0) {
-      throw new ParseException("Truncated unicode escape sequence.");
-    }
-
-    if (lastCharWasEscapeChar) {
-      throw new ParseException("Term can not end with escape character.");
-    }
-
-    return new String(output, 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("None-hex character in unicode escape sequence: " + c);
-    }
-  }
-
-  /**
-   * 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();
-  }
-
-  /**
-   * Command line tool to test QueryParser, using {@link org.apache.lucene.analysis.SimpleAnalyzer}.
-   * Usage:<br>
-   * <code>java org.apache.lucene.queryParser.QueryParser &lt;input&gt;</code>
-   */
-  public static void main(String[] args) throws Exception {
-    if (args.length == 0) {
-      System.out.println("Usage: java org.apache.lucene.queryParser.QueryParser <input>");
-      System.exit(0);
-    }
-    QueryParser qp = new QueryParser("field",
-                           new org.apache.lucene.analysis.SimpleAnalyzer());
-    Query q = qp.parse(args[0]);
-    System.out.println(q.toString("field"));
-  }
-}
-
-PARSER_END(QueryParser)
-
-/* ***************** */
-/* 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; }
-}
-
-int Modifiers() : {
-  int ret = MOD_NONE;
-}
-{
-  [
-     <PLUS> { ret = MOD_REQ; }
-     | <MINUS> { ret = MOD_NOT; }
-     | <NOT> { ret = MOD_NOT; }
-  ]
-  { return ret; }
-}
-
-// This makes sure that there is no garbage after the query string
-Query TopLevelQuery(String field) : 
-{
-	Query q;
-}
-{
-	q=Query(field) <EOF>
-	{
-		return q;
-	}
-}
-
-Query Query(String field) :
-{
-  List clauses = new ArrayList();
-  Query q, firstQuery=null;
-  int conj, mods;
-}
-{
-  mods=Modifiers() q=Clause(field)
-  {
-    addClause(clauses, CONJ_NONE, mods, q);
-    if (mods == MOD_NONE)
-        firstQuery=q;
-  }
-  (
-    conj=Conjunction() mods=Modifiers() q=Clause(field)
-    { addClause(clauses, conj, mods, q); }
-  )*
-    {
-      if (clauses.size() == 1 && firstQuery != null)
-        return firstQuery;
-      else {
-  return getBooleanQuery(clauses);
-      }
-    }
-}
-
-Query Clause(String field) : {
-  Query q;
-  Token fieldToken=null, boost=null;
-}
-{
-  [
-    LOOKAHEAD(2)
-    (
-    fieldToken=<TERM> <COLON> {field=discardEscapeChar(fieldToken.image);}
-    | <STAR> <COLON> {field="*";}
-    )
-  ]
-
-  (
-   q=Term(field)
-   | <LPAREN> q=Query(field) <RPAREN> (<CARAT> boost=<NUMBER>)?
-
-  )
-    {
-      if (boost != null) {
-        float f = (float)1.0;
-  try {
-    f = Float.valueOf(boost.image).floatValue();
-          q.setBoost(f);
-  } catch (Exception ignored) { }
-      }
-      return q;
-    }
-}
-
-
-Query Term(String field) : {
-  Token term, boost=null, fuzzySlop=null, goop1, goop2;
-  boolean prefix = false;
-  boolean wildcard = false;
-  boolean fuzzy = false;
-  Query q;
-}
-{
-  (
-     (
-       term=<TERM>
-       | term=<STAR> { wildcard=true; }
-       | term=<PREFIXTERM> { prefix=true; }
-       | term=<WILDTERM> { wildcard=true; }
-       | term=<NUMBER>
-     )
-     [ fuzzySlop=<FUZZY_SLOP> { fuzzy=true; } ]
-     [ <CARAT> boost=<NUMBER> [ fuzzySlop=<FUZZY_SLOP> { fuzzy=true; } ] ]
-     {
-       String termImage=discardEscapeChar(term.image);
-       if (wildcard) {
-       q = getWildcardQuery(field, termImage);
-       } else if (prefix) {
-         q = getPrefixQuery(field,
-           discardEscapeChar(term.image.substring
-          (0, term.image.length()-1)));
-       } else if (fuzzy) {
-       	  float fms = fuzzyMinSim;
-       	  try {
-            fms = Float.valueOf(fuzzySlop.image.substring(1)).floatValue();
-       	  } catch (Exception ignored) { }
-       	 if(fms < 0.0f || fms > 1.0f){
-       	   throw new ParseException("Minimum similarity for a FuzzyQuery has to be between 0.0f and 1.0f !");
-       	 }
-       	 q = getFuzzyQuery(field, termImage,fms);
-       } else {
-         q = getFieldQuery(field, termImage);
-       }
-     }
-     | ( <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);
-          }
-          q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true);
-        }
-     | ( <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);
-          }
-
-          q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false);
-        }
-     | term=<QUOTED>
-       [ fuzzySlop=<FUZZY_SLOP> ]
-       [ <CARAT> boost=<NUMBER> ]
-       {
-         int s = phraseSlop;
-
-         if (fuzzySlop != null) {
-           try {
-             s = Float.valueOf(fuzzySlop.image.substring(1)).intValue();
-           }
-           catch (Exception ignored) { }
-         }
-         q = getFieldQuery(field, discardEscapeChar(term.image.substring(1, term.image.length()-1)), s);
-       }
-  )
-  {
-    if (boost != null) {
-      float f = (float) 1.0;
-      try {
-        f = Float.valueOf(boost.image).floatValue();
-      }
-      catch (Exception ignored) {
-    /* Should this be handled somehow? (defaults to "no boost", if
-     * boost number is invalid)
-     */
-      }
-
-      // avoid boosting null queries, such as those caused by stop words
-      if (q != null) {
-        q.setBoost(f);
-      }
-    }
-    return q;
-  }
-}
Index: src/java/org/apache/lucene/queryParser/Token.java
===================================================================
--- src/java/org/apache/lucene/queryParser/Token.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/Token.java	(working copy)
@@ -1,124 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */
-/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null */
-package org.apache.lucene.queryParser;
-
-/**
- * Describes the input token stream.
- */
-
-public class Token {
-
-  /**
-   * 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=37b1923f964a5a434f5ea3d6952ff200 (do not edit this line) */
Index: src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java
===================================================================
--- src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.java	(revision 0)
@@ -0,0 +1,50 @@
+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;
+        
+}
Index: src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties
===================================================================
--- src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties	(revision 0)
+++ src/java/org/apache/lucene/queryParser/messages/QueryParserMessages.properties	(revision 0)
@@ -0,0 +1,52 @@
+ # 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.
+
+# 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 = 
+
Index: src/java/org/apache/lucene/queryParser/messages/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/messages/package.html	(revision 0)
+++ 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, using <tt>org.apache.lucene.messages.NLS</tt> API.
+</body>
+</html>
Index: src/java/org/apache/lucene/queryParser/lucene2/MultiFieldQueryParserWrapper.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/MultiFieldQueryParserWrapper.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/MultiFieldQueryParserWrapper.java	(revision 0)
@@ -0,0 +1,250 @@
+package org.apache.lucene.queryParser.lucene2;
+
+/**
+ * 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.lucene2.config.LuceneMultiFieldQueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.processors.MultiFieldQueryNodeProcessor;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.MultiFieldQueryParser;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+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/>
+ * @depracated 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 {
+	protected String[] fields;
+
+    protected Map boosts;
+
+    /**
+     * 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);
+        this.boosts = boosts;
+        this.fields = fields;
+
+        setQueryConfig(new LuceneMultiFieldQueryConfigHandler(this, null,
+                fields, 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);
+
+        this.fields = fields;
+        setQueryConfig(new LuceneMultiFieldQueryConfigHandler(this, null,
+                fields, null));
+
+        QueryNodeProcessorPipeline newProcessorPipeline = new QueryNodeProcessorPipeline();
+        newProcessorPipeline.addProcessor(new MultiFieldQueryNodeProcessor());
+        newProcessorPipeline.addProcessor(getQueryProcessor());
+
+        setQueryProcessor(newProcessorPipeline);
+
+    }
+
+    /**
+     * Parses a query which searches on the fields specified.
+     * <p>
+     * If x fields are specified, this effectively constructs:
+     * <pre>
+     * <code>
+     * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
+     * </code>
+     * </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:
+     * <code>
+     * String[] fields = {"filename", "contents", "description"};
+     * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+     *                BooleanClause.Occur.MUST,
+     *                BooleanClause.Occur.MUST_NOT};
+     * MultiFieldQueryParser.parse("query", fields, flags, analyzer);
+     * </code>
+     * </pre>
+     *<p>
+     * The code above would construct a query:
+     * <pre>
+     * <code>
+     * (filename:query) +(contents:query) -(description:query)
+     * </code>
+     * </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:
+     * <code>
+     * String[] query = {"query1", "query2", "query3"};
+     * String[] fields = {"filename", "contents", "description"};
+     * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+     *                BooleanClause.Occur.MUST,
+     *                BooleanClause.Occur.MUST_NOT};
+     * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+     * </code>
+     * </pre>
+     *<p>
+     * The code above would construct a query:
+     * <pre>
+     * <code>
+     * (filename:query1) +(contents:query2) -(description:query3)
+     * </code>
+     * </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;
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/QueryParserWrapper.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/QueryParserWrapper.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/QueryParserWrapper.java	(revision 0)
@@ -0,0 +1,360 @@
+package org.apache.lucene.queryParser.lucene2;
+
+/**
+ * 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.QueryNodeException;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.builders.LuceneQueryBuilder;
+import org.apache.lucene.queryParser.lucene2.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.lucene2.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.lucene2.config.ConstantScoreRewriteAttribute;
+import org.apache.lucene.queryParser.lucene2.config.DateResolutionAttribute;
+import org.apache.lucene.queryParser.lucene2.config.DefaultOperatorAttribute;
+import org.apache.lucene.queryParser.lucene2.config.DefaultPhraseSlopAttribute;
+import org.apache.lucene.queryParser.lucene2.config.LocaleAttribute;
+import org.apache.lucene.queryParser.lucene2.config.LowercaseExpandedTermsAttribute;
+import org.apache.lucene.queryParser.lucene2.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.lucene2.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.lucene2.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessor;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Query;
+
+/**
+ * This class extends {@link QueryParser} 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/>
+ * @depracated 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 extends QueryParser {
+
+	private org.apache.lucene.queryParser.lucene2.parser.QueryParser luceneQueryParser = new org.apache.lucene.queryParser.lucene2.parser.QueryParser();
+
+    private LuceneQueryConfigHandler config;
+
+    private QueryNodeProcessor processorPipeline;
+
+    private LuceneQueryBuilder builder = new LuceneQueryTreeBuilder();
+
+    public QueryParserWrapper(String defaultField, Analyzer analizer) {
+        super(defaultField, analizer);
+        this.config = new LuceneQueryConfigHandler(this, null);
+        this.processorPipeline = new LuceneQueryNodeProcessorPipeline(
+                this.config);
+        
+    }
+    
+    /**
+     * 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.lucene2.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 {@link QueryNodeProcessor} used to process the query
+     * node tree generated by the {@link org.apache.lucene.queryParser.lucene2.parser.QueryParser}. 
+     * 
+     * @return
+     */
+    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 super.getAllowLeadingWildcard();
+        
+    }
+
+    public boolean getConstantScoreRewrite() {
+        
+        if (this.config != null && this.config.hasAttribute(ConstantScoreRewriteAttribute.class)) {
+            return ((ConstantScoreRewriteAttribute) this.config.getAttribute(ConstantScoreRewriteAttribute.class)).isConstantScoreRewrite();
+        }
+        
+        return super.getConstantScoreRewrite();
+        
+    }
+
+    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 super.getEnablePositionIncrements();
+        
+    }
+
+    public float getFuzzyMinSim() {
+        return super.getFuzzyMinSim();
+    }
+
+    public int getFuzzyPrefixLength() {
+        return super.getFuzzyPrefixLength();
+    }
+
+    public Locale getLocale() {
+        
+        if (this.config != null && this.config.hasAttribute(LocaleAttribute.class)) {
+            return ((LocaleAttribute) this.config.getAttribute(LocaleAttribute.class)).getLocale();
+        }
+        
+        return super.getLocale();
+        
+    }
+
+    public boolean getLowercaseExpandedTerms() {
+        
+        if (this.config != null && this.config.hasAttribute(LowercaseExpandedTermsAttribute.class)) {
+            return ((LowercaseExpandedTermsAttribute) this.config.getAttribute(LowercaseExpandedTermsAttribute.class)).isLowercaseExpandedTerms();
+        }
+        
+        return super.getLowercaseExpandedTerms();
+        
+    }
+
+    public int getPhraseSlop() {
+        
+        if (this.config != null && this.config.hasAttribute(AllowLeadingWildcardAttribute.class)) {
+            return ((DefaultPhraseSlopAttribute) this.config.getAttribute(DefaultPhraseSlopAttribute.class)).getDefaultPhraseSlop();
+        }
+        
+        return super.getPhraseSlop();
+        
+    }
+
+    public Collator getRangeCollator() {
+        
+        if (this.config != null && this.config.hasAttribute(RangeCollatorAttribute.class)) {
+            return ((RangeCollatorAttribute) this.config.getAttribute(RangeCollatorAttribute.class)).getRangeCollator();
+        }
+        
+        return super.getRangeCollator();
+        
+    }
+
+    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(QueryParserWrapper.Operator op) {
+        this.config.setDefaultOperator(op);
+    }
+        
+    public QueryParserWrapper.Operator getDefaultOperator() {
+        
+        if (this.config != null && this.config.hasAttribute(DefaultOperatorAttribute.class)) {
+            return ((DefaultOperatorAttribute) this.config.getAttribute(DefaultOperatorAttribute.class)).getDefaultOperator();
+        }
+        
+        return super.getDefaultOperator();
+        
+    }
+
+    public void setEnablePositionIncrements(boolean enable) {
+        this.config.setPositionIncrementsEnabled(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) {
+        super.setUseOldRangeQuery(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();
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/BooleanQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/BooleanQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/BooleanQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,107 @@
+package org.apache.lucene.queryParser.lucene2.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.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) {
+
+                        // TODO: create a good message for this exception
+                        throw new QueryNodeException(new MessageImpl(
+                                QueryParserMessages.EMPTY_MESSAGE), 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;
+
+                // TODO: what should be the best way to get the default modifier
+                case MOD_NONE:
+                    return BooleanClause.Occur.SHOULD;
+
+            }
+
+        }
+
+        return BooleanClause.Occur.SHOULD;
+
+    }
+
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/BoostQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/BoostQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/BoostQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,52 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/builders/FieldQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/FieldQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/FieldQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.lucene2.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 AbstractTermQueryNode} 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: src/java/org/apache/lucene/queryParser/lucene2/builders/FuzzyQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/FuzzyQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/FuzzyQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,45 @@
+package org.apache.lucene.queryParser.lucene2.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;
+        
+        // TODO: the prefix length should be extracted from the FuzzyQueryNode instead of using the default one
+        return new FuzzyQuery(new Term(fuzzyNode.getFieldAsString(), fuzzyNode.getTextAsString()),
+                fuzzyNode.getSimilarity(), FuzzyQuery.defaultPrefixLength);
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/GroupQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/GroupQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/GroupQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,45 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneBooleanQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneBooleanQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneBooleanQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,108 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.nodes.LuceneBooleanQueryNode;
+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.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) {
+
+                        // TODO: create a good message for this exception
+                        throw new QueryNodeException(new MessageImpl(
+                                QueryParserMessages.EMPTY_MESSAGE), 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: src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneQueryBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneQueryBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneQueryBuilder.java	(revision 0)
@@ -0,0 +1,38 @@
+package org.apache.lucene.queryParser.lucene2.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 a {@link QueryNode} object.
+ * <br/>
+ * @see QueryBuilder
+ * @see QueryTreeBuilder
+ */
+public interface LuceneQueryBuilder extends QueryBuilder {
+    
+    public Query build(QueryNode queryNode) throws QueryNodeException;
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneQueryTreeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneQueryTreeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/LuceneQueryTreeBuilder.java	(revision 0)
@@ -0,0 +1,75 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.nodes.LuceneBooleanQueryNode;
+import org.apache.lucene.queryParser.lucene2.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.lucene2.nodes.RangeQueryNode;
+import org.apache.lucene.queryParser.lucene2.processors.LuceneQueryNodeProcessorPipeline;
+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.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+import org.apache.lucene.search.Query;
+
+
+/**
+ * This query tree builder only defines the necessary map to build a {@link Query} object. 
+ * It should be used to generate a {@link Query} 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: src/java/org/apache/lucene/queryParser/lucene2/builders/MatchAllDocsQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/MatchAllDocsQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/MatchAllDocsQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,50 @@
+package org.apache.lucene.queryParser.lucene2.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.nodes.MatchAllDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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)) {
+            
+         // TODO: node should be converted to a readable query instead of just invoking node.toString()
+            throw new QueryNodeException(new MessageImpl("Q0019E.LUCENE_QUERY_CONVERSION_ERROR", queryNode.toString(), queryNode.getClass().getName()));
+            
+        }
+        
+        return new MatchAllDocsQuery();
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/MatchNoDocsQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/MatchNoDocsQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/MatchNoDocsQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,50 @@
+package org.apache.lucene.queryParser.lucene2.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.nodes.MatchNoDocsQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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)) {
+            
+         // TODO: node should be converted to a readable query instead of just invoking node.toString()
+            throw new QueryNodeException(new MessageImpl("Q0019E.LUCENE_QUERY_CONVERSION_ERROR", queryNode.toString(), queryNode.getClass().getName()));
+            
+        }
+        
+        return new BooleanQuery();
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/ModifierQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/ModifierQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/ModifierQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,45 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/builders/MultiPhraseQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/MultiPhraseQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/MultiPhraseQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,81 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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: src/java/org/apache/lucene/queryParser/lucene2/builders/PhraseQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/PhraseQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/PhraseQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,64 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/builders/PrefixWildcardQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/PrefixWildcardQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/PrefixWildcardQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/builders/RangeQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/RangeQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/RangeQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,62 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.nodes.RangeQueryNode;
+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.search.RangeQuery;
+
+/**
+ * Builds a {@link RangeQuery} object from a {@link RangeQueryNode} object.
+ */
+public class RangeQueryNodeBuilder implements LuceneQueryBuilder {
+    
+    public RangeQueryNodeBuilder() {
+        // empty constructor
+    }
+
+    public RangeQuery 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();
+        
+        RangeQuery rangeQuery = new RangeQuery(field, lower.getTextAsString(), upper.getTextAsString(), lowerInclusive, upperInclusive, rangeNode.getCollator()); 
+                
+        rangeQuery.setConstantScoreRewrite(rangeNode.isConstantScoreRewrite());
+        
+        return rangeQuery;
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/builders/SlopQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/SlopQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/SlopQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,56 @@
+package org.apache.lucene.queryParser.lucene2.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.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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: src/java/org/apache/lucene/queryParser/lucene2/builders/WildcardQueryNodeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/WildcardQueryNodeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/builders/WildcardQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,43 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/builders/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/builders/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/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>Lucene 2 Query Node Builders</h2>
+<p>
+The package org.apache.lucene.queryParser.lucene2.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 LuceneQueryNodeProcessorPipeline.
+</p>
+<p>
+LuceneQueryTreeBuilder is a builder that already contains a defined map that maps each QueryNode object
+with its respective builder.
+</p>
+</body>
+</html>
Index: src/java/org/apache/lucene/queryParser/lucene2/config/AllowLeadingWildcardAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/AllowLeadingWildcardAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/AllowLeadingWildcardAttribute.java	(revision 0)
@@ -0,0 +1,77 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#setAllowLeadingWildcard(boolean)
+ */
+public class AllowLeadingWildcardAttribute extends Attribute {
+    
+    private static final long serialVersionUID = -2804763012723049527L;
+    
+    private boolean allowLeadingWildcard = true;
+    
+    public AllowLeadingWildcardAttribute() {
+        // empty constructor
+    }
+    
+    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 + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/AnalyzerAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/AnalyzerAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/AnalyzerAttribute.java	(revision 0)
@@ -0,0 +1,84 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#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 + "'/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/BoostAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/BoostAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/BoostAttribute.java	(revision 0)
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 MultiFieldQueryParser
+ */
+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 + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/ConstantScoreRewriteAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/ConstantScoreRewriteAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/ConstantScoreRewriteAttribute.java	(revision 0)
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#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 + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/DateResolutionAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/DateResolutionAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/DateResolutionAttribute.java	(revision 0)
@@ -0,0 +1,86 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#setDateResolution(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 + "'/>";
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/DefaultOperatorAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/DefaultOperatorAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/DefaultOperatorAttribute.java	(revision 0)
@@ -0,0 +1,85 @@
+package org.apache.lucene.queryParser.lucene2.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.Attribute;
+import org.apache.lucene.queryParser.QueryParser.Operator;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.processors.GroupQueryNodeProcessor;
+
+/**
+ * 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 QueryParser#setDefaultOperator(Operator)
+ */
+public class DefaultOperatorAttribute extends Attribute {
+    
+    private static final long serialVersionUID = -6804760312723049526L;
+    
+    private Operator operator;
+    
+    public DefaultOperatorAttribute() {
+        // empty constructor
+    }
+    
+    void setDefaultOperator(Operator operator) {
+        this.operator = operator;
+    }
+    
+    public Operator getDefaultOperator() {
+        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.operator == this.operator
+                    || (this.operator != null && defaultOperatorAttr.operator != null && this.operator.equals(defaultOperatorAttr.operator))) {
+
+                return true;
+
+            }
+
+        }
+        
+        return false;
+        
+    }
+
+    public int hashCode() {
+       return (this.operator == null) ? 0 : this.operator.hashCode();
+    }
+
+    public String toString() {
+        return "<defaultOperatorAttribute defaultOperator=" + this.operator + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/DefaultPhraseSlopAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/DefaultPhraseSlopAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/DefaultPhraseSlopAttribute.java	(revision 0)
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#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 + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/LocaleAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/LocaleAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/LocaleAttribute.java	(revision 0)
@@ -0,0 +1,85 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#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 + "/>";
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/LowercaseExpandedTermsAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/LowercaseExpandedTermsAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/LowercaseExpandedTermsAttribute.java	(revision 0)
@@ -0,0 +1,80 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#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 + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/LuceneMultiFieldQueryConfigHandler.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/LuceneMultiFieldQueryConfigHandler.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/LuceneMultiFieldQueryConfigHandler.java	(revision 0)
@@ -0,0 +1,72 @@
+package org.apache.lucene.queryParser.lucene2.config;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.lucene2.MultiFieldQueryParserWrapper;
+
+
+/**
+ * This configuration handler holds every configuration supported by {@link LuceneQueryConfigHandler}
+ * plus a field boost mapping and the list of fields that should be used to expand each term.
+ * <br/>
+ * @see MultiFieldQueryParser
+ * @see MultiFieldQueryParserWrapper
+ */
+public class LuceneMultiFieldQueryConfigHandler extends LuceneQueryConfigHandler {
+
+    private Map<CharSequence, Float> boosts;
+    
+    /**
+     * @param queryParser
+     * @param defaultDateResolution
+     */
+    public LuceneMultiFieldQueryConfigHandler(QueryParser queryParser,
+            Resolution defaultDateResolution, CharSequence[] fields, Map<CharSequence, Float> boosts) {
+        
+        super(queryParser, defaultDateResolution);
+        
+        MultiFieldAttribute multiFieldAttr = (MultiFieldAttribute) addAttribute(MultiFieldAttribute.class);
+        multiFieldAttr.setFields(fields);
+        
+        this.boosts = boosts;
+        
+    }
+    
+    public FieldConfig getFieldConfig(CharSequence fieldName) {
+        FieldConfig fc = super.getFieldConfig(fieldName);
+        
+        if (this.boosts != null) {
+            BoostAttribute boostAttr = (BoostAttribute) fc.addAttribute(BoostAttribute.class);
+            Float boost = this.boosts.get(fieldName);
+            
+            if (boost != null) {
+                boostAttr.setBoost(boost.floatValue());
+            }
+            
+        }
+        
+        return fc;
+        
+    }
+   
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/config/LuceneQueryConfigHandler.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/LuceneQueryConfigHandler.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/LuceneQueryConfigHandler.java	(revision 0)
@@ -0,0 +1,186 @@
+package org.apache.lucene.queryParser.lucene2.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 org.apache.lucene.document.DateTools;
+import org.apache.lucene.queryParser.config.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.QueryParserWrapper;
+import org.apache.lucene.queryParser.lucene2.processors.LuceneQueryNodeProcessorPipeline;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.QueryParser.Operator;
+
+
+/**
+ * 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 QueryParser
+ * @see LuceneQueryNodeProcessorPipeline
+ * @see QueryParserWrapper
+ */
+public class LuceneQueryConfigHandler extends QueryConfigHandler {
+    
+    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 LocaleAttribute localeAttribute;
+    
+    private HashMap<CharSequence, DateTools.Resolution> dateResolutions;
+    
+    public LuceneQueryConfigHandler(QueryParser queryParser, DateTools.Resolution defaultDateResolution) {
+        Operator op = queryParser.getDefaultOperator();
+        Collator collator = queryParser.getRangeCollator();
+        Locale locale = queryParser.getLocale();
+        int defaultPhraseSlop = queryParser.getPhraseSlop();
+        boolean lowercaseExpandedTerms = queryParser.getLowercaseExpandedTerms();
+        boolean allowLeadingWildcard = queryParser.getAllowLeadingWildcard();
+        
+        boolean constantScoreRewrite = queryParser.getConstantScoreRewrite();
+        
+        boolean positionIncrementsEnabled = queryParser.getEnablePositionIncrements();
+        this.defaultDateResolution = defaultDateResolution;
+        
+        this.rangeCollatorAttribute = ((RangeCollatorAttribute) addAttribute(RangeCollatorAttribute.class));
+        this.rangeCollatorAttribute.setDateResolution(collator);
+        
+        this.defaultOperatorAttribute = ((DefaultOperatorAttribute) addAttribute(DefaultOperatorAttribute.class));
+        this.defaultOperatorAttribute.setDefaultOperator(op);
+        
+        AnalyzerAttribute analyzerAttr = ((AnalyzerAttribute) addAttribute(AnalyzerAttribute.class));
+        analyzerAttr.setAnalyzer(queryParser.getAnalyzer());
+        
+        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);
+        
+    }
+  
+    public FieldConfig getFieldConfig(CharSequence fieldName) {
+        // TODO: cache a field config when it's constructed for the first time,
+        // consecutive calls could return the cached object
+        
+        if (fieldName != null) {
+            FieldConfig fieldConfig = new FieldConfig(fieldName);
+            
+            DateResolutionAttribute dateResolutionAttr = (DateResolutionAttribute) fieldConfig.addAttribute(DateResolutionAttribute.class);
+            DateTools.Resolution dateRes = null;
+            
+            if (this.dateResolutions != null) {
+                dateRes = this.dateResolutions.get(fieldName.toString());
+            }
+            
+            if (dateRes == null) {
+                dateRes = this.defaultDateResolution;
+            }
+            
+            dateResolutionAttr.setDateResolution(dateRes);
+            
+            return fieldConfig;
+            
+        }
+        
+        return null;
+        
+    }
+    
+    public void setRangeCollator(Collator collator) {
+        this.rangeCollatorAttribute.setDateResolution(collator);
+    }
+
+    public void setDefaultOperator(Operator op) {
+        this.defaultOperatorAttribute.setDefaultOperator(op);
+    }
+    
+    public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
+        this.lowercaseExpandedTermsAttr.setLowercaseExpandedTerms(lowercaseExpandedTerms);
+    }
+    
+    /**
+     * @param allowLeadingWildcard
+     */
+    public void setAllowLeadingWildcard(boolean allowLeadingWildcard) {
+        this.allowLeadingWildcardAttribute.setAllowLeadingWildcard(allowLeadingWildcard);
+    }
+    
+    public void setPositionIncrementsEnabled(boolean enabled) {
+        this.positionIncrementsAttribute.setPositionIncrementsEnabled(enabled);
+    }
+    
+    public void setConstantScoreRewrite(boolean constantScoreRewrite) {
+        this.constantScoreRewriteAttribute.setConstantScoreRewrite(constantScoreRewrite);
+    }
+    
+    public void setDateResolution(DateTools.Resolution dateResolution) {
+        this.defaultDateResolution = dateResolution;
+    }
+    
+    public void setLocale(Locale locale) {
+        this.localeAttribute.setLocale(locale);
+    }
+    
+    public void setDefaultPhraseSlop(int defaultPhraseSlop) {
+        this.defaultPhraseSlopAttribute.setDefaultPhraseSlop(defaultPhraseSlop);
+    }
+    
+    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);
+        }
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/config/MultiFieldAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/MultiFieldAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/MultiFieldAttribute.java	(revision 0)
@@ -0,0 +1,81 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 MultiFieldQueryParser
+ */
+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) + "/>";
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/PositionIncrementsAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/PositionIncrementsAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/PositionIncrementsAttribute.java	(revision 0)
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.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 QueryParser#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 + "/>";
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/RangeCollatorAttribute.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/RangeCollatorAttribute.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/config/RangeCollatorAttribute.java	(revision 0)
@@ -0,0 +1,88 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.processors.ParametricRangeQueryNodeProcessor;
+import org.apache.lucene.search.RangeQuery;
+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 RangeQuery}
+ * <br/>
+ * @see QueryParser#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 + "'/>";
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/config/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/config/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/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>Lucene 2 Query Configuration</h2>
+<p>
+The package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/nodes/BooleanModifierNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/nodes/BooleanModifierNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/nodes/BooleanModifierNode.java	(revision 0)
@@ -0,0 +1,39 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.processors.GroupQueryNodeProcessor;
+import org.apache.lucene.queryParser.nodes.ModifierQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+
+/**
+ * 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: src/java/org/apache/lucene/queryParser/lucene2/nodes/LuceneBooleanQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/nodes/LuceneBooleanQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/nodes/LuceneBooleanQueryNode.java	(revision 0)
@@ -0,0 +1,56 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/nodes/MultiPhraseQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/nodes/MultiPhraseQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/nodes/MultiPhraseQueryNode.java	(revision 0)
@@ -0,0 +1,109 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/nodes/RangeQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/nodes/RangeQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/nodes/RangeQueryNode.java	(revision 0)
@@ -0,0 +1,78 @@
+package org.apache.lucene.queryParser.lucene2.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 QueryParser#setConstantScoreRewrite(boolean)
+ * @see QueryParser#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: src/java/org/apache/lucene/queryParser/lucene2/nodes/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/nodes/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/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>Lucene 2 Query Nodes</h2>
+<p>
+The package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/package.html	(revision 0)
@@ -0,0 +1,44 @@
+<!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.lucene2
+are used to reproduce the same behaviour as the old 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>
Index: src/java/org/apache/lucene/queryParser/lucene2/parser/EscapeQuerySyntaxImpl.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/EscapeQuerySyntaxImpl.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/EscapeQuerySyntaxImpl.java	(revision 0)
@@ -0,0 +1,283 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/parser/JavaCharStream.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/JavaCharStream.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/JavaCharStream.java	(revision 0)
@@ -0,0 +1,634 @@
+/* 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.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/parser/ParseException.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/ParseException.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/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.lucene2.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.
+   */
+  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.
+   */
+  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.
+   */
+  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.
+   */
+  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: src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParser.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParser.java	(revision 0)
@@ -0,0 +1,938 @@
+/* Generated By:JavaCC: Do not edit this line. QueryParser.java */
+package org.apache.lucene.queryParser.lucene2.parser;
+
+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 QueryParser 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 QueryParser() {
+        this(new StringReader(""));
+  }
+     /** Parses a query string, returning a {@link com.ibm.es.nuvo.search.query.tree.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) { }
+         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 QueryParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public QueryParser(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 QueryParser(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 QueryParser(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: src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParser.jj
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParser.jj	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParser.jj	(revision 0)
@@ -0,0 +1,486 @@
+/**
+ * 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.
+ */
+ 
+/**
+ * Original file is based on the QueryParser.jj from lucene 2.3
+ */
+ 
+//this is based on revision 535448
+
+options {
+  STATIC=false;
+  JAVA_UNICODE_ESCAPE=true;
+  USER_CHAR_STREAM=false;
+  IGNORE_CASE=false;
+  JDK_VERSION="1.5";
+}
+
+PARSER_BEGIN(QueryParser)
+package org.apache.lucene.queryParser.lucene2.parser;
+
+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 QueryParser 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 QueryParser() {
+   	this(new StringReader(""));
+  }
+     /** Parses a query string, returning a {@link com.ibm.es.nuvo.search.query.tree.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(QueryParser)
+
+/* ***************** */
+/* 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;
+  }
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParserConstants.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParserConstants.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParserConstants.java	(revision 0)
@@ -0,0 +1,125 @@
+/* Generated By:JavaCC: Do not edit this line. QueryParserConstants.java */
+package org.apache.lucene.queryParser.lucene2.parser;
+
+
+/**
+ * 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: src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParserTokenManager.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParserTokenManager.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/QueryParserTokenManager.java	(revision 0)
@@ -0,0 +1,1258 @@
+/* Generated By:JavaCC: Do not edit this line. QueryParserTokenManager.java */
+package org.apache.lucene.queryParser.lucene2.parser;
+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;
+
+/** 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;
+   }
+}
+private final int jjStartNfa_3(int pos, long active0)
+{
+   return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_3()
+{
+   switch(curChar)
+   {
+      case 40:
+         return jjStopAtPos(0, 13);
+      case 41:
+         return jjStopAtPos(0, 14);
+      case 42:
+         return jjStartNfaWithStates_3(0, 16, 36);
+      case 43:
+         return jjStopAtPos(0, 11);
+      case 45:
+         return jjStopAtPos(0, 12);
+      case 58:
+         return jjStopAtPos(0, 15);
+      case 91:
+         return jjStopAtPos(0, 23);
+      case 94:
+         return jjStopAtPos(0, 17);
+      case 123:
+         return jjStopAtPos(0, 24);
+      default :
+         return jjMoveNfa_3(0, 0);
+   }
+}
+private int jjStartNfaWithStates_3(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_3(state, pos + 1);
+}
+static final long[] jjbitVec0 = {
+   0x1L, 0x0L, 0x0L, 0x0L
+};
+static final long[] jjbitVec1 = {
+   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec3 = {
+   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec4 = {
+   0xfffefffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_3(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 36;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 36:
+               case 25:
+                  if ((0xfbfffcf8ffffd9ffL & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 0:
+                  if ((0xfbffd4f8ffffd9ffL & l) != 0L)
+                  {
+                     if (kind > 22)
+                        kind = 22;
+                     jjCheckNAddTwoStates(25, 26);
+                  }
+                  else if ((0x100002600L & l) != 0L)
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  else if (curChar == 34)
+                     jjCheckNAddStates(0, 2);
+                  else if (curChar == 33)
+                  {
+                     if (kind > 10)
+                        kind = 10;
+                  }
+                  if ((0x7bffd0f8ffffd9ffL & l) != 0L)
+                  {
+                     if (kind > 19)
+                        kind = 19;
+                     jjCheckNAddStates(3, 7);
+                  }
+                  else if (curChar == 42)
+                  {
+                     if (kind > 21)
+                        kind = 21;
+                  }
+                  if (curChar == 38)
+                     jjstateSet[jjnewStateCnt++] = 4;
+                  break;
+               case 4:
+                  if (curChar == 38 && kind > 8)
+                     kind = 8;
+                  break;
+               case 5:
+                  if (curChar == 38)
+                     jjstateSet[jjnewStateCnt++] = 4;
+                  break;
+               case 13:
+                  if (curChar == 33 && kind > 10)
+                     kind = 10;
+                  break;
+               case 14:
+                  if (curChar == 34)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 15:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 17:
+                  jjCheckNAddStates(0, 2);
+                  break;
+               case 18:
+                  if (curChar == 34 && kind > 18)
+                     kind = 18;
+                  break;
+               case 20:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 20)
+                     kind = 20;
+                  jjAddStates(8, 9);
+                  break;
+               case 21:
+                  if (curChar == 46)
+                     jjCheckNAdd(22);
+                  break;
+               case 22:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 20)
+                     kind = 20;
+                  jjCheckNAdd(22);
+                  break;
+               case 23:
+                  if (curChar == 42 && kind > 21)
+                     kind = 21;
+                  break;
+               case 24:
+                  if ((0xfbffd4f8ffffd9ffL & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 27:
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 28:
+                  if ((0x7bffd0f8ffffd9ffL & l) == 0L)
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddStates(3, 7);
+                  break;
+               case 29:
+                  if ((0x7bfff8f8ffffd9ffL & l) == 0L)
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddTwoStates(29, 30);
+                  break;
+               case 31:
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddTwoStates(29, 30);
+                  break;
+               case 32:
+                  if ((0x7bfff8f8ffffd9ffL & l) != 0L)
+                     jjCheckNAddStates(10, 12);
+                  break;
+               case 34:
+                  jjCheckNAddStates(10, 12);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 36:
+                  if ((0x97ffffff87ffffffL & l) != 0L)
+                  {
+                     if (kind > 22)
+                        kind = 22;
+                     jjCheckNAddTwoStates(25, 26);
+                  }
+                  else if (curChar == 92)
+                     jjCheckNAddTwoStates(27, 27);
+                  break;
+               case 0:
+                  if ((0x97ffffff87ffffffL & l) != 0L)
+                  {
+                     if (kind > 19)
+                        kind = 19;
+                     jjCheckNAddStates(3, 7);
+                  }
+                  else if (curChar == 92)
+                     jjCheckNAddStates(13, 15);
+                  else if (curChar == 126)
+                  {
+                     if (kind > 20)
+                        kind = 20;
+                     jjstateSet[jjnewStateCnt++] = 20;
+                  }
+                  if ((0x97ffffff87ffffffL & l) != 0L)
+                  {
+                     if (kind > 22)
+                        kind = 22;
+                     jjCheckNAddTwoStates(25, 26);
+                  }
+                  if (curChar == 78)
+                     jjstateSet[jjnewStateCnt++] = 11;
+                  else if (curChar == 124)
+                     jjstateSet[jjnewStateCnt++] = 8;
+                  else if (curChar == 79)
+                     jjstateSet[jjnewStateCnt++] = 6;
+                  else if (curChar == 65)
+                     jjstateSet[jjnewStateCnt++] = 2;
+                  break;
+               case 1:
+                  if (curChar == 68 && kind > 8)
+                     kind = 8;
+                  break;
+               case 2:
+                  if (curChar == 78)
+                     jjstateSet[jjnewStateCnt++] = 1;
+                  break;
+               case 3:
+                  if (curChar == 65)
+                     jjstateSet[jjnewStateCnt++] = 2;
+                  break;
+               case 6:
+                  if (curChar == 82 && kind > 9)
+                     kind = 9;
+                  break;
+               case 7:
+                  if (curChar == 79)
+                     jjstateSet[jjnewStateCnt++] = 6;
+                  break;
+               case 8:
+                  if (curChar == 124 && kind > 9)
+                     kind = 9;
+                  break;
+               case 9:
+                  if (curChar == 124)
+                     jjstateSet[jjnewStateCnt++] = 8;
+                  break;
+               case 10:
+                  if (curChar == 84 && kind > 10)
+                     kind = 10;
+                  break;
+               case 11:
+                  if (curChar == 79)
+                     jjstateSet[jjnewStateCnt++] = 10;
+                  break;
+               case 12:
+                  if (curChar == 78)
+                     jjstateSet[jjnewStateCnt++] = 11;
+                  break;
+               case 15:
+                  if ((0xffffffffefffffffL & l) != 0L)
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 16:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 17;
+                  break;
+               case 17:
+                  jjCheckNAddStates(0, 2);
+                  break;
+               case 19:
+                  if (curChar != 126)
+                     break;
+                  if (kind > 20)
+                     kind = 20;
+                  jjstateSet[jjnewStateCnt++] = 20;
+                  break;
+               case 24:
+                  if ((0x97ffffff87ffffffL & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 25:
+                  if ((0x97ffffff87ffffffL & l) == 0L)
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 26:
+                  if (curChar == 92)
+                     jjCheckNAddTwoStates(27, 27);
+                  break;
+               case 27:
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 28:
+                  if ((0x97ffffff87ffffffL & l) == 0L)
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddStates(3, 7);
+                  break;
+               case 29:
+                  if ((0x97ffffff87ffffffL & l) == 0L)
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddTwoStates(29, 30);
+                  break;
+               case 30:
+                  if (curChar == 92)
+                     jjCheckNAddTwoStates(31, 31);
+                  break;
+               case 31:
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddTwoStates(29, 30);
+                  break;
+               case 32:
+                  if ((0x97ffffff87ffffffL & l) != 0L)
+                     jjCheckNAddStates(10, 12);
+                  break;
+               case 33:
+                  if (curChar == 92)
+                     jjCheckNAddTwoStates(34, 34);
+                  break;
+               case 34:
+                  jjCheckNAddStates(10, 12);
+                  break;
+               case 35:
+                  if (curChar == 92)
+                     jjCheckNAddStates(13, 15);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 36:
+               case 25:
+                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 0:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 22)
+                        kind = 22;
+                     jjCheckNAddTwoStates(25, 26);
+                  }
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 19)
+                        kind = 19;
+                     jjCheckNAddStates(3, 7);
+                  }
+                  break;
+               case 15:
+               case 17:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddStates(0, 2);
+                  break;
+               case 24:
+                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 27:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 22)
+                     kind = 22;
+                  jjCheckNAddTwoStates(25, 26);
+                  break;
+               case 28:
+                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddStates(3, 7);
+                  break;
+               case 29:
+                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddTwoStates(29, 30);
+                  break;
+               case 31:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 19)
+                     kind = 19;
+                  jjCheckNAddTwoStates(29, 30);
+                  break;
+               case 32:
+                  if (jjCanMove_2(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddStates(10, 12);
+                  break;
+               case 34:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjCheckNAddStates(10, 12);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 36 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+private final int jjStopStringLiteralDfa_1(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x40000000L) != 0L)
+         {
+            jjmatchedKind = 33;
+            return 6;
+         }
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_1(int pos, long active0)
+{
+   return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_1()
+{
+   switch(curChar)
+   {
+      case 84:
+         return jjMoveStringLiteralDfa1_1(0x40000000L);
+      case 125:
+         return jjStopAtPos(0, 31);
+      default :
+         return jjMoveNfa_1(0, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_1(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_1(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 79:
+         if ((active0 & 0x40000000L) != 0L)
+            return jjStartNfaWithStates_1(1, 30, 6);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_1(0, active0);
+}
+private int jjStartNfaWithStates_1(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_1(state, pos + 1);
+}
+private int jjMoveNfa_1(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 7;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0xfffffffeffffffffL & l) != 0L)
+                  {
+                     if (kind > 33)
+                        kind = 33;
+                     jjCheckNAdd(6);
+                  }
+                  if ((0x100002600L & l) != 0L)
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  else if (curChar == 34)
+                     jjCheckNAddTwoStates(2, 4);
+                  break;
+               case 1:
+                  if (curChar == 34)
+                     jjCheckNAddTwoStates(2, 4);
+                  break;
+               case 2:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddStates(16, 18);
+                  break;
+               case 3:
+                  if (curChar == 34)
+                     jjCheckNAddStates(16, 18);
+                  break;
+               case 5:
+                  if (curChar == 34 && kind > 32)
+                     kind = 32;
+                  break;
+               case 6:
+                  if ((0xfffffffeffffffffL & l) == 0L)
+                     break;
+                  if (kind > 33)
+                     kind = 33;
+                  jjCheckNAdd(6);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+               case 6:
+                  if ((0xdfffffffffffffffL & l) == 0L)
+                     break;
+                  if (kind > 33)
+                     kind = 33;
+                  jjCheckNAdd(6);
+                  break;
+               case 2:
+                  jjAddStates(16, 18);
+                  break;
+               case 4:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 3;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 33)
+                        kind = 33;
+                     jjCheckNAdd(6);
+                  }
+                  break;
+               case 2:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjAddStates(16, 18);
+                  break;
+               case 6:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 33)
+                     kind = 33;
+                  jjCheckNAdd(6);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+   return jjMoveNfa_0(0, 0);
+}
+private int jjMoveNfa_0(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 3;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 25)
+                     kind = 25;
+                  jjAddStates(19, 20);
+                  break;
+               case 1:
+                  if (curChar == 46)
+                     jjCheckNAdd(2);
+                  break;
+               case 2:
+                  if ((0x3ff000000000000L & l) == 0L)
+                     break;
+                  if (kind > 25)
+                     kind = 25;
+                  jjCheckNAdd(2);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+private final int jjStopStringLiteralDfa_2(int pos, long active0)
+{
+   switch (pos)
+   {
+      case 0:
+         if ((active0 & 0x4000000L) != 0L)
+         {
+            jjmatchedKind = 29;
+            return 6;
+         }
+         return -1;
+      default :
+         return -1;
+   }
+}
+private final int jjStartNfa_2(int pos, long active0)
+{
+   return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_2()
+{
+   switch(curChar)
+   {
+      case 84:
+         return jjMoveStringLiteralDfa1_2(0x4000000L);
+      case 93:
+         return jjStopAtPos(0, 27);
+      default :
+         return jjMoveNfa_2(0, 0);
+   }
+}
+private int jjMoveStringLiteralDfa1_2(long active0)
+{
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) {
+      jjStopStringLiteralDfa_2(0, active0);
+      return 1;
+   }
+   switch(curChar)
+   {
+      case 79:
+         if ((active0 & 0x4000000L) != 0L)
+            return jjStartNfaWithStates_2(1, 26, 6);
+         break;
+      default :
+         break;
+   }
+   return jjStartNfa_2(0, active0);
+}
+private int jjStartNfaWithStates_2(int pos, int kind, int state)
+{
+   jjmatchedKind = kind;
+   jjmatchedPos = pos;
+   try { curChar = input_stream.readChar(); }
+   catch(java.io.IOException e) { return pos + 1; }
+   return jjMoveNfa_2(state, pos + 1);
+}
+private int jjMoveNfa_2(int startState, int curPos)
+{
+   int startsAt = 0;
+   jjnewStateCnt = 7;
+   int i = 1;
+   jjstateSet[0] = startState;
+   int kind = 0x7fffffff;
+   for (;;)
+   {
+      if (++jjround == 0x7fffffff)
+         ReInitRounds();
+      if (curChar < 64)
+      {
+         long l = 1L << curChar;
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if ((0xfffffffeffffffffL & l) != 0L)
+                  {
+                     if (kind > 29)
+                        kind = 29;
+                     jjCheckNAdd(6);
+                  }
+                  if ((0x100002600L & l) != 0L)
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  else if (curChar == 34)
+                     jjCheckNAddTwoStates(2, 4);
+                  break;
+               case 1:
+                  if (curChar == 34)
+                     jjCheckNAddTwoStates(2, 4);
+                  break;
+               case 2:
+                  if ((0xfffffffbffffffffL & l) != 0L)
+                     jjCheckNAddStates(16, 18);
+                  break;
+               case 3:
+                  if (curChar == 34)
+                     jjCheckNAddStates(16, 18);
+                  break;
+               case 5:
+                  if (curChar == 34 && kind > 28)
+                     kind = 28;
+                  break;
+               case 6:
+                  if ((0xfffffffeffffffffL & l) == 0L)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAdd(6);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else if (curChar < 128)
+      {
+         long l = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+               case 6:
+                  if ((0xffffffffdfffffffL & l) == 0L)
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAdd(6);
+                  break;
+               case 2:
+                  jjAddStates(16, 18);
+                  break;
+               case 4:
+                  if (curChar == 92)
+                     jjstateSet[jjnewStateCnt++] = 3;
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      else
+      {
+         int hiByte = (int)(curChar >> 8);
+         int i1 = hiByte >> 6;
+         long l1 = 1L << (hiByte & 077);
+         int i2 = (curChar & 0xff) >> 6;
+         long l2 = 1L << (curChar & 077);
+         do
+         {
+            switch(jjstateSet[--i])
+            {
+               case 0:
+                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 7)
+                        kind = 7;
+                  }
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                  {
+                     if (kind > 29)
+                        kind = 29;
+                     jjCheckNAdd(6);
+                  }
+                  break;
+               case 2:
+                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     jjAddStates(16, 18);
+                  break;
+               case 6:
+                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
+                     break;
+                  if (kind > 29)
+                     kind = 29;
+                  jjCheckNAdd(6);
+                  break;
+               default : break;
+            }
+         } while(i != startsAt);
+      }
+      if (kind != 0x7fffffff)
+      {
+         jjmatchedKind = kind;
+         jjmatchedPos = curPos;
+         kind = 0x7fffffff;
+      }
+      ++curPos;
+      if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
+         return curPos;
+      try { curChar = input_stream.readChar(); }
+      catch(java.io.IOException e) { return curPos; }
+   }
+}
+static final int[] jjnextStates = {
+   15, 16, 18, 29, 32, 23, 33, 30, 20, 21, 32, 23, 33, 31, 34, 27, 
+   2, 4, 5, 0, 1, 
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 48:
+         return ((jjbitVec0[i2] & l2) != 0L);
+      default :
+         return false;
+   }
+}
+private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec3[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec1[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+private static final boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2)
+{
+   switch(hiByte)
+   {
+      case 0:
+         return ((jjbitVec3[i2] & l2) != 0L);
+      case 48:
+         return ((jjbitVec1[i2] & l2) != 0L);
+      default :
+         if ((jjbitVec4[i1] & l1) != 0L)
+            return true;
+         return false;
+   }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, null, null, null, "\53", "\55", 
+"\50", "\51", "\72", "\52", "\136", null, null, null, null, null, "\133", "\173", 
+null, "\124\117", "\135", null, null, "\124\117", "\175", null, null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+   "Boost",
+   "RangeEx",
+   "RangeIn",
+   "DEFAULT",
+};
+
+/** Lex State array. */
+public static final int[] jjnewLexState = {
+   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 2, 1, 
+   3, -1, 3, -1, -1, -1, 3, -1, -1, 
+};
+static final long[] jjtoToken = {
+   0x3ffffff01L, 
+};
+static final long[] jjtoSkip = {
+   0x80L, 
+};
+protected JavaCharStream input_stream;
+private final int[] jjrounds = new int[36];
+private final int[] jjstateSet = new int[72];
+protected char curChar;
+/** Constructor. */
+public 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: src/java/org/apache/lucene/queryParser/lucene2/parser/Readme.txt
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/Readme.txt	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/Readme.txt	(revision 0)
@@ -0,0 +1,50 @@
+
+To build the QueryParser, run JavaCC on QueryParser.jj. That will generate:
+- QueryParser.java
+- QueryParserConstants.java
+- QueryParserTokenManager.java
+- TokenMgrError.java
+
+It would also generate 
+- JavaCharStream.java
+- ParseException.java
+- Token.java
+- JavaCharStream.java
+
+If you change anything in QueryParser.jj, run JavaCC on it, you need check in
+at least QueryParser.java. If you modified token definitions, you also need to
+check in QueryParserTokenmanager.java. If you add new rules, you probably need
+to check in QueryParserConstants, too. The other files usually don't change.
+
+Also, to avoid lots of warnings in the generated code:
+- add @SupressWarnings("all") to QueryParserTokenManager.java, tokenMgrError.java, 
+	JavaCharStream.java, Token.java and JavaCharStream.java
+	immediately preceding the class declaration. 
+- remove all imports from TokenMgrError.java
+- edit the ParseException class to extend from QueryNodeParseException class
+  "public class ParseException extends QueryNodeParseException".
+  Recreate the all the constructors like this:
+    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 needs to be done after each time these files are generated by javacc. If you don't 
+change the grammar, don't check out QueryParserTokenManager.java and it should 
+be fine. Also, TokenMgrError.java will only be generated if it did not exist.
+So, there is hope that for most changes to QueryParser.jj, this is not needed. 
+
Index: src/java/org/apache/lucene/queryParser/lucene2/parser/Token.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/Token.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/Token.java	(revision 0)
@@ -0,0 +1,148 @@
+/* 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.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/parser/TokenMgrError.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/TokenMgrError.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/parser/TokenMgrError.java	(revision 0)
@@ -0,0 +1,164 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
+/* JavaCCOptions: */
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/parser/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/parser/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/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.lucene2.parser contains the query parser.
+</p>
+<p>
+This new query parser only performs the syntax validation and create an QueryNode tree
+from a string of text.
+</p>
+</body>
+</html>
Index: src/java/org/apache/lucene/queryParser/lucene2/processors/AllowLeadingWildcardProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/AllowLeadingWildcardProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/AllowLeadingWildcardProcessor.java	(revision 0)
@@ -0,0 +1,96 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.config.AllowLeadingWildcardAttribute;
+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.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 QueryParser#setAllowLeadingWildcard(boolean)
+ * @see AllowLeadingWildcardAttribute
+ */
+public class AllowLeadingWildcardProcessor extends QueryNodeProcessorImpl {
+    
+    public AllowLeadingWildcardProcessor() {
+        // empty constructor
+    }
+    
+    public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+        
+        if (getQueryConfigHandler().hasAttribute(AllowLeadingWildcardAttribute.class)) {
+            
+            if (!((AllowLeadingWildcardAttribute) getQueryConfigHandler().getAttribute(AllowLeadingWildcardAttribute.class)).isAllowLeadingWildcard()) { 
+                return super.process(queryTree);    
+            }
+            
+        }
+        
+        return queryTree;
+        
+    }
+
+    protected QueryNode postProcessNode(QueryNode node)
+            throws QueryNodeException {
+        
+        if (node instanceof WildcardQueryNode) {
+            WildcardQueryNode wildcardNode = (WildcardQueryNode) node;
+            
+            switch (wildcardNode.getText().charAt(0)) {
+                
+                case '*' :
+                case '?' :
+                    // TODO: create a message for this exception: "'*' not allowed as first character in PrefixQuery"
+                    throw new QueryNodeException(new MessageImpl(QueryParserMessages.EMPTY_MESSAGE));
+                
+            }
+            
+        }
+        
+        return node;
+        
+    }
+
+    protected QueryNode preProcessNode(QueryNode node)
+            throws QueryNodeException {
+        
+        return node;
+        
+    }
+
+    protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+            throws QueryNodeException {
+        
+        return children;
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/processors/AnalyzerQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/AnalyzerQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/AnalyzerQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,336 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.config.AnalyzerAttribute;
+import org.apache.lucene.queryParser.lucene2.config.PositionIncrementsAttribute;
+import org.apache.lucene.queryParser.lucene2.nodes.LuceneBooleanQueryNode;
+import org.apache.lucene.queryParser.lucene2.nodes.MultiPhraseQueryNode;
+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.TokenizedPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.WildcardQueryNode;
+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 {
+
+        // TODO: it should check if it's an instance of "TextableNode" interface instead of FieldQueryNode
+        if (node instanceof FieldQueryNode
+                && !(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: src/java/org/apache/lucene/queryParser/lucene2/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/BooleanSingleChildOptimizationQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,90 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.nodes.BooleanModifierNode;
+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.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: src/java/org/apache/lucene/queryParser/lucene2/processors/DefaultPhraseSlopQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/DefaultPhraseSlopQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/DefaultPhraseSlopQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,117 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.config.DefaultPhraseSlopAttribute;
+import org.apache.lucene.queryParser.lucene2.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+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 QueryParser#setPhraseSlop(int)
+ */
+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: src/java/org/apache/lucene/queryParser/lucene2/processors/GroupQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/GroupQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/GroupQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,223 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.config.DefaultOperatorAttribute;
+import org.apache.lucene.queryParser.lucene2.nodes.BooleanModifierNode;
+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.processors.QueryNodeProcessor;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.queryParser.QueryParser.Operator;
+
+
+/**
+ * The {@link org.apache.lucene.queryParser.lucene2.parser.QueryParser} 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 QueryParser
+ */
+public class GroupQueryNodeProcessor implements QueryNodeProcessor {
+        
+    private ArrayList<QueryNode> queryNodeList;
+    
+    private Operator defaultOperator = null;
+    
+    private boolean latestNodeVerified;
+    
+    private QueryConfigHandler queryConfig;
+    
+    public GroupQueryNodeProcessor() {
+        // empty constructor
+    }
+    
+    public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+        
+        if (this.defaultOperator == null) {
+        
+            if (!getQueryConfigHandler().hasAttribute(DefaultOperatorAttribute.class)) {
+                throw new IllegalArgumentException("DefaultOperatorAttribute should be set on the QueryConfigHandler");
+            }
+        
+            this.defaultOperator = ((DefaultOperatorAttribute) getQueryConfigHandler().getAttribute(DefaultOperatorAttribute.class)).getDefaultOperator();
+            
+        }
+        
+        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.defaultOperator = null;
+        
+        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.defaultOperator == QueryParser.AND_OPERATOR) {
+            
+            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: src/java/org/apache/lucene/queryParser/lucene2/processors/LowercaseExpandedTermsQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/LowercaseExpandedTermsQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/LowercaseExpandedTermsQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,94 @@
+package org.apache.lucene.queryParser.lucene2.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.QueryParser;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.config.AllowLeadingWildcardAttribute;
+import org.apache.lucene.queryParser.lucene2.config.LowercaseExpandedTermsAttribute;
+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.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 QueryParser#setLowercaseExpandedTerms(boolean)
+ * @see LowercaseExpandedTermsAttribute
+ */
+public class LowercaseExpandedTermsQueryNodeProcessor extends QueryNodeProcessorImpl {
+    
+    public LowercaseExpandedTermsQueryNodeProcessor() {
+        // empty constructor
+    }
+    
+    public QueryNode process(QueryNode queryTree) throws QueryNodeException {
+        
+        if (getQueryConfigHandler().hasAttribute(LowercaseExpandedTermsAttribute.class)) {
+            
+            if (((LowercaseExpandedTermsAttribute) getQueryConfigHandler().getAttribute(LowercaseExpandedTermsAttribute.class)).isLowercaseExpandedTerms()) { 
+                return super.process(queryTree);    
+            }
+            
+        }
+        
+        return queryTree;
+        
+    }
+
+    protected QueryNode postProcessNode(QueryNode node)
+            throws QueryNodeException {
+        
+        if (node instanceof WildcardQueryNode ||
+                node instanceof FuzzyQueryNode ||
+                node instanceof ParametricQueryNode) {
+            
+            FieldQueryNode fieldNode = (FieldQueryNode) node;
+            fieldNode.setText(fieldNode.getText().toString().toLowerCase()); 
+            
+        }
+        
+        return node;
+        
+    }
+
+    protected QueryNode preProcessNode(QueryNode node)
+            throws QueryNodeException {
+        
+        return node;
+        
+    }
+
+    protected List<QueryNode> setChildrenOrder(List<QueryNode> children)
+            throws QueryNodeException {
+        
+        return children;
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/processors/LuceneQueryNodeProcessorPipeline.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/LuceneQueryNodeProcessorPipeline.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/LuceneQueryNodeProcessorPipeline.java	(revision 0)
@@ -0,0 +1,65 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.builders.LuceneQueryTreeBuilder;
+import org.apache.lucene.queryParser.lucene2.config.LuceneQueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.parser.QueryParser;
+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 QueryParser} 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 QueryParser
+ */
+public class LuceneQueryNodeProcessorPipeline extends QueryNodeProcessorPipeline {
+    
+    public LuceneQueryNodeProcessorPipeline(QueryConfigHandler queryConfig) {
+        super(queryConfig);
+        
+        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());
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/lucene2/processors/MatchAllDocsQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/MatchAllDocsQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/MatchAllDocsQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,76 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/processors/MultiFieldQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/MultiFieldQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/MultiFieldQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,168 @@
+package org.apache.lucene.queryParser.lucene2.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.FieldConfig;
+import org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.MultiFieldQueryParserWrapper;
+import org.apache.lucene.queryParser.lucene2.config.BoostAttribute;
+import org.apache.lucene.queryParser.lucene2.config.MultiFieldAttribute;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.BoostQueryNode;
+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.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/><br/>  
+ * This processor also looks a {@link BoostAttribute} for each field in the {@link QueryConfigHandler}.
+ * If there is a {@link BoostAttribute} in a specific field, this boost is applied to the {@link FieldableNode}.
+ * <br/>
+ * @see BoostAttribute
+ * @see MultiFieldAttribute
+ * @see MultiFieldQueryParser
+ * @see MultiFieldQueryParserWrapper
+ */
+public class MultiFieldQueryNodeProcessor extends QueryNodeProcessorImpl {
+
+    private boolean processChildren = true;
+
+    public MultiFieldQueryNodeProcessor() {
+        // empty constructor
+    }
+
+    protected QueryNode postProcessNode(QueryNode node)
+            throws QueryNodeException {
+
+        return node;
+
+    }
+
+    private QueryNode addBoost(FieldableNode node) throws QueryNodeException {
+        FieldConfig fieldConfig = getQueryConfigHandler().getFieldConfig(
+                node.getField());
+
+        if (fieldConfig != null) {
+
+            if (fieldConfig.hasAttribute(BoostAttribute.class)) {
+                float boost = ((BoostAttribute) fieldConfig.getAttribute(BoostAttribute.class)).getBoost();
+
+                return new BoostQueryNode(node, boost);
+
+            }
+
+        }
+
+        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]);
+                    QueryNode boostedNode = addBoost(fieldNode);
+
+                    if (fields.length == 1) {
+                        return boostedNode;
+
+                    } else {
+                        LinkedList<QueryNode> children = new LinkedList<QueryNode>();
+                        children.add(boostedNode);
+
+                        for (int i = 1; i < fields.length; i++) {
+                            try {
+                                fieldNode = (FieldableNode) fieldNode.cloneTree();
+                                fieldNode.setField(fields[i]);
+                                boostedNode = addBoost(fieldNode);
+
+                                children.add(boostedNode);
+
+                            } 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;
+
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/lucene2/processors/ParametricRangeQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/ParametricRangeQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/ParametricRangeQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,178 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.config.ConstantScoreRewriteAttribute;
+import org.apache.lucene.queryParser.lucene2.config.DateResolutionAttribute;
+import org.apache.lucene.queryParser.lucene2.config.LocaleAttribute;
+import org.apache.lucene.queryParser.lucene2.config.RangeCollatorAttribute;
+import org.apache.lucene.queryParser.lucene2.nodes.RangeQueryNode;
+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.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: src/java/org/apache/lucene/queryParser/lucene2/processors/PhraseSlopQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/PhraseSlopQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/PhraseSlopQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,74 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.nodes.MultiPhraseQueryNode;
+import org.apache.lucene.queryParser.nodes.SlopQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.nodes.TokenizedPhraseQueryNode;
+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: src/java/org/apache/lucene/queryParser/lucene2/processors/PrefixWildcardQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/PrefixWildcardQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/PrefixWildcardQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,74 @@
+package org.apache.lucene.queryParser.lucene2.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.lucene2.parser.QueryParser;
+import org.apache.lucene.queryParser.nodes.PrefixWildcardQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+import org.apache.lucene.search.PrefixQuery;
+
+
+/**
+ * The {@link QueryParser} 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: src/java/org/apache/lucene/queryParser/lucene2/processors/RemoveEmptyNonLeafQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/RemoveEmptyNonLeafQueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/processors/RemoveEmptyNonLeafQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,113 @@
+package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/lucene2/processors/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/lucene2/processors/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/lucene2/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 2 Query Node Processors</h2>
+<p>
+The package org.apache.lucene.queryParser.lucene2.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: src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/builders/QueryBuilder.java	(revision 0)
@@ -0,0 +1,41 @@
+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;
+    
+}
Index: src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java
===================================================================
--- src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/builders/QueryTreeBuilder.java	(revision 0)
@@ -0,0 +1,194 @@
+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;
+
+
+/**
+ * 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 interface and classes 
+ *        this class implements 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}. 
+ * 
+ * @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) {
+      
+            List<QueryNode> children = node.getChildren();
+            
+            if (children  != null) {
+                
+                for (QueryNode child : children) {
+                    process(child);
+                }
+                
+            }
+            
+            processNode(node);
+        
+        }
+        
+    }
+    
+    private void processNode(QueryNode node) throws QueryNodeException {
+        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);
+                        
+        }
+        
+        if (builder == null) {
+            // TODO: node should be converted to a readable query instead of just invoking node.toString()
+            throw new QueryNodeException(new MessageImpl(QueryParserMessages.LUCENE_QUERY_CONVERSION_ERROR, node.toString(), 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);
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/builders/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/builders/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/builders/package.html	(revision 0)
@@ -0,0 +1,36 @@
+<!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 <tt>QueryTreeBuilder</tt> walks the tree
+and call the Builder for each node in the tree.
+
+These builders expect that the query node tree was already processed by a processor pipeline.
+
+</p>
+<p>
+</p>
+</body>
+</html>
Index: src/java/org/apache/lucene/queryParser/ParseException.java
===================================================================
--- src/java/org/apache/lucene/queryParser/ParseException.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/ParseException.java	(working copy)
@@ -1,198 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */
-/* JavaCCOptions:KEEP_LINE_COL=null */
-package org.apache.lucene.queryParser;
-
-/**
- * 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 Exception {
-
-  /**
-   * 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.  The boolean
-   * flag "specialConstructor" is also set to true to indicate that
-   * this constructor was used to create this object.
-   * This constructor calls its super class with the empty string
-   * to force the "toString" method of parent class "Throwable" to
-   * print the error message in the form:
-   *     ParseException: <result of getMessage>
-   */
-  public ParseException(Token currentTokenVal,
-                        int[][] expectedTokenSequencesVal,
-                        String[] tokenImageVal
-                       )
-  {
-    super("");
-    specialConstructor = true;
-    currentToken = currentTokenVal;
-    expectedTokenSequences = expectedTokenSequencesVal;
-    tokenImage = tokenImageVal;
-  }
-
-  /**
-   * The following constructors are for use by you for whatever
-   * purpose you can think of.  Constructing the exception in this
-   * manner makes the exception behave in the normal way - i.e., as
-   * documented in the class "Throwable".  The fields "errorToken",
-   * "expectedTokenSequences", and "tokenImage" do not contain
-   * relevant information.  The JavaCC generated code does not use
-   * these constructors.
-   */
-
-  public ParseException() {
-    super();
-    specialConstructor = false;
-  }
-
-  /** Constructor with message. */
-  public ParseException(String message) {
-    super(message);
-    specialConstructor = false;
-  }
-
-  /**
-   * This variable determines which constructor was used to create
-   * this object and thereby affects the semantics of the
-   * "getMessage" method (see below).
-   */
-  protected boolean specialConstructor;
-
-  /**
-   * 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.
-   */
-  public 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.
-   */
-  public 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.
-   */
-  public String[] tokenImage;
-
-  /**
-   * This method has the standard behavior when this object has been
-   * created using the standard constructors.  Otherwise, 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), then this method is called during the printing
-   * of the final stack trace, and hence the correct error message
-   * gets displayed.
-   */
-  public String getMessage() {
-    if (!specialConstructor) {
-      return super.getMessage();
-    }
-    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.
-   */
-  protected 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.
-   */
-  protected 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=c63b396885c4ff44d7aa48d3feae60cd (do not edit this line) */
Index: src/java/org/apache/lucene/queryParser/QueryParserConstants.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParserConstants.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/QueryParserConstants.java	(working copy)
@@ -1,125 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. QueryParserConstants.java */
-package org.apache.lucene.queryParser;
-
-
-/**
- * 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: src/java/org/apache/lucene/queryParser/processors/NoChildOptimizationQueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/processors/NoChildOptimizationQueryNodeProcessor.java	(revision 0)
+++ 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;
+import org.apache.lucene.queryParser.processors.QueryNodeProcessorImpl;
+
+
+/**
+ * A {@link NoChildOptimizationQueryNodeProcessor} removes every BooleanQueryNode, 
+ * BoostQueryNode, TokenizedPhraseQueryNode or ModifierQueryNode that do not have 
+ * a valid children
+ * Example: When the children of these nodes are removed for any reason then the 
+ * nodes may become invalid.
+ */
+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;
+        
+    }   
+    
+}
Index: src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,72 @@
+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;
+
+/**
+ * A {@link QueryNodeProcessor} is a interface for classes that process a 
+ * query node tree.
+ * 
+ * The implementor of this class should perform some operation on a query node tree
+ * and return the same or another query node tree.
+ * 
+ * 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. 
+ * 
+ * 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.
+ * 
+ */
+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 query tree root node
+     * 
+     * @return the processed query tree
+     * 
+     * @throws QueryNodeException
+     * 
+     * @throws CloneNotSupportedException 
+     */
+    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();
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java
===================================================================
--- src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorImpl.java	(revision 0)
@@ -0,0 +1,148 @@
+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;
+
+
+/**
+ * @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;
+        
+    }
+
+    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;
+
+    }
+    
+    public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
+        this.queryConfig = queryConfigHandler;
+    }
+    
+    public QueryConfigHandler getQueryConfigHandler() {
+        return this.queryConfig;
+    }
+
+    abstract protected QueryNode preProcessNode(QueryNode node)
+            throws QueryNodeException;
+
+    abstract protected QueryNode postProcessNode(QueryNode node)
+            throws QueryNodeException;
+
+    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;
+
+    }
+
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java
===================================================================
--- src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/processors/QueryNodeProcessorPipeline.java	(revision 0)
@@ -0,0 +1,99 @@
+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;
+    }
+
+    public QueryConfigHandler getQueryConfigHandler() {
+        return this.queryConfig;
+    }
+
+    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);
+        
+    }
+
+    public void setQueryConfigHandler(QueryConfigHandler queryConfigHandler) {
+        this.queryConfig = queryConfigHandler;
+        
+        for (QueryNodeProcessor processor : this.processors) {
+            processor.setQueryConfigHandler(this.queryConfig);
+        }
+        
+    }
+    
+}
+
+
Index: src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java
===================================================================
--- src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/processors/RemoveDeletedQueryNodesProcessor.java	(revision 0)
@@ -0,0 +1,114 @@
+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.BooleanQueryNode;
+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 instanceof BooleanQueryNode) {
+            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;
+        
+    }
+
+}
Index: src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/AndQueryNode.java	(revision 0)
@@ -0,0 +1,75 @@
+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() + " )";
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/AnyQueryNode.java	(revision 0)
@@ -0,0 +1,114 @@
+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 matchingElements = 0;
+    
+    /**
+     * @param clauses - the query nodes to be or'ed   
+     */
+    public AnyQueryNode(List<QueryNode> clauses, CharSequence field, int matchingElements) {
+        super(clauses);
+        this.field = field;
+        this.matchingElements = matchingElements;
+    }
+    
+    /**
+     * 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.matchingElements = this.matchingElements;
+       
+        return clone;        
+    }
+    
+    public String toString() {      
+        if (getChildren() == null || getChildren().size() == 0)
+            return "<any field='" + this.field + "'  matchelements=" +  this.matchingElements + "/>";
+        StringBuilder sb = new StringBuilder();
+        sb.append("<any field='" + this.field + "'  matchelements=" +  this.matchingElements + ">");
+        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.matchingElements;
+
+        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 + ")";
+        }        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/BooleanQueryNode.java	(revision 0)
@@ -0,0 +1,84 @@
+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.*;
+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;
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/BoostQueryNode.java	(revision 0)
@@ -0,0 +1,119 @@
+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;        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/DeletedQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/DeletedQueryNode.java	(revision 0)
+++ 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;
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/FieldQueryNode.java	(revision 0)
@@ -0,0 +1,163 @@
+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 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;
+    }
+    
+    /**
+     * Returns the term.
+     * @return The "original" form of the term.
+     */
+    public CharSequence getText() {
+        return this.text;
+    }
+    
+    public CharSequence getField() {
+        return this.field;
+    }
+    
+    /**
+     * @param text the text to set
+     */
+    public void setText(CharSequence text) {
+        this.text = text;
+    }
+    
+    public void setField(CharSequence field) {
+        this.field = field;
+    }
+    
+    public int getPositionIncrement() {
+        return this.positionIncrement;
+    }
+
+    public void setPositionIncrement(int pi) {
+        this.positionIncrement = pi;
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/FieldableNode.java	(revision 0)
@@ -0,0 +1,44 @@
+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);
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/FuzzyQueryNode.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 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;    
+    
+    /**
+     * @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 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 FuzzyQueryNode cloneTree() throws CloneNotSupportedException {        
+        FuzzyQueryNode clone=(FuzzyQueryNode)super.cloneTree();
+        
+        clone.similarity = this.similarity;
+       
+        return clone;        
+    }
+
+    /**
+     * @return the similarity
+     */
+    public float getSimilarity() {
+        return this.similarity;
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/GroupQueryNode.java	(revision 0)
@@ -0,0 +1,86 @@
+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);
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/MatchAllDocsQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/MatchAllDocsQueryNode.java	(revision 0)
+++ 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;        
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/MatchNoDocsQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/MatchNoDocsQueryNode.java	(revision 0)
+++ 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/>";
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/ModifierQueryNode.java	(revision 0)
@@ -0,0 +1,152 @@
+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);
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/MultiLevelFieldQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/MultiLevelFieldQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/MultiLevelFieldQueryNode.java	(revision 0)
@@ -0,0 +1,154 @@
+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 MultiLevelFieldQueryNode} 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 MultiLevelFieldQueryNode.QueryText("company", 1, 7));
+ * values.add(new MultiLevelFieldQueryNode.QueryText("USA", 9, 12));
+ * values.add(new MultiLevelFieldQueryNode.QueryText("California", 14, 23));
+ * QueryNode q = new MultiLevelFieldQueryNode(values);
+ * 
+ */
+public class MultiLevelFieldQueryNode extends QueryNodeImpl implements FieldableNode {
+
+    private static final long serialVersionUID = -8325921322405804789L;
+
+    public static class QueryText {
+        CharSequence value = 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;
+        }
+    }
+
+    private List<QueryText> values = null;
+    /**
+     * @param values - List of QueryText objects
+     */
+    public MultiLevelFieldQueryNode(List<QueryText> pValues) {
+        this.values = pValues;
+    }
+
+    public CharSequence getField() {
+        //first value contains the field name
+        return this.values.get(0).value;
+    }
+    
+    public CharSequence getText() {
+        //second value contains the text value
+        return this.values.get(1).value;
+    }
+    
+    CharSequence getTermEscaped(EscapeQuerySyntax escaper){
+        return escaper.escape(this.values.get(1).value, Locale.getDefault(), Type.NORMAL);
+    }
+    
+    CharSequence getTermEscapeQuoted(EscapeQuerySyntax escaper){
+        return escaper.escape(this.values.get(1).value, Locale.getDefault(), Type.STRING);
+    }
+
+    public void setField(CharSequence fieldName) {
+        List<QueryNode> children = getChildren();
+        
+        if (children != null) {
+        
+            for (QueryNode child : children) {
+                
+                if (child instanceof FieldableNode) {
+                    ((FieldableNode) child).setField(fieldName);
+                }
+                
+            }
+        
+        }
+        
+    }
+    
+    public CharSequence toQueryString(EscapeQuerySyntax escaper) {
+        if (isDefaultField(this.values.get(0).value)) {
+            return "/DEFAULT/" + getTermEscaped(escaper);
+        } else {
+            return "/" + this.values.get(0).value + "/\"" + getTermEscaped(escaper) + "\"";
+        }
+    }
+    
+    public String toString() {
+        QueryText text = this.values.get(0);
+        
+        return "<multilevelfield start='" + text.begin 
+               + "' end='" + text.end 
+               + "' field='" + text.value + "' text='" + this.values.get(1).value +"'/>";
+    }
+    
+    public QueryNode cloneTree() throws CloneNotSupportedException {
+    	MultiLevelFieldQueryNode clone=(MultiLevelFieldQueryNode)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;
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/NoTokenFoundQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/NoTokenFoundQueryNode.java	(revision 0)
+++ 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;        
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/OpaqueQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/OpaqueQueryNode.java	(revision 0)
+++ 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;
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/OrQueryNode.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.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() + " )";
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/ParametricQueryNode.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 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 text, int begin, int end) {
+    	super(field, text, 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;
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/ParametricRangeQueryNode.java	(revision 0)
@@ -0,0 +1,112 @@
+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);
+                }
+                
+            }
+        
+        }
+        
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/PrefixWildcardQueryNode.java	(revision 0)
@@ -0,0 +1,55 @@
+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 term - 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;        
+    }    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/ProximityQueryNode.java	(revision 0)
@@ -0,0 +1,232 @@
+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 lucene2 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;
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/QueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/QueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/QueryNode.java	(revision 0)
@@ -0,0 +1,96 @@
+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 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
+     * @param value
+     */
+    public void unsetTag(CharSequence tagName);
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/QueryNodeImpl.java	(revision 0)
@@ -0,0 +1,216 @@
+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.QueryNode.toString()
+     */
+    public String toString() {
+         return super.toString();
+    }
+    
+    /**
+     * @see org.apache.lucene.queryParser.QueryNode.getTags()
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public Map<CharSequence, Object> getTags() {
+        return (Map<CharSequence, Object>) this.tags.clone();
+    }
+
+} // end class QueryNodeImpl
Index: src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/QuotedFieldQueryNode.java	(revision 0)
@@ -0,0 +1,60 @@
+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;        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/SlopQueryNode.java	(revision 0)
@@ -0,0 +1,113 @@
+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 QueryParser 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);
+        }
+        
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/nodes/TokenizedPhraseQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/TokenizedPhraseQueryNode.java	(revision 0)
+++ 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
Index: src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/WildcardQueryNode.java	(revision 0)
@@ -0,0 +1,60 @@
+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;        
+    }
+}
Index: src/java/org/apache/lucene/queryParser/nodes/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/nodes/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/nodes/package.html	(revision 0)
@@ -0,0 +1,76 @@
+<!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 QueryNodes.
+QueryNodes are serializable.
+These basic QueryNodes are used by the text parser to create a syntax tree.
+These nodes are designed to be used by UI or other parsers.
+A current reference implementation is <tt>org.apache.lucene.queryParser.lucene2.parser.QueryParser</tt>,
+this parser implements lucene 2.4 syntax.
+
+QueryNode interface is implement by all QueryNodes, the class QueryNodeImpl implements QueryNode and is extended
+by all QueryNode implementations.
+
+A QueryNode tree can be printed to the a stream, and it generates a seudo XML representation
+with all the nodes.
+
+A QueryNode tree can also generate a query String that can be parsed back by the original text parser,
+at this point only the lucene2 syntax is supported.
+
+Grouping nodes:
+AndQueryNode - used for AND operator
+AnyQueryNode - used for ANY operator
+OrQueryNode - used for OR operator
+BooleanQueryNode - used when no operator is specified
+ModifierQueryNode - used for modifier operator
+GroupQueryNode - used for parenthesis
+BoostQueryNode - used for Boost operator
+
+Final Nodes:
+FieldQueryNode - field/value node
+FuzzyQueryNode - fuzzy node
+MultiLevelFieldQueryNode - QueryNode object used with hierarchical multi-values  
+OpaqueQueryNode - Used as for part of the query that can be parsed by other parsers. schema/value 
+ParametricQueryNode - used for parametric field [>=|<=|=|<|>] value
+ParametricRangeQueryNode - used for parametric field:[low_value TO high_value]
+SlopQueryNode - phrase slop
+PrefixWildcardQueryNode - non-phrase wildcard query
+ProximityQueryNode - used for proximity search
+QuotedFieldQUeryNode - regular phrase node
+TokenizedPhraseQueryNode - used by tokenizers/lemmatizers/analizers for phrases/autophrases
+WildcardQueryNode - non-phrase wildcard query
+
+Final Utility Nodes:
+DeletedQueryNode - used by Processors on optimizations
+MatchAllDocsQueryNode - used by Processors on optimizations
+MatchNoDocsQueryNode - used by Processors on optimizations
+NoTokenFoundQueryNode - used by tokenizers/lemmatizers/analizers
+
+
+</p>
+<p>
+
+</p>
+</body>
+</html>
Index: src/java/org/apache/lucene/queryParser/QueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParser.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/QueryParser.java	(working copy)
@@ -1,1904 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. QueryParser.java */
-package org.apache.lucene.queryParser;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.text.Collator;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Vector;
-
-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.document.DateField;
-import org.apache.lucene.document.DateTools;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.ConstantScoreRangeQuery;
-import org.apache.lucene.search.FuzzyQuery;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.MultiPhraseQuery;
-import org.apache.lucene.search.PhraseQuery;
-import org.apache.lucene.search.PrefixQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.RangeQuery;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.WildcardQuery;
-import org.apache.lucene.util.Parameter;
-
-/**
- * This class is generated by JavaCC.  The most important method is
- * {@link #parse(String)}.
- *
- * The syntax for query strings is as follows:
- * 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 ::= ["+", "-"] [&lt;TERM&gt; ":"] ( &lt;TERM&gt; | "(" Query ")" )
- * </pre>
- *
- * <p>
- * Examples of appropriately formatted queries can be found in the <a
- * href="../../../../../../queryparsersyntax.html">query syntax
- * documentation</a>.
- * </p>
- *
- * <p>
- * In {@link RangeQuery}s, QueryParser tries to detect date values, e.g.
- * <tt>date:[6/1/2005 TO 6/4/2005]</tt> produces a range query that searches
- * for "date" fields between 2005-06-01 and 2005-06-04. Note that the format
- * of the accepted input depends on {@link #setLocale(Locale) the locale}.
- * By default a date is converted into a search term using the deprecated
- * {@link DateField} for compatibility reasons.
- * To use the new {@link DateTools} to convert dates, a
- * {@link org.apache.lucene.document.DateTools.Resolution} has to be set.
- * </p>
- * <p>
- * The date resolution that shall be used for RangeQueries can be set
- * using {@link #setDateResolution(DateTools.Resolution)}
- * or {@link #setDateResolution(String, DateTools.Resolution)}. The former
- * sets the default date resolution for all fields, whereas the latter can
- * be used to set field specific date resolutions. Field specific date
- * resolutions take, if set, precedence over the default date resolution.
- * </p>
- * <p>
- * If you use neither {@link DateField} nor {@link DateTools} in your
- * index, you can create your own
- * query parser that inherits QueryParser and overwrites
- * {@link #getRangeQuery(String, String, String, boolean)} to
- * use a different method for date conversion.
- * </p>
- *
- * <p>Note that QueryParser is <em>not</em> thread-safe.</p>
- */
-public class QueryParser implements QueryParserConstants {
-
-  private static final int CONJ_NONE   = 0;
-  private static final int CONJ_AND    = 1;
-  private static final int CONJ_OR     = 2;
-
-  private static final int MOD_NONE    = 0;
-  private static final int MOD_NOT     = 10;
-  private static final int MOD_REQ     = 11;
-
-  // make it possible to call setDefaultOperator() without accessing 
-  // 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;
-
-  /** The actual operator that parser uses to combine query terms */
-  private Operator operator = OR_OPERATOR;
-
-  boolean lowercaseExpandedTerms = true;
-  boolean constantScoreRewrite= true;
-  boolean allowLeadingWildcard = false;
-  boolean enablePositionIncrements = false;
-
-  Analyzer analyzer;
-  String field;
-  int phraseSlop = 0;
-  float fuzzyMinSim = FuzzyQuery.defaultMinSimilarity;
-  int fuzzyPrefixLength = FuzzyQuery.defaultPrefixLength;
-  Locale locale = Locale.getDefault();
-
-  // the default date resolution
-  DateTools.Resolution dateResolution = null;
-  // maps field names to date resolutions
-  Map fieldToDateResolution = null;
-
-  // The collator to use when determining range inclusion,
-  // for use when constructing RangeQuerys.
-  Collator rangeCollator = null;
-
-  /** The default operator for parsing queries. 
-   * Use {@link QueryParser#setDefaultOperator} to change it.
-   */
-  static public final class Operator extends Parameter {
-    private Operator(String name) {
-      super(name);
-    }
-    static public final Operator OR = new Operator("OR");
-    static public final Operator AND = new Operator("AND");
-  }
-
-
-  /** Constructs a query parser.
-   *  @param f  the default field for query terms.
-   *  @param a   used to find terms in the query text.
-   */
-  public QueryParser(String f, Analyzer a) {
-    this(new FastCharStream(new StringReader("")));
-    analyzer = a;
-    field = f;
-  }
-
-  /** Parses a query string, returning a {@link org.apache.lucene.search.Query}.
-   *  @param query  the query string to be parsed.
-   *  @throws ParseException if the parsing fails
-   */
-  public Query parse(String query) throws ParseException {
-    ReInit(new FastCharStream(new StringReader(query)));
-    try {
-      // TopLevelQuery is a Query followed by the end-of-input (EOF)
-      Query res = TopLevelQuery(field);
-      return res!=null ? res : newBooleanQuery(false);
-    }
-    catch (ParseException tme) {
-      // rethrow to include the original query:
-      throw new ParseException("Cannot parse '" +query+ "': " + tme.getMessage());
-    }
-    catch (TokenMgrError tme) {
-      throw new ParseException("Cannot parse '" +query+ "': " + tme.getMessage());
-    }
-    catch (BooleanQuery.TooManyClauses tmc) {
-      throw new ParseException("Cannot parse '" +query+ "': too many boolean clauses");
-    }
-  }
-
-   /**
-   * @return Returns the analyzer.
-   */
-  public Analyzer getAnalyzer() {
-    return analyzer;
-  }
-
-  /**
-   * @return Returns the field.
-   */
-  public String getField() {
-    return field;
-  }
-
-   /**
-   * Get the minimal similarity for fuzzy queries.
-   */
-  public float getFuzzyMinSim() {
-      return fuzzyMinSim;
-  }
-
-  /**
-   * Set the minimum similarity for fuzzy queries.
-   * Default is 0.5f.
-   */
-  public void setFuzzyMinSim(float fuzzyMinSim) {
-      this.fuzzyMinSim = fuzzyMinSim;
-  }
-
-   /**
-   * Get the prefix length for fuzzy queries. 
-   * @return Returns the fuzzyPrefixLength.
-   */
-  public int getFuzzyPrefixLength() {
-    return fuzzyPrefixLength;
-  }
-
-  /**
-   * Set the prefix length for fuzzy queries. Default is 0.
-   * @param fuzzyPrefixLength The fuzzyPrefixLength to set.
-   */
-  public void setFuzzyPrefixLength(int fuzzyPrefixLength) {
-    this.fuzzyPrefixLength = fuzzyPrefixLength;
-  }
-
-  /**
-   * Sets the default slop for phrases.  If zero, then exact phrase matches
-   * are required.  Default value is zero.
-   */
-  public void setPhraseSlop(int phraseSlop) {
-    this.phraseSlop = phraseSlop;
-  }
-
-  /**
-   * Gets the default slop for phrases.
-   */
-  public int getPhraseSlop() {
-    return phraseSlop;
-  }
-
-
-  /**
-   * 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.allowLeadingWildcard = allowLeadingWildcard;
-  }
-
-  /**
-   * @see #setAllowLeadingWildcard(boolean)
-   */
-  public boolean getAllowLeadingWildcard() {
-    return 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 enable) {
-    this.enablePositionIncrements = enable;
-  }
-
-  /**
-   * @see #setEnablePositionIncrements(boolean)
-   */
-  public boolean getEnablePositionIncrements() {
-    return enablePositionIncrements;
-  }
-
-  /**
-   * Sets the boolean operator of the QueryParser.
-   * In default mode (<code>OR_OPERATOR</code>) 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 <code>AND_OPERATOR</code> 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 op) {
-    this.operator = op;
-  }
-
-
-  /**
-   * Gets implicit operator setting, which will be either AND_OPERATOR
-   * or OR_OPERATOR.
-   */
-  public Operator getDefaultOperator() {
-    return operator;
-  }
-
-
-  /**
-   * Whether terms of wildcard, prefix, fuzzy and range queries are to be automatically
-   * lower-cased or not.  Default is <code>true</code>.
-   */
-  public void setLowercaseExpandedTerms(boolean lowercaseExpandedTerms) {
-    this.lowercaseExpandedTerms = lowercaseExpandedTerms;
-  }
-
-
-  /**
-   * @see #setLowercaseExpandedTerms(boolean)
-   */
-  public boolean getLowercaseExpandedTerms() {
-    return lowercaseExpandedTerms;
-  }
-
-  /**
-   * @deprecated Please use {@link #setConstantScoreRewrite} instead.
-   */
-  public void setUseOldRangeQuery(boolean useOldRangeQuery) {
-    constantScoreRewrite = !useOldRangeQuery;
-  }
-
-
-  /**
-   * @deprecated Please use {@link #getConstantScoreRewrite} instead.
-   */
-  public boolean getUseOldRangeQuery() {
-    return !constantScoreRewrite;
-  }
-
-  /**
-   * By default QueryParser uses constant-score rewriting
-   * when creating a PrefixQuery, WildcardQuery or RangeQuery. This implementation is generally preferable because it 
-   * a) Runs faster b) Does not have the scarcity of terms unduly influence score 
-   * c) avoids any "TooManyBooleanClauses" exception.
-   * However, if your application really needs to use the
-   * old-fashioned BooleanQuery 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 v) {
-    constantScoreRewrite = v;
-  }
-
-
-  /**
-   * @see #setConstantScoreRewrite(boolean)
-   */
-  public boolean getConstantScoreRewrite() {
-    return constantScoreRewrite;
-  }
-
-  /**
-   * Set locale used by date range parsing.
-   */
-  public void setLocale(Locale locale) {
-    this.locale = locale;
-  }
-
-  /**
-   * Returns current locale, allowing access by subclasses.
-   */
-  public Locale getLocale() {
-    return locale;
-  }
-
-  /**
-   * Sets the default date resolution used by RangeQueries 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.dateResolution = dateResolution;
-  }
-
-  /**
-   * Sets the date resolution used by RangeQueries for a specific field.
-   *  
-   * @param fieldName field for which the date resolution is to be set 
-   * @param dateResolution date resolution to set
-   */
-  public void setDateResolution(String fieldName, DateTools.Resolution dateResolution) {
-    if (fieldName == null) {
-      throw new IllegalArgumentException("Field cannot be null.");
-    }
-
-    if (fieldToDateResolution == null) {
-      // lazily initialize HashMap
-      fieldToDateResolution = new HashMap();
-    }
-
-    fieldToDateResolution.put(fieldName, dateResolution);
-  }
-
-  /**
-   * Returns the date resolution that is used by RangeQueries for the given field. 
-   * Returns null, 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 (fieldToDateResolution == null) {
-      // no field specific date resolutions set; return default date resolution instead
-      return this.dateResolution;
-    }
-
-    DateTools.Resolution resolution = (DateTools.Resolution) fieldToDateResolution.get(fieldName);
-    if (resolution == null) {
-      // no date resolutions set for the given field; return default date resolution instead
-      resolution = this.dateResolution;
-    }
-
-    return resolution;
-  }
-
-  /** 
-   * 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 rc  the collator to use when constructing RangeQuerys
-   */
-  public void setRangeCollator(Collator rc) {
-    rangeCollator = rc;
-  }
-
-  /**
-   * @return the collator used to determine index term inclusion in ranges
-   * for RangeQuerys.
-   */
-  public Collator getRangeCollator() {
-    return rangeCollator;
-  }
-
-  /**
-   * @deprecated use {@link #addClause(List, int, int, Query)} instead.
-   */
-  protected void addClause(Vector clauses, int conj, int mods, Query q) {
-    addClause((List) clauses, conj, mods, q);
-  }
-
-  protected void addClause(List clauses, int conj, int mods, Query q) {
-    boolean required, prohibited;
-
-    // If this term is introduced by AND, make the preceding term required,
-    // unless it's already prohibited
-    if (clauses.size() > 0 && conj == CONJ_AND) {
-      BooleanClause c = (BooleanClause) clauses.get(clauses.size()-1);
-      if (!c.isProhibited())
-        c.setOccur(BooleanClause.Occur.MUST);
-    }
-
-    if (clauses.size() > 0 && operator == AND_OPERATOR && conj == CONJ_OR) {
-      // If this term is introduced by OR, make the preceding term optional,
-      // unless it's prohibited (that means we leave -a OR b but +a OR b-->a OR b)
-      // notice if the input is a OR b, first term is parsed as required; without
-      // this modification a OR b would parsed as +a OR b
-      BooleanClause c = (BooleanClause) clauses.get(clauses.size()-1);
-      if (!c.isProhibited())
-        c.setOccur(BooleanClause.Occur.SHOULD);
-    }
-
-    // We might have been passed a null query; the term might have been
-    // filtered away by the analyzer.
-    if (q == null)
-      return;
-
-    if (operator == OR_OPERATOR) {
-      // We set REQUIRED if we're introduced by AND or +; PROHIBITED if
-      // introduced by NOT or -; make sure not to set both.
-      prohibited = (mods == MOD_NOT);
-      required = (mods == MOD_REQ);
-      if (conj == CONJ_AND && !prohibited) {
-        required = true;
-      }
-    } else {
-      // We set PROHIBITED if we're introduced by NOT or -; We set REQUIRED
-      // if not PROHIBITED and not introduced by OR
-      prohibited = (mods == MOD_NOT);
-      required   = (!prohibited && conj != CONJ_OR);
-    }
-    if (required && !prohibited)
-      clauses.add(newBooleanClause(q, BooleanClause.Occur.MUST));
-    else if (!required && !prohibited)
-      clauses.add(newBooleanClause(q, BooleanClause.Occur.SHOULD));
-    else if (!required && prohibited)
-      clauses.add(newBooleanClause(q, BooleanClause.Occur.MUST_NOT));
-    else
-      throw new RuntimeException("Clause cannot be both required and prohibited");
-  }
-
-
-  /**
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getFieldQuery(String field, String queryText)  throws ParseException {
-    // Use the analyzer to get all the tokens, and then build a TermQuery,
-    // PhraseQuery, or nothing based on the term count
-
-    TokenStream source = analyzer.tokenStream(field, new StringReader(queryText));
-    CachingTokenFilter buffer = new CachingTokenFilter(source);
-    TermAttribute termAtt = null;
-    PositionIncrementAttribute posIncrAtt = null;
-    int numTokens = 0;
-
-    org.apache.lucene.analysis.Token reusableToken = null;
-    org.apache.lucene.analysis.Token nextToken = null;
-
-
-    boolean useNewAPI = TokenStream.useNewAPIDefault();
-
-    if (useNewAPI) {
-      boolean success = false;
-      try {
-        buffer.reset();
-        success = true;
-      } catch (IOException e) {
-        // success==false if we hit an exception
-      }
-      if (success) {
-        if (buffer.hasAttribute(TermAttribute.class)) {
-          termAtt = (TermAttribute) buffer.getAttribute(TermAttribute.class);
-        }
-        if (buffer.hasAttribute(PositionIncrementAttribute.class)) {
-          posIncrAtt = (PositionIncrementAttribute) buffer.getAttribute(PositionIncrementAttribute.class);
-        }
-      }
-    } else {
-      reusableToken = new org.apache.lucene.analysis.Token();
-    }
-
-    int positionCount = 0;
-    boolean severalTokensAtSamePosition = false;
-
-    if (useNewAPI) {
-      if (termAtt != null) {
-        try {
-          while (buffer.incrementToken()) {
-            numTokens++;
-            int positionIncrement = (posIncrAtt != null) ? posIncrAtt.getPositionIncrement() : 1;
-            if (positionIncrement != 0) {
-              positionCount += positionIncrement;
-            } else {
-              severalTokensAtSamePosition = true;
-            }
-          }
-        } catch (IOException e) {
-          // ignore
-        }
-      }
-    } else {
-      while (true) {
-        try {
-          nextToken = buffer.next(reusableToken);
-        }
-        catch (IOException e) {
-          nextToken = null;
-        }
-        if (nextToken == null)
-          break;
-        numTokens++;
-        if (nextToken.getPositionIncrement() != 0)
-          positionCount += nextToken.getPositionIncrement();
-        else
-          severalTokensAtSamePosition = true;
-      }
-    }
-    try {
-      // rewind the buffer stream
-      buffer.reset();
-
-      // close original stream - all tokens buffered
-      source.close();
-    }
-    catch (IOException e) {
-      // ignore
-    }
-
-    if (numTokens == 0)
-      return null;
-    else if (numTokens == 1) {
-      String term = null;
-      try {
-
-        if (useNewAPI) {
-          boolean hasNext = buffer.incrementToken();
-          assert hasNext == true;
-          term = termAtt.term();
-        } else {
-          nextToken = buffer.next(reusableToken);
-          assert nextToken != null;
-          term = nextToken.term();
-        }
-      } catch (IOException e) {
-        // safe to ignore, because we know the number of tokens
-      }
-      return newTermQuery(new Term(field, term));
-    } else {
-      if (severalTokensAtSamePosition) {
-        if (positionCount == 1) {
-          // no phrase query:
-          BooleanQuery q = newBooleanQuery(true);
-          for (int i = 0; i < numTokens; i++) {
-            String term = null;
-            try {
-              if (useNewAPI) {
-                boolean hasNext = buffer.incrementToken();
-                assert hasNext == true;
-                term = termAtt.term();
-              } else {
-                nextToken = buffer.next(reusableToken);
-                assert nextToken != null;
-                term = nextToken.term();
-              }
-            } catch (IOException e) {
-              // safe to ignore, because we know the number of tokens
-            }
-
-            Query currentQuery = newTermQuery(
-                new Term(field, term));
-            q.add(currentQuery, BooleanClause.Occur.SHOULD);
-          }
-          return q;
-        }
-        else {
-          // phrase query:
-          MultiPhraseQuery mpq = newMultiPhraseQuery();
-          mpq.setSlop(phraseSlop);
-          List multiTerms = new ArrayList();
-          int position = -1;
-          for (int i = 0; i < numTokens; i++) {
-            String term = null;
-            int positionIncrement = 1;
-            try {
-              if (useNewAPI) {
-                boolean hasNext = buffer.incrementToken();
-                assert hasNext == true;
-                term = termAtt.term();
-                if (posIncrAtt != null) {
-                  positionIncrement = posIncrAtt.getPositionIncrement();
-                }
-              } else {
-                nextToken = buffer.next(reusableToken);
-                assert nextToken != null;
-                term = nextToken.term();
-                positionIncrement = nextToken.getPositionIncrement();
-              }
-            } catch (IOException e) {
-              // safe to ignore, because we know the number of tokens
-            }
-
-            if (positionIncrement > 0 && multiTerms.size() > 0) {
-              if (enablePositionIncrements) {
-                mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
-              } else {
-                mpq.add((Term[])multiTerms.toArray(new Term[0]));
-              }
-              multiTerms.clear();
-            }
-            position += positionIncrement;
-            multiTerms.add(new Term(field, term));
-          }
-          if (enablePositionIncrements) {
-            mpq.add((Term[])multiTerms.toArray(new Term[0]),position);
-          } else {
-            mpq.add((Term[])multiTerms.toArray(new Term[0]));
-          }
-          return mpq;
-        }
-      }
-      else {
-        PhraseQuery pq = newPhraseQuery();
-        pq.setSlop(phraseSlop);
-        int position = -1;
-
-
-        for (int i = 0; i < numTokens; i++) {
-          String term = null;
-          int positionIncrement = 1;
-
-          try {
-            if (useNewAPI) {
-
-              boolean hasNext = buffer.incrementToken();
-              assert hasNext == true;
-              term = termAtt.term();
-              if (posIncrAtt != null) {
-                positionIncrement = posIncrAtt.getPositionIncrement();
-              }
-            } else {
-              nextToken = buffer.next(reusableToken);
-              assert nextToken != null;
-              term = nextToken.term();
-              positionIncrement = nextToken.getPositionIncrement();
-            }
-          } catch (IOException e) {
-            // safe to ignore, because we know the number of tokens
-          }
-
-          if (enablePositionIncrements) {
-            position += positionIncrement;
-            pq.add(new Term(field, term),position);
-          } else {
-            pq.add(new Term(field, term));
-          }
-        }
-        return pq;
-      }
-    }
-  }
-
-
-
-  /**
-   * 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 {
-    Query query = getFieldQuery(field, queryText);
-
-    if (query instanceof PhraseQuery) {
-      ((PhraseQuery) query).setSlop(slop);
-    }
-    if (query instanceof MultiPhraseQuery) {
-      ((MultiPhraseQuery) query).setSlop(slop);
-    }
-
-    return query;
-  }
-
-
-  /**
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getRangeQuery(String field,
-                                String part1,
-                                String part2,
-                                boolean inclusive) throws ParseException
-  {
-    if (lowercaseExpandedTerms) {
-      part1 = part1.toLowerCase();
-      part2 = part2.toLowerCase();
-    }
-    try {
-      DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
-      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();
-      }
-      DateTools.Resolution resolution = getDateResolution(field);
-      if (resolution == 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, resolution);
-        part2 = DateTools.dateToString(d2, resolution);
-      }
-    }
-    catch (Exception e) { }
-
-    return newRangeQuery(field, part1, part2, inclusive);
-  }
-
- /**
-  * Builds a new BooleanQuery instance
-  * @param disableCoord disable coord
-  * @return new BooleanQuery instance
-  */
-  protected BooleanQuery newBooleanQuery(boolean disableCoord) {
-    return new BooleanQuery(disableCoord);
-  }
-
- /**
-  * Builds a new BooleanClause instance
-  * @param q sub query
-  * @param occur how this clause should occur when matching documents
-  * @return new BooleanClause instance
-  */
-  protected BooleanClause newBooleanClause(Query q, BooleanClause.Occur occur) {
-    return new BooleanClause(q, occur);
-  }
-
-  /**
-   * Builds a new TermQuery instance
-   * @param term term
-   * @return new TermQuery instance
-   */
-  protected Query newTermQuery(Term term){
-    return new TermQuery(term);
-  }
-
-  /**
-   * Builds a new PhraseQuery instance
-   * @return new PhraseQuery instance
-   */
-  protected PhraseQuery newPhraseQuery(){
-    return new PhraseQuery();
-  }
-
-  /**
-   * Builds a new MultiPhraseQuery instance
-   * @return new MultiPhraseQuery instance
-   */
-  protected MultiPhraseQuery newMultiPhraseQuery(){
-    return new MultiPhraseQuery();
-  }
-
-  /**
-   * Builds a new PrefixQuery instance
-   * @param prefix Prefix term
-   * @return new PrefixQuery instance
-   */
-  protected Query newPrefixQuery(Term prefix){
-    PrefixQuery query = new PrefixQuery(prefix);
-    query.setConstantScoreRewrite(constantScoreRewrite);
-    return query;
-  }
-
-  /**
-   * Builds a new FuzzyQuery instance
-   * @param term Term
-   * @param minimumSimilarity minimum similarity
-   * @param prefixLength prefix length
-   * @return new FuzzyQuery Instance
-   */
-  protected Query newFuzzyQuery(Term term, float minimumSimilarity, int prefixLength) {
-    // FuzzyQuery doesn't yet allow constant score rewrite
-    return new FuzzyQuery(term,minimumSimilarity,prefixLength);
-  }
-
-  /**
-   * Builds a new RangeQuery instance
-   * @param field Field
-   * @param part1 min
-   * @param part2 max
-   * @param inclusive true if range is inclusive
-   * @return new RangeQuery instance
-   */
-  protected Query newRangeQuery(String field, String part1, String part2, boolean inclusive) {
-    RangeQuery query;
-
-    if (constantScoreRewrite) {
-      // TODO: remove in Lucene 3.0
-      query = new ConstantScoreRangeQuery(field, part1, part2, inclusive, inclusive, rangeCollator);
-    } else {
-      query = new RangeQuery(field, part1, part2, inclusive, inclusive, rangeCollator);
-    }
-    query.setConstantScoreRewrite(constantScoreRewrite);
-    return query;
-  }
-
-  /**
-   * Builds a new MatchAllDocsQuery instance
-   * @return new MatchAllDocsQuery instance
-   */
-  protected Query newMatchAllDocsQuery() {
-    return new MatchAllDocsQuery();
-  }
-
-  /**
-   * Builds a new WildcardQuery instance
-   * @param t wildcard term
-   * @return new WildcardQuery instance
-   */
-  protected Query newWildcardQuery(Term t) {
-    WildcardQuery query = new WildcardQuery(t);
-    query.setConstantScoreRewrite(constantScoreRewrite);
-    return query;
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   * @deprecated use {@link #getBooleanQuery(List)} instead
-   */
-  protected Query getBooleanQuery(Vector clauses) throws ParseException {
-    return getBooleanQuery((List) clauses, false);
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getBooleanQuery(List clauses) throws ParseException {
-    return getBooleanQuery(clauses, false);
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   * @param disableCoord true if coord scoring should be disabled.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   * @deprecated use {@link #getBooleanQuery(List, boolean)} instead
-   */
-  protected Query getBooleanQuery(Vector clauses, boolean disableCoord)
-    throws ParseException
-  {
-    return getBooleanQuery((List) clauses, disableCoord);
-  }
-
-  /**
-   * Factory method for generating query, given a set of clauses.
-   * By default creates a boolean query composed of clauses passed in.
-   *
-   * Can be overridden by extending classes, to modify query being
-   * returned.
-   *
-   * @param clauses List that contains {@link BooleanClause} instances
-   *    to join.
-   * @param disableCoord true if coord scoring should be disabled.
-   *
-   * @return Resulting {@link Query} object.
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getBooleanQuery(List clauses, boolean disableCoord)
-    throws ParseException
-  {
-    if (clauses.size()==0) {
-      return null; // all clause words were filtered away by the analyzer.
-    }
-    BooleanQuery query = newBooleanQuery(disableCoord);
-    for (int i = 0; i < clauses.size(); i++) {
-      query.add((BooleanClause)clauses.get(i));
-    }
-    return query;
-  }
-
-  /**
-   * Factory method for generating a query. Called when parser
-   * parses an input term token that contains one or more wildcard
-   * characters (? and *), but is not a prefix term token (one
-   * that has just a single * character at the end)
-   *<p>
-   * Depending on settings, prefix term may be lower-cased
-   * automatically. It will not go through the default Analyzer,
-   * however, since normal Analyzers are unlikely to work properly
-   * with wildcard templates.
-   *<p>
-   * Can be overridden by extending classes, to provide custom handling for
-   * wildcard queries, which may be necessary due to missing analyzer calls.
-   *
-   * @param field Name of the field query will use.
-   * @param termStr Term token that contains one or more wild card
-   *   characters (? or *), but is not simple prefix term
-   *
-   * @return Resulting {@link Query} built for the term
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getWildcardQuery(String field, String termStr) throws ParseException
-  {
-    if ("*".equals(field)) {
-      if ("*".equals(termStr)) return newMatchAllDocsQuery();
-    }
-    if (!allowLeadingWildcard && (termStr.startsWith("*") || termStr.startsWith("?")))
-      throw new ParseException("'*' or '?' not allowed as first character in WildcardQuery");
-    if (lowercaseExpandedTerms) {
-      termStr = termStr.toLowerCase();
-    }
-    Term t = new Term(field, termStr);
-    return newWildcardQuery(t);
-  }
-
-  /**
-   * Factory method for generating a query (similar to
-   * {@link #getWildcardQuery}). Called when parser parses an input term
-   * token that uses prefix notation; that is, contains a single '*' wildcard
-   * character as its last character. Since this is a special case
-   * of generic wildcard term, and such a query can be optimized easily,
-   * this usually results in a different query object.
-   *<p>
-   * Depending on settings, a prefix term may be lower-cased
-   * automatically. It will not go through the default Analyzer,
-   * however, since normal Analyzers are unlikely to work properly
-   * with wildcard templates.
-   *<p>
-   * Can be overridden by extending classes, to provide custom handling for
-   * wild card queries, which may be necessary due to missing analyzer calls.
-   *
-   * @param field Name of the field query will use.
-   * @param termStr Term token to use for building term for the query
-   *    (<b>without</b> trailing '*' character!)
-   *
-   * @return Resulting {@link Query} built for the term
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getPrefixQuery(String field, String termStr) throws ParseException
-  {
-    if (!allowLeadingWildcard && termStr.startsWith("*"))
-      throw new ParseException("'*' not allowed as first character in PrefixQuery");
-    if (lowercaseExpandedTerms) {
-      termStr = termStr.toLowerCase();
-    }
-    Term t = new Term(field, termStr);
-    return newPrefixQuery(t);
-  }
-
-   /**
-   * Factory method for generating a query (similar to
-   * {@link #getWildcardQuery}). Called when parser parses
-   * an input term token that has the fuzzy suffix (~) appended.
-   *
-   * @param field Name of the field query will use.
-   * @param termStr Term token to use for building term for the query
-   *
-   * @return Resulting {@link Query} built for the term
-   * @exception ParseException throw in overridden method to disallow
-   */
-  protected Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException
-  {
-    if (lowercaseExpandedTerms) {
-      termStr = termStr.toLowerCase();
-    }
-    Term t = new Term(field, termStr);
-    return newFuzzyQuery(t, minSimilarity, fuzzyPrefixLength);
-  }
-
-  /**
-   * 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>\\u0041</code> to <code>A</code>.
-   * 
-   */
-  private String discardEscapeChar(String input) throws ParseException {
-    // Create char array to hold unescaped char sequence
-    char[] output = new char[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;
-          length++;
-        }
-        lastCharWasEscapeChar = false;
-      } else {
-        if (curChar == '\\') {
-          lastCharWasEscapeChar = true;
-        } else {
-          output[length] = curChar;
-          length++;
-        }
-      }
-    }
-
-    if (codePointMultiplier > 0) {
-      throw new ParseException("Truncated unicode escape sequence.");
-    }
-
-    if (lastCharWasEscapeChar) {
-      throw new ParseException("Term can not end with escape character.");
-    }
-
-    return new String(output, 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("None-hex character in unicode escape sequence: " + c);
-    }
-  }
-
-  /**
-   * 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();
-  }
-
-  /**
-   * Command line tool to test QueryParser, using {@link org.apache.lucene.analysis.SimpleAnalyzer}.
-   * Usage:<br>
-   * <code>java org.apache.lucene.queryParser.QueryParser &lt;input&gt;</code>
-   */
-  public static void main(String[] args) throws Exception {
-    if (args.length == 0) {
-      System.out.println("Usage: java org.apache.lucene.queryParser.QueryParser <input>");
-      System.exit(0);
-    }
-    QueryParser qp = new QueryParser("field",
-                           new org.apache.lucene.analysis.SimpleAnalyzer());
-    Query q = qp.parse(args[0]);
-    System.out.println(q.toString("field"));
-  }
-
-// *   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 int Modifiers() throws ParseException {
-  int ret = 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 = MOD_REQ;
-        break;
-      case MINUS:
-        jj_consume_token(MINUS);
-                 ret = MOD_NOT;
-        break;
-      case NOT:
-        jj_consume_token(NOT);
-               ret = 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 Query TopLevelQuery(String field) throws ParseException {
-        Query q;
-    q = Query(field);
-    jj_consume_token(0);
-                {if (true) return q;}
-    throw new Error("Missing return statement in function");
-  }
-
-  final public Query Query(String field) throws ParseException {
-  List clauses = new ArrayList();
-  Query q, firstQuery=null;
-  int conj, mods;
-    mods = Modifiers();
-    q = Clause(field);
-    addClause(clauses, CONJ_NONE, mods, q);
-    if (mods == MOD_NONE)
-        firstQuery=q;
-    label_1:
-    while (true) {
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case AND:
-      case OR:
-      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;
-      }
-      conj = Conjunction();
-      mods = Modifiers();
-      q = Clause(field);
-      addClause(clauses, conj, mods, q);
-    }
-      if (clauses.size() == 1 && firstQuery != null)
-        {if (true) return firstQuery;}
-      else {
-  {if (true) return getBooleanQuery(clauses);}
-      }
-    throw new Error("Missing return statement in function");
-  }
-
-  final public Query Clause(String field) throws ParseException {
-  Query q;
-  Token fieldToken=null, boost=null;
-    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=discardEscapeChar(fieldToken.image);
-        break;
-      case STAR:
-        jj_consume_token(STAR);
-        jj_consume_token(COLON);
-                      field="*";
-        break;
-      default:
-        jj_la1[5] = 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[6] = jj_gen;
-        ;
-      }
-      break;
-    default:
-      jj_la1[7] = jj_gen;
-      jj_consume_token(-1);
-      throw new ParseException();
-    }
-      if (boost != null) {
-        float f = (float)1.0;
-  try {
-    f = Float.valueOf(boost.image).floatValue();
-          q.setBoost(f);
-  } catch (Exception ignored) { }
-      }
-      {if (true) return q;}
-    throw new Error("Missing return statement in function");
-  }
-
-  final public Query Term(String field) throws ParseException {
-  Token term, boost=null, fuzzySlop=null, goop1, goop2;
-  boolean prefix = false;
-  boolean wildcard = false;
-  boolean fuzzy = false;
-  Query q;
-    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);
-        break;
-      case STAR:
-        term = jj_consume_token(STAR);
-                       wildcard=true;
-        break;
-      case PREFIXTERM:
-        term = jj_consume_token(PREFIXTERM);
-                             prefix=true;
-        break;
-      case WILDTERM:
-        term = jj_consume_token(WILDTERM);
-                           wildcard=true;
-        break;
-      case NUMBER:
-        term = jj_consume_token(NUMBER);
-        break;
-      default:
-        jj_la1[8] = 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[9] = 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[10] = jj_gen;
-          ;
-        }
-        break;
-      default:
-        jj_la1[11] = jj_gen;
-        ;
-      }
-       String termImage=discardEscapeChar(term.image);
-       if (wildcard) {
-       q = getWildcardQuery(field, termImage);
-       } else if (prefix) {
-         q = getPrefixQuery(field,
-           discardEscapeChar(term.image.substring
-          (0, term.image.length()-1)));
-       } else if (fuzzy) {
-          float fms = fuzzyMinSim;
-          try {
-            fms = Float.valueOf(fuzzySlop.image.substring(1)).floatValue();
-          } catch (Exception ignored) { }
-         if(fms < 0.0f || fms > 1.0f){
-           {if (true) throw new ParseException("Minimum similarity for a FuzzyQuery has to be between 0.0f and 1.0f !");}
-         }
-         q = getFuzzyQuery(field, termImage,fms);
-       } else {
-         q = getFieldQuery(field, termImage);
-       }
-      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[12] = 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[13] = 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[14] = 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[15] = 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);
-          }
-          q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), true);
-      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[16] = 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[17] = 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[18] = 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[19] = 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);
-          }
-
-          q = getRangeQuery(field, discardEscapeChar(goop1.image), discardEscapeChar(goop2.image), false);
-      break;
-    case QUOTED:
-      term = jj_consume_token(QUOTED);
-      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
-      case FUZZY_SLOP:
-        fuzzySlop = jj_consume_token(FUZZY_SLOP);
-        break;
-      default:
-        jj_la1[20] = 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[21] = jj_gen;
-        ;
-      }
-         int s = phraseSlop;
-
-         if (fuzzySlop != null) {
-           try {
-             s = Float.valueOf(fuzzySlop.image.substring(1)).intValue();
-           }
-           catch (Exception ignored) { }
-         }
-         q = getFieldQuery(field, discardEscapeChar(term.image.substring(1, term.image.length()-1)), s);
-      break;
-    default:
-      jj_la1[22] = jj_gen;
-      jj_consume_token(-1);
-      throw new ParseException();
-    }
-    if (boost != null) {
-      float f = (float) 1.0;
-      try {
-        f = Float.valueOf(boost.image).floatValue();
-      }
-      catch (Exception ignored) {
-    /* Should this be handled somehow? (defaults to "no boost", if
-     * boost number is invalid)
-     */
-      }
-
-      // avoid boosting null queries, such as those caused by stop words
-      if (q != null) {
-        q.setBoost(f);
-      }
-    }
-    {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_2() {
-    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_2()) {
-    jj_scanpos = xsp;
-    if (jj_3R_3()) return true;
-    }
-    return false;
-  }
-
-  private boolean jj_3R_3() {
-    if (jj_scan_token(STAR)) return true;
-    if (jj_scan_token(COLON)) return true;
-    return false;
-  }
-
-  /** Generated Token Manager. */
-  public QueryParserTokenManager token_source;
-  /** 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[23];
-  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,0x3ed3f00,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,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 user supplied CharStream. */
-  public QueryParser(CharStream stream) {
-    token_source = new QueryParserTokenManager(stream);
-    token = new Token();
-    jj_ntk = -1;
-    jj_gen = 0;
-    for (int i = 0; i < 23; 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(CharStream stream) {
-    token_source.ReInit(stream);
-    token = new Token();
-    jj_ntk = -1;
-    jj_gen = 0;
-    for (int i = 0; i < 23; 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 QueryParser(QueryParserTokenManager tm) {
-    token_source = tm;
-    token = new Token();
-    jj_ntk = -1;
-    jj_gen = 0;
-    for (int i = 0; i < 23; 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 < 23; i++) jj_la1[i] = -1;
-    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
-  }
-
-  private Token jj_consume_token(int kind) throws ParseException {
-    Token oldToken;
-    if ((oldToken = token).next != null) token = token.next;
-    else token = token.next = token_source.getNextToken();
-    jj_ntk = -1;
-    if (token.kind == kind) {
-      jj_gen++;
-      if (++jj_gc > 100) {
-        jj_gc = 0;
-        for (int i = 0; i < jj_2_rtns.length; i++) {
-          JJCalls c = jj_2_rtns[i];
-          while (c != null) {
-            if (c.gen < jj_gen) c.first = null;
-            c = c.next;
-          }
-        }
-      }
-      return token;
-    }
-    token = oldToken;
-    jj_kind = kind;
-    throw generateParseException();
-  }
-
-  static private final class LookaheadSuccess extends java.lang.Error { }
-  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
-  private boolean jj_scan_token(int kind) {
-    if (jj_scanpos == jj_lastpos) {
-      jj_la--;
-      if (jj_scanpos.next == null) {
-        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
-      } else {
-        jj_lastpos = jj_scanpos = jj_scanpos.next;
-      }
-    } else {
-      jj_scanpos = jj_scanpos.next;
-    }
-    if (jj_rescan) {
-      int i = 0; Token tok = token;
-      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
-      if (tok != null) jj_add_error_token(kind, i);
-    }
-    if (jj_scanpos.kind != kind) return true;
-    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
-    return false;
-  }
-
-
-/** Get the next Token. */
-  final public Token getNextToken() {
-    if (token.next != null) token = token.next;
-    else token = token.next = token_source.getNextToken();
-    jj_ntk = -1;
-    jj_gen++;
-    return token;
-  }
-
-/** Get the specific Token. */
-  final public Token getToken(int index) {
-    Token t = token;
-    for (int i = 0; i < index; i++) {
-      if (t.next != null) t = t.next;
-      else t = t.next = token_source.getNextToken();
-    }
-    return t;
-  }
-
-  private int jj_ntk() {
-    if ((jj_nt=token.next) == null)
-      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
-    else
-      return (jj_ntk = jj_nt.kind);
-  }
-
-  private java.util.List jj_expentries = new java.util.ArrayList();
-  private int[] jj_expentry;
-  private int jj_kind = -1;
-  private int[] jj_lasttokens = new int[100];
-  private int jj_endpos;
-
-  private void jj_add_error_token(int kind, int pos) {
-    if (pos >= 100) return;
-    if (pos == jj_endpos + 1) {
-      jj_lasttokens[jj_endpos++] = kind;
-    } else if (jj_endpos != 0) {
-      jj_expentry = new int[jj_endpos];
-      for (int i = 0; i < jj_endpos; i++) {
-        jj_expentry[i] = jj_lasttokens[i];
-      }
-      jj_entries_loop: for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) {
-        int[] oldentry = (int[])(it.next());
-        if (oldentry.length == jj_expentry.length) {
-          for (int i = 0; i < jj_expentry.length; i++) {
-            if (oldentry[i] != jj_expentry[i]) {
-              continue jj_entries_loop;
-            }
-          }
-          jj_expentries.add(jj_expentry);
-          break jj_entries_loop;
-        }
-      }
-      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
-    }
-  }
-
-  /** Generate ParseException. */
-  public ParseException generateParseException() {
-    jj_expentries.clear();
-    boolean[] la1tokens = new boolean[34];
-    if (jj_kind >= 0) {
-      la1tokens[jj_kind] = true;
-      jj_kind = -1;
-    }
-    for (int i = 0; i < 23; 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] = (int[])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: src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/QueryParserTokenManager.java	(working copy)
@@ -1,1260 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. QueryParserTokenManager.java */
-package org.apache.lucene.queryParser;
-import java.io.IOException;
-import java.io.StringReader;
-import java.text.Collator;
-import java.text.DateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Vector;
-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.document.DateField;
-import org.apache.lucene.document.DateTools;
-import org.apache.lucene.index.Term;
-import org.apache.lucene.search.BooleanClause;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.ConstantScoreRangeQuery;
-import org.apache.lucene.search.FuzzyQuery;
-import org.apache.lucene.search.MatchAllDocsQuery;
-import org.apache.lucene.search.MultiPhraseQuery;
-import org.apache.lucene.search.PhraseQuery;
-import org.apache.lucene.search.PrefixQuery;
-import org.apache.lucene.search.Query;
-import org.apache.lucene.search.RangeQuery;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.WildcardQuery;
-import org.apache.lucene.util.Parameter;
-
-/** 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;
-   }
-}
-private final int jjStartNfa_3(int pos, long active0)
-{
-   return jjMoveNfa_3(jjStopStringLiteralDfa_3(pos, active0), pos + 1);
-}
-private int jjStopAtPos(int pos, int kind)
-{
-   jjmatchedKind = kind;
-   jjmatchedPos = pos;
-   return pos + 1;
-}
-private int jjMoveStringLiteralDfa0_3()
-{
-   switch(curChar)
-   {
-      case 40:
-         return jjStopAtPos(0, 13);
-      case 41:
-         return jjStopAtPos(0, 14);
-      case 42:
-         return jjStartNfaWithStates_3(0, 16, 36);
-      case 43:
-         return jjStopAtPos(0, 11);
-      case 45:
-         return jjStopAtPos(0, 12);
-      case 58:
-         return jjStopAtPos(0, 15);
-      case 91:
-         return jjStopAtPos(0, 23);
-      case 94:
-         return jjStopAtPos(0, 17);
-      case 123:
-         return jjStopAtPos(0, 24);
-      default :
-         return jjMoveNfa_3(0, 0);
-   }
-}
-private int jjStartNfaWithStates_3(int pos, int kind, int state)
-{
-   jjmatchedKind = kind;
-   jjmatchedPos = pos;
-   try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) { return pos + 1; }
-   return jjMoveNfa_3(state, pos + 1);
-}
-static final long[] jjbitVec0 = {
-   0x1L, 0x0L, 0x0L, 0x0L
-};
-static final long[] jjbitVec1 = {
-   0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
-};
-static final long[] jjbitVec3 = {
-   0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
-};
-static final long[] jjbitVec4 = {
-   0xfffefffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
-};
-private int jjMoveNfa_3(int startState, int curPos)
-{
-   int startsAt = 0;
-   jjnewStateCnt = 36;
-   int i = 1;
-   jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
-   for (;;)
-   {
-      if (++jjround == 0x7fffffff)
-         ReInitRounds();
-      if (curChar < 64)
-      {
-         long l = 1L << curChar;
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 36:
-               case 25:
-                  if ((0xfbfffcf8ffffd9ffL & l) == 0L)
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 0:
-                  if ((0xfbffd4f8ffffd9ffL & l) != 0L)
-                  {
-                     if (kind > 22)
-                        kind = 22;
-                     jjCheckNAddTwoStates(25, 26);
-                  }
-                  else if ((0x100002600L & l) != 0L)
-                  {
-                     if (kind > 7)
-                        kind = 7;
-                  }
-                  else if (curChar == 34)
-                     jjCheckNAddStates(0, 2);
-                  else if (curChar == 33)
-                  {
-                     if (kind > 10)
-                        kind = 10;
-                  }
-                  if ((0x7bffd0f8ffffd9ffL & l) != 0L)
-                  {
-                     if (kind > 19)
-                        kind = 19;
-                     jjCheckNAddStates(3, 7);
-                  }
-                  else if (curChar == 42)
-                  {
-                     if (kind > 21)
-                        kind = 21;
-                  }
-                  if (curChar == 38)
-                     jjstateSet[jjnewStateCnt++] = 4;
-                  break;
-               case 4:
-                  if (curChar == 38 && kind > 8)
-                     kind = 8;
-                  break;
-               case 5:
-                  if (curChar == 38)
-                     jjstateSet[jjnewStateCnt++] = 4;
-                  break;
-               case 13:
-                  if (curChar == 33 && kind > 10)
-                     kind = 10;
-                  break;
-               case 14:
-                  if (curChar == 34)
-                     jjCheckNAddStates(0, 2);
-                  break;
-               case 15:
-                  if ((0xfffffffbffffffffL & l) != 0L)
-                     jjCheckNAddStates(0, 2);
-                  break;
-               case 17:
-                  jjCheckNAddStates(0, 2);
-                  break;
-               case 18:
-                  if (curChar == 34 && kind > 18)
-                     kind = 18;
-                  break;
-               case 20:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 20)
-                     kind = 20;
-                  jjAddStates(8, 9);
-                  break;
-               case 21:
-                  if (curChar == 46)
-                     jjCheckNAdd(22);
-                  break;
-               case 22:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 20)
-                     kind = 20;
-                  jjCheckNAdd(22);
-                  break;
-               case 23:
-                  if (curChar == 42 && kind > 21)
-                     kind = 21;
-                  break;
-               case 24:
-                  if ((0xfbffd4f8ffffd9ffL & l) == 0L)
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 27:
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 28:
-                  if ((0x7bffd0f8ffffd9ffL & l) == 0L)
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddStates(3, 7);
-                  break;
-               case 29:
-                  if ((0x7bfff8f8ffffd9ffL & l) == 0L)
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddTwoStates(29, 30);
-                  break;
-               case 31:
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddTwoStates(29, 30);
-                  break;
-               case 32:
-                  if ((0x7bfff8f8ffffd9ffL & l) != 0L)
-                     jjCheckNAddStates(10, 12);
-                  break;
-               case 34:
-                  jjCheckNAddStates(10, 12);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else if (curChar < 128)
-      {
-         long l = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 36:
-                  if ((0x97ffffff87ffffffL & l) != 0L)
-                  {
-                     if (kind > 22)
-                        kind = 22;
-                     jjCheckNAddTwoStates(25, 26);
-                  }
-                  else if (curChar == 92)
-                     jjCheckNAddTwoStates(27, 27);
-                  break;
-               case 0:
-                  if ((0x97ffffff87ffffffL & l) != 0L)
-                  {
-                     if (kind > 19)
-                        kind = 19;
-                     jjCheckNAddStates(3, 7);
-                  }
-                  else if (curChar == 92)
-                     jjCheckNAddStates(13, 15);
-                  else if (curChar == 126)
-                  {
-                     if (kind > 20)
-                        kind = 20;
-                     jjstateSet[jjnewStateCnt++] = 20;
-                  }
-                  if ((0x97ffffff87ffffffL & l) != 0L)
-                  {
-                     if (kind > 22)
-                        kind = 22;
-                     jjCheckNAddTwoStates(25, 26);
-                  }
-                  if (curChar == 78)
-                     jjstateSet[jjnewStateCnt++] = 11;
-                  else if (curChar == 124)
-                     jjstateSet[jjnewStateCnt++] = 8;
-                  else if (curChar == 79)
-                     jjstateSet[jjnewStateCnt++] = 6;
-                  else if (curChar == 65)
-                     jjstateSet[jjnewStateCnt++] = 2;
-                  break;
-               case 1:
-                  if (curChar == 68 && kind > 8)
-                     kind = 8;
-                  break;
-               case 2:
-                  if (curChar == 78)
-                     jjstateSet[jjnewStateCnt++] = 1;
-                  break;
-               case 3:
-                  if (curChar == 65)
-                     jjstateSet[jjnewStateCnt++] = 2;
-                  break;
-               case 6:
-                  if (curChar == 82 && kind > 9)
-                     kind = 9;
-                  break;
-               case 7:
-                  if (curChar == 79)
-                     jjstateSet[jjnewStateCnt++] = 6;
-                  break;
-               case 8:
-                  if (curChar == 124 && kind > 9)
-                     kind = 9;
-                  break;
-               case 9:
-                  if (curChar == 124)
-                     jjstateSet[jjnewStateCnt++] = 8;
-                  break;
-               case 10:
-                  if (curChar == 84 && kind > 10)
-                     kind = 10;
-                  break;
-               case 11:
-                  if (curChar == 79)
-                     jjstateSet[jjnewStateCnt++] = 10;
-                  break;
-               case 12:
-                  if (curChar == 78)
-                     jjstateSet[jjnewStateCnt++] = 11;
-                  break;
-               case 15:
-                  if ((0xffffffffefffffffL & l) != 0L)
-                     jjCheckNAddStates(0, 2);
-                  break;
-               case 16:
-                  if (curChar == 92)
-                     jjstateSet[jjnewStateCnt++] = 17;
-                  break;
-               case 17:
-                  jjCheckNAddStates(0, 2);
-                  break;
-               case 19:
-                  if (curChar != 126)
-                     break;
-                  if (kind > 20)
-                     kind = 20;
-                  jjstateSet[jjnewStateCnt++] = 20;
-                  break;
-               case 24:
-                  if ((0x97ffffff87ffffffL & l) == 0L)
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 25:
-                  if ((0x97ffffff87ffffffL & l) == 0L)
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 26:
-                  if (curChar == 92)
-                     jjCheckNAddTwoStates(27, 27);
-                  break;
-               case 27:
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 28:
-                  if ((0x97ffffff87ffffffL & l) == 0L)
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddStates(3, 7);
-                  break;
-               case 29:
-                  if ((0x97ffffff87ffffffL & l) == 0L)
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddTwoStates(29, 30);
-                  break;
-               case 30:
-                  if (curChar == 92)
-                     jjCheckNAddTwoStates(31, 31);
-                  break;
-               case 31:
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddTwoStates(29, 30);
-                  break;
-               case 32:
-                  if ((0x97ffffff87ffffffL & l) != 0L)
-                     jjCheckNAddStates(10, 12);
-                  break;
-               case 33:
-                  if (curChar == 92)
-                     jjCheckNAddTwoStates(34, 34);
-                  break;
-               case 34:
-                  jjCheckNAddStates(10, 12);
-                  break;
-               case 35:
-                  if (curChar == 92)
-                     jjCheckNAddStates(13, 15);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else
-      {
-         int hiByte = (int)(curChar >> 8);
-         int i1 = hiByte >> 6;
-         long l1 = 1L << (hiByte & 077);
-         int i2 = (curChar & 0xff) >> 6;
-         long l2 = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 36:
-               case 25:
-                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 0:
-                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 7)
-                        kind = 7;
-                  }
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 22)
-                        kind = 22;
-                     jjCheckNAddTwoStates(25, 26);
-                  }
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 19)
-                        kind = 19;
-                     jjCheckNAddStates(3, 7);
-                  }
-                  break;
-               case 15:
-               case 17:
-                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     jjCheckNAddStates(0, 2);
-                  break;
-               case 24:
-                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 27:
-                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 22)
-                     kind = 22;
-                  jjCheckNAddTwoStates(25, 26);
-                  break;
-               case 28:
-                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddStates(3, 7);
-                  break;
-               case 29:
-                  if (!jjCanMove_2(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddTwoStates(29, 30);
-                  break;
-               case 31:
-                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 19)
-                     kind = 19;
-                  jjCheckNAddTwoStates(29, 30);
-                  break;
-               case 32:
-                  if (jjCanMove_2(hiByte, i1, i2, l1, l2))
-                     jjCheckNAddStates(10, 12);
-                  break;
-               case 34:
-                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     jjCheckNAddStates(10, 12);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      if (kind != 0x7fffffff)
-      {
-         jjmatchedKind = kind;
-         jjmatchedPos = curPos;
-         kind = 0x7fffffff;
-      }
-      ++curPos;
-      if ((i = jjnewStateCnt) == (startsAt = 36 - (jjnewStateCnt = startsAt)))
-         return curPos;
-      try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
-   }
-}
-private final int jjStopStringLiteralDfa_1(int pos, long active0)
-{
-   switch (pos)
-   {
-      case 0:
-         if ((active0 & 0x40000000L) != 0L)
-         {
-            jjmatchedKind = 33;
-            return 6;
-         }
-         return -1;
-      default :
-         return -1;
-   }
-}
-private final int jjStartNfa_1(int pos, long active0)
-{
-   return jjMoveNfa_1(jjStopStringLiteralDfa_1(pos, active0), pos + 1);
-}
-private int jjMoveStringLiteralDfa0_1()
-{
-   switch(curChar)
-   {
-      case 84:
-         return jjMoveStringLiteralDfa1_1(0x40000000L);
-      case 125:
-         return jjStopAtPos(0, 31);
-      default :
-         return jjMoveNfa_1(0, 0);
-   }
-}
-private int jjMoveStringLiteralDfa1_1(long active0)
-{
-   try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_1(0, active0);
-      return 1;
-   }
-   switch(curChar)
-   {
-      case 79:
-         if ((active0 & 0x40000000L) != 0L)
-            return jjStartNfaWithStates_1(1, 30, 6);
-         break;
-      default :
-         break;
-   }
-   return jjStartNfa_1(0, active0);
-}
-private int jjStartNfaWithStates_1(int pos, int kind, int state)
-{
-   jjmatchedKind = kind;
-   jjmatchedPos = pos;
-   try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) { return pos + 1; }
-   return jjMoveNfa_1(state, pos + 1);
-}
-private int jjMoveNfa_1(int startState, int curPos)
-{
-   int startsAt = 0;
-   jjnewStateCnt = 7;
-   int i = 1;
-   jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
-   for (;;)
-   {
-      if (++jjround == 0x7fffffff)
-         ReInitRounds();
-      if (curChar < 64)
-      {
-         long l = 1L << curChar;
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-                  if ((0xfffffffeffffffffL & l) != 0L)
-                  {
-                     if (kind > 33)
-                        kind = 33;
-                     jjCheckNAdd(6);
-                  }
-                  if ((0x100002600L & l) != 0L)
-                  {
-                     if (kind > 7)
-                        kind = 7;
-                  }
-                  else if (curChar == 34)
-                     jjCheckNAddTwoStates(2, 4);
-                  break;
-               case 1:
-                  if (curChar == 34)
-                     jjCheckNAddTwoStates(2, 4);
-                  break;
-               case 2:
-                  if ((0xfffffffbffffffffL & l) != 0L)
-                     jjCheckNAddStates(16, 18);
-                  break;
-               case 3:
-                  if (curChar == 34)
-                     jjCheckNAddStates(16, 18);
-                  break;
-               case 5:
-                  if (curChar == 34 && kind > 32)
-                     kind = 32;
-                  break;
-               case 6:
-                  if ((0xfffffffeffffffffL & l) == 0L)
-                     break;
-                  if (kind > 33)
-                     kind = 33;
-                  jjCheckNAdd(6);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else if (curChar < 128)
-      {
-         long l = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-               case 6:
-                  if ((0xdfffffffffffffffL & l) == 0L)
-                     break;
-                  if (kind > 33)
-                     kind = 33;
-                  jjCheckNAdd(6);
-                  break;
-               case 2:
-                  jjAddStates(16, 18);
-                  break;
-               case 4:
-                  if (curChar == 92)
-                     jjstateSet[jjnewStateCnt++] = 3;
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else
-      {
-         int hiByte = (int)(curChar >> 8);
-         int i1 = hiByte >> 6;
-         long l1 = 1L << (hiByte & 077);
-         int i2 = (curChar & 0xff) >> 6;
-         long l2 = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 7)
-                        kind = 7;
-                  }
-                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 33)
-                        kind = 33;
-                     jjCheckNAdd(6);
-                  }
-                  break;
-               case 2:
-                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     jjAddStates(16, 18);
-                  break;
-               case 6:
-                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 33)
-                     kind = 33;
-                  jjCheckNAdd(6);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      if (kind != 0x7fffffff)
-      {
-         jjmatchedKind = kind;
-         jjmatchedPos = curPos;
-         kind = 0x7fffffff;
-      }
-      ++curPos;
-      if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
-         return curPos;
-      try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
-   }
-}
-private int jjMoveStringLiteralDfa0_0()
-{
-   return jjMoveNfa_0(0, 0);
-}
-private int jjMoveNfa_0(int startState, int curPos)
-{
-   int startsAt = 0;
-   jjnewStateCnt = 3;
-   int i = 1;
-   jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
-   for (;;)
-   {
-      if (++jjround == 0x7fffffff)
-         ReInitRounds();
-      if (curChar < 64)
-      {
-         long l = 1L << curChar;
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 25)
-                     kind = 25;
-                  jjAddStates(19, 20);
-                  break;
-               case 1:
-                  if (curChar == 46)
-                     jjCheckNAdd(2);
-                  break;
-               case 2:
-                  if ((0x3ff000000000000L & l) == 0L)
-                     break;
-                  if (kind > 25)
-                     kind = 25;
-                  jjCheckNAdd(2);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else if (curChar < 128)
-      {
-         long l = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else
-      {
-         int hiByte = (int)(curChar >> 8);
-         int i1 = hiByte >> 6;
-         long l1 = 1L << (hiByte & 077);
-         int i2 = (curChar & 0xff) >> 6;
-         long l2 = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      if (kind != 0x7fffffff)
-      {
-         jjmatchedKind = kind;
-         jjmatchedPos = curPos;
-         kind = 0x7fffffff;
-      }
-      ++curPos;
-      if ((i = jjnewStateCnt) == (startsAt = 3 - (jjnewStateCnt = startsAt)))
-         return curPos;
-      try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
-   }
-}
-private final int jjStopStringLiteralDfa_2(int pos, long active0)
-{
-   switch (pos)
-   {
-      case 0:
-         if ((active0 & 0x4000000L) != 0L)
-         {
-            jjmatchedKind = 29;
-            return 6;
-         }
-         return -1;
-      default :
-         return -1;
-   }
-}
-private final int jjStartNfa_2(int pos, long active0)
-{
-   return jjMoveNfa_2(jjStopStringLiteralDfa_2(pos, active0), pos + 1);
-}
-private int jjMoveStringLiteralDfa0_2()
-{
-   switch(curChar)
-   {
-      case 84:
-         return jjMoveStringLiteralDfa1_2(0x4000000L);
-      case 93:
-         return jjStopAtPos(0, 27);
-      default :
-         return jjMoveNfa_2(0, 0);
-   }
-}
-private int jjMoveStringLiteralDfa1_2(long active0)
-{
-   try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) {
-      jjStopStringLiteralDfa_2(0, active0);
-      return 1;
-   }
-   switch(curChar)
-   {
-      case 79:
-         if ((active0 & 0x4000000L) != 0L)
-            return jjStartNfaWithStates_2(1, 26, 6);
-         break;
-      default :
-         break;
-   }
-   return jjStartNfa_2(0, active0);
-}
-private int jjStartNfaWithStates_2(int pos, int kind, int state)
-{
-   jjmatchedKind = kind;
-   jjmatchedPos = pos;
-   try { curChar = input_stream.readChar(); }
-   catch(java.io.IOException e) { return pos + 1; }
-   return jjMoveNfa_2(state, pos + 1);
-}
-private int jjMoveNfa_2(int startState, int curPos)
-{
-   int startsAt = 0;
-   jjnewStateCnt = 7;
-   int i = 1;
-   jjstateSet[0] = startState;
-   int kind = 0x7fffffff;
-   for (;;)
-   {
-      if (++jjround == 0x7fffffff)
-         ReInitRounds();
-      if (curChar < 64)
-      {
-         long l = 1L << curChar;
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-                  if ((0xfffffffeffffffffL & l) != 0L)
-                  {
-                     if (kind > 29)
-                        kind = 29;
-                     jjCheckNAdd(6);
-                  }
-                  if ((0x100002600L & l) != 0L)
-                  {
-                     if (kind > 7)
-                        kind = 7;
-                  }
-                  else if (curChar == 34)
-                     jjCheckNAddTwoStates(2, 4);
-                  break;
-               case 1:
-                  if (curChar == 34)
-                     jjCheckNAddTwoStates(2, 4);
-                  break;
-               case 2:
-                  if ((0xfffffffbffffffffL & l) != 0L)
-                     jjCheckNAddStates(16, 18);
-                  break;
-               case 3:
-                  if (curChar == 34)
-                     jjCheckNAddStates(16, 18);
-                  break;
-               case 5:
-                  if (curChar == 34 && kind > 28)
-                     kind = 28;
-                  break;
-               case 6:
-                  if ((0xfffffffeffffffffL & l) == 0L)
-                     break;
-                  if (kind > 29)
-                     kind = 29;
-                  jjCheckNAdd(6);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else if (curChar < 128)
-      {
-         long l = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-               case 6:
-                  if ((0xffffffffdfffffffL & l) == 0L)
-                     break;
-                  if (kind > 29)
-                     kind = 29;
-                  jjCheckNAdd(6);
-                  break;
-               case 2:
-                  jjAddStates(16, 18);
-                  break;
-               case 4:
-                  if (curChar == 92)
-                     jjstateSet[jjnewStateCnt++] = 3;
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      else
-      {
-         int hiByte = (int)(curChar >> 8);
-         int i1 = hiByte >> 6;
-         long l1 = 1L << (hiByte & 077);
-         int i2 = (curChar & 0xff) >> 6;
-         long l2 = 1L << (curChar & 077);
-         do
-         {
-            switch(jjstateSet[--i])
-            {
-               case 0:
-                  if (jjCanMove_0(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 7)
-                        kind = 7;
-                  }
-                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                  {
-                     if (kind > 29)
-                        kind = 29;
-                     jjCheckNAdd(6);
-                  }
-                  break;
-               case 2:
-                  if (jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     jjAddStates(16, 18);
-                  break;
-               case 6:
-                  if (!jjCanMove_1(hiByte, i1, i2, l1, l2))
-                     break;
-                  if (kind > 29)
-                     kind = 29;
-                  jjCheckNAdd(6);
-                  break;
-               default : break;
-            }
-         } while(i != startsAt);
-      }
-      if (kind != 0x7fffffff)
-      {
-         jjmatchedKind = kind;
-         jjmatchedPos = curPos;
-         kind = 0x7fffffff;
-      }
-      ++curPos;
-      if ((i = jjnewStateCnt) == (startsAt = 7 - (jjnewStateCnt = startsAt)))
-         return curPos;
-      try { curChar = input_stream.readChar(); }
-      catch(java.io.IOException e) { return curPos; }
-   }
-}
-static final int[] jjnextStates = {
-   15, 16, 18, 29, 32, 23, 33, 30, 20, 21, 32, 23, 33, 31, 34, 27, 
-   2, 4, 5, 0, 1, 
-};
-private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
-{
-   switch(hiByte)
-   {
-      case 48:
-         return ((jjbitVec0[i2] & l2) != 0L);
-      default :
-         return false;
-   }
-}
-private static final boolean jjCanMove_1(int hiByte, int i1, int i2, long l1, long l2)
-{
-   switch(hiByte)
-   {
-      case 0:
-         return ((jjbitVec3[i2] & l2) != 0L);
-      default :
-         if ((jjbitVec1[i1] & l1) != 0L)
-            return true;
-         return false;
-   }
-}
-private static final boolean jjCanMove_2(int hiByte, int i1, int i2, long l1, long l2)
-{
-   switch(hiByte)
-   {
-      case 0:
-         return ((jjbitVec3[i2] & l2) != 0L);
-      case 48:
-         return ((jjbitVec1[i2] & l2) != 0L);
-      default :
-         if ((jjbitVec4[i1] & l1) != 0L)
-            return true;
-         return false;
-   }
-}
-
-/** Token literal values. */
-public static final String[] jjstrLiteralImages = {
-"", null, null, null, null, null, null, null, null, null, null, "\53", "\55", 
-"\50", "\51", "\72", "\52", "\136", null, null, null, null, null, "\133", "\173", 
-null, "\124\117", "\135", null, null, "\124\117", "\175", null, null, };
-
-/** Lexer state names. */
-public static final String[] lexStateNames = {
-   "Boost",
-   "RangeEx",
-   "RangeIn",
-   "DEFAULT",
-};
-
-/** Lex State array. */
-public static final int[] jjnewLexState = {
-   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, 2, 1, 
-   3, -1, 3, -1, -1, -1, 3, -1, -1, 
-};
-static final long[] jjtoToken = {
-   0x3ffffff01L, 
-};
-static final long[] jjtoSkip = {
-   0x80L, 
-};
-protected CharStream input_stream;
-private final int[] jjrounds = new int[36];
-private final int[] jjstateSet = new int[72];
-protected char curChar;
-/** Constructor. */
-public QueryParserTokenManager(CharStream stream){
-   input_stream = stream;
-}
-
-/** Constructor. */
-public QueryParserTokenManager(CharStream stream, int lexState){
-   this(stream);
-   SwitchTo(lexState);
-}
-
-/** Reinitialise parser. */
-public void ReInit(CharStream 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(CharStream 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: src/java/org/apache/lucene/queryParser/util/QueryNodeOperation.java
===================================================================
--- src/java/org/apache/lucene/queryParser/util/QueryNodeOperation.java	(revision 0)
+++ 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;
+
+    }
+
+}
Index: src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java
===================================================================
--- src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/util/UnescapedCharSequence.java	(revision 0)
@@ -0,0 +1,137 @@
+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();
+    }
+}
Index: src/java/org/apache/lucene/queryParser/util/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/util/package.html	(revision 0)
+++ 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>
Index: src/java/org/apache/lucene/queryParser/config/FieldConfig.java
===================================================================
--- src/java/org/apache/lucene/queryParser/config/FieldConfig.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/config/FieldConfig.java	(revision 0)
@@ -0,0 +1,58 @@
+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 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;
+    }
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java
===================================================================
--- src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/config/QueryConfigHandler.java	(revision 0)
@@ -0,0 +1,50 @@
+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.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
+ */
+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);
+    
+}\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/config/package.html
===================================================================
--- src/java/org/apache/lucene/queryParser/config/package.html	(revision 0)
+++ src/java/org/apache/lucene/queryParser/config/package.html	(revision 0)
@@ -0,0 +1,46 @@
+<!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.
+
+See <tt>org.apache.lucene.queryParser.lucene2.config.LuceneQueryConfigHandler</tt> for a reference
+implementation
+
+FieldConfig and Queryconfig should use <tt>org.apache.lucene.util.Attribute</tt> to store all attributes
+required by the config implementation. See <tt>org.apache.lucene.queryParser.lucene2.config.*Attribute</tt>
+for reference implementation.
+
+The QueryConfigHandler, FieldConfig, and Attributes are used in the Processors to access config
+information in a flexible and independent way.
+See <tt>org.apache.lucene.queryParser.lucene2.processors.ParametricRangeQueryNodeProcessor</tt> for a 
+reference implementation.
+
+</p>
+<p>
+
+</p>
+</body>
+</html>\ No newline at end of file
Index: src/java/org/apache/lucene/queryParser/CharStream.java
===================================================================
--- src/java/org/apache/lucene/queryParser/CharStream.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/CharStream.java	(working copy)
@@ -1,112 +0,0 @@
-/* Generated By:JavaCC: Do not edit this line. CharStream.java Version 4.1 */
-/* JavaCCOptions:STATIC=false */
-package org.apache.lucene.queryParser;
-
-/**
- * This interface describes a character stream that maintains line and
- * column number positions of the characters.  It also has the capability
- * to backup the stream to some extent.  An implementation of this
- * interface is used in the TokenManager implementation generated by
- * JavaCCParser.
- *
- * All the methods except backup can be implemented in any fashion. backup
- * needs to be implemented correctly for the correct operation of the lexer.
- * Rest of the methods are all used to get information like line number,
- * 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.
- */
-
-public interface CharStream {
-
-  /**
-   * Returns the next character from the selected input.  The method
-   * of selecting the input is the responsibility of the class
-   * implementing this interface.  Can throw any java.io.IOException.
-   */
-  char readChar() throws java.io.IOException;
-
-  /**
-   * Returns the column position of the character last read.
-   * @deprecated
-   * @see #getEndColumn
-   */
-  int getColumn();
-
-  /**
-   * Returns the line number of the character last read.
-   * @deprecated
-   * @see #getEndLine
-   */
-  int getLine();
-
-  /**
-   * Returns the column number of the last character for current token (being
-   * matched after the last call to BeginTOken).
-   */
-  int getEndColumn();
-
-  /**
-   * Returns the line number of the last character for current token (being
-   * matched after the last call to BeginTOken).
-   */
-  int getEndLine();
-
-  /**
-   * Returns the column number of the first character for current token (being
-   * matched after the last call to BeginTOken).
-   */
-  int getBeginColumn();
-
-  /**
-   * Returns the line number of the first character for current token (being
-   * matched after the last call to BeginTOken).
-   */
-  int getBeginLine();
-
-  /**
-   * Backs up the input stream by amount steps. Lexer calls this method if it
-   * had already read some characters, but could not use them to match a
-   * (longer) token. So, they will be used again as the prefix of the next
-   * token and it is the implemetation's responsibility to do this right.
-   */
-  void backup(int amount);
-
-  /**
-   * Returns the next character that marks the beginning of the next token.
-   * All characters must remain in the buffer between two successive calls
-   * to this method to implement backup correctly.
-   */
-  char BeginToken() throws java.io.IOException;
-
-  /**
-   * Returns a string made up of characters from the marked token beginning
-   * to the current buffer position. Implementations have the choice of returning
-   * anything that they want to. For example, for efficiency, one might decide
-   * to just return null, which is a valid implementation.
-   */
-  String GetImage();
-
-  /**
-   * Returns an array of characters that make up the suffix of length 'len' for
-   * the currently matched token. This is used to build up the matched string
-   * for use in actions in the case of MORE. A simple and inefficient
-   * implementation of this is as follows :
-   *
-   *   {
-   *      String t = GetImage();
-   *      return t.substring(t.length() - len, t.length()).toCharArray();
-   *   }
-   */
-  char[] GetSuffix(int len);
-
-  /**
-   * The lexer calls this function to indicate that it is done with the stream
-   * and hence implementations can free any resources held by this class.
-   * Again, the body of this function can be just empty and it will not
-   * affect the lexer's operation.
-   */
-  void Done();
-
-}
-/* JavaCC - OriginalChecksum=a83909a2403f969f94d18375f9f143e4 (do not edit this line) */
Index: src/java/org/apache/lucene/queryParser/FastCharStream.java
===================================================================
--- src/java/org/apache/lucene/queryParser/FastCharStream.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/FastCharStream.java	(working copy)
@@ -1,122 +0,0 @@
-// FastCharStream.java
-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.io.*;
-
-/** 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. */
-public final class FastCharStream implements CharStream {
-  char[] buffer = null;
-
-  int bufferLength = 0;				  // end of valid chars
-  int bufferPosition = 0;			  // next char to read
-
-  int tokenStart = 0;				  // offset in buffer
-  int bufferStart = 0;				  // position in file of buffer
-
-  Reader input;					  // source of chars
-
-  /** Constructs from a Reader. */
-  public FastCharStream(Reader r) {
-    input = r;
-  }
-
-  public final char readChar() throws IOException {
-    if (bufferPosition >= bufferLength)
-      refill();
-    return buffer[bufferPosition++];
-  }
-
-  private final void refill() throws IOException {
-    int newPosition = bufferLength - tokenStart;
-
-    if (tokenStart == 0) {			  // token won't fit in buffer
-      if (buffer == null) {			  // first time: alloc buffer
-	buffer = new char[2048];
-      } else if (bufferLength == buffer.length) { // grow buffer
-	char[] newBuffer = new char[buffer.length*2];
-	System.arraycopy(buffer, 0, newBuffer, 0, bufferLength);
-	buffer = newBuffer;
-      }
-    } else {					  // shift token to front
-      System.arraycopy(buffer, tokenStart, buffer, 0, newPosition);
-    }
-
-    bufferLength = newPosition;			  // update state
-    bufferPosition = newPosition;
-    bufferStart += tokenStart;
-    tokenStart = 0;
-
-    int charsRead =				  // fill space in buffer
-      input.read(buffer, newPosition, buffer.length-newPosition);
-    if (charsRead == -1)
-      throw new IOException("read past eof");
-    else
-      bufferLength += charsRead;
-  }
-
-  public final char BeginToken() throws IOException {
-    tokenStart = bufferPosition;
-    return readChar();
-  }
-
-  public final void backup(int amount) {
-    bufferPosition -= amount;
-  }
-
-  public final String GetImage() {
-    return new String(buffer, tokenStart, bufferPosition - tokenStart);
-  }
-
-  public final char[] GetSuffix(int len) {
-    char[] value = new char[len];
-    System.arraycopy(buffer, bufferPosition - len, value, 0, len);
-    return value;
-  }
-
-  public final void Done() {
-    try {
-      input.close();
-    } catch (IOException e) {
-      System.err.println("Caught: " + e + "; ignoring.");
-    }
-  }
-
-  public final int getColumn() {
-    return bufferStart + bufferPosition;
-  }
-  public final int getLine() {
-    return 1;
-  }
-  public final int getEndColumn() {
-    return bufferStart + bufferPosition;
-  }
-  public final int getEndLine() {
-    return 1;
-  }
-  public final int getBeginColumn() {
-    return bufferStart + tokenStart;
-  }
-  public final int getBeginLine() {
-    return 1;
-  }
-}
Index: src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java
===================================================================
--- src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java	(revision 757685)
+++ src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java	(working copy)
@@ -1,321 +0,0 @@
-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.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;
-import org.apache.lucene.search.BooleanQuery;
-import org.apache.lucene.search.MultiPhraseQuery;
-import org.apache.lucene.search.PhraseQuery;
-import org.apache.lucene.search.Query;
-
-/**
- * A QueryParser which constructs queries to search multiple fields.
- *
- *
- * @version $Revision$
- */
-public class MultiFieldQueryParser extends QueryParser
-{
-  protected String[] fields;
-  protected Map      boosts;
-
-  /**
-   * 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 MultiFieldQueryParser(String[] fields, Analyzer analyzer, Map boosts) {
-    this(fields,analyzer);
-    this.boosts = 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 MultiFieldQueryParser(String[] fields, Analyzer analyzer) {
-    super(null, analyzer);
-    this.fields = fields;
-  }
-  
-  protected Query getFieldQuery(String field, String queryText, int slop) throws ParseException {
-    if (field == null) {
-      List clauses = new ArrayList();
-      for (int i = 0; i < fields.length; i++) {
-        Query q = super.getFieldQuery(fields[i], queryText);
-        if (q != null) {
-          //If the user passes a map of boosts
-          if (boosts != null) {
-            //Get the boost from the map and apply them
-            Float boost = (Float)boosts.get(fields[i]);
-            if (boost != null) {
-              q.setBoost(boost.floatValue());
-            }
-          }
-          applySlop(q,slop);
-          clauses.add(new BooleanClause(q, BooleanClause.Occur.SHOULD));
-        }
-      }
-      if (clauses.size() == 0)  // happens for stopwords
-        return null;
-      return getBooleanQuery(clauses, true);
-    }
-    Query q = super.getFieldQuery(field, queryText);
-    applySlop(q,slop);
-    return q;
-  }
-
-  private void applySlop(Query q, int slop) {
-    if (q instanceof PhraseQuery) {
-      ((PhraseQuery) q).setSlop(slop);
-    } else if (q instanceof MultiPhraseQuery) {
-      ((MultiPhraseQuery) q).setSlop(slop);
-    }
-  }
-  
-
-  protected Query getFieldQuery(String field, String queryText) throws ParseException {
-    return getFieldQuery(field, queryText, 0);
-  }
-
-
-  protected Query getFuzzyQuery(String field, String termStr, float minSimilarity) throws ParseException
-  {
-    if (field == null) {
-      List clauses = new ArrayList();
-      for (int i = 0; i < fields.length; i++) {
-        clauses.add(new BooleanClause(getFuzzyQuery(fields[i], termStr, minSimilarity),
-            BooleanClause.Occur.SHOULD));
-      }
-      return getBooleanQuery(clauses, true);
-    }
-    return super.getFuzzyQuery(field, termStr, minSimilarity);
-  }
-
-  protected Query getPrefixQuery(String field, String termStr) throws ParseException
-  {
-    if (field == null) {
-      List clauses = new ArrayList();
-      for (int i = 0; i < fields.length; i++) {
-        clauses.add(new BooleanClause(getPrefixQuery(fields[i], termStr),
-            BooleanClause.Occur.SHOULD));
-      }
-      return getBooleanQuery(clauses, true);
-    }
-    return super.getPrefixQuery(field, termStr);
-  }
-
-  protected Query getWildcardQuery(String field, String termStr) throws ParseException {
-    if (field == null) {
-      List clauses = new ArrayList();
-      for (int i = 0; i < fields.length; i++) {
-        clauses.add(new BooleanClause(getWildcardQuery(fields[i], termStr),
-            BooleanClause.Occur.SHOULD));
-      }
-      return getBooleanQuery(clauses, true);
-    }
-    return super.getWildcardQuery(field, termStr);
-  }
-
- 
-  protected Query getRangeQuery(String field, String part1, String part2, boolean inclusive) throws ParseException {
-    if (field == null) {
-      List clauses = new ArrayList();
-      for (int i = 0; i < fields.length; i++) {
-        clauses.add(new BooleanClause(getRangeQuery(fields[i], part1, part2, inclusive),
-            BooleanClause.Occur.SHOULD));
-      }
-      return getBooleanQuery(clauses, true);
-    }
-    return super.getRangeQuery(field, part1, part2, inclusive);
-  }
-
-  /**
-   * Parses a query which searches on the fields specified.
-   * <p>
-   * If x fields are specified, this effectively constructs:
-   * <pre>
-   * <code>
-   * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
-   * </code>
-   * </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++)
-    {
-      QueryParser qp = new QueryParser(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:
-   * <code>
-   * String[] fields = {"filename", "contents", "description"};
-   * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
-   *                BooleanClause.Occur.MUST,
-   *                BooleanClause.Occur.MUST_NOT};
-   * MultiFieldQueryParser.parse("query", fields, flags, analyzer);
-   * </code>
-   * </pre>
-   *<p>
-   * The code above would construct a query:
-   * <pre>
-   * <code>
-   * (filename:query) +(contents:query) -(description:query)
-   * </code>
-   * </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++) {
-      QueryParser qp = new QueryParser(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:
-   * <code>
-   * String[] query = {"query1", "query2", "query3"};
-   * String[] fields = {"filename", "contents", "description"};
-   * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
-   *                BooleanClause.Occur.MUST,
-   *                BooleanClause.Occur.MUST_NOT};
-   * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
-   * </code>
-   * </pre>
-   *<p>
-   * The code above would construct a query:
-   * <pre>
-   * <code>
-   * (filename:query1) +(contents:query2) -(description:query3)
-   * </code>
-   * </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++)
-    {
-      QueryParser qp = new QueryParser(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;
-  }
-
-}
Index: src/java/org/apache/lucene/queryParser/QueryNodeError.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryNodeError.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/QueryNodeError.java	(revision 0)
@@ -0,0 +1,69 @@
+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;
+    }
+    
+}
Index: src/java/org/apache/lucene/queryParser/QueryNodeParseException.java
===================================================================
--- src/java/org/apache/lucene/queryParser/QueryNodeParseException.java	(revision 0)
+++ src/java/org/apache/lucene/queryParser/QueryNodeParseException.java	(revision 0)
@@ -0,0 +1,106 @@
+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;
+
+/**
+ * TODO: document this class
+ */
+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;
+    }
+}
Index: src/java/org/apache/lucene/messages/Message.java
===================================================================
--- src/java/org/apache/lucene/messages/Message.java	(revision 0)
+++ 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);
+    
+}
Index: src/java/org/apache/lucene/messages/MessageImpl.java
===================================================================
--- src/java/org/apache/lucene/messages/MessageImpl.java	(revision 0)
+++ src/java/org/apache/lucene/messages/MessageImpl.java	(revision 0)
@@ -0,0 +1,71 @@
+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;
+    }
+    
+}
Index: src/java/org/apache/lucene/messages/NLS.java
===================================================================
--- src/java/org/apache/lucene/messages/NLS.java	(revision 0)
+++ src/java/org/apache/lucene/messages/NLS.java	(revision 0)
@@ -0,0 +1,199 @@
+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;
+                }
+            });
+        }
+    }
+}
Index: src/java/org/apache/lucene/messages/NLSException.java
===================================================================
--- src/java/org/apache/lucene/messages/NLSException.java	(revision 0)
+++ src/java/org/apache/lucene/messages/NLSException.java	(revision 0)
@@ -0,0 +1,30 @@
+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();
+}
Index: src/test/org/apache/lucene/messages/MessagesTest.java
===================================================================
--- src/test/org/apache/lucene/messages/MessagesTest.java	(revision 0)
+++ src/test/org/apache/lucene/messages/MessagesTest.java	(revision 0)
@@ -0,0 +1,41 @@
+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 MessagesTest extends NLS {
+    
+    private static final String BUNDLE_NAME= MessagesTest.class.getName();
+
+    private MessagesTest() {
+    	// should never be instantiated
+    }
+    
+    static {
+        // register all string ids with NLS class and initialize static string values
+        NLS.initializeMessages(BUNDLE_NAME, MessagesTest.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;
+}
Index: src/test/org/apache/lucene/messages/MessagesTest.properties
===================================================================
--- src/test/org/apache/lucene/messages/MessagesTest.properties	(revision 0)
+++ src/test/org/apache/lucene/messages/MessagesTest.properties	(revision 0)
@@ -0,0 +1,3 @@
+Q0001E_INVALID_SYNTAX = Syntax Error: {0}
+
+Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION = Truncated unicode escape sequence.
Index: src/test/org/apache/lucene/messages/MessagesTest_ja.properties
===================================================================
--- src/test/org/apache/lucene/messages/MessagesTest_ja.properties	(revision 0)
+++ src/test/org/apache/lucene/messages/MessagesTest_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
Index: src/test/org/apache/lucene/messages/TestNLS.java
===================================================================
--- src/test/org/apache/lucene/messages/TestNLS.java	(revision 0)
+++ src/test/org/apache/lucene/messages/TestNLS.java	(revision 0)
@@ -0,0 +1,67 @@
+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(MessagesTest.Q0001E_INVALID_SYNTAX, "XXX");        
+        assertEquals("Syntax Error: XXX", invalidSyntax.getLocalizedMessage());
+    }
+    
+    public void testMessageLoading_ja() {        
+        Message invalidSyntax = new MessageImpl(MessagesTest.Q0001E_INVALID_SYNTAX, "XXX");        
+        assertEquals("構文エラー: XXX", invalidSyntax.getLocalizedMessage(Locale.JAPANESE));
+    }
+    
+    public void testNLSLoading() {        
+        String message = NLS.getLocalizedMessage(MessagesTest.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION);
+        assertEquals("Truncated unicode escape sequence.", message);
+        
+        message = NLS.getLocalizedMessage(MessagesTest.Q0001E_INVALID_SYNTAX, "XXX");
+        assertEquals("Syntax Error: XXX", message);
+    }
+    
+    public void testNLSLoading_ja() {        
+        String message = NLS.getLocalizedMessage(MessagesTest.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION, Locale.JAPANESE);
+        assertEquals("切り捨てられたユニコード・エスケープ・シーケンス。", message);
+        
+        message = NLS.getLocalizedMessage(MessagesTest.Q0001E_INVALID_SYNTAX, Locale.JAPANESE, "XXX");
+        assertEquals("構文エラー: XXX", message);
+    }
+    
+    public void testNLSLoading_xx_XX() {        
+        Locale locale = new Locale("xx","XX","");
+        String message = NLS.getLocalizedMessage(MessagesTest.Q0004E_INVALID_SYNTAX_ESCAPE_UNICODE_TRUNCATION, locale);
+        assertEquals("Truncated unicode escape sequence.", message);
+        
+        message = NLS.getLocalizedMessage(MessagesTest.Q0001E_INVALID_SYNTAX, locale, "XXX");
+        assertEquals("Syntax Error: XXX", message);
+    }
+    
+    public void testMissingMessage() {        
+        Locale locale = Locale.ENGLISH;
+        String message = NLS.getLocalizedMessage(MessagesTest.Q0005E_MESSAGE_NOT_IN_BUNDLE, locale);
+        
+        assertEquals("Message with key:Q0005E_MESSAGE_NOT_IN_BUNDLE and locale: " + locale.toString() + " not found.", message);
+    }
+}
Index: src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/SpanOrQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,54 @@
+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.lucene2.builders.LuceneQueryBuilder;
+import org.apache.lucene.queryParser.nodes.BooleanQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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);
+		
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/SpanTermQueryNodeBuilder.java	(revision 0)
@@ -0,0 +1,39 @@
+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.lucene2.builders.LuceneQueryBuilder;
+import org.apache.lucene.queryParser.nodes.FieldQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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()));
+		
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/SpansQueryConfigHandler.java	(revision 0)
+++ 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;
+		
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/SpansQueryTreeBuilder.java	(revision 0)
@@ -0,0 +1,48 @@
+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.lucene2.builders.LuceneQueryBuilder;
+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.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);
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/SpansValidatorQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,70 @@
+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;
+		
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParser.java	(revision 0)
@@ -0,0 +1,213 @@
+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 org.apache.lucene.queryParser.QueryNodeException;
+import org.apache.lucene.queryParser.lucene2.parser.QueryParser;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * 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 QueryParser}).<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 QueryParser}.<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 "unique field" from the configuration and convert every field defined
+ *   in every pair to this "unique field". For that, a {@link SpansQueryConfigHandler} is
+ *   used, which has the {@link UniqueFieldAttribute} defined in it.</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 QueryParser
+ * @see UniqueFieldQueryNodeProcessor
+ * @see UniqueFieldAttribute
+ * 
+ */
+public class TestSpanQueryParser extends LuceneTestCase {
+	
+	private QueryNodeProcessorPipeline spanProcessorPipeline;
+	
+	private SpansQueryConfigHandler spanQueryConfigHandler;
+	
+	private SpansQueryTreeBuilder spansQueryTreeBuilder;
+	
+	private QueryParser queryParser = new QueryParser();
+	
+	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
+		}
+		
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/TestSpanQueryParserSimpleSample.java	(revision 0)
@@ -0,0 +1,130 @@
+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 org.apache.lucene.queryParser.config.QueryConfigHandler;
+import org.apache.lucene.queryParser.lucene2.parser.QueryParser;
+import org.apache.lucene.queryParser.nodes.OrQueryNode;
+import org.apache.lucene.queryParser.nodes.QueryNode;
+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;
+import org.apache.lucene.util.LuceneTestCase;
+
+/**
+ * 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 QueryParser}).<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 QueryParser}.<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 "unique field" from the configuration and convert every field defined
+ *   in every pair to this "unique field". For that, a {@link SpansQueryConfigHandler} is
+ *   used, which has the {@link UniqueFieldAttribute} defined in it.</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 QueryParser
+ * @see UniqueFieldQueryNodeProcessor
+ * @see UniqueFieldAttribute
+ * 
+ */
+public class TestSpanQueryParserSimpleSample extends LuceneTestCase {
+		
+	public TestSpanQueryParserSimpleSample() {
+		// empty constructor
+	}
+	
+	public void testBasicDemo() throws Exception {		
+		Parser queryParser = new QueryParser();
+		
+		// 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 QueryTree before being processed
+		System.out.println(queryTree);
+		
+		// Process the QueryTree using our new Processors
+		queryTree = spanProcessorPipeline.process(queryTree);
+
+		// print to show out the QueryTree 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");
+		
+	}
+	
+}
Index: src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/UniqueFieldAttribute.java	(revision 0)
@@ -0,0 +1,88 @@
+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 + "'/>";
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java
===================================================================
--- src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/spans/UniqueFieldQueryNodeProcessor.java	(revision 0)
@@ -0,0 +1,81 @@
+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;
+		
+	}
+
+}
Index: src/test/org/apache/lucene/queryParser/TestQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/TestQueryParser.java	(revision 757685)
+++ src/test/org/apache/lucene/queryParser/TestQueryParser.java	(working copy)
@@ -1,996 +0,0 @@
-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.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.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.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.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.RangeQuery;
-import org.apache.lucene.search.ScoreDoc;
-import org.apache.lucene.search.TermQuery;
-import org.apache.lucene.search.WildcardQuery;
-import org.apache.lucene.store.RAMDirectory;
-import org.apache.lucene.util.LuceneTestCase;
-
-/**
- * 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 boolean incrementToken() throws IOException {
-      if (inPhrase) {
-        inPhrase = false;
-        termAtt.setTermBuffer("phrase2");
-        offsetAtt.setStartOffset(savedStart);
-        offsetAtt.setEndOffset(savedEnd);
-        return true;
-      } else
-        while (input.incrementToken()) {
-          if (termAtt.term().equals("phrase")) {
-            inPhrase = true;
-            savedStart = offsetAtt.startOffset();
-            savedEnd = offsetAtt.endOffset();
-            termAtt.setTermBuffer("phrase1");
-            offsetAtt.setStartOffset(savedStart);
-            offsetAtt.setEndOffset(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 QueryParser {
-    public QPTestParser(String f, Analyzer a) {
-      super(f, a);
-    }
-
-    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 int originalMaxClauses;
-
-  public void setUp() throws Exception {
-    super.setUp();
-    originalMaxClauses = BooleanQuery.getMaxClauseCount();
-  }
-
-  public QueryParser getParser(Analyzer a) throws Exception {
-    if (a == null)
-      a = new SimpleAnalyzer();
-    QueryParser qp = new QueryParser("field", a);
-    qp.setDefaultOperator(QueryParser.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(QueryParser 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 = QueryParser.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 {
-    QueryParser 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 {
-    QueryParser 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();
-    QueryParser qp = new QueryParser("field", a);
-    qp.setDefaultOperator(QueryParser.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 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\"");
-    
-    QueryParser qp = new QueryParser("field", new StandardAnalyzer());
-    // make sure OR is the default:
-    assertEquals(QueryParser.OR_OPERATOR, qp.getDefaultOperator());
-    qp.setDefaultOperator(QueryParser.AND_OPERATOR);
-    assertEquals(QueryParser.AND_OPERATOR, qp.getDefaultOperator());
-    qp.setDefaultOperator(QueryParser.OR_OPERATOR);
-    assertEquals(QueryParser.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:
-    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 {
-    QueryParser 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(((RangeQuery)getQuery("[ a TO z]", null)).getConstantScoreRewrite());
-
-    QueryParser qp = new QueryParser("field", new SimpleAnalyzer());
-	  qp.setConstantScoreRewrite(false);
-    assertFalse(((RangeQuery)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);
-
-    QueryParser qp = new QueryParser("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";
-    QueryParser qp = new QueryParser("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(QueryParser 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");
-
-    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"});
-    QueryParser qp = new QueryParser("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);
-
-    QueryParser qp2 = new QueryParser("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 {
-      QueryParser qp = new QueryParser("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 {
-    QueryParser qp = new QueryParser("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 QueryParser("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 {
-    QueryParser qp = new QueryParser("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 {
-      QueryParser qp = new QueryParser("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 {
-    QueryParser qp = new QueryParser("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 {
-    QueryParser qp = new QueryParser("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: src/test/org/apache/lucene/queryParser/TestMultiAnalyzer.java
===================================================================
--- src/test/org/apache/lucene/queryParser/TestMultiAnalyzer.java	(revision 757685)
+++ src/test/org/apache/lucene/queryParser/TestMultiAnalyzer.java	(working copy)
@@ -1,273 +0,0 @@
-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.io.IOException;
-import java.io.Reader;
-
-import org.apache.lucene.analysis.Analyzer;
-import org.apache.lucene.analysis.LowerCaseFilter;
-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.search.Query;
-import org.apache.lucene.util.LuceneTestCase;
-
-/**
- * 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 TestMultiAnalyzer extends LuceneTestCase {
-
-  private static int multiToken = 0;
-
-  public void testMultiAnalyzer() throws ParseException {
-    
-    QueryParser qp = new QueryParser("", 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(QueryParser.AND_OPERATOR);
-    assertEquals("+(multi multi2) +foo", qp.parse("multi foo").toString());
-
-  }
-    
-  public void testMultiAnalyzerWithSubclassOfQueryParser() throws ParseException {
-
-    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 {
-    QueryParser qp = new QueryParser("", 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);
-    }
-
-    public final boolean incrementToken() throws java.io.IOException {
-      if (multiToken > 0) {
-        termAtt.setTermBuffer("multi"+(multiToken+1));
-        offsetAtt.setStartOffset(prevStartOffset);
-        offsetAtt.setEndOffset(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 final class TestPosIncrementFilter extends TokenFilter {
-    
-    TermAttribute termAtt;
-    PositionIncrementAttribute posIncrAtt;
-    
-    public TestPosIncrementFilter(TokenStream in) {
-      super(in);
-      termAtt = (TermAttribute) addAttribute(TermAttribute.class);
-      posIncrAtt = (PositionIncrementAttribute) addAttribute(PositionIncrementAttribute.class);
-    }
-
-    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;
-    }
-  }
-
-    /** a very simple subclass of QueryParser */
-    private final static class DumbQueryParser extends QueryParser {
-        
-        public DumbQueryParser(String f, Analyzer a) {
-            super(f, a);
-        }
-
-        /** expose super's version */
-        public Query getSuperFieldQuery(String f, String t) 
-            throws ParseException {
-            return super.getFieldQuery(f,t);
-        }
-        /** wrap super's version */
-        protected Query getFieldQuery(String f, String t)
-            throws ParseException {
-            return new DumbQueryWrapper(getSuperFieldQuery(f,t));
-        }
-    }
-    
-    /**
-     * A very simple wrapper to prevent instanceof checks but uses
-     * the toString of the query it wraps.
-     */
-    private final static class DumbQueryWrapper extends Query {
-
-        private Query q;
-        public DumbQueryWrapper(Query q) {
-            super();
-            this.q = q;
-        }
-        public String toString(String f) {
-            return q.toString(f);
-        }
-    }
-    
-}
Index: src/test/org/apache/lucene/queryParser/lucene2/LuceneQueryParserTestSuite.java
===================================================================
--- src/test/org/apache/lucene/queryParser/lucene2/LuceneQueryParserTestSuite.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/lucene2/LuceneQueryParserTestSuite.java	(revision 0)
@@ -0,0 +1,41 @@
+package org.apache.lucene.queryParser.lucene2;
+
+/**
+ * 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 junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test QueryParser's old testcases using the Flexible Query Parser
+ * wrappers to validate old testcases
+ *
+ */
+public class LuceneQueryParserTestSuite {
+    
+    public static Test suite() {
+        TestSuite suite = new TestSuite("Apache Lucene query parser test cases");
+        
+        suite.addTestSuite(org.apache.lucene.queryParser.lucene2.TestMultiAnalyzer.class);
+        suite.addTestSuite(org.apache.lucene.queryParser.lucene2.TestMultiFieldQueryParser.class);
+        suite.addTestSuite(org.apache.lucene.queryParser.lucene2.TestQueryParser.class);
+        
+        return suite;
+        
+    }
+    
+}
Index: src/test/org/apache/lucene/queryParser/lucene2/TestMultiAnalyzer.java
===================================================================
--- src/test/org/apache/lucene/queryParser/lucene2/TestMultiAnalyzer.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/lucene2/TestMultiAnalyzer.java	(revision 0)
@@ -0,0 +1,305 @@
+package org.apache.lucene.queryParser.lucene2;
+
+/**
+ * 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.util.LuceneTestCase;
+
+/**
+ * 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 TestMultiAnalyzer 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.setStartOffset(prevStartOffset);
+          offsetAtt.setEndOffset(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: src/test/org/apache/lucene/queryParser/lucene2/TestMultiFieldQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/lucene2/TestMultiFieldQueryParser.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/lucene2/TestMultiFieldQueryParser.java	(revision 0)
@@ -0,0 +1,328 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.lucene.queryParser.lucene2;
+
+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.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 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();
+    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;
+      }
+    }
+  }
+
+}
Index: src/test/org/apache/lucene/queryParser/lucene2/TestQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/lucene2/TestQueryParser.java	(revision 0)
+++ src/test/org/apache/lucene/queryParser/lucene2/TestQueryParser.java	(revision 0)
@@ -0,0 +1,1099 @@
+package org.apache.lucene.queryParser.lucene2;
+
+/**
+ * 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.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.RangeQuery;
+import org.apache.lucene.search.ScoreDoc;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.WildcardQuery;
+import org.apache.lucene.store.RAMDirectory;
+import org.apache.lucene.util.LuceneTestCase;
+
+
+/**
+ * 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.setStartOffset(savedStart);
+          offsetAtt.setEndOffset(savedEnd);
+          return true;
+        } else
+          while (input.incrementToken()) {
+            if (termAtt.term().equals("phrase")) {
+              inPhrase = true;
+              savedStart = offsetAtt.startOffset();
+              savedEnd = offsetAtt.endOffset();
+              termAtt.setTermBuffer("phrase1");
+              offsetAtt.setStartOffset(savedStart);
+              offsetAtt.setEndOffset(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(((RangeQuery)getQuery("[ a TO z]", null)).getConstantScoreRewrite());
+
+    QueryParserWrapper qp = new QueryParserWrapper("field", new SimpleAnalyzer());
+          qp.setConstantScoreRewrite(false);
+    assertFalse(((RangeQuery)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: src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java
===================================================================
--- src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java	(revision 757685)
+++ src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java	(working copy)
@@ -1,326 +0,0 @@
-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.io.Reader;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.lucene.analysis.Analyzer;
-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.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 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();
-    MultiFieldQueryParser mfqp = new MultiFieldQueryParser(fields, a);
-    
-    Query q = mfqp.parse(qtxt);
-    assertEquals(expectedRes, q.toString());
-    
-    q = MultiFieldQueryParser.parse(qtxt, fields, occur, a);
-    assertEquals(expectedRes, q.toString());
-  }
-  
-  public void testSimple() throws Exception {
-    String[] fields = {"b", "t"};
-    MultiFieldQueryParser mfqp = new MultiFieldQueryParser(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: MultiFieldQueryParser 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(QueryParser.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"};
-      MultiFieldQueryParser mfqp = new MultiFieldQueryParser(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 = MultiFieldQueryParser.parse(queries, fields, new StandardAnalyzer());
-    assertEquals("b:one t:two", q.toString());
-
-    String[] queries2 = {"+one", "+two"};
-    q = MultiFieldQueryParser.parse(queries2, fields, new StandardAnalyzer());
-    assertEquals("(+b:one) (+t:two)", q.toString());
-
-    String[] queries3 = {"one", "+two"};
-    q = MultiFieldQueryParser.parse(queries3, fields, new StandardAnalyzer());
-    assertEquals("b:one (+t:two)", q.toString());
-
-    String[] queries4 = {"one +more", "+two"};
-    q = MultiFieldQueryParser.parse(queries4, fields, new StandardAnalyzer());
-    assertEquals("(b:one +b:more) (+t:two)", q.toString());
-
-    String[] queries5 = {"blah"};
-    try {
-      q = MultiFieldQueryParser.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 = MultiFieldQueryParser.parse(queries6, fields, stopA);
-    assertEquals("", q.toString());
-    
-    String[] queries7 = {"one ((+stop)) +more", "+((stop)) +two"};
-    q = MultiFieldQueryParser.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 = MultiFieldQueryParser.parse("one", fields, flags, new StandardAnalyzer());
-    assertEquals("+b:one -t:one", q.toString());
-
-    q = MultiFieldQueryParser.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 = MultiFieldQueryParser.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 = {MultiFieldQueryParser.REQUIRED_FIELD, MultiFieldQueryParser.PROHIBITED_FIELD};
-      BooleanClause.Occur[] flags = {BooleanClause.Occur.MUST, BooleanClause.Occur.MUST_NOT};
-      MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer());
-
-    Query q = MultiFieldQueryParser.parse("one", fields, flags, new StandardAnalyzer());//, fields, flags, new StandardAnalyzer());
-    assertEquals("+b:one -t:one", q.toString());
-
-    q = MultiFieldQueryParser.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 = MultiFieldQueryParser.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 = MultiFieldQueryParser.parse(queries, fields, flags, new StandardAnalyzer());
-    assertEquals("+f1:one -f2:two f3:three", q.toString());
-
-    try {
-      BooleanClause.Occur[] flags2 = {BooleanClause.Occur.MUST};
-      q = MultiFieldQueryParser.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 = MultiFieldQueryParser.parse(queries, fields, flags, new StandardAnalyzer());
-    assertEquals("+b:one -t:two", q.toString());
-
-    try {
-      BooleanClause.Occur[] flags2 = {BooleanClause.Occur.MUST};
-      q = MultiFieldQueryParser.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" };
-    MultiFieldQueryParser parser = new MultiFieldQueryParser(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();
-    
-    MultiFieldQueryParser mfqp = 
-      new MultiFieldQueryParser(new String[] {"body"}, analyzer);
-    mfqp.setDefaultOperator(QueryParser.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;
-      }
-    }
-  }
-
-}
Index: common-build.xml
===================================================================
--- common-build.xml	(revision 757685)
+++ common-build.xml	(working copy)
@@ -1,588 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
-    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.
- -->
-	
-<project name="common" xmlns:artifact="antlib:org.apache.maven.artifact.ant">
-  <description>
-    This file is designed for importing into a main build file, and not intended
-    for standalone use.
-  </description>
-
-  <dirname file="${ant.file.common}" property="common.dir"/>
-
-  <!-- Give user a chance to override without editing this file
-      (and without typing -D each time it compiles it -->
-  <property file="${user.home}/lucene.build.properties"/>
-  <property file="${user.home}/build.properties"/>
-  <property file="${basedir}/build.properties"/>
-  <property file="${common.dir}/build.properties"/>
-
-  <tstamp>
-    <format property="current.year" pattern="yyyy"/>
-    <format property="DSTAMP" pattern="yyyy-MM-dd"/>
-    <format property="TSTAMP" pattern="HH:mm:ss"/>
-  </tstamp>
-
-  <property name="name" value="${ant.project.name}"/>
-  <property name="Name" value="Lucene"/>
-  <property name="version" value="2.9-dev"/>
-  <property name="compatibility.tag" value="lucene_2_4_back_compat_tests_20090320"/>
-  <property name="spec.version" value="${version}"/>	
-  <property name="year" value="2000-${current.year}"/>
-  <property name="final.name" value="lucene-${name}-${version}"/>
-
-  <property name="junit.jar" value="junit-3.8.2.jar"/>
-  <property name="junit-location.jar" value="${common.dir}/lib/${junit.jar}"/>
-  <path id="junit-path">
-    <pathelement location="${junit-location.jar}"/>
-  </path>
-
-  <property name="javac.deprecation" value="off"/>
-  <property name="javac.debug" value="on"/>
-  <property name="javac.source" value="1.4"/>
-  <property name="javac.target" value="1.4"/>
-
-  <property name="javadoc.link" value="http://java.sun.com/j2se/1.4/docs/api/"/>
-  <property name="javadoc.access" value="protected"/>
-  <property name="javadoc.dir" value="${common.dir}/build/docs/api"/>
-  <!-- Javadoc classpath -->
-  <path id="javadoc.classpath">
-    <path refid="classpath"/>
-    <pathelement location="${ant.home}/lib/ant.jar"/>
-  </path>
-	
-  <property name="changes.src.dir" value="${common.dir}/src/site/changes"/>
-  <property name="changes.target.dir" value="${common.dir}/build/docs/changes"/>
-
-  <property name="project.name" value="site"/> <!-- todo: is this used by anakia or something else? -->
-  <property name="build.encoding" value="utf-8"/>
-
-  <property name="src.dir" location="src/java"/>
-  <property name="build.dir" location="build"/>
-  <property name="tags.dir" location="tags"/>
-  <property name="dist.dir" location="dist"/>
-  <property name="maven.dist.dir" location="dist/maven"/>
-  <property name="m2.repository.url" value="file://${maven.dist.dir}"/>
-  <property name="m2.repository.private.key" value="${user.home}/.ssh/id_dsa"/>
-
-  <property name="javacc.home" location="${common.dir}"/>
-  <property name="jflex.home" location="${common.dir}"/>
-
-  <property name="junit.output.dir" location="${build.dir}/test"/>
-  <property name="junit.reports" location="${build.dir}/test/reports"/>
-  <property name="junit.includes" value="**/Test*.java,**/*Test.java"/>
-  <property name="junit.excludes" value=""/>
-
-  <property name="manifest.file" location="${common.dir}/build/MANIFEST.MF"/>
-
-  <!-- 
-    we attempt to exec svnversion to get details build information
-    for jar manifests.  this property can be set at runtime to an
-    explicit path as needed, or ant will just try to find it in the
-    default PATH. (this is useful for Hudson)
-  -->
-  <property name="svnversion.exe" value="svnversion" />
-  <property name="svn.exe" value="svn" />
-  
-  <condition property="build-1-5-contrib">
-     <equals arg1="1.5" arg2="${ant.java.version}" />
-  </condition>
-  
-  <property name="clover.db.dir" location="${common.dir}/build/test/clover/db"/>
-  <property name="clover.report.dir" location="${common.dir}/build/test/clover/reports"/>
-
-    <available
-            property="clover.present"
-            classname="com.cenqua.clover.tasks.CloverReportTask"
-            />
-   <condition property="clover.enabled">
-       <and>
-           <isset property="run.clover"/>
-           <isset property="clover.present"/>
-       </and>
-   </condition>
-
-
-  <available
-    property="javacc.present"
-    classname="org.javacc.parser.Main"
-    classpath="${javacc.home}/bin/lib/javacc.jar"
-    />
-
-   <available
-    property="jflex.present"
-    classname="JFlex.anttask.JFlexTask"
-    classpath="${jflex.home}/lib/JFlex.jar"
-    />
-
-  <available
-    property="maven.ant.tasks.present"
-    classname="org.apache.maven.artifact.ant.Pom"
-  />
-	
-  <target name="clean"
-    description="Removes contents of build and dist directories">
-    <delete dir="${build.dir}"/>
-    <delete dir="${dist.dir}"/>
-    <delete file="velocity.log"/>
-  </target>
-
-  <!-- TODO: maybe make JavaCC checking specific to only the projects
-             that use it (Lucene core and contrib/miscellaneous
-  -->
-  <target name="javacc-uptodate-check">
-    <uptodate property="javacc.files.uptodate">
-      <srcfiles dir="src" includes="**/*.jj" />
-      <mapper type="glob" from="*.jj" to="*.java"/>
-    </uptodate>
-  </target>
-
-  <target name="javacc-notice" unless="javacc.files.uptodate">
-    <echo>
-      One or more of the JavaCC .jj files is newer than its corresponding
-      .java file.  Run the "javacc" target to regenerate the artifacts.
-    </echo>
-  </target>
-
-  <target name="init" depends="javacc-uptodate-check, javacc-notice, jflex-uptodate-check, jflex-notice">
-  </target>
-
-  <target name="jflex-uptodate-check">
-    <uptodate property="jflex.files.uptodate">
-      <srcfiles dir="src" includes="**/*.jflex" />
-      <mapper type="glob" from="*.jflex" to="*.java"/>
-    </uptodate>
-  </target>
- 
-  <target name="jflex-notice" unless="jflex.files.uptodate">
-    <echo>
-      One or more of the JFlex .jflex files is newer than its corresponding
-      .java file.  Run the "jflex" target to regenerate the artifacts.
-    </echo>
-  </target>
-
-  <target name="javacc-check">
-    <fail unless="javacc.present">
-      ##################################################################
-      JavaCC not found.
-      JavaCC Home: ${javacc.home}
-      JavaCC JAR: ${javacc.jar}
-
-      Please download and install JavaCC from:
-
-      &lt;http://javacc.dev.java.net&gt;
-
-      Then, create a build.properties file either in your home
-      directory, or within the Lucene directory and set the javacc.home
-      property to the path where JavaCC is installed. For example,
-      if you installed JavaCC in /usr/local/java/javacc-3.2, then set the
-      javacc.home property to:
-
-      javacc.home=/usr/local/java/javacc-3.2
-
-      If you get an error like the one below, then you have not installed
-      things correctly. Please check all your paths and try again.
-
-      java.lang.NoClassDefFoundError: org.javacc.parser.Main
-      ##################################################################
-    </fail>
-
-  </target>
-	
-  <target name="jflex-check">
-    <fail unless="jflex.present">
-      ##################################################################
-      JFlex not found.
-      JFlex Home: ${jflex.home}
-
-      Please download and install JFlex from:
-
-      &lt;http://jflex.de/download.html&gt;
-
-      Then, create a build.properties file either in your home
-      directory, or within the Lucene directory and set the jflex.home
-      property to the path where JFlex is installed. For example,
-      if you installed JFlex in /usr/local/java/jflex-1.4.1, then set the
-      jflex.home property to:
-
-      jflex.home=/usr/local/java/jflex-1.4.1
-
-      ##################################################################
-    </fail>
-  </target>
-
-  <target name="compile-core" depends="init, clover"
-          description="Compiles core classes">
-    <compile
-      srcdir="src/java"
-      destdir="${build.dir}/classes/java">
-      <classpath refid="classpath"/>
-    </compile>
-  </target>
-
-  <target name="compile" depends="compile-core">
-    <!-- convenience target to compile core -->
-  </target>
-
-  <target name="jar-core" depends="compile-core"
-    description="Packages the JAR file">
-    <jarify/>
-  </target>
-
-  <target name="maven.ant.tasks-check">
-	<fail unless="maven.ant.tasks.present">
-	  ##################################################################
-      Maven ant tasks not found.
-      Please make sure the maven-ant-tasks jar is in ANT_HOME/lib, or made 
-      available to Ant using other mechanisms like -lib or CLASSPATH.
-      ##################################################################
-  	</fail>
-  </target>
-
-  <property name="pom.xml" value="pom.xml.template"/>
-
-  <macrodef name="m2-deploy" description="Builds a Maven artifact">
-  	<element name="artifact-attachments" optional="yes"/>
-    <attribute name="pom.xml" default="${pom.xml}"/>
-    <sequential>
-      <copy file="@{pom.xml}" tofile="${build.dir}/@{pom.xml}">
-        <filterset begintoken="@" endtoken="@"> 
-          <filter token="version" value="${version}"/>
-        </filterset>
-      </copy>
-	  <artifact:install-provider artifactId="wagon-ssh" version="1.0-beta-2"/>
-    	
-      <artifact:pom id="maven.project" file="${build.dir}/@{pom.xml}" />
-      <artifact:deploy file="${build.dir}/${maven.project.build.finalName}.jar">
-        <artifact-attachments/>
-      	<remoteRepository url="${m2.repository.url}">
-          <authentication username="${m2.repository.username}" privateKey="${m2.repository.private.key}"/>
-		</remoteRepository>
-        <pom refid="maven.project"/>
-      </artifact:deploy>
-    </sequential>
-  </macrodef>  	
-	
-	
-	
-  <macrodef name="build-manifest" description="Builds a manifest file">
-  	<attribute name="title" default="Lucene Search Engine: ${ant.project.name}" />
-  	<sequential>
-      <manifest file="${manifest.file}">
-        <attribute name="Specification-Title" value="@{title}"/>
-		<!-- spec version must match "digit+{.digit+}*" -->
-		<attribute name="Specification-Version" value="${spec.version}"/>
-		<attribute name="Specification-Vendor"
-		           value="The Apache Software Foundation"/>
-		<attribute name="Implementation-Title" value="org.apache.lucene"/>
-		<!-- impl version can be any string -->
-		<attribute name="Implementation-Version"
-		           value="${version} ${svnversion} - ${DSTAMP} ${TSTAMP}"/>
-		<attribute name="Implementation-Vendor"
-		           value="The Apache Software Foundation"/>
-		<attribute name="X-Compile-Source-JDK" 
-		           value="${javac.source}"/>
-		<attribute name="X-Compile-Target-JDK" 
-		           value="${javac.target}"/>
-	  </manifest>
-  	</sequential>
-  </macrodef>
-	
-  <macrodef name="jarify" description="Builds a JAR file">
-  	<attribute name="basedir" default="${build.dir}/classes/java"/>
-  	<attribute name="destfile" default="${build.dir}/${final.name}.jar"/>
-    <element name="manifest-attributes" optional="yes"/>
-  	<element name="metainf-includes" optional="yes"/>
-    <sequential>
-      <!-- If possible, include the svnversion -->
-      <exec dir="." executable="${svnversion.exe}"
-            outputproperty="svnversion" failifexecutionfails="false">
-        <arg line="."/>
-      </exec>
-      
-      <build-manifest/>
-    	
-      <jar
-        destfile="@{destfile}"
-        basedir="@{basedir}"
-      	manifest="${manifest.file}">
-        <manifest>
-        	<manifest-attributes/>
-        </manifest>
-        <metainf dir="${common.dir}">
-          <include name="LICENSE.txt"/>
-          <include name="NOTICE.txt"/>
-        </metainf>
-        <metainf-includes/>
-      </jar>
-    </sequential>
-  </macrodef>
-
-  <target name="compile-test" depends="compile-core">
-  	<compile-test-macro srcdir="src/test" destdir="${build.dir}/classes/test"
-  						test.classpath="test.classpath"/>
-  </target>
-
-  <property name="tests.verbose" value="false"/>
-	
-  <macrodef name="compile-test-macro" description="Compiles junit tests.">
-  	<attribute name="srcdir"/>
-  	<attribute name="destdir"/>
-  	<attribute name="test.classpath"/>
-   	<sequential>
-      <compile
-        srcdir="@{srcdir}" 
-        destdir="@{destdir}">
-        <classpath refid="@{test.classpath}"/>
-      </compile>
-
-      <!-- Copy any data files present to the classpath -->
-      <copy todir="@{destdir}">
-        <fileset dir="@{srcdir}" excludes="**/*.java"/>
-      </copy>
-  	</sequential>
-  </macrodef>
-	
-  <macrodef name="test-macro" description="Executes junit tests.">
-  	<attribute name="junit.output.dir" default="${junit.output.dir}"/>
-  	<attribute name="junit.classpath" default="junit.classpath"/>
-  	<attribute name="dataDir"/>
-  	<attribute name="tempDir"/>
-  	<element name="contrib-settings" optional="yes"/>
-  	
-  	<sequential>
-	  	<mkdir dir="@{junit.output.dir}"/>
-	    <junit printsummary="off" haltonfailure="no" maxmemory="512M"
-	      errorProperty="tests.failed" failureProperty="tests.failed">
-	      <classpath refid="@{junit.classpath}"/>
-	      <assertions>
-	        <enable package="org.apache.lucene"/>
-	      </assertions>
-	
-	      <!-- allow tests to control debug prints -->
-	      <sysproperty key="tests.verbose" value="${tests.verbose}"/>
-	
-	      <!-- TODO: create propertyset for test properties, so each project can have its own set -->
-	      <sysproperty key="dataDir" file="@{dataDir}"/>
-	      <sysproperty key="tempDir" file="@{tempDir}"/>
-	      <sysproperty key="java.io.tmpdir" file="@{tempDir}"/>
-	
-		  <contrib-settings />
-	    	
-	      <formatter type="xml"/>
-	      <formatter type="brief" usefile="false"/>
-	      <batchtest fork="yes" todir="@{junit.output.dir}" unless="testcase">
-	        <fileset dir="@{dataDir}" includes="${junit.includes}" excludes="${junit.excludes}"/>
-	      </batchtest>
-	      <batchtest fork="yes" todir="@{junit.output.dir}" if="testcase">
-	        <fileset dir="@{dataDir}" includes="**/${testcase}.java"/>
-	      </batchtest>
-	    </junit>
-	    <!-- create this file, then if we don't fail, delete it -->
-	    <!-- this meme makes it easy to tell if contribs have failed later -->
-	    <echo file="@{junit.output.dir}/junitfailed.flag">MAYBE</echo>
-	    <fail if="tests.failed">Tests failed!</fail>
-	    <!-- life would be easier if echo had an 'if' attribute like fail -->
-	    <delete file="@{junit.output.dir}/junitfailed.flag" />
-  	</sequential>
-  </macrodef>
-	
-  <target name="test" depends="compile-test" description="Runs unit tests">
-    <test-macro dataDir="src/test" tempDir="${build.dir}/test">
-    	<contrib-settings>
-	      <!-- set as a system property so contrib tests can have a fixed root
-	           to reference file paths from, and "ant test" can work from
-	           anywhere.
-	       -->
-	      <sysproperty key="lucene.common.dir" file="${common.dir}" />
-	      
-	      <!-- contrib/ant IndexTaskTest needs these two system properties -->
-	      <sysproperty key="docs.dir" file="src/test"/>
-	      <sysproperty key="index.dir" file="${build.dir}/test/index"/>
-	
-	      <!-- contrib/benchmark uses this system property to locate docs data and defined tasks -->
-	      <sysproperty key="tasks.dir" file="${build.dir}/classes/java/org/apache/lucene/benchmark/byTask/tasks"/>
-	      <sysproperty key="benchmark.work.dir" file="${common.dir}/contrib/benchmark/work"/>
-	  </contrib-settings>
-    </test-macro>
-  </target>
-
-    <!--
-     If you want clover test code coverage, run this before the tests.  You need clover.jar and the license in your ANT classspath and you need to specify -Drun.clover=true on the command line.
-
-     See http://issues.apache.org/jira/browse/LUCENE-721
-     -->
-  <target name="clover" depends="clover.setup, clover.info" description="Instrument the Unit tests using Clover.  Requires a Clover 1.3.2 license and clover.jar in the ANT classpath.  To use, specify -Drun.clover=true on the command line."/>
-
-  <target name="clover.setup" if="clover.enabled">
-    <taskdef resource="clovertasks"/>
-    <mkdir dir="${clover.db.dir}"/>
-    <clover-setup initString="${clover.db.dir}/lucene_coverage.db">
-      <fileset dir="src/java">
-        <!-- see https://svn.apache.org/repos/private/committers/donated-licenses/clover/1.3.2/README.txt -->
-        <include name="org/apache/**" />
-        <include name="javax/**" />
-        <include name="org/xml/**" />
-        <include name="org/w3c/**" />
-        <include name="com/example/**" />
-      	<exclude name="org/apache/lucene/analysis/ASCIIFoldingFilter.java" /> <!-- Class too large for clover -->
-      </fileset>
-    </clover-setup>
-  </target>
-
-  <target name="clover.info" unless="clover.present">
-  	<echo>
-      Clover not found. Code coverage reports disabled.
-  	</echo>
-  </target>
-
-  <target name="clover.check">
-	<fail unless="clover.present">
-	  ##################################################################
-      Clover not found.
-      Please make sure clover.jar is in ANT_HOME/lib, or made available
-      to Ant using other mechanisms like -lib or CLASSPATH.
-      ##################################################################
-  	</fail>
-  </target>
-    <!--
-     Run after Junit tests.
-     -->
-  <target name="generate-clover-reports" depends="clover.check, clover">
-    <mkdir dir="${clover.report.dir}"/>
-    <clover-report>
-       <current outfile="${clover.report.dir}" title="${final.name}">
-          <format type="html"/>
-       </current>
-       <current outfile="${clover.report.dir}/clover.xml" title="${final.name}">
-          <format type="xml"/>
-       </current>
-    </clover-report>
-  </target>
-
-  <target name="generate-test-reports" description="Generates test reports">
-    <mkdir dir="${junit.reports}"/>
-    <junitreport todir="${junit.output.dir}">
-      <!-- this fileset let's the task work for individual contribs,
-           as well as the project as a whole
-       -->
-      <fileset dir="${build.dir}">
-        <include name="**/test/TEST-*.xml"/>
-      </fileset>
-      <report format="frames" todir="${junit.reports}"/>
-    </junitreport>
-  </target>
-
-  <target name="jar" depends="jar-core">
-    <!-- convenience target to package core JAR -->
-  </target>
-
-  <target name="jar-src" depends="init">
-  	<jarify basedir="${src.dir}" destfile="${build.dir}/${final.name}-src.jar"/>
-  </target>
-
-  <target name="default" depends="jar-core"/>
-
-  <!--+
-      | M A C R O S
-      +-->
-  <macrodef name="compile">
-    <attribute name="srcdir"/>
-    <attribute name="destdir"/>
-    <element name="nested" implicit="yes" optional="yes"/>
-
-    <sequential>
-      <mkdir dir="@{destdir}"/>
-      <javac
-        encoding="${build.encoding}"
-        srcdir="@{srcdir}"
-        destdir="@{destdir}"
-        deprecation="${javac.deprecation}"
-        debug="${javac.debug}"
-        source="${javac.source}"
-        target="${javac.target}">
-        <nested/>
-        <compilerarg line="-Xmaxwarns 10000000"/>
-        <compilerarg line="-Xmaxerrs 10000000"/>
-      </javac>
-    </sequential>
-  </macrodef>
-
-  <macrodef name="invoke-javacc">
-    <attribute name="target"/>
-    <attribute name="outputDir"/>
-    <sequential>
-      <mkdir dir="@{outputDir}"/>
-      <javacc
-          target="@{target}"
-          outputDirectory="@{outputDir}"
-          debugTokenManager="${javacc.debug.tokenmgr}"
-          debugParser="${javacc.debug.parser}"
-          debuglookahead="${javacc.debug.lookahead}"
-          javacchome="${javacc.home}"
-      />
-      <fixcrlf srcdir="@{outputDir}" includes="*.java">
-        <containsregexp expression="Generated.*By.*JavaCC"/>
-      </fixcrlf>
-    </sequential>
-  </macrodef>
-	
-  <macrodef name="invoke-javadoc">
-    <element name="sources" optional="yes"/>
-    <attribute name="destdir"/>
-  	<attribute name="title" default="${Name} ${version} API"/>
-    <sequential>
-      <javadoc
-          overview="src/java/overview.html"
-          packagenames="org.apache.lucene.*"
-          destdir="@{destdir}"
-          access="${javadoc.access}"
-          encoding="${build.encoding}"
-          author="true"
-          version="true"
-          use="true"
-          source="${ant.java.version}"
-          link="${javadoc.link}"
-          windowtitle="${Name} ${version} API"
-          doctitle="@{title}"
-          bottom="Copyright &amp;copy; ${year} Apache Software Foundation.  All Rights Reserved.">
-        <tag name="todo" description="To Do:"/>
-        <tag name="uml.property" description="UML Property:"/>
-      	<link offline="true" packagelistLoc="${javadoc.dir}"/>
-      	
-      	<sources />
-      	      	
-        <classpath refid="javadoc.classpath"/>
-      </javadoc>
-   </sequential>
-  </macrodef>
-
-
-</project>
-
-
-
-
-
-
-
-
-
-
-
-
