You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2016/12/07 13:48:25 UTC

[07/11] lucenenet git commit: Ported QueryParser.Xml + tests

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/Builders/TermsQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/Builders/TermsQueryBuilder.cs b/src/Lucene.Net.QueryParser/Xml/Builders/TermsQueryBuilder.cs
new file mode 100644
index 0000000..521b21a
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/Builders/TermsQueryBuilder.cs
@@ -0,0 +1,77 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.Analysis.Tokenattributes;
+using Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System;
+using System.IO;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml.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.
+     */
+
+    /// <summary>
+    /// Builds a <see cref="BooleanQuery"/> from all of the terms found in the XML element using the choice of analyzer
+    /// </summary>
+    public class TermsQueryBuilder : IQueryBuilder
+    {
+        private readonly Analyzer analyzer;
+
+        public TermsQueryBuilder(Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+        }
+
+        public virtual Query GetQuery(XmlElement e)
+        {
+            string fieldName = DOMUtils.GetAttributeWithInheritanceOrFail(e, "fieldName");
+            string text = DOMUtils.GetNonBlankTextOrFail(e);
+
+            BooleanQuery bq = new BooleanQuery(DOMUtils.GetAttribute(e, "disableCoord", false));
+            bq.MinimumNumberShouldMatch = DOMUtils.GetAttribute(e, "minimumNumberShouldMatch", 0);
+            TokenStream ts = null;
+            try
+            {
+                ts = analyzer.TokenStream(fieldName, text);
+                ITermToBytesRefAttribute termAtt = ts.AddAttribute<ITermToBytesRefAttribute>();
+                Term term = null;
+                BytesRef bytes = termAtt.BytesRef;
+                ts.Reset();
+                while (ts.IncrementToken())
+                {
+                    termAtt.FillBytesRef();
+                    term = new Term(fieldName, BytesRef.DeepCopyOf(bytes));
+                    bq.Add(new BooleanClause(new TermQuery(term), BooleanClause.Occur.SHOULD));
+                }
+                ts.End();
+            }
+            catch (IOException ioe)
+            {
+                throw new Exception("Error constructing terms from index:" + ioe);
+            }
+            finally
+            {
+                IOUtils.CloseWhileHandlingException(ts);
+            }
+
+            bq.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+            return bq;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/Builders/UserInputQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/Builders/UserInputQueryBuilder.cs b/src/Lucene.Net.QueryParser/Xml/Builders/UserInputQueryBuilder.cs
new file mode 100644
index 0000000..40d34e7
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/Builders/UserInputQueryBuilder.cs
@@ -0,0 +1,100 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.QueryParsers.Classic;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml.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.
+     */
+
+    /// <summary>
+    /// <see cref="UserInputQueryBuilder"/> uses 1 of 2 strategies for thread-safe parsing:
+    /// 1) Synchronizing access to "Parse" calls on a previously supplied <see cref="QueryParser"/>
+    /// or..
+    /// 2) creating a new <see cref="QueryParser"/> object for each parse request
+    /// </summary>
+    public class UserInputQueryBuilder : IQueryBuilder
+    {
+        private QueryParser unSafeParser;
+        private Analyzer analyzer;
+        private string defaultField;
+
+        /// <summary>
+        /// This constructor has the disadvantage of not being able to change choice of default field name
+        /// </summary>
+        /// <param name="parser">thread un-safe query parser</param>
+        public UserInputQueryBuilder(QueryParser parser)
+        {
+            this.unSafeParser = parser;
+        }
+
+        public UserInputQueryBuilder(string defaultField, Analyzer analyzer)
+        {
+            this.analyzer = analyzer;
+            this.defaultField = defaultField;
+        }
+
+        /// <summary>
+        /// (non-Javadoc)
+        /// @see org.apache.lucene.xmlparser.QueryObjectBuilder#process(org.w3c.dom.Element)
+        /// </summary>
+        /// <param name="e"></param>
+        /// <returns></returns>
+        public virtual Query GetQuery(XmlElement e)
+        {
+            string text = DOMUtils.GetText(e);
+            try
+            {
+                Query q = null;
+                if (unSafeParser != null)
+                {
+                    //synchronize on unsafe parser
+                    lock (unSafeParser)
+                    {
+                        q = unSafeParser.Parse(text);
+                    }
+                }
+                else
+                {
+                    string fieldName = DOMUtils.GetAttribute(e, "fieldName", defaultField);
+                    //Create new parser
+                    QueryParser parser = CreateQueryParser(fieldName, analyzer);
+                    q = parser.Parse(text);
+                }
+                q.Boost = DOMUtils.GetAttribute(e, "boost", 1.0f);
+                return q;
+            }
+            catch (ParseException e1)
+            {
+                throw new ParserException(e1.Message);
+            }
+        }
+
+        /// <summary>
+        /// Method to create a <see cref="QueryParser"/> - designed to be overridden
+        /// </summary>
+        /// <returns><see cref="QueryParser"/></returns>
+        protected virtual QueryParser CreateQueryParser(string fieldName, Analyzer analyzer)
+        {
+#pragma warning disable 612, 618
+            return new QueryParser(LuceneVersion.LUCENE_CURRENT, fieldName, analyzer);
+#pragma warning restore 612, 618
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/CoreParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/CoreParser.cs b/src/Lucene.Net.QueryParser/Xml/CoreParser.cs
new file mode 100644
index 0000000..30f0ff8
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/CoreParser.cs
@@ -0,0 +1,185 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.QueryParsers.Classic;
+using Lucene.Net.QueryParsers.Xml.Builders;
+using Lucene.Net.Search;
+using System;
+using System.IO;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Assembles a <see cref="IQueryBuilder"/> which uses only core Lucene Query objects
+    /// </summary>
+    public class CoreParser : IQueryBuilder
+    {
+        protected Analyzer analyzer;
+        protected QueryParser parser;
+        protected QueryBuilderFactory queryFactory;
+        protected FilterBuilderFactory filterFactory;
+        //Controls the max size of the LRU cache used for QueryFilter objects parsed.
+        public static int maxNumCachedFilters = 20;
+
+        /// <summary>
+        /// Construct an XML parser that uses a single instance <see cref="QueryParser"/> for handling
+        /// UserQuery tags - all parse operations are synchronised on this parser
+        /// </summary>
+        /// <param name="analyzer"></param>
+        /// <param name="parser">A <see cref="QueryParser"/> which will be synchronized on during parse calls.</param>
+        public CoreParser(Analyzer analyzer, QueryParser parser)
+            : this(null, analyzer, parser)
+        {
+        }
+
+        /// <summary>
+        /// Constructs an XML parser that creates a <see cref="QueryParser"/> for each UserQuery request.
+        /// </summary>
+        /// <param name="defaultField">The default field name used by <see cref="QueryParser"/>s constructed for UserQuery tags</param>
+        /// <param name="analyzer"></param>
+        public CoreParser(string defaultField, Analyzer analyzer)
+            : this(defaultField, analyzer, null)
+        {
+        }
+
+        protected CoreParser(string defaultField, Analyzer analyzer, QueryParser parser)
+        {
+            this.analyzer = analyzer;
+            this.parser = parser;
+            filterFactory = new FilterBuilderFactory();
+            filterFactory.AddBuilder("RangeFilter", new RangeFilterBuilder());
+            filterFactory.AddBuilder("NumericRangeFilter", new NumericRangeFilterBuilder());
+
+            queryFactory = new QueryBuilderFactory();
+            queryFactory.AddBuilder("TermQuery", new TermQueryBuilder());
+            queryFactory.AddBuilder("TermsQuery", new TermsQueryBuilder(analyzer));
+            queryFactory.AddBuilder("MatchAllDocsQuery", new MatchAllDocsQueryBuilder());
+            queryFactory.AddBuilder("BooleanQuery", new BooleanQueryBuilder(queryFactory));
+            queryFactory.AddBuilder("NumericRangeQuery", new NumericRangeQueryBuilder());
+            queryFactory.AddBuilder("DisjunctionMaxQuery", new DisjunctionMaxQueryBuilder(queryFactory));
+            if (parser != null)
+            {
+                queryFactory.AddBuilder("UserQuery", new UserInputQueryBuilder(parser));
+            }
+            else
+            {
+                queryFactory.AddBuilder("UserQuery", new UserInputQueryBuilder(defaultField, analyzer));
+            }
+            queryFactory.AddBuilder("FilteredQuery", new FilteredQueryBuilder(filterFactory, queryFactory));
+            queryFactory.AddBuilder("ConstantScoreQuery", new ConstantScoreQueryBuilder(filterFactory));
+
+            filterFactory.AddBuilder("CachedFilter", new CachedFilterBuilder(queryFactory,
+                filterFactory, maxNumCachedFilters));
+
+            SpanQueryBuilderFactory sqof = new SpanQueryBuilderFactory();
+
+            SpanNearBuilder snb = new SpanNearBuilder(sqof);
+            sqof.AddBuilder("SpanNear", snb);
+            queryFactory.AddBuilder("SpanNear", snb);
+
+            BoostingTermBuilder btb = new BoostingTermBuilder();
+            sqof.AddBuilder("BoostingTermQuery", btb);
+            queryFactory.AddBuilder("BoostingTermQuery", btb);
+
+            SpanTermBuilder snt = new SpanTermBuilder();
+            sqof.AddBuilder("SpanTerm", snt);
+            queryFactory.AddBuilder("SpanTerm", snt);
+
+            SpanOrBuilder sot = new SpanOrBuilder(sqof);
+            sqof.AddBuilder("SpanOr", sot);
+            queryFactory.AddBuilder("SpanOr", sot);
+
+            SpanOrTermsBuilder sots = new SpanOrTermsBuilder(analyzer);
+            sqof.AddBuilder("SpanOrTerms", sots);
+            queryFactory.AddBuilder("SpanOrTerms", sots);
+
+            SpanFirstBuilder sft = new SpanFirstBuilder(sqof);
+            sqof.AddBuilder("SpanFirst", sft);
+            queryFactory.AddBuilder("SpanFirst", sft);
+
+            SpanNotBuilder snot = new SpanNotBuilder(sqof);
+            sqof.AddBuilder("SpanNot", snot);
+            queryFactory.AddBuilder("SpanNot", snot);
+        }
+
+        public Query Parse(Stream xmlStream)
+        {
+            return GetQuery(ParseXML(xmlStream).DocumentElement);
+        }
+
+        public void AddQueryBuilder(string nodeName, IQueryBuilder builder)
+        {
+            queryFactory.AddBuilder(nodeName, builder);
+        }
+
+        public void AddFilterBuilder(string nodeName, IFilterBuilder builder)
+        {
+            filterFactory.AddBuilder(nodeName, builder);
+        }
+
+        private static XmlDocument ParseXML(Stream pXmlFile)
+        {
+            XmlDocument doc = new XmlDocument();
+            try
+            {
+                doc.Load(pXmlFile);
+            }
+            catch (Exception se)
+            {
+                throw new ParserException("Error parsing XML stream:" + se, se);
+            }
+            return doc;
+        }
+
+        // LUCENENET specific overload for TextReader
+        private static XmlDocument ParseXML(TextReader pXmlFile)
+        {
+            XmlDocument doc = new XmlDocument();
+            try
+            {
+                doc.Load(pXmlFile);
+            }
+            catch (Exception se)
+            {
+                throw new ParserException("Error parsing XML stream:" + se, se);
+            }
+            return doc;
+        }
+
+        // LUCENENET specific overload for XmlReader
+        private static XmlDocument ParseXML(XmlReader pXmlFile)
+        {
+            XmlDocument doc = new XmlDocument();
+            try
+            {
+                doc.Load(pXmlFile);
+            }
+            catch (Exception se)
+            {
+                throw new ParserException("Error parsing XML stream:" + se, se);
+            }
+            return doc;
+        }
+
+        public virtual Query GetQuery(XmlElement e)
+        {
+            return queryFactory.GetQuery(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/CorePlusExtensionsParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/CorePlusExtensionsParser.cs b/src/Lucene.Net.QueryParser/Xml/CorePlusExtensionsParser.cs
new file mode 100644
index 0000000..4c6b77f
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/CorePlusExtensionsParser.cs
@@ -0,0 +1,64 @@
+\ufeffusing Lucene.Net.Analysis;
+using Lucene.Net.QueryParsers.Classic;
+using Lucene.Net.QueryParsers.Xml.Builders;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Assembles a <see cref="QueryBuilder"/> which uses <see cref="Query"/> objects from
+    /// Lucene's <c>sandbox</c> and <c>queries</c>
+    /// modules in addition to core queries.
+    /// </summary>
+    public class CorePlusExtensionsParser : CoreParser
+    {
+        /// <summary>
+        /// Construct an XML parser that uses a single instance <see cref="QueryParser"/> for handling
+        /// UserQuery tags - all parse operations are synchronized on this parser
+        /// </summary>
+        /// <param name="analyzer"></param>
+        /// <param name="parser">A <see cref="QueryParser"/> which will be synchronized on during parse calls.</param>
+        public CorePlusExtensionsParser(Analyzer analyzer, QueryParser parser)
+            : this(null, analyzer, parser)
+        {
+        }
+
+        /// <summary>
+        /// Constructs an XML parser that creates a <see cref="QueryParser"/> for each UserQuery request.
+        /// </summary>
+        /// <param name="defaultField">The default field name used by <see cref="QueryParser"/>s constructed for UserQuery tags</param>
+        /// <param name="analyzer"></param>
+        public CorePlusExtensionsParser(string defaultField, Analyzer analyzer)
+            : this(defaultField, analyzer, null)
+        {
+        }
+
+        private CorePlusExtensionsParser(string defaultField, Analyzer analyzer, QueryParser parser)
+            : base(defaultField, analyzer, parser)
+        {
+            filterFactory.AddBuilder("TermsFilter", new TermsFilterBuilder(analyzer));
+            filterFactory.AddBuilder("BooleanFilter", new BooleanFilterBuilder(filterFactory));
+            filterFactory.AddBuilder("DuplicateFilter", new DuplicateFilterBuilder());
+            string[] fields = { "contents" };
+            queryFactory.AddBuilder("LikeThisQuery", new LikeThisQueryBuilder(analyzer, fields));
+            queryFactory.AddBuilder("BoostingQuery", new BoostingQueryBuilder(queryFactory));
+            queryFactory.AddBuilder("FuzzyLikeThisQuery", new FuzzyLikeThisQueryBuilder(analyzer));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/DOMUtils.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/DOMUtils.cs b/src/Lucene.Net.QueryParser/Xml/DOMUtils.cs
new file mode 100644
index 0000000..3e3379e
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/DOMUtils.cs
@@ -0,0 +1,276 @@
+\ufeffusing System;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Helper methods for parsing XML
+    /// </summary>
+    public class DOMUtils
+    {
+        public static XmlElement GetChildByTagOrFail(XmlElement e, string name)
+        {
+            XmlElement kid = GetChildByTagName(e, name);
+            if (null == kid)
+            {
+                throw new ParserException(e.ToString() + " missing \"" + name
+                    + "\" child element");
+            }
+            return kid;
+        }
+
+        public static XmlElement GetFirstChildOrFail(XmlElement e)
+        {
+            XmlElement kid = GetFirstChildElement(e);
+            if (null == kid)
+            {
+                throw new ParserException(e.ToString()
+                    + " does not contain a child element");
+            }
+            return kid;
+        }
+
+        public static string GetAttributeOrFail(XmlElement e, string name)
+        {
+            string v = e.GetAttribute(name);
+            if (null == v)
+            {
+                throw new ParserException(e.ToString() + " missing \"" + name
+                    + "\" attribute");
+            }
+            return v;
+        }
+
+        public static string GetAttributeWithInheritanceOrFail(XmlElement e, string name)
+        {
+            string v = GetAttributeWithInheritance(e, name);
+            if (null == v)
+            {
+                throw new ParserException(e.ToString() + " missing \"" + name
+                    + "\" attribute");
+            }
+            return v;
+        }
+
+        public static string GetNonBlankTextOrFail(XmlElement e)
+        {
+            string v = GetText(e);
+            if (null != v)
+                v = v.Trim();
+            if (null == v || 0 == v.Length)
+            {
+                throw new ParserException(e.ToString() + " has no text");
+            }
+            return v;
+        }
+
+        /// <summary>Convenience method where there is only one child <see cref="XmlElement"/> of a given name</summary>
+        public static XmlElement GetChildByTagName(XmlElement e, string name)
+        {
+            for (XmlNode kid = e.FirstChild; kid != null; kid = kid.NextSibling)
+            {
+                if ((kid.NodeType == XmlNodeType.Element) && (name.Equals(kid.Name)))
+                {
+                    return (XmlElement)kid;
+                }
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Returns an attribute value from this node, or first parent node with this attribute defined
+        /// </summary>
+        /// <param name="element"></param>
+        /// <param name="attributeName"></param>
+        /// <returns>A non-zero-length value if defined, otherwise null</returns>
+        public static string GetAttributeWithInheritance(XmlElement element, string attributeName)
+        {
+            string result = element.GetAttribute(attributeName);
+            if ((result == null) || ("".Equals(result)))
+            {
+                XmlNode n = element.ParentNode;
+                if ((n == element) || (n == null))
+                {
+                    return null;
+                }
+                if (n is XmlElement)
+                {
+                    XmlElement parent = (XmlElement)n;
+                    return GetAttributeWithInheritance(parent, attributeName);
+                }
+                return null; //we reached the top level of the document without finding attribute
+            }
+            return result;
+        }
+
+
+        /// <summary>Convenience method where there is only one child <see cref="XmlElement"/> of a given name</summary>
+        public static string GetChildTextByTagName(XmlElement e, string tagName)
+        {
+            XmlElement child = GetChildByTagName(e, tagName);
+            return child != null ? GetText(child) : null;
+        }
+
+        /// <summary>Convenience method to append a new child with text</summary>
+        public static XmlElement InsertChild(XmlElement parent, string tagName, string text)
+        {
+            XmlElement child = parent.OwnerDocument.CreateElement(tagName);
+            parent.AppendChild(child);
+            if (text != null)
+            {
+                child.AppendChild(child.OwnerDocument.CreateTextNode(text));
+            }
+            return child;
+        }
+
+        public static string GetAttribute(XmlElement element, string attributeName, string deflt)
+        {
+            string result = element.GetAttribute(attributeName);
+            return (result == null) || ("".Equals(result)) ? deflt : result;
+        }
+
+        public static float GetAttribute(XmlElement element, string attributeName, float deflt)
+        {
+            string result = element.GetAttribute(attributeName);
+            return (result == null) || ("".Equals(result)) ? deflt : Convert.ToSingle(result);
+        }
+
+        public static int GetAttribute(XmlElement element, string attributeName, int deflt)
+        {
+            string result = element.GetAttribute(attributeName);
+            return (result == null) || ("".Equals(result)) ? deflt : Convert.ToInt32(result);
+        }
+
+        public static bool GetAttribute(XmlElement element, string attributeName,
+                                           bool deflt)
+        {
+            string result = element.GetAttribute(attributeName);
+            return (result == null) || ("".Equals(result)) ? deflt : Convert.ToBoolean(result);
+        }
+
+        /* Returns text of node and all child nodes - without markup */
+        //MH changed to Node from Element 25/11/2005
+
+        public static string GetText(XmlNode e)
+        {
+            StringBuilder sb = new StringBuilder();
+            GetTextBuffer(e, sb);
+            return sb.ToString();
+        }
+
+        public static XmlElement GetFirstChildElement(XmlElement element)
+        {
+            for (XmlNode kid = element.FirstChild; kid != null; kid = kid.NextSibling)
+            {
+                if (kid.NodeType == XmlNodeType.Element)
+                {
+                    return (XmlElement)kid;
+                }
+            }
+            return null;
+        }
+
+        private static void GetTextBuffer(XmlNode e, StringBuilder sb)
+        {
+            for (XmlNode kid = e.FirstChild; kid != null; kid = kid.NextSibling)
+            {
+                switch (kid.NodeType)
+                {
+                    case XmlNodeType.Text:
+                        {
+                            sb.Append(kid.Value);
+                            break;
+                        }
+                    case XmlNodeType.Element:
+                        {
+                            GetTextBuffer(kid, sb);
+                            break;
+                        }
+                    case XmlNodeType.EntityReference:
+                        {
+                            GetTextBuffer(kid, sb);
+                            break;
+                        }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Helper method to parse an XML file into a DOM tree, given a <see cref="TextReader"/>.
+        /// </summary>
+        /// <param name="input">reader of the XML file to be parsed</param>
+        /// <returns>an <see cref="XmlDocument"/> object</returns>
+        public static XmlDocument LoadXML(TextReader input)
+        {
+            XmlDocument result = new XmlDocument();
+            try
+            {
+                result.Load(input);
+            }
+            catch (Exception se)
+            {
+                throw new Exception("Error parsing file:" + se, se);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Helper method to parse an XML file into a DOM tree, given a <see cref="Stream"/>.
+        /// </summary>
+        /// <param name="input">reader of the XML file to be parsed</param>
+        /// <returns>an <see cref="XmlDocument"/> object</returns>
+        // LUCENENET specific
+        public static XmlDocument LoadXML(Stream input)
+        {
+            XmlDocument result = new XmlDocument();
+            try
+            {
+                result.Load(input);
+            }
+            catch (Exception se)
+            {
+                throw new Exception("Error parsing file:" + se, se);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Helper method to parse an XML file into a DOM tree, given an <see cref="XmlReader"/>.
+        /// </summary>
+        /// <param name="input">reader of the XML file to be parsed</param>
+        /// <returns>an <see cref="XmlDocument"/> object</returns>
+        // LUCENENET specific
+        public static XmlDocument LoadXML(XmlReader input)
+        {
+            XmlDocument result = new XmlDocument();
+            try
+            {
+                result.Load(input);
+            }
+            catch (Exception se)
+            {
+                throw new Exception("Error parsing file:" + se, se);
+            }
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/FilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/FilterBuilder.cs b/src/Lucene.Net.QueryParser/Xml/FilterBuilder.cs
new file mode 100644
index 0000000..772de16
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/FilterBuilder.cs
@@ -0,0 +1,30 @@
+\ufeffusing Lucene.Net.Search;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Interface for building <see cref="Filter"/>s
+    /// </summary>
+    public interface IFilterBuilder
+    {
+        Filter GetFilter(XmlElement e);
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/FilterBuilderFactory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/FilterBuilderFactory.cs b/src/Lucene.Net.QueryParser/Xml/FilterBuilderFactory.cs
new file mode 100644
index 0000000..701638e
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/FilterBuilderFactory.cs
@@ -0,0 +1,53 @@
+\ufeffusing Lucene.Net.Search;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Factory for <see cref="IFilterBuilder"/>
+    /// </summary>
+    public class FilterBuilderFactory : IFilterBuilder
+    {
+        IDictionary<string, IFilterBuilder> builders = new Dictionary<string, IFilterBuilder>();
+
+        public virtual Filter GetFilter(XmlElement n)
+        {
+            IFilterBuilder builder;
+            if (!builders.TryGetValue(n.Name, out builder) || builder == null)
+            {
+                throw new ParserException("No FilterBuilder defined for node " + n.Name);
+            }
+            return builder.GetFilter(n);
+        }
+
+        public void AddBuilder(string nodeName, IFilterBuilder builder)
+        {
+            builders[nodeName] = builder;
+        }
+
+        public IFilterBuilder GetFilterBuilder(string nodeName)
+        {
+            IFilterBuilder result;
+            builders.TryGetValue(nodeName, out result);
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/ParserException.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/ParserException.cs b/src/Lucene.Net.QueryParser/Xml/ParserException.cs
new file mode 100644
index 0000000..97be757
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/ParserException.cs
@@ -0,0 +1,49 @@
+\ufeffusing System;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Thrown when the xml queryparser encounters 
+    /// invalid syntax/configuration.
+    /// </summary>
+    [Serializable]
+    public class ParserException : Exception
+    {
+        public ParserException()
+            : base()
+        {
+        }
+
+        public ParserException(String message)
+            : base(message)
+        {
+        }
+
+        public ParserException(String message, Exception cause)
+            : base(message, cause)
+        {
+        }
+
+        public ParserException(Exception cause)
+            : base(cause.Message, cause)
+        {
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/QueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/QueryBuilder.cs b/src/Lucene.Net.QueryParser/Xml/QueryBuilder.cs
new file mode 100644
index 0000000..3c9df84
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/QueryBuilder.cs
@@ -0,0 +1,31 @@
+\ufeffusing Lucene.Net.Search;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Implemented by objects that produce Lucene Query objects from XML streams. Implementations are
+    /// expected to be thread-safe so that they can be used to simultaneously parse multiple XML documents.
+    /// </summary>
+    public interface IQueryBuilder
+    {
+        Query GetQuery(XmlElement e);
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/QueryBuilderFactory.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/QueryBuilderFactory.cs b/src/Lucene.Net.QueryParser/Xml/QueryBuilderFactory.cs
new file mode 100644
index 0000000..3b85766
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/QueryBuilderFactory.cs
@@ -0,0 +1,53 @@
+\ufeffusing Lucene.Net.Search;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Factory for <see cref="IQueryBuilder"/>
+    /// </summary>
+    public class QueryBuilderFactory : IQueryBuilder
+    {
+        IDictionary<string, IQueryBuilder> builders = new Dictionary<string, IQueryBuilder>();
+
+        public virtual Query GetQuery(XmlElement n)
+        {
+            IQueryBuilder builder;
+            if (!builders.TryGetValue(n.Name, out builder) || builder == null)
+            {
+                throw new ParserException("No QueryObjectBuilder defined for node " + n.Name);
+            }
+            return builder.GetQuery(n);
+        }
+
+        public void AddBuilder(string nodeName, IQueryBuilder builder)
+        {
+            builders[nodeName] = builder;
+        }
+
+        public IQueryBuilder GetQueryBuilder(string nodeName)
+        {
+            IQueryBuilder result;
+            builders.TryGetValue(nodeName, out result);
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.QueryParser/Xml/QueryTemplateManager.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Xml/QueryTemplateManager.cs b/src/Lucene.Net.QueryParser/Xml/QueryTemplateManager.cs
new file mode 100644
index 0000000..ee05624
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Xml/QueryTemplateManager.cs
@@ -0,0 +1,191 @@
+\ufeffusing System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.Xsl;
+
+namespace Lucene.Net.QueryParsers.Xml
+{
+    /*
+     * Licensed to the Apache Software Foundation (ASF) under one or more
+     * contributor license agreements.  See the NOTICE file distributed with
+     * this work for additional information regarding copyright ownership.
+     * The ASF licenses this file to You under the Apache License, Version 2.0
+     * (the "License"); you may not use this file except in compliance with
+     * the License.  You may obtain a copy of the License at
+     *
+     *     http://www.apache.org/licenses/LICENSE-2.0
+     *
+     * Unless required by applicable law or agreed to in writing, software
+     * distributed under the License is distributed on an "AS IS" BASIS,
+     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     * See the License for the specific language governing permissions and
+     * limitations under the License.
+     */
+
+    /// <summary>
+    /// Provides utilities for turning query form input (such as from a web page or Swing gui) into
+    /// Lucene XML queries by using XSL templates.  This approach offers a convenient way of externalizing
+    /// and changing how user input is turned into Lucene queries.
+    /// Database applications often adopt similar practices by externalizing SQL in template files that can
+    /// be easily changed/optimized by a DBA.
+    /// The static methods can be used on their own or by creating an instance of this class you can store and
+    /// re-use compiled stylesheets for fast use (e.g. in a server environment)
+    /// </summary>
+    public class QueryTemplateManager
+    {
+        IDictionary<string, XslCompiledTransform> compiledTemplatesCache = new Dictionary<string, XslCompiledTransform>();
+        XslCompiledTransform defaultCompiledTemplates = null;
+
+        public QueryTemplateManager()
+        {
+        }
+
+        public QueryTemplateManager(Stream xslIs)
+        {
+            AddDefaultQueryTemplate(xslIs);
+        }
+
+        public void AddDefaultQueryTemplate(Stream xslIs)
+        {
+            defaultCompiledTemplates = GetTemplates(xslIs);
+        }
+
+        public void AddQueryTemplate(string name, Stream xslIs)
+        {
+            compiledTemplatesCache[name] = GetTemplates(xslIs);
+        }
+
+        public string GetQueryAsXmlString(IDictionary<string, string> formProperties, string queryTemplateName)
+        {
+            XslCompiledTransform ts = compiledTemplatesCache[queryTemplateName];
+            return GetQueryAsXmlString(formProperties, ts);
+        }
+
+        public XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties, string queryTemplateName)
+        {
+            XslCompiledTransform ts = compiledTemplatesCache[queryTemplateName];
+            return GetQueryAsDOM(formProperties, ts);
+        }
+
+        public string GetQueryAsXmlString(IDictionary<string, string> formProperties)
+        {
+            return GetQueryAsXmlString(formProperties, defaultCompiledTemplates);
+        }
+
+        public XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties)
+        {
+            return GetQueryAsDOM(formProperties, defaultCompiledTemplates);
+        }
+
+        /// <summary>
+        /// Fast means of constructing query using a precompiled stylesheet
+        /// </summary>
+        public static string GetQueryAsXmlString(IDictionary<string, string> formProperties, XslCompiledTransform template)
+        {
+            // TODO: Suppress XML header with encoding (as Strings have no encoding)
+            using (var stream = new MemoryStream())
+            {
+                TransformCriteria(formProperties, template, stream);
+                using (StreamReader reader = new StreamReader(stream))
+                {
+                    return reader.ReadToEnd();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Slow means of constructing query parsing a stylesheet from an input stream
+        /// </summary>
+        public static string GetQueryAsXmlString(IDictionary<string, string> formProperties, Stream xslIs)
+        {
+            // TODO: Suppress XML header with encoding (as Strings have no encoding)
+            using (var stream = new MemoryStream())
+            {
+                TransformCriteria(formProperties, xslIs, stream);
+                using (StreamReader reader = new StreamReader(stream))
+                {
+                    return reader.ReadToEnd();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Fast means of constructing query using a cached,precompiled stylesheet
+        /// </summary>
+        public static XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties, XslCompiledTransform template)
+        {
+            XmlDocument result = new XmlDocument();
+            using (var stream = new MemoryStream())
+            {
+                TransformCriteria(formProperties, template, stream);
+                stream.Position = 0;
+                result.Load(stream);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Slow means of constructing query - parses stylesheet from input stream
+        /// </summary>
+        public static XmlDocument GetQueryAsDOM(IDictionary<string, string> formProperties, Stream xslIs)
+        {
+            XmlDocument result = new XmlDocument();
+            using (var stream = new MemoryStream())
+            {
+                TransformCriteria(formProperties, xslIs, stream);
+                stream.Position = 0;
+                result.Load(stream);
+            }
+            return result;
+        }
+
+        /// <summary>
+        /// Slower transformation using an uncompiled stylesheet (suitable for development environment)
+        /// </summary>
+        public static void TransformCriteria(IDictionary<string, string> formProperties, Stream xslIs, Stream result)
+        {
+            XmlDocument xslDoc = new XmlDocument();
+            xslDoc.Load(xslIs);
+
+            XslCompiledTransform transformer = new XslCompiledTransform();
+            transformer.Load(xslDoc);
+
+            TransformCriteria(formProperties, transformer, result);
+        }
+
+        /// <summary>
+        /// Fast transformation using a pre-compiled stylesheet (suitable for production environments)
+        /// </summary>   
+        public static void TransformCriteria(IDictionary<string, string> formProperties, XslCompiledTransform transformer, Stream result)
+        {
+            XmlDocument doc = new XmlDocument();
+            XmlElement root = doc.CreateElement("Document");
+            doc.AppendChild(root);
+
+            foreach (var prop in formProperties)
+            {
+                string propName = prop.Key;
+                string value = prop.Value;
+                if ((value != null) && (value.Length > 0))
+                {
+                    DOMUtils.InsertChild(root, propName, value);
+                }
+            }
+
+            transformer.Transform(doc, null, result);
+        }
+
+        /// <summary>
+        /// Parses a query stylesheet for repeated use
+        /// </summary>
+        public static XslCompiledTransform GetTemplates(Stream xslIs)
+        {
+            using (var reader = XmlReader.Create(xslIs))
+            {
+                XslCompiledTransform xslt = new XslCompiledTransform();
+                xslt.Load(reader);
+                return xslt;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj b/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
index 6a9d560..b33a18d 100644
--- a/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
+++ b/src/Lucene.Net.Tests.QueryParser/Lucene.Net.Tests.QueryParser.csproj
@@ -86,6 +86,10 @@
     <Compile Include="Surround\Query\Test02Boolean.cs" />
     <Compile Include="Surround\Query\Test03Distance.cs" />
     <Compile Include="Util\QueryParserTestBase.cs" />
+    <Compile Include="Xml\Builders\TestNumericRangeFilterBuilder.cs" />
+    <Compile Include="Xml\Builders\TestNumericRangeQueryBuilder.cs" />
+    <Compile Include="Xml\TestParser.cs" />
+    <Compile Include="Xml\TestQueryTemplateManager.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />
@@ -118,6 +122,33 @@
       <LastGenOutput>MessagesTestBundleBundle.Designer.cs</LastGenOutput>
     </EmbeddedResource>
   </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Xml\albumBooleanQuery.xsl" />
+    <EmbeddedResource Include="Xml\albumFilteredQuery.xsl" />
+    <EmbeddedResource Include="Xml\albumLuceneClassicQuery.xsl" />
+    <EmbeddedResource Include="Xml\BooleanFilter.xml" />
+    <EmbeddedResource Include="Xml\BooleanQuery.xml" />
+    <EmbeddedResource Include="Xml\BoostingQuery.xml" />
+    <EmbeddedResource Include="Xml\BoostingTermQuery.xml" />
+    <EmbeddedResource Include="Xml\CachedFilter.xml" />
+    <EmbeddedResource Include="Xml\ConstantScoreQuery.xml" />
+    <EmbeddedResource Include="Xml\DisjunctionMaxQuery.xml" />
+    <EmbeddedResource Include="Xml\DuplicateFilterQuery.xml" />
+    <EmbeddedResource Include="Xml\FuzzyLikeThisQuery.xml" />
+    <EmbeddedResource Include="Xml\LikeThisQuery.xml" />
+    <EmbeddedResource Include="Xml\MatchAllDocsQuery.xml" />
+    <EmbeddedResource Include="Xml\NestedBooleanQuery.xml" />
+    <EmbeddedResource Include="Xml\NumericRangeFilterQuery.xml" />
+    <EmbeddedResource Include="Xml\NumericRangeQueryQuery.xml" />
+    <EmbeddedResource Include="Xml\RangeFilterQuery.xml" />
+    <EmbeddedResource Include="Xml\reuters21578.txt" />
+    <EmbeddedResource Include="Xml\SpanQuery.xml" />
+    <EmbeddedResource Include="Xml\TermQuery.xml" />
+    <EmbeddedResource Include="Xml\TermsFilterQuery.xml" />
+    <EmbeddedResource Include="Xml\TermsQuery.xml" />
+    <EmbeddedResource Include="Xml\UserInputQuery.xml" />
+    <EmbeddedResource Include="Xml\UserInputQueryCustomField.xml" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs b/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
index 698ba35..e6c4621 100644
--- a/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
+++ b/src/Lucene.Net.Tests.QueryParser/Util/QueryParserTestBase.cs
@@ -1004,7 +1004,7 @@ namespace Lucene.Net.QueryParsers.Util
         }
 
         // LUCENETODO: convert this from DateField to DateUtil
-        //  public void testLocalDateFormat() throws IOException, ParseException {
+        //  public void TestLocalDateFormat() throws IOException, ParseException {
         //    Directory ramDir = newDirectory();
         //    IndexWriter iw = new IndexWriter(ramDir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random, MockTokenizer.WHITESPACE, false)));
         //    addDateDoc("a", 2005, 12, 2, 10, 15, 33, iw);

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/BooleanFilter.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/BooleanFilter.xml b/src/Lucene.Net.Tests.QueryParser/Xml/BooleanFilter.xml
new file mode 100644
index 0000000..b601d79
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/BooleanFilter.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FilteredQuery>
+	<Query>
+		<MatchAllDocsQuery/>
+	</Query>
+	
+	<Filter>
+		<!--
+			This query illustrates how a BooleanFilter can be used to combine
+			multiple filters in the same way BooleanQueries can be combined
+			with must, should and mustnot clauses
+			-->
+		<BooleanFilter>
+			<Clause occurs="should">
+				<RangeFilter fieldName="date" lowerTerm="19870409" upperTerm="19870412"/>
+			</Clause>
+			<Clause occurs="mustNot">
+				<TermsFilter fieldName="contents">Emcore</TermsFilter> 
+			</Clause>
+		</BooleanFilter>
+		
+	</Filter>
+	
+</FilteredQuery>
+

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/BooleanQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/BooleanQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/BooleanQuery.xml
new file mode 100644
index 0000000..bba1d34
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/BooleanQuery.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<BooleanQuery fieldName="contents">
+	<Clause occurs="should">
+		<TermQuery>merger</TermQuery>
+	</Clause>
+	<Clause occurs="mustnot">
+		<TermQuery>sumitomo</TermQuery>
+	</Clause>
+	<Clause occurs="must">
+		<TermQuery>bank</TermQuery>
+	</Clause>
+</BooleanQuery>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/BoostingQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/BoostingQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/BoostingQuery.xml
new file mode 100644
index 0000000..10cfa88
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/BoostingQuery.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<BoostingQuery>
+	<!-- Find docs about banks, preferably merger info and preferably not "World bank" -->
+	<Query>
+		<BooleanQuery fieldName="contents">
+			<Clause occurs="should">
+				<TermQuery>merger</TermQuery>
+			</Clause>
+			<Clause occurs="must">
+				<TermQuery>bank</TermQuery>
+			</Clause>
+		</BooleanQuery>	
+	</Query>
+	<BoostQuery boost="0.01">
+			<UserQuery>"world bank"</UserQuery>
+	</BoostQuery>
+</BoostingQuery>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/BoostingTermQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/BoostingTermQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/BoostingTermQuery.xml
new file mode 100644
index 0000000..65bbd61
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/BoostingTermQuery.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<BoostingTermQuery fieldName="contents">sumitomo</BoostingTermQuery>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeFilterBuilder.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeFilterBuilder.cs b/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeFilterBuilder.cs
new file mode 100644
index 0000000..5295916
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeFilterBuilder.cs
@@ -0,0 +1,217 @@
+\ufeffusing Lucene.Net.Index;
+using Lucene.Net.Search;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Text;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml.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.
+     */
+
+    public class TestNumericRangeFilterBuilder : LuceneTestCase
+    {
+        [Test]
+        public void TestGetFilterHandleNumericParseErrorStrict()
+        {
+            NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+            filterBuilder.SetStrictMode(true);
+
+            String xml = "<NumericRangeFilter fieldName='AGE' type='int' lowerTerm='-1' upperTerm='NaN'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            try
+            {
+                filterBuilder.GetFilter(doc.DocumentElement);
+            }
+#pragma warning disable 168
+            catch (ParserException e)
+#pragma warning restore 168
+            {
+                return;
+            }
+            fail("Expected to throw " + typeof(ParserException));
+        }
+
+        [Test]
+        public void TestGetFilterHandleNumericParseError()
+        {
+            NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+            filterBuilder.SetStrictMode(false);
+
+            String xml = "<NumericRangeFilter fieldName='AGE' type='int' lowerTerm='-1' upperTerm='NaN'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            Filter filter = filterBuilder.GetFilter(doc.DocumentElement);
+            Store.Directory ramDir = NewDirectory();
+            IndexWriter writer = new IndexWriter(ramDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, null));
+            writer.Commit();
+            try
+            {
+                AtomicReader reader = SlowCompositeReaderWrapper.Wrap(DirectoryReader.Open(ramDir));
+                try
+                {
+                    assertNull(filter.GetDocIdSet(reader.AtomicContext, reader.LiveDocs));
+                }
+                finally
+                {
+                    reader.Dispose();
+                }
+            }
+            finally
+            {
+                writer.Commit();
+                writer.Dispose();
+                ramDir.Dispose();
+            }
+        }
+
+        [Test]
+        public void TestGetFilterInt()
+        {
+            NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+            filterBuilder.SetStrictMode(true);
+
+            String xml = "<NumericRangeFilter fieldName='AGE' type='int' lowerTerm='-1' upperTerm='10'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            Filter filter = filterBuilder.GetFilter(doc.DocumentElement);
+            assertTrue(filter is NumericRangeFilter<int>);
+
+            NumericRangeFilter<int> numRangeFilter = (NumericRangeFilter<int>)filter;
+            assertEquals(Convert.ToInt32(-1), numRangeFilter.Min);
+            assertEquals(Convert.ToInt32(10), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeFilter fieldName='AGE' type='int' lowerTerm='-1' upperTerm='10' includeUpper='false'/>";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+            Filter filter2 = filterBuilder.GetFilter(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeFilter<int>);
+
+            NumericRangeFilter<int> numRangeFilter2 = (NumericRangeFilter<int>)filter2;
+            assertEquals(Convert.ToInt32(-1), numRangeFilter2.Min);
+            assertEquals(Convert.ToInt32(10), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        [Test]
+        public void TestGetFilterLong()
+        {
+            NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+            filterBuilder.SetStrictMode(true);
+
+            String xml = "<NumericRangeFilter fieldName='AGE' type='LoNg' lowerTerm='-2321' upperTerm='60000000'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            Filter filter = filterBuilder.GetFilter(doc.DocumentElement);
+            assertTrue(filter is NumericRangeFilter<long>);
+
+            NumericRangeFilter<long> numRangeFilter = (NumericRangeFilter<long>)filter;
+            assertEquals(Convert.ToInt64(-2321L), numRangeFilter.Min);
+            assertEquals(Convert.ToInt64(60000000L), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeFilter fieldName='AGE' type='LoNg' lowerTerm='-2321' upperTerm='60000000' includeUpper='false'/>";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+            Filter filter2 = filterBuilder.GetFilter(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeFilter<long>);
+            NumericRangeFilter<long> numRangeFilter2 = (NumericRangeFilter<long>)filter2;
+            assertEquals(Convert.ToInt64(-2321L), numRangeFilter2.Min);
+            assertEquals(Convert.ToInt64(60000000L), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        [Test]
+        public void TestGetFilterDouble()
+        {
+            NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+            filterBuilder.SetStrictMode(true);
+
+            String xml = "<NumericRangeFilter fieldName='AGE' type='doubLe' lowerTerm='-23.21' upperTerm='60000.00023'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+
+            Filter filter = filterBuilder.GetFilter(doc.DocumentElement);
+            assertTrue(filter is NumericRangeFilter<double>);
+
+            NumericRangeFilter<double> numRangeFilter = (NumericRangeFilter<double>)filter;
+            assertEquals(Convert.ToDouble(-23.21d), numRangeFilter.Min);
+            assertEquals(Convert.ToDouble(60000.00023d), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeFilter fieldName='AGE' type='doubLe' lowerTerm='-23.21' upperTerm='60000.00023' includeUpper='false'/>";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+            Filter filter2 = filterBuilder.GetFilter(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeFilter<double>);
+
+            NumericRangeFilter<double> numRangeFilter2 = (NumericRangeFilter<double>)filter2;
+            assertEquals(Convert.ToDouble(-23.21d), numRangeFilter2.Min);
+            assertEquals(Convert.ToDouble(60000.00023d), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        [Test]
+        public void TestGetFilterFloat()
+        {
+            NumericRangeFilterBuilder filterBuilder = new NumericRangeFilterBuilder();
+            filterBuilder.SetStrictMode(true);
+
+            String xml = "<NumericRangeFilter fieldName='AGE' type='FLOAT' lowerTerm='-2.321432' upperTerm='32432.23'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+
+            Filter filter = filterBuilder.GetFilter(doc.DocumentElement);
+            assertTrue(filter is NumericRangeFilter<float>);
+
+            NumericRangeFilter<float> numRangeFilter = (NumericRangeFilter<float>)filter;
+            assertEquals(Convert.ToSingle(-2.321432f), numRangeFilter.Min);
+            assertEquals(Convert.ToSingle(32432.23f), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeFilter fieldName='AGE' type='FLOAT' lowerTerm='-2.321432' upperTerm='32432.23' includeUpper='false' precisionStep='2' />";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+
+            Filter filter2 = filterBuilder.GetFilter(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeFilter<float>);
+
+            NumericRangeFilter<float> numRangeFilter2 = (NumericRangeFilter<float>)filter2;
+            assertEquals(Convert.ToSingle(-2.321432f), numRangeFilter2.Min);
+            assertEquals(Convert.ToSingle(32432.23f), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        private static XmlDocument GetDocumentFromString(String str)
+        {
+            XmlDocument result = new XmlDocument();
+            result.LoadXml(str);
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeQueryBuilder.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeQueryBuilder.cs b/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeQueryBuilder.cs
new file mode 100644
index 0000000..4d6e84d
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/Builders/TestNumericRangeQueryBuilder.cs
@@ -0,0 +1,177 @@
+\ufeffusing Lucene.Net.Search;
+using Lucene.Net.Util;
+using NUnit.Framework;
+using System;
+using System.Xml;
+
+namespace Lucene.Net.QueryParsers.Xml.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.
+     */
+
+    public class TestNumericRangeQueryBuilder : LuceneTestCase
+    {
+        [Test]
+        public void TestGetFilterHandleNumericParseErrorStrict()
+        {
+            NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+            String xml = "<NumericRangeQuery fieldName='AGE' type='int' lowerTerm='-1' upperTerm='NaN'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            try
+            {
+                filterBuilder.GetQuery(doc.DocumentElement);
+            }
+#pragma warning disable 168
+            catch (ParserException e)
+#pragma warning restore 168
+            {
+                return;
+            }
+            fail("Expected to throw " + typeof(ParserException));
+        }
+
+        [Test]
+        public void TestGetFilterInt()
+        {
+            NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+            String xml = "<NumericRangeQuery fieldName='AGE' type='int' lowerTerm='-1' upperTerm='10'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            Query filter = filterBuilder.GetQuery(doc.DocumentElement);
+            assertTrue(filter is NumericRangeQuery<int>);
+
+            NumericRangeQuery<int> numRangeFilter = (NumericRangeQuery<int>)filter;
+            assertEquals(Convert.ToInt32(-1), numRangeFilter.Min);
+            assertEquals(Convert.ToInt32(10), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeQuery fieldName='AGE' type='int' lowerTerm='-1' upperTerm='10' includeUpper='false'/>";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+            Query filter2 = filterBuilder.GetQuery(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeQuery<int>);
+
+            NumericRangeQuery<int> numRangeFilter2 = (NumericRangeQuery<int>)filter2;
+            assertEquals(Convert.ToInt32(-1), numRangeFilter2.Min);
+            assertEquals(Convert.ToInt32(10), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        [Test]
+        public void TestGetFilterLong()
+        {
+            NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+            String xml = "<NumericRangeQuery fieldName='AGE' type='LoNg' lowerTerm='-2321' upperTerm='60000000'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+            Query filter = filterBuilder.GetQuery(doc.DocumentElement);
+            assertTrue(filter is NumericRangeQuery<long>);
+            NumericRangeQuery<long> numRangeFilter = (NumericRangeQuery<long>)filter;
+            assertEquals(Convert.ToInt64(-2321L), numRangeFilter.Min);
+            assertEquals(Convert.ToInt64(60000000L), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeQuery fieldName='AGE' type='LoNg' lowerTerm='-2321' upperTerm='60000000' includeUpper='false'/>";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+            Query filter2 = filterBuilder.GetQuery(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeQuery<long>);
+
+            NumericRangeQuery<long> numRangeFilter2 = (NumericRangeQuery<long>)filter2;
+            assertEquals(Convert.ToInt64(-2321L), numRangeFilter2.Min);
+            assertEquals(Convert.ToInt64(60000000L), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        [Test]
+        public void TestGetFilterDouble()
+        {
+            NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+            String xml = "<NumericRangeQuery fieldName='AGE' type='doubLe' lowerTerm='-23.21' upperTerm='60000.00023'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+
+            Query filter = filterBuilder.GetQuery(doc.DocumentElement);
+            assertTrue(filter is NumericRangeQuery<double>);
+
+            NumericRangeQuery<double> numRangeFilter = (NumericRangeQuery<double>)filter;
+            assertEquals(Convert.ToDouble(-23.21d), numRangeFilter.Min);
+            assertEquals(Convert.ToDouble(60000.00023d), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeQuery fieldName='AGE' type='doubLe' lowerTerm='-23.21' upperTerm='60000.00023' includeUpper='false'/>";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+            Query filter2 = filterBuilder.GetQuery(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeQuery<double>);
+
+            NumericRangeQuery<double> numRangeFilter2 = (NumericRangeQuery<double>)filter2;
+            assertEquals(Convert.ToDouble(-23.21d), numRangeFilter2.Min);
+            assertEquals(Convert.ToDouble(60000.00023d), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        [Test]
+        public void TestGetFilterFloat()
+        {
+            NumericRangeQueryBuilder filterBuilder = new NumericRangeQueryBuilder();
+
+            String xml = "<NumericRangeQuery fieldName='AGE' type='FLOAT' lowerTerm='-2.321432' upperTerm='32432.23'/>";
+            XmlDocument doc = GetDocumentFromString(xml);
+
+            Query filter = filterBuilder.GetQuery(doc.DocumentElement);
+            assertTrue(filter is NumericRangeQuery<float>);
+
+            NumericRangeQuery<float> numRangeFilter = (NumericRangeQuery<float>)filter;
+            assertEquals(Convert.ToSingle(-2.321432f), numRangeFilter.Min);
+            assertEquals(Convert.ToSingle(32432.23f), numRangeFilter.Max);
+            assertEquals("AGE", numRangeFilter.Field);
+            assertTrue(numRangeFilter.IncludesMin());
+            assertTrue(numRangeFilter.IncludesMax());
+
+            String xml2 = "<NumericRangeQuery fieldName='AGE' type='FLOAT' lowerTerm='-2.321432' upperTerm='32432.23' includeUpper='false' precisionStep='2' />";
+            XmlDocument doc2 = GetDocumentFromString(xml2);
+
+            Query filter2 = filterBuilder.GetQuery(doc2.DocumentElement);
+            assertTrue(filter2 is NumericRangeQuery<float>);
+
+            NumericRangeQuery<float> numRangeFilter2 = (NumericRangeQuery<float>)filter2;
+            assertEquals(Convert.ToSingle(-2.321432f), numRangeFilter2.Min);
+            assertEquals(Convert.ToSingle(32432.23f), numRangeFilter2.Max);
+            assertEquals("AGE", numRangeFilter2.Field);
+            assertTrue(numRangeFilter2.IncludesMin());
+            assertFalse(numRangeFilter2.IncludesMax());
+        }
+
+        private static XmlDocument GetDocumentFromString(String str)
+        {
+            XmlDocument result = new XmlDocument();
+            result.LoadXml(str);
+            return result;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/CachedFilter.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/CachedFilter.xml b/src/Lucene.Net.Tests.QueryParser/Xml/CachedFilter.xml
new file mode 100644
index 0000000..7d10711
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/CachedFilter.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FilteredQuery>
+	<Query>
+		<BooleanQuery fieldName="contents">
+			<Clause occurs="should">
+				<TermQuery>merger</TermQuery>
+			</Clause>
+			<Clause occurs="mustnot">
+				<TermQuery >sumitomo</TermQuery>		
+			</Clause>
+		</BooleanQuery>
+	</Query>
+	
+	<Filter>
+		<!--
+			CachedFilter elements can contain any Query or Filter. 
+			CachedFilters are cached in an LRU Cache keyed on the contained query/filter object. 
+			Using this will speed up overall performance for repeated uses of the same expensive 
+			query/filter. The sorts of queries likely to benefit from caching need not necessarily be 
+			complex - e.g. simple TermQuerys with a large DF (document frequency) can be expensive
+			on large indexes. A good example of this might be a term query on a field with only 2 possible 
+			values - "true" or "false". In a large index, querying or filtering on this field requires 
+			reading millions of document ids from disk which can more usefully be cached as a 
+			QueryFilter bitset.
+			
+			For Queries/Filters to be cached and reused the object must implement hashcode and
+			equals methods correctly so that duplicate queries/filters can be detected in the cache.
+			
+			The CoreParser.maxNumCachedFilters property can be used to control the size
+			of the LRU Cache established during the construction of CoreParser instances.
+			-->
+		<CachedFilter>
+			<!-- Example query to be cached for fast, repeated use -->
+			<TermQuery fieldName="contents">bank</TermQuery> 
+			<!-- Alternatively, a filter object can be cached ....
+				<RangeFilter fieldName="date" lowerTerm="19870409" upperTerm="19870412"/>
+			-->				
+		</CachedFilter>
+	</Filter>
+	
+</FilteredQuery>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/ConstantScoreQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/ConstantScoreQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/ConstantScoreQuery.xml
new file mode 100644
index 0000000..c5994d1
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/ConstantScoreQuery.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<ConstantScoreQuery>
+	<RangeFilter fieldName="date" lowerTerm="19870409" upperTerm="19870412"/>
+</ConstantScoreQuery>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/DisjunctionMaxQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/DisjunctionMaxQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/DisjunctionMaxQuery.xml
new file mode 100644
index 0000000..eb47816
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/DisjunctionMaxQuery.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<DisjunctionMaxQuery>
+	<TermQuery fieldName="a">merger</TermQuery>
+	<DisjunctionMaxQuery tieBreaker="1.2">
+		<TermQuery fieldName="b">verger</TermQuery>
+	</DisjunctionMaxQuery>
+</DisjunctionMaxQuery>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/DuplicateFilterQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/DuplicateFilterQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/DuplicateFilterQuery.xml
new file mode 100644
index 0000000..c5002c7
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/DuplicateFilterQuery.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FilteredQuery>
+	<Query>
+		<BooleanQuery fieldName="contents">
+			<Clause occurs="should">
+				<TermQuery>money</TermQuery>
+			</Clause>
+			<Clause occurs="must">
+				<TermQuery fieldName="date">19870408</TermQuery>
+			</Clause>
+		</BooleanQuery>
+	</Query>	
+	<Filter>
+		<!-- Filters to last document with this date -->
+		<DuplicateFilter fieldName="date" keepMode="last"/>
+	</Filter>
+	
+</FilteredQuery>

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/2ae0b1bb/src/Lucene.Net.Tests.QueryParser/Xml/FuzzyLikeThisQuery.xml
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests.QueryParser/Xml/FuzzyLikeThisQuery.xml b/src/Lucene.Net.Tests.QueryParser/Xml/FuzzyLikeThisQuery.xml
new file mode 100644
index 0000000..2d11b4e
--- /dev/null
+++ b/src/Lucene.Net.Tests.QueryParser/Xml/FuzzyLikeThisQuery.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FuzzyLikeThisQuery>
+	<!-- Matches on misspelt "Sumitomo" bank -->
+	<Field fieldName="contents">
+		Sumitimo bank 
+	</Field>
+</FuzzyLikeThisQuery>