lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nightowl...@apache.org
Subject [05/58] lucenenet git commit: WIP on QueryParsers.Flexible
Date Tue, 06 Dec 2016 15:11:40 GMT
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/FuzzyQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/FuzzyQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/FuzzyQueryNodeProcessor.cs
new file mode 100644
index 0000000..59fc57d
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/FuzzyQueryNodeProcessor.cs
@@ -0,0 +1,75 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processor iterates the query node tree looking for every
+    /// {@link FuzzyQueryNode}, when this kind of node is found, it checks on the
+    /// query configuration for
+    /// {@link ConfigurationKeys#FUZZY_CONFIG}, gets the
+    /// fuzzy prefix length and default similarity from it and set to the fuzzy node.
+    /// For more information about fuzzy prefix length check: {@link FuzzyQuery}.
+    /// </summary>
+    /// <seealso cref="ConfigurationKeys#FUZZY_CONFIG"/>
+    /// <seealso cref="FuzzyQuery"/>
+    /// <seealso cref="FuzzyQueryNode"/>
+    public class FuzzyQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            if (node is FuzzyQueryNode)
+            {
+                FuzzyQueryNode fuzzyNode = (FuzzyQueryNode)node;
+                QueryConfigHandler config = GetQueryConfigHandler();
+
+                FuzzyConfig fuzzyConfig = null;
+
+                if (config != null && (fuzzyConfig = config.Get(ConfigurationKeys.FUZZY_CONFIG)) != null)
+                {
+                    fuzzyNode.SetPrefixLength(fuzzyConfig.GetPrefixLength());
+
+                    if (fuzzyNode.GetSimilarity() < 0)
+                    {
+                        fuzzyNode.SetSimilarity(fuzzyConfig.GetMinSimilarity());
+                    }
+
+                }
+                else if (fuzzyNode.GetSimilarity() < 0)
+                {
+                    throw new ArgumentException("No FUZZY_CONFIG set in the config");
+                }
+
+            }
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/GroupQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/GroupQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/GroupQueryNodeProcessor.cs
new file mode 100644
index 0000000..d13f79e
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/GroupQueryNodeProcessor.cs
@@ -0,0 +1,240 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// The {@link SyntaxParser}
+    /// generates query node trees that consider the boolean operator precedence, but
+    /// Lucene current syntax does not support boolean precedence, so this processor
+    /// remove all the precedence and apply the equivalent modifier according to the
+    /// boolean operation defined on an specific query node.
+    /// <para/>
+    /// If there is a {@link GroupQueryNode} in the query node tree, the query node
+    /// tree is not merged with the one above it.
+    /// <para/>
+    /// Example: TODO: describe a good example to show how this processor works
+    /// </summary>
+    /// <seealso cref="StandardQueryConfigHandler"/>
+    [Obsolete("Use BooleanQuery2ModifierNodeProcessor instead")]
+    public class GroupQueryNodeProcessor : IQueryNodeProcessor
+    {
+        private List<IQueryNode> queryNodeList;
+
+        private bool latestNodeVerified;
+
+        private QueryConfigHandler queryConfig;
+
+        private bool usingAnd = false;
+
+        public GroupQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        public virtual IQueryNode Process(IQueryNode queryTree)
+        {
+            Operator? defaultOperator = GetQueryConfigHandler().Get(ConfigurationKeys.DEFAULT_OPERATOR);
+
+            if (defaultOperator == null)
+            {
+                throw new ArgumentException(
+                    "DEFAULT_OPERATOR should be set on the QueryConfigHandler");
+            }
+
+            this.usingAnd = Operator.AND == defaultOperator;
+
+            if (queryTree is GroupQueryNode)
+            {
+                queryTree = ((GroupQueryNode)queryTree).GetChild();
+            }
+
+            this.queryNodeList = new List<IQueryNode>();
+            this.latestNodeVerified = false;
+            ReadTree(queryTree);
+
+            List<IQueryNode> actualQueryNodeList = this.queryNodeList;
+
+            for (int i = 0; i < actualQueryNodeList.Count; i++)
+            {
+                IQueryNode node = actualQueryNodeList[i];
+
+                if (node is GroupQueryNode)
+                {
+                    actualQueryNodeList[i] = Process(node);
+                }
+
+            }
+
+            this.usingAnd = false;
+
+            if (queryTree is BooleanQueryNode)
+            {
+                queryTree.Set(actualQueryNodeList);
+
+                return queryTree;
+
+            }
+            else
+            {
+                return new BooleanQueryNode(actualQueryNodeList);
+            }
+
+        }
+
+        /**
+         */
+        private IQueryNode ApplyModifier(IQueryNode node, IQueryNode parent)
+        {
+
+            if (this.usingAnd)
+            {
+
+                if (parent is OrQueryNode)
+                {
+
+                    if (node is ModifierQueryNode)
+                    {
+
+                        ModifierQueryNode modNode = (ModifierQueryNode)node;
+
+                        if (modNode.GetModifier() == Modifier.MOD_REQ)
+                        {
+                            return modNode.GetChild();
+                        }
+
+                    }
+
+                }
+                else
+                {
+
+                    if (node is 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() is AndQueryNode)
+                {
+
+                    if (node is 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(IQueryNode node)
+        {
+
+            if (node is BooleanQueryNode)
+            {
+                IList<IQueryNode> children = node.GetChildren();
+
+                if (children != null && children.Count > 0)
+                {
+
+                    for (int i = 0; i < children.Count - 1; i++)
+                    {
+                        ReadTree(children[i]);
+                    }
+
+                    ProcessNode(node);
+                    ReadTree(children[children.Count - 1]);
+
+                }
+                else
+                {
+                    ProcessNode(node);
+                }
+
+            }
+            else
+            {
+                ProcessNode(node);
+            }
+
+        }
+
+        private void ProcessNode(IQueryNode node)
+        {
+
+            if (node is AndQueryNode || node is OrQueryNode)
+            {
+
+                if (!this.latestNodeVerified && this.queryNodeList.Any())
+                {
+                    var value = this.queryNodeList[this.queryNodeList.Count - 1];
+                    this.queryNodeList.Remove(value);
+
+                    this.queryNodeList.Add(ApplyModifier(value, node));
+                    this.latestNodeVerified = true;
+
+                }
+
+            }
+            else if (!(node is BooleanQueryNode))
+            {
+                this.queryNodeList.Add(ApplyModifier(node, node.GetParent()));
+                this.latestNodeVerified = false;
+
+            }
+
+        }
+
+
+        public virtual QueryConfigHandler GetQueryConfigHandler()
+        {
+            return this.queryConfig;
+        }
+
+
+        public virtual void SetQueryConfigHandler(QueryConfigHandler queryConfigHandler)
+        {
+            this.queryConfig = queryConfigHandler;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/LowercaseExpandedTermsQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/LowercaseExpandedTermsQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/LowercaseExpandedTermsQueryNodeProcessor.cs
new file mode 100644
index 0000000..ce22ea0
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/LowercaseExpandedTermsQueryNodeProcessor.cs
@@ -0,0 +1,87 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Core.Util;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processor verifies if 
+    /// {@link ConfigurationKeys#LOWERCASE_EXPANDED_TERMS} is defined in the
+    /// {@link QueryConfigHandler}. If it is and the expanded terms should be
+    /// lower-cased, it looks for every {@link WildcardQueryNode},
+    /// {@link FuzzyQueryNode} and children of a {@link RangeQueryNode} and lower-case its
+    /// term.
+    /// </summary>
+    /// <seealso cref="ConfigurationKeys#LOWERCASE_EXPANDED_TERMS"/>.
+    public class LowercaseExpandedTermsQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        public LowercaseExpandedTermsQueryNodeProcessor()
+        {
+        }
+
+
+        public override IQueryNode Process(IQueryNode queryTree)
+        {
+            bool? lowercaseExpandedTerms = GetQueryConfigHandler().Get(ConfigurationKeys.LOWERCASE_EXPANDED_TERMS);
+
+            if (lowercaseExpandedTerms != null && lowercaseExpandedTerms.Value)
+            {
+                return base.Process(queryTree);
+            }
+
+            return queryTree;
+
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            CultureInfo locale = GetQueryConfigHandler().Get(ConfigurationKeys.LOCALE);
+            if (locale == null)
+            {
+                locale = CultureInfo.InvariantCulture; //Locale.getDefault();
+            }
+
+            if (node is WildcardQueryNode
+                || node is FuzzyQueryNode
+                || (node is FieldQueryNode && node.GetParent() is IRangeQueryNode)
+                || node is RegexpQueryNode)
+            {
+
+                ITextableQueryNode txtNode = (ITextableQueryNode)node;
+                ICharSequence text = txtNode.Text;
+                txtNode.Text = text != null ? UnescapedCharSequence.ToLowerCase(text, locale) : null;
+            }
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MatchAllDocsQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MatchAllDocsQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MatchAllDocsQueryNodeProcessor.cs
new file mode 100644
index 0000000..4b216ac
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MatchAllDocsQueryNodeProcessor.cs
@@ -0,0 +1,62 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processor converts every {@link WildcardQueryNode} that is "*:*" to
+    /// {@link MatchAllDocsQueryNode}.
+    /// </summary>
+    /// <seealso cref="MatchAllDocsQueryNode"/>
+    /// <seealso cref="MatchAllDocsQuery"/>
+    public class MatchAllDocsQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        public MatchAllDocsQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            if (node is FieldQueryNode)
+            {
+                FieldQueryNode fqn = (FieldQueryNode)node;
+
+                if (fqn.Field.ToString().Equals("*")
+                    && fqn.Text.Equals("*"))
+                {
+
+                    return new MatchAllDocsQueryNode();
+
+                }
+
+            }
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiFieldQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiFieldQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiFieldQueryNodeProcessor.cs
new file mode 100644
index 0000000..1ec617d
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiFieldQueryNodeProcessor.cs
@@ -0,0 +1,130 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// 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.
+    /// <para/>
+    /// 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 ConfigurationKeys#MULTI_FIELDS} 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.
+    /// </summary>
+    /// <seealso cref="ConfigurationKeys#MULTI_FIELDS"/>
+    public class MultiFieldQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        private bool processChildren = true;
+
+        public MultiFieldQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override void ProcessChildren(IQueryNode queryTree)
+        {
+
+            if (this.processChildren)
+            {
+                base.ProcessChildren(queryTree);
+
+            }
+            else
+            {
+                this.processChildren = true;
+            }
+
+        }
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            if (node is IFieldableNode)
+            {
+                this.processChildren = false;
+                IFieldableNode fieldNode = (IFieldableNode)node;
+
+                if (fieldNode.Field == null)
+                {
+                    string[] fields = GetQueryConfigHandler().Get(ConfigurationKeys.MULTI_FIELDS);
+
+                    if (fields == null)
+                    {
+                        throw new ArgumentException(
+                            "StandardQueryConfigHandler.ConfigurationKeys.MULTI_FIELDS should be set on the QueryConfigHandler");
+                    }
+
+                    if (fields != null && fields.Length > 0)
+                    {
+                        fieldNode.Field = fields[0];
+
+                        if (fields.Length == 1)
+                        {
+                            return fieldNode;
+
+                        }
+                        else
+                        {
+                            List<IQueryNode> children = new List<IQueryNode>();
+                            children.Add(fieldNode);
+
+                            for (int i = 1; i < fields.Length; i++)
+                            {
+                                //try
+                                //{
+                                fieldNode = (IFieldableNode)fieldNode.CloneTree();
+                                fieldNode.Field = fields[i];
+
+                                children.Add(fieldNode);
+
+                                //}
+                                //catch (CloneNotSupportedException e)
+                                //{
+                                //    // should never happen
+                                //}
+
+                            }
+
+                            return new GroupQueryNode(new OrQueryNode(children));
+
+                        }
+
+                    }
+
+                }
+
+            }
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiTermRewriteMethodProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiTermRewriteMethodProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiTermRewriteMethodProcessor.cs
new file mode 100644
index 0000000..33e31b5
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/MultiTermRewriteMethodProcessor.cs
@@ -0,0 +1,64 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processor instates the default
+    /// {@link org.apache.lucene.search.MultiTermQuery.RewriteMethod},
+    /// {@link MultiTermQuery#CONSTANT_SCORE_AUTO_REWRITE_DEFAULT}, for multi-term
+    /// query nodes.
+    /// </summary>
+    public class MultiTermRewriteMethodProcessor : QueryNodeProcessorImpl
+    {
+        public static readonly string TAG_ID = "MultiTermRewriteMethodConfiguration";
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            // set setMultiTermRewriteMethod for WildcardQueryNode and
+            // PrefixWildcardQueryNode
+            if (node is WildcardQueryNode
+                || node is IAbstractRangeQueryNode || node is RegexpQueryNode)
+            {
+
+                MultiTermQuery.RewriteMethod rewriteMethod = GetQueryConfigHandler().Get(ConfigurationKeys.MULTI_TERM_REWRITE_METHOD);
+
+                if (rewriteMethod == null)
+                {
+                    // This should not happen, this configuration is set in the
+                    // StandardQueryConfigHandler
+                    throw new ArgumentException(
+                        "StandardQueryConfigHandler.ConfigurationKeys.MULTI_TERM_REWRITE_METHOD should be set on the QueryConfigHandler");
+                }
+
+                // use a TAG to take the value to the Builder
+                node.SetTag(MultiTermRewriteMethodProcessor.TAG_ID, rewriteMethod);
+
+            }
+
+            return node;
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+            return node;
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+            return children;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs
new file mode 100644
index 0000000..de5a5b4
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericQueryNodeProcessor.cs
@@ -0,0 +1,150 @@
+using Lucene.Net.Documents;
+using Lucene.Net.QueryParsers.Flexible.Core;
+using Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processor is used to convert {@link FieldQueryNode}s to
+    /// {@link NumericRangeQueryNode}s. It looks for
+    /// {@link ConfigurationKeys#NUMERIC_CONFIG} set in the {@link FieldConfig} of
+    /// every {@link FieldQueryNode} found. If
+    /// {@link ConfigurationKeys#NUMERIC_CONFIG} is found, it considers that
+    /// {@link FieldQueryNode} to be a numeric query and convert it to
+    /// {@link NumericRangeQueryNode} with upper and lower inclusive and lower and
+    /// upper equals to the value represented by the {@link FieldQueryNode} converted
+    /// to {@link Number}. It means that <b>field:1</b> is converted to <b>field:[1
+    /// TO 1]</b>.
+    /// <para/>
+    /// Note that {@link FieldQueryNode}s children of a
+    /// {@link RangeQueryNode} are ignored.
+    /// </summary>
+    /// <seealso cref="ConfigurationKeys#NUMERIC_CONFIG"/>
+    /// <seealso cref="FieldQueryNode"/>
+    /// <seealso cref="NumericConfig"/>
+    /// <seealso cref="NumericQueryNode"/>
+    public class NumericQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        /**
+   * Constructs a {@link NumericQueryNodeProcessor} object.
+   */
+        public NumericQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            if (node is FieldQueryNode
+                && !(node.GetParent() is IRangeQueryNode))
+            {
+
+                QueryConfigHandler config = GetQueryConfigHandler();
+
+                if (config != null)
+                {
+                    FieldQueryNode fieldNode = (FieldQueryNode)node;
+                    FieldConfig fieldConfig = config.GetFieldConfig(fieldNode
+                        .GetFieldAsString());
+
+                    if (fieldConfig != null)
+                    {
+                        NumericConfig numericConfig = fieldConfig
+                            .Get(ConfigurationKeys.NUMERIC_CONFIG);
+
+                        if (numericConfig != null)
+                        {
+
+                            /*NumberFormat*/
+                            string numberFormat = numericConfig.GetNumberFormat();
+                            string text = fieldNode.GetTextAsString();
+                            /*Number*/
+                            object number = null;
+
+                            if (text.Length > 0)
+                            {
+
+                                try
+                                {
+                                    //number = numberFormat.parse(text);
+                                    number = decimal.Parse(text, NumberStyles.Any);// LUCENENET TODO: use the current culture?
+
+                                }
+                                catch (FormatException e)
+                                {
+                                    throw new QueryNodeParseException(new MessageImpl(
+                                        QueryParserMessages.COULD_NOT_PARSE_NUMBER, fieldNode
+                                            .GetTextAsString(), numberFormat.GetType()
+                                            .AssemblyQualifiedName), e);
+                                }
+
+                                switch (numericConfig.GetType())
+                                {
+                                    case FieldType.NumericType.LONG:
+                                        number = Convert.ToInt64(number);
+                                        break;
+                                    case FieldType.NumericType.INT:
+                                        number = Convert.ToInt32(number);
+                                        break;
+                                    case FieldType.NumericType.DOUBLE:
+                                        number = Convert.ToDouble(number);
+                                        break;
+                                    case FieldType.NumericType.FLOAT:
+                                        number = Convert.ToSingle(number);
+                                        break;
+                                }
+
+                            }
+                            else
+                            {
+                                throw new QueryNodeParseException(new MessageImpl(
+                                    QueryParserMessages.NUMERIC_CANNOT_BE_EMPTY, fieldNode.GetFieldAsString()));
+                            }
+
+                            NumericQueryNode lowerNode = new NumericQueryNode(fieldNode
+                                .Field, number, numberFormat);
+                            NumericQueryNode upperNode = new NumericQueryNode(fieldNode
+                                .Field, number, numberFormat);
+
+                            return new NumericRangeQueryNode(lowerNode, upperNode, true, true,
+                                numericConfig);
+
+                        }
+
+                    }
+
+                }
+
+            }
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+            return node;
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+            return children;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs
new file mode 100644
index 0000000..f78e218
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/NumericRangeQueryNodeProcessor.cs
@@ -0,0 +1,164 @@
+using Lucene.Net.Documents;
+using Lucene.Net.QueryParsers.Flexible.Core;
+using Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Core.Util;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processor is used to convert {@link TermRangeQueryNode}s to
+    /// {@link NumericRangeQueryNode}s. It looks for
+    /// {@link ConfigurationKeys#NUMERIC_CONFIG} set in the {@link FieldConfig} of
+    /// every {@link TermRangeQueryNode} found. If
+    /// {@link ConfigurationKeys#NUMERIC_CONFIG} is found, it considers that
+    /// {@link TermRangeQueryNode} to be a numeric range query and convert it to
+    /// {@link NumericRangeQueryNode}.
+    /// </summary>
+    /// <seealso cref="ConfigurationKeys#NUMERIC_CONFIG"/>
+    /// <seealso cref="TermRangeQueryNode"/>
+    /// <seealso cref="NumericConfig"/>
+    /// <seealso cref="NumericRangeQueryNode"/>
+    public class NumericRangeQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        /**
+   * Constructs an empty {@link NumericRangeQueryNode} object.
+   */
+        public NumericRangeQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            if (node is TermRangeQueryNode)
+            {
+                QueryConfigHandler config = GetQueryConfigHandler();
+
+                if (config != null)
+                {
+                    TermRangeQueryNode termRangeNode = (TermRangeQueryNode)node;
+                    FieldConfig fieldConfig = config.GetFieldConfig(StringUtils
+                        .ToString(termRangeNode.Field));
+
+                    if (fieldConfig != null)
+                    {
+
+                        NumericConfig numericConfig = fieldConfig
+                            .Get(ConfigurationKeys.NUMERIC_CONFIG);
+
+                        if (numericConfig != null)
+                        {
+
+                            FieldQueryNode lower = (FieldQueryNode)termRangeNode.LowerBound;
+                            FieldQueryNode upper = (FieldQueryNode)termRangeNode.UpperBound;
+
+                            string lowerText = lower.GetTextAsString();
+                            string upperText = upper.GetTextAsString();
+                            /*NumberFormat*/ string numberFormat = numericConfig.GetNumberFormat();
+                            /*Number*/
+                            object lowerNumber = null, upperNumber = null;
+
+                            if (lowerText.Length > 0)
+                            {
+
+                                try
+                                {
+                                    //lowerNumber = numberFormat.parse(lowerText);
+                                    lowerNumber = decimal.Parse(lowerText, NumberStyles.Any);// LUCENENET TODO: use the current culture?
+                                }
+                                catch (FormatException e)
+                                {
+                                    throw new QueryNodeParseException(new MessageImpl(
+                                        QueryParserMessages.COULD_NOT_PARSE_NUMBER, lower
+                                            .GetTextAsString(), numberFormat.GetType()
+                                            .AssemblyQualifiedName), e);
+                                }
+
+                            }
+
+                            if (upperText.Length > 0)
+                            {
+
+                                try
+                                {
+                                    //upperNumber = numberFormat.parse(upperText);
+                                    upperNumber = decimal.Parse(upperText, NumberStyles.Any);// LUCENENET TODO: use the current culture?
+                                }
+                                catch (FormatException e)
+                                {
+                                    throw new QueryNodeParseException(new MessageImpl(
+                                        QueryParserMessages.COULD_NOT_PARSE_NUMBER, upper
+                                            .GetTextAsString(), numberFormat.GetType()
+                                            .AssemblyQualifiedName), e);
+                                }
+
+                            }
+
+                            switch (numericConfig.GetType())
+                            {
+                                case FieldType.NumericType.LONG:
+                                    if (upperNumber != null) upperNumber = Convert.ToInt64(upperNumber);
+                                    if (lowerNumber != null) lowerNumber = Convert.ToInt64(lowerNumber);
+                                    break;
+                                case FieldType.NumericType.INT:
+                                    if (upperNumber != null) upperNumber = Convert.ToInt32(upperNumber);
+                                    if (lowerNumber != null) lowerNumber = Convert.ToInt32(lowerNumber);
+                                    break;
+                                case FieldType.NumericType.DOUBLE:
+                                    if (upperNumber != null) upperNumber = Convert.ToDouble(upperNumber);
+                                    if (lowerNumber != null) lowerNumber = Convert.ToDouble(lowerNumber);
+                                    break;
+                                case FieldType.NumericType.FLOAT:
+                                    if (upperNumber != null) upperNumber = Convert.ToSingle(upperNumber);
+                                    if (lowerNumber != null) lowerNumber = Convert.ToSingle(lowerNumber);
+                                    break;
+                            }
+
+                            NumericQueryNode lowerNode = new NumericQueryNode(
+                                termRangeNode.Field, lowerNumber, numberFormat);
+                            NumericQueryNode upperNode = new NumericQueryNode(
+                                termRangeNode.Field, upperNumber, numberFormat);
+
+                            bool lowerInclusive = termRangeNode.IsLowerInclusive;
+                            bool upperInclusive = termRangeNode.IsUpperInclusive;
+
+                            return new NumericRangeQueryNode(lowerNode, upperNode,
+                                lowerInclusive, upperInclusive, numericConfig);
+
+                        }
+
+                    }
+
+                }
+
+            }
+
+            return node;
+
+        }
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+            return node;
+        }
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+            return children;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/OpenRangeQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/OpenRangeQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/OpenRangeQueryNodeProcessor.cs
new file mode 100644
index 0000000..9fbf008
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/OpenRangeQueryNodeProcessor.cs
@@ -0,0 +1,69 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Core.Util;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// Processes {@link TermRangeQuery}s with open ranges.
+    /// </summary>
+    public class OpenRangeQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        public readonly static string OPEN_RANGE_TOKEN = "*";
+
+        public OpenRangeQueryNodeProcessor() { }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            if (node is TermRangeQueryNode)
+            {
+                TermRangeQueryNode rangeNode = (TermRangeQueryNode)node;
+                FieldQueryNode lowerNode = (FieldQueryNode)rangeNode.LowerBound;
+                FieldQueryNode upperNode = (FieldQueryNode)rangeNode.UpperBound;
+                ICharSequence lowerText = lowerNode.Text;
+                ICharSequence upperText = upperNode.Text;
+
+                if (OPEN_RANGE_TOKEN.Equals(upperNode.GetTextAsString())
+                    && (!(upperText is UnescapedCharSequence) || !((UnescapedCharSequence)upperText)
+                        .WasEscaped(0)))
+                {
+                    upperText = "".ToCharSequence();
+                }
+
+                if (OPEN_RANGE_TOKEN.Equals(lowerNode.GetTextAsString())
+                    && (!(lowerText is UnescapedCharSequence) || !((UnescapedCharSequence)lowerText)
+                        .WasEscaped(0)))
+                {
+                    lowerText = "".ToCharSequence();
+                }
+
+                lowerNode.Text = lowerText;
+                upperNode.Text = upperText;
+            }
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+            return node;
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+            return children;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/PhraseSlopQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/PhraseSlopQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/PhraseSlopQueryNodeProcessor.cs
new file mode 100644
index 0000000..9755442
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/PhraseSlopQueryNodeProcessor.cs
@@ -0,0 +1,61 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// 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}.
+    /// </summary>
+    /// <seealso cref="SlopQueryNode"/>
+    public class PhraseSlopQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        public PhraseSlopQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            if (node is SlopQueryNode)
+            {
+                SlopQueryNode phraseSlopNode = (SlopQueryNode)node;
+
+                if (!(phraseSlopNode.GetChild() is TokenizedPhraseQueryNode)
+          && !(phraseSlopNode.GetChild() is MultiPhraseQueryNode))
+                {
+                    return phraseSlopNode.GetChild();
+                }
+
+            }
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs
new file mode 100644
index 0000000..896f749
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs
@@ -0,0 +1,110 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// 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.
+    /// <para/>
+    /// 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.
+    /// </summary>
+    /// <seealso cref="QueryNode"/>
+    /// <seealso cref="MatchNoDocsQueryNode"/>
+    public class RemoveEmptyNonLeafQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        private List<IQueryNode> childrenBuffer = new List<IQueryNode>();
+
+        public RemoveEmptyNonLeafQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        public override IQueryNode Process(IQueryNode queryTree)
+        {
+            queryTree = base.Process(queryTree);
+
+            if (!queryTree.IsLeaf())
+            {
+
+                IList<IQueryNode> children = queryTree.GetChildren();
+
+                if (children == null || children.Count == 0)
+                {
+                    return new MatchNoDocsQueryNode();
+                }
+
+            }
+
+            return queryTree;
+
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            try
+            {
+
+                foreach (IQueryNode child in children)
+                {
+
+                    if (!child.IsLeaf())
+                    {
+
+                        IList<IQueryNode> grandChildren = child.GetChildren();
+
+                        if (grandChildren != null && grandChildren.Count > 0)
+                        {
+                            this.childrenBuffer.Add(child);
+                        }
+
+                    }
+                    else
+                    {
+                        this.childrenBuffer.Add(child);
+                    }
+
+                }
+
+                children.Clear();
+                children.AddRange(this.childrenBuffer);
+
+            }
+            finally
+            {
+                this.childrenBuffer.Clear();
+            }
+
+            return children;
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/StandardQueryNodeProcessorPipeline.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/StandardQueryNodeProcessorPipeline.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/StandardQueryNodeProcessorPipeline.cs
new file mode 100644
index 0000000..35b4491
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/StandardQueryNodeProcessorPipeline.cs
@@ -0,0 +1,54 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This pipeline has all the processors needed to process a query node tree,
+    /// generated by {@link StandardSyntaxParser}, already assembled.
+    /// <para/>
+    /// The order they are assembled affects the results.
+    /// <para/>
+    /// This processor pipeline was designed to work with
+    /// {@link StandardQueryConfigHandler}.
+    /// <para/>
+    /// The result query node tree can be used to build a {@link Query} object using
+    /// {@link StandardQueryTreeBuilder}.
+    /// </summary>
+    /// <seealso cref="StandardQueryTreeBuilder"/>
+    /// <seealso cref="StandardQueryConfigHandler"/>
+    /// <seealso cref="StandardSyntaxParser"/>
+    public class StandardQueryNodeProcessorPipeline : QueryNodeProcessorPipeline
+    {
+        public StandardQueryNodeProcessorPipeline(QueryConfigHandler queryConfig)
+            : base(queryConfig)
+        {
+            Add(new WildcardQueryNodeProcessor());
+            Add(new MultiFieldQueryNodeProcessor());
+            Add(new FuzzyQueryNodeProcessor());
+            Add(new MatchAllDocsQueryNodeProcessor());
+            Add(new OpenRangeQueryNodeProcessor());
+            Add(new NumericQueryNodeProcessor());
+            Add(new NumericRangeQueryNodeProcessor());
+            Add(new LowercaseExpandedTermsQueryNodeProcessor());
+            Add(new TermRangeQueryNodeProcessor());
+            Add(new AllowLeadingWildcardProcessor());
+            Add(new AnalyzerQueryNodeProcessor());
+            Add(new PhraseSlopQueryNodeProcessor());
+            //add(new GroupQueryNodeProcessor());
+            Add(new BooleanQuery2ModifierNodeProcessor());
+            Add(new NoChildOptimizationQueryNodeProcessor());
+            Add(new RemoveDeletedQueryNodesProcessor());
+            Add(new RemoveEmptyNonLeafQueryNodeProcessor());
+            Add(new BooleanSingleChildOptimizationQueryNodeProcessor());
+            Add(new DefaultPhraseSlopQueryNodeProcessor());
+            Add(new BoostQueryNodeProcessor());
+            Add(new MultiTermRewriteMethodProcessor());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
new file mode 100644
index 0000000..6ddbd75
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/TermRangeQueryNodeProcessor.cs
@@ -0,0 +1,164 @@
+using Lucene.Net.Documents;
+using Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Standard.Config;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// This processors process {@link TermRangeQueryNode}s. It reads the lower and
+    /// upper bounds value from the {@link TermRangeQueryNode} 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 TermRangeQueryNode}
+    /// using the non-parsed values.
+    /// <para/>
+    /// If a {@link ConfigurationKeys#LOCALE} is defined in the
+    /// {@link QueryConfigHandler} it will be used to parse the date, otherwise
+    /// {@link Locale#getDefault()} will be used.
+    /// <para/>
+    /// If a {@link ConfigurationKeys#DATE_RESOLUTION} is defined and the
+    /// {@link Resolution} is not <code>null</code> it will also be used to parse the
+    /// date value.
+    /// </summary>
+    /// <seealso cref="ConfigurationKeys#DATE_RESOLUTION"/>
+    /// <seealso cref="ConfigurationKeys#LOCALE"/>
+    /// <seealso cref="TermRangeQueryNode"/>
+    public class TermRangeQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        public TermRangeQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            if (node is TermRangeQueryNode)
+            {
+                TermRangeQueryNode termRangeNode = (TermRangeQueryNode)node;
+                FieldQueryNode upper = (FieldQueryNode)termRangeNode.UpperBound;
+                FieldQueryNode lower = (FieldQueryNode)termRangeNode.LowerBound;
+
+                // LUCENENET TODO: Add a NOT_SET value so we have a logical default?
+                DateTools.Resolution dateRes = DateTools.Resolution.MINUTE/* = null*/;
+                bool inclusive = false;
+                CultureInfo locale = GetQueryConfigHandler().Get(ConfigurationKeys.LOCALE);
+
+                if (locale == null)
+                {
+                    locale = CultureInfo.CurrentCulture; //Locale.getDefault();
+                }
+
+                TimeZoneInfo timeZone = GetQueryConfigHandler().Get(ConfigurationKeys.TIMEZONE);
+
+                if (timeZone == null)
+                {
+                    timeZone = TimeZoneInfo.Local; //TimeZone.getDefault();
+                }
+
+                string field = termRangeNode.Field;
+                string fieldStr = null;
+
+                if (field != null)
+                {
+                    fieldStr = field.ToString();
+                }
+
+                FieldConfig fieldConfig = GetQueryConfigHandler()
+                    .GetFieldConfig(fieldStr);
+
+                if (fieldConfig != null)
+                {
+                    dateRes = fieldConfig.Get(ConfigurationKeys.DATE_RESOLUTION);
+                }
+
+                if (termRangeNode.IsUpperInclusive)
+                {
+                    inclusive = true;
+                }
+
+                string part1 = lower.GetTextAsString();
+                string part2 = upper.GetTextAsString();
+
+                try
+                {
+                    //DateFormat df = DateFormat.GetDateInstance(DateFormat.SHORT, locale);
+                    //df.setLenient(true);
+
+                    if (part1.Length > 0)
+                    {
+                        //DateTime d1 = df.parse(part1);
+                        DateTime d1 = DateTime.Parse(part1, locale);
+                        part1 = DateTools.DateToString(d1, dateRes);
+                        lower.Text = new StringCharSequenceWrapper(part1);
+                    }
+
+                    if (part2.Length > 0)
+                    {
+                        //DateTime d2 = df.parse(part2);
+                        DateTime d2 = DateTime.Parse(part2, locale);
+                        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(timeZone, 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();
+
+                            var cal = locale.Calendar;
+                            d2 = cal.AddHours(d2, 23);
+                            d2 = cal.AddMinutes(d2, 59);
+                            d2 = cal.AddSeconds(d2, 59);
+                            d2 = cal.AddMilliseconds(d2, 999);
+                        }
+
+                        part2 = DateTools.DateToString(d2, dateRes);
+                        upper.Text = new StringCharSequenceWrapper(part2);
+
+                    }
+
+                }
+                catch (Exception e)
+                {
+                    // do nothing
+                }
+
+            }
+
+            return node;
+
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/WildcardQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/WildcardQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/WildcardQueryNodeProcessor.cs
new file mode 100644
index 0000000..b38f60b
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/WildcardQueryNodeProcessor.cs
@@ -0,0 +1,131 @@
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using Lucene.Net.QueryParsers.Flexible.Core.Processors;
+using Lucene.Net.QueryParsers.Flexible.Core.Util;
+using Lucene.Net.QueryParsers.Flexible.Standard.Nodes;
+using Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors
+{
+    /// <summary>
+    /// The {@link StandardSyntaxParser} 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.
+    /// </summary>
+    /// <seealso cref="PrefixQuery"/>
+    /// <seealso cref="PrefixWildcardQueryNode"/>
+    public class WildcardQueryNodeProcessor : QueryNodeProcessorImpl
+    {
+        public WildcardQueryNodeProcessor()
+        {
+            // empty constructor
+        }
+
+
+        protected override IQueryNode PostProcessNode(IQueryNode node)
+        {
+
+            // the old Lucene Parser ignores FuzzyQueryNode that are also PrefixWildcardQueryNode or WildcardQueryNode
+            // we do the same here, also ignore empty terms
+            if (node is FieldQueryNode || node is FuzzyQueryNode)
+            {
+                FieldQueryNode fqn = (FieldQueryNode)node;
+                string text = fqn.Text.ToString();
+
+                // do not process wildcards for TermRangeQueryNode children and 
+                // QuotedFieldQueryNode to reproduce the old parser behavior
+                if (fqn.GetParent() is TermRangeQueryNode
+                    || fqn is QuotedFieldQueryNode
+                    || text.Length <= 0)
+                {
+                    // Ignore empty terms
+                    return node;
+                }
+
+                // Code below simulates the old lucene parser behavior for wildcards
+
+                if (IsPrefixWildcard(text))
+                {
+                    PrefixWildcardQueryNode prefixWildcardQN = new PrefixWildcardQueryNode(fqn);
+                    return prefixWildcardQN;
+
+                }
+                else if (IsWildcard(text))
+                {
+                    WildcardQueryNode wildcardQN = new WildcardQueryNode(fqn);
+                    return wildcardQN;
+                }
+
+            }
+
+            return node;
+
+        }
+
+        private bool IsWildcard(string text)
+        {
+            if (text == null || text.Length <= 0) return false;
+
+            // If a un-escaped '*' or '?' if found return true
+            // start at the end since it's more common to put wildcards at the end
+            for (int i = text.Length - 1; i >= 0; i--)
+            {
+                if ((text[i] == '*' || text[i] == '?') && !UnescapedCharSequence.WasEscaped(new StringCharSequenceWrapper(text), i))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        private bool IsPrefixWildcard(string text)
+        {
+            if (text == null || text.Length <= 0 || !IsWildcard(text)) return false;
+
+            // Validate last character is a '*' and was not escaped
+            // If single '*' is is a wildcard not prefix to simulate old queryparser
+            if (text[text.Length - 1] != '*') return false;
+            if (UnescapedCharSequence.WasEscaped(new StringCharSequenceWrapper(text), text.Length - 1)) return false;
+            if (text.Length == 1) return false;
+
+            // Only make a prefix if there is only one single star at the end and no '?' or '*' characters
+            // If single wildcard return false to mimic old queryparser
+            for (int i = 0; i < text.Length; i++)
+            {
+                if (text[i] == '?') return false;
+                if (text[i] == '*' && !UnescapedCharSequence.WasEscaped(new StringCharSequenceWrapper(text), i))
+                {
+                    if (i == text.Length - 1)
+                        return true;
+                    else
+                        return false;
+                }
+            }
+
+            return false;
+        }
+
+
+        protected override IQueryNode PreProcessNode(IQueryNode node)
+        {
+
+            return node;
+
+        }
+
+
+        protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+        {
+
+            return children;
+
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Standard/QueryParserUtil.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/QueryParserUtil.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/QueryParserUtil.cs
new file mode 100644
index 0000000..55eb099
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Standard/QueryParserUtil.cs
@@ -0,0 +1,202 @@
+using Lucene.Net.Analysis;
+using Lucene.Net.Search;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Standard
+{
+    /// <summary>
+    /// This class defines utility methods to (help) parse query strings into
+    /// {@link Query} objects.
+    /// </summary>
+    public sealed class QueryParserUtil
+    {
+        /**
+   * 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 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)
+        {
+            if (queries.Length != fields.Length)
+                throw new ArgumentException("queries.length != fields.length");
+            BooleanQuery bQuery = new BooleanQuery();
+
+            StandardQueryParser qp = new StandardQueryParser();
+            qp.Analyzer = analyzer;
+
+            for (int i = 0; i < fields.Length; i++)
+            {
+                Query q = qp.Parse(queries[i], fields[i]) as Query;
+
+                if (q != null && // q never null, just being defensive
+                    (!(q is BooleanQuery) || ((BooleanQuery)q).GetClauses().Count > 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>
+         * 
+         * Usage:
+         * <pre class="prettyprint">
+         * <code>
+         * String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};
+         * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+         *                BooleanClause.Occur.MUST,
+         *                BooleanClause.Occur.MUST_NOT};
+         * MultiFieldQueryParser.parse(&quot;query&quot;, fields, flags, analyzer);
+         * </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 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)
+        {
+            if (fields.Length != flags.Length)
+                throw new ArgumentException("fields.length != flags.length");
+            BooleanQuery bQuery = new BooleanQuery();
+
+            StandardQueryParser qp = new StandardQueryParser();
+            qp.Analyzer = analyzer;
+
+            for (int i = 0; i < fields.Length; i++)
+            {
+                Query q = qp.Parse(query, fields[i]) as Query;
+
+                if (q != null && // q never null, just being defensive
+                    (!(q is BooleanQuery) || ((BooleanQuery)q).GetClauses().Count > 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>
+         * 
+         * Usage:
+         * <pre class="prettyprint">
+         * <code>
+         * String[] query = {&quot;query1&quot;, &quot;query2&quot;, &quot;query3&quot;};
+         * String[] fields = {&quot;filename&quot;, &quot;contents&quot;, &quot;description&quot;};
+         * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+         *                BooleanClause.Occur.MUST,
+         *                BooleanClause.Occur.MUST_NOT};
+         * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+         * </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 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)
+        {
+            if (!(queries.Length == fields.Length && queries.Length == flags.Length))
+                throw new ArgumentException(
+                    "queries, fields, and flags array have have different length");
+            BooleanQuery bQuery = new BooleanQuery();
+
+            StandardQueryParser qp = new StandardQueryParser();
+            qp.Analyzer = analyzer;
+
+            for (int i = 0; i < fields.Length; i++)
+            {
+                Query q = qp.Parse(queries[i], fields[i]) as Query;
+
+                if (q != null && // q never null, just being defensive
+                    (!(q is BooleanQuery) || ((BooleanQuery)q).GetClauses().Count > 0))
+                {
+                    bQuery.Add(q, flags[i]);
+                }
+            }
+            return bQuery;
+        }
+
+        /**
+         * Returns a String where those characters that TextParser expects to be
+         * escaped are escaped by a preceding <code>\</code>.
+         */
+        public static string Escape(string s)
+        {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < s.Length; i++)
+            {
+                char c = s[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 == '&' || c == '/')
+                {
+                    sb.Append('\\');
+                }
+                sb.Append(c);
+            }
+            return sb.ToString();
+        }
+    }
+}


Mime
View raw message