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/06 15:11:45 UTC
[10/58] lucenenet git commit: WIP on QueryParsers.Flexible
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PathQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PathQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PathQueryNode.cs
new file mode 100644
index 0000000..264f9fd
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PathQueryNode.cs
@@ -0,0 +1,233 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Parser;
+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.Core.Nodes
+{
+ /// <summary>
+ /// A {@link PathQueryNode} is used to store queries like
+ /// /company/USA/California /product/shoes/brown. QueryText are objects that
+ /// contain the text, begin position and end position in the query.
+ /// <para>
+ /// Example how the text parser creates these objects:
+ /// </para>
+ /// <code>
+ /// List values = new List();
+ /// values.add(new PathQueryNode.QueryText("company", 1, 7));
+ /// values.add(new PathQueryNode.QueryText("USA", 9, 12));
+ /// values.add(new PathQueryNode.QueryText("California", 14, 23));
+ /// QueryNode q = new PathQueryNode(values);
+ /// </code>
+ ///
+ /// </summary>
+ public class PathQueryNode : QueryNodeImpl
+ {
+ /**
+ * Term text with a beginning and end position
+ */
+ public class QueryText : ICloneable
+ {
+ internal string value = null;
+ /**
+ * != null The term's begin position.
+ */
+ internal int begin;
+
+ /**
+ * The term's end position.
+ */
+ internal int end;
+
+ /**
+ * @param value
+ * - text value
+ * @param begin
+ * - position in the query string
+ * @param end
+ * - position in the query string
+ */
+ public QueryText(string value, int begin, int end)
+ : base()
+ {
+ this.value = value;
+ this.begin = begin;
+ this.end = end;
+ }
+
+
+ public virtual /*QueryText*/ object Clone()
+ {
+ QueryText clone = (QueryText)this.MemberwiseClone();
+ clone.value = this.value;
+ clone.begin = this.begin;
+ clone.end = this.end;
+ return clone;
+ }
+
+ /**
+ * @return the value
+ */
+ public string GetValue()
+ {
+ return value;
+ }
+
+ /**
+ * @return the begin
+ */
+ public int GetBegin()
+ {
+ return begin;
+ }
+
+ /**
+ * @return the end
+ */
+ public int GetEnd()
+ {
+ return end;
+ }
+
+ public override string ToString()
+ {
+ return value + ", " + begin + ", " + end;
+ }
+ }
+
+ private IList<QueryText> values = null;
+
+ /**
+ * @param pathElements
+ * - List of QueryText objects
+ */
+ public PathQueryNode(IList<QueryText> pathElements)
+ {
+ this.values = pathElements;
+ if (pathElements.Count <= 1)
+ {
+ // this should not happen
+ throw new Exception(
+ "PathQuerynode requires more 2 or more path elements.");
+ }
+ }
+
+ /**
+ * Returns the a List with all QueryText elements
+ *
+ * @return QueryText List size
+ */
+ public IList<QueryText> GetPathElements()
+ {
+ return values;
+ }
+
+ /**
+ * Returns the a List with all QueryText elements
+ */
+ public void SetPathElements(IList<QueryText> elements)
+ {
+ this.values = elements;
+ }
+
+ /**
+ * Returns the a specific QueryText element
+ *
+ * @return QueryText List size
+ */
+ public QueryText GetPathElement(int index)
+ {
+ return values[index];
+ }
+
+ /**
+ * Returns the CharSequence value of a specific QueryText element
+ *
+ * @return the CharSequence for a specific QueryText element
+ */
+ public string GetFirstPathElement()
+ {
+ return values[0].value;
+ }
+
+ /**
+ * Returns a List QueryText element from position startIndex
+ *
+ * @return a List QueryText element from position startIndex
+ */
+ public IList<QueryText> GetPathElements(int startIndex)
+ {
+ List<PathQueryNode.QueryText> rValues = new List<PathQueryNode.QueryText>();
+ for (int i = startIndex; i < this.values.Count; i++)
+ {
+ //try
+ //{
+ rValues.Add((QueryText)this.values[i].Clone());
+ //}
+ //catch (CloneNotSupportedException e)
+ //{
+ // // this will not happen
+ //}
+ }
+ return rValues;
+ }
+
+ private string GetPathString()
+ {
+ StringBuilder path = new StringBuilder();
+
+ foreach (QueryText pathelement in values)
+ {
+ path.Append("/").Append(pathelement.value);
+ }
+ return path.ToString();
+ }
+
+
+ public override string ToQueryString(IEscapeQuerySyntax escaper)
+ {
+ StringBuilder path = new StringBuilder();
+ path.Append("/").Append(GetFirstPathElement());
+
+ foreach (QueryText pathelement in GetPathElements(1))
+ {
+ string value = escaper.Escape(new StringCharSequenceWrapper(pathelement.value),
+ CultureInfo.InvariantCulture, EscapeQuerySyntax.Type.STRING).ToString();
+ path.Append("/\"").Append(value).Append("\"");
+ }
+ return path.ToString();
+ }
+
+
+ public override string ToString()
+ {
+ QueryText text = this.values[0];
+
+ return "<path start='" + text.begin + "' end='" + text.end + "' path='"
+ + GetPathString() + "'/>";
+ }
+
+
+ public override IQueryNode CloneTree()
+ {
+ PathQueryNode clone = (PathQueryNode)base.CloneTree();
+
+ // copy children
+ if (this.values != null)
+ {
+ List<QueryText> localValues = new List<QueryText>();
+ foreach (QueryText value in this.values)
+ {
+ localValues.Add((QueryText)value.Clone());
+ }
+ clone.values = localValues;
+ }
+
+ return clone;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs
new file mode 100644
index 0000000..63b19c1
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/PhraseSlopQueryNode.cs
@@ -0,0 +1,106 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Core.Parser;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// Query node for <see cref="PhraseQuery"/>'s slop factor.
+ /// </summary>
+ public class PhraseSlopQueryNode : QueryNodeImpl, IFieldableNode
+ {
+ private int value = 0;
+
+ /**
+ * @exception QueryNodeError throw in overridden method to disallow
+ */
+ public PhraseSlopQueryNode(IQueryNode query, int value)
+ {
+ if (query == null)
+ {
+ throw new QueryNodeError(new MessageImpl(
+ QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
+ }
+
+ this.value = value;
+ SetLeaf(false);
+ Allocate();
+ Add(query);
+ }
+
+ public IQueryNode GetChild()
+ {
+ return GetChildren()[0];
+ }
+
+ public int GetValue()
+ {
+ return this.value;
+ }
+
+ private string GetValueString()
+ {
+ float f = this.value;
+ if (f == (long)f)
+ return "" + (long)f;
+ else
+ return "" + f;
+
+ }
+
+
+ public override string ToString()
+ {
+ return "<phraseslop value='" + GetValueString() + "'>" + "\n"
+ + GetChild().ToString() + "\n</phraseslop>";
+ }
+
+
+ public override string ToQueryString(IEscapeQuerySyntax escapeSyntaxParser)
+ {
+ if (GetChild() == null)
+ return "";
+ return GetChild().ToQueryString(escapeSyntaxParser) + "~"
+ + GetValueString();
+ }
+
+
+ public override IQueryNode CloneTree()
+ {
+ PhraseSlopQueryNode clone = (PhraseSlopQueryNode)base.CloneTree();
+
+ clone.value = this.value;
+
+ return clone;
+ }
+
+ public virtual string Field
+ {
+ get
+ {
+ IQueryNode child = GetChild();
+
+ if (child is IFieldableNode)
+ {
+ return ((IFieldableNode)child).Field;
+ }
+
+ return null;
+ }
+ set
+ {
+ IQueryNode child = GetChild();
+
+ if (child is IFieldableNode)
+ {
+ ((IFieldableNode)child).Field = value;
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs
new file mode 100644
index 0000000..da1bf0b
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ProximityQueryNode.cs
@@ -0,0 +1,288 @@
+\ufeff//using System;
+using Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Core.Parser;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// A {@link ProximityQueryNode} represents a query where the terms should meet
+ /// specific distance conditions. (a b c) WITHIN [SENTENCE|PARAGRAPH|NUMBER]
+ /// [INORDER] ("a" "b" "c") WITHIN [SENTENCE|PARAGRAPH|NUMBER] [INORDER]
+ ///
+ /// TODO: Add this to the future standard Lucene parser/processor/builder
+ /// </summary>
+ public class ProximityQueryNode : BooleanQueryNode
+ {
+ /**
+ * Distance condition: PARAGRAPH, SENTENCE, or NUMBER
+ */
+
+ public enum Type
+ {
+ PARAGRAPH,
+ SENTENCE,
+ NUMBER
+ }
+
+ // public enum Type
+ // {
+ // PARAGRAPH /*{
+ // @Override
+ // CharSequence toQueryString() { return "WITHIN PARAGRAPH";
+ // }
+ // }*/,
+ // SENTENCE /*{
+ // @Override
+ // CharSequence toQueryString() { return "WITHIN SENTENCE"; }
+ //}*/,
+ // NUMBER /* {
+ // @Override
+ // CharSequence toQueryString() { return "WITHIN"; }
+ // };*/
+ // }
+
+ // LUCENENET TODO: Implement this on enum
+ // internal abstract string ToQueryString();
+ //}
+
+ /** utility class containing the distance condition and number */
+ public class ProximityType
+ {
+ internal int pDistance = 0;
+
+ ProximityQueryNode.Type pType/* = null*/;
+
+ public ProximityType(ProximityQueryNode.Type type)
+ : this(type, 0)
+ {
+ }
+
+ public ProximityType(ProximityQueryNode.Type type, int distance)
+ {
+ this.pType = type;
+ this.pDistance = distance;
+ }
+ }
+
+ private ProximityQueryNode.Type proximityType = ProximityQueryNode.Type.SENTENCE;
+ private int distance = -1;
+ private bool inorder = false;
+ private string field = null;
+
+ /**
+ * @param clauses
+ * - QueryNode children
+ * @param field
+ * - field name
+ * @param type
+ * - type of proximity query
+ * @param distance
+ * - positive integer that specifies the distance
+ * @param inorder
+ * - true, if the tokens should be matched in the order of the
+ * clauses
+ */
+ public ProximityQueryNode(IList<IQueryNode> clauses, string field,
+ ProximityQueryNode.Type type, int distance, bool inorder)
+ : base(clauses)
+ {
+
+ SetLeaf(false);
+ this.proximityType = type;
+ this.inorder = inorder;
+ this.field = field;
+ if (type == ProximityQueryNode.Type.NUMBER)
+ {
+ if (distance <= 0)
+ {
+ throw new QueryNodeError(new MessageImpl(
+ QueryParserMessages.PARAMETER_VALUE_NOT_SUPPORTED, "distance",
+ distance));
+
+ }
+ else
+ {
+ this.distance = distance;
+ }
+
+ }
+ ClearFields(clauses, field);
+ }
+
+ /**
+ * @param clauses
+ * - QueryNode children
+ * @param field
+ * - field name
+ * @param type
+ * - type of proximity query
+ * @param inorder
+ * - true, if the tokens should be matched in the order of the
+ * clauses
+ */
+ public ProximityQueryNode(IList<IQueryNode> clauses, string field,
+ ProximityQueryNode.Type type, bool inorder)
+ : this(clauses, field, type, -1, inorder)
+ {
+
+ }
+
+ private static void ClearFields(IList<IQueryNode> nodes, string field)
+ {
+ if (nodes == null || nodes.Count == 0)
+ return;
+
+ foreach (IQueryNode clause in nodes)
+ {
+
+ if (clause is FieldQueryNode)
+ {
+ ((FieldQueryNode)clause).toQueryStringIgnoreFields = true;
+ ((FieldQueryNode)clause).Field = field;
+ }
+ }
+ }
+
+ public ProximityQueryNode.Type GetProximityType()
+ {
+ return this.proximityType;
+ }
+
+ public override string ToString()
+ {
+ string distanceSTR = ((this.distance == -1) ? ("")
+ : (" distance='" + this.distance) + "'");
+
+ if (GetChildren() == null || GetChildren().Count == 0)
+ return "<proximity field='" + this.field + "' inorder='" + this.inorder
+ + "' type='" + this.proximityType.ToString() + "'" + distanceSTR
+ + "/>";
+ StringBuilder sb = new StringBuilder();
+ sb.Append("<proximity field='" + this.field + "' inorder='" + this.inorder
+ + "' type='" + this.proximityType.ToString() + "'" + distanceSTR + ">");
+ foreach (IQueryNode child in GetChildren())
+ {
+ sb.Append("\n");
+ sb.Append(child.ToString());
+ }
+ sb.Append("\n</proximity>");
+ return sb.ToString();
+ }
+
+
+ public override string ToQueryString(IEscapeQuerySyntax escapeSyntaxParser)
+ {
+ string withinSTR = this.proximityType.ToQueryString()
+ + ((this.distance == -1) ? ("") : (" " + this.distance))
+ + ((this.inorder) ? (" INORDER") : (""));
+
+ StringBuilder sb = new StringBuilder();
+ if (GetChildren() == null || GetChildren().Count == 0)
+ {
+ // no children case
+ }
+ else
+ {
+ string filler = "";
+ foreach (IQueryNode child in GetChildren())
+ {
+ sb.Append(filler).Append(child.ToQueryString(escapeSyntaxParser));
+ filler = " ";
+ }
+ }
+
+ if (IsDefaultField(this.field))
+ {
+ return "( " + sb.ToString() + " ) " + withinSTR;
+ }
+ else
+ {
+ return this.field + ":(( " + sb.ToString() + " ) " + withinSTR + ")";
+ }
+ }
+
+
+ public override IQueryNode CloneTree()
+ {
+ ProximityQueryNode clone = (ProximityQueryNode)base.CloneTree();
+
+ clone.proximityType = this.proximityType;
+ clone.distance = this.distance;
+ clone.field = this.field;
+
+ return clone;
+ }
+
+ /**
+ * @return the distance
+ */
+ public int GetDistance()
+ {
+ return this.distance;
+ }
+
+ /**
+ * returns null if the field was not specified in the query string
+ *
+ * @return the field
+ */
+ public string GetField()
+ {
+ return this.field;
+ }
+
+ /**
+ * returns null if the field was not specified in the query string
+ *
+ * @return the field
+ */
+ public string GetFieldAsString()
+ {
+ if (this.field == null)
+ return null;
+ else
+ return this.field.ToString();
+ }
+
+ /**
+ * @param field
+ * the field to set
+ */
+ public void SetField(string field)
+ {
+ this.field = field;
+ }
+
+ /**
+ * @return terms must be matched in the specified order
+ */
+ public bool IsInOrder()
+ {
+ return this.inorder;
+ }
+ }
+
+ public static class ProximityQueryNode_TypeExtensions
+ {
+ public static string ToQueryString(this ProximityQueryNode.Type type)
+ {
+ switch (type)
+ {
+ case ProximityQueryNode.Type.NUMBER:
+ return "WITHIN";
+ case ProximityQueryNode.Type.PARAGRAPH:
+ return "WITHIN PARAGRAPH";
+ case ProximityQueryNode.Type.SENTENCE:
+ return "WITHIN SENTENCE";
+ }
+
+ throw new ArgumentException("Invalid ProximityQueryNode.Type");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNode.cs
new file mode 100644
index 0000000..ad641eb
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNode.cs
@@ -0,0 +1,84 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Parser;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Lucene.Net.Search;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// A {@link QueryNode} is a interface implemented by all nodes on a QueryNode
+ /// tree.
+ /// </summary>
+ public interface IQueryNode
+ {
+ /** convert to a query string understood by the query parser */
+ // TODO: this interface might be changed in the future
+ string ToQueryString(IEscapeQuerySyntax escapeSyntaxParser);
+
+ /** for printing */
+
+ //public override string ToString();
+
+ /** get Children nodes */
+ IList<IQueryNode> GetChildren();
+
+ /** verify if a node is a Leaf node */
+ bool IsLeaf();
+
+ /** verify if a node contains a tag */
+ bool ContainsTag(string tagName);
+
+ /**
+ * Returns object stored under that tag name
+ */
+ object GetTag(string tagName);
+
+ IQueryNode GetParent();
+
+ /**
+ * Recursive clone the QueryNode tree The tags are not copied to the new tree
+ * when you call the cloneTree() method
+ *
+ * @return the cloned tree
+ */
+ IQueryNode CloneTree();
+
+ // Below are the methods that can change state of a QueryNode
+ // Write Operations (not Thread Safe)
+
+ // add a new child to a non Leaf node
+ void Add(IQueryNode child);
+
+ void Add(IList<IQueryNode> children);
+
+ // reset the children of a node
+ void Set(IList<IQueryNode> children);
+
+ /**
+ * Associate the specified value with the specified tagName. If the tagName
+ * already exists, the old value is replaced. The tagName and value cannot be
+ * null. tagName will be converted to lowercase.
+ */
+ void SetTag(string tagName, object value);
+
+ /**
+ * Unset a tag. tagName will be converted to lowercase.
+ */
+ void UnsetTag(string tagName);
+
+ /**
+ * Returns a map containing all tags attached to this query node.
+ *
+ * @return a map containing all tags attached to this query node
+ */
+ IDictionary<string, object> GetTagMap();
+
+ /**
+ * Removes this query node from its parent.
+ */
+ void RemoveFromParent();
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs
new file mode 100644
index 0000000..31186de
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QueryNodeImpl.cs
@@ -0,0 +1,292 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Core.Parser;
+using Lucene.Net.QueryParsers.Flexible.Core.Util;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// A {@link QueryNodeImpl} is the default implementation of the interface
+ /// {@link QueryNode}
+ /// </summary>
+ public abstract class QueryNodeImpl : IQueryNode, ICloneable
+ {
+ /* index default field */
+ // TODO remove PLAINTEXT_FIELD_NAME replacing it with configuration APIs
+ public static readonly string PLAINTEXT_FIELD_NAME = "_plain";
+
+ private bool isLeaf = true;
+
+ private Dictionary<string, object> tags = new Dictionary<string, object>();
+
+ private List<IQueryNode> clauses = null;
+
+ protected virtual void Allocate()
+ {
+
+ if (this.clauses == null)
+ {
+ this.clauses = new List<IQueryNode>();
+
+ }
+ else
+ {
+ this.clauses.Clear();
+ }
+
+ }
+
+ public void Add(IQueryNode child)
+ {
+
+ if (IsLeaf() || this.clauses == null || child == null)
+ {
+ throw new ArgumentException(NLS
+ .GetLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+ }
+
+ this.clauses.Add(child);
+ ((QueryNodeImpl)child).SetParent(this);
+
+ }
+
+
+ public void Add(IList<IQueryNode> children)
+ {
+
+ if (IsLeaf() || this.clauses == null)
+ {
+ throw new ArgumentException(NLS
+ .GetLocalizedMessage(QueryParserMessages.NODE_ACTION_NOT_SUPPORTED));
+ }
+
+ foreach (IQueryNode child in children)
+ {
+ Add(child);
+ }
+
+ }
+
+
+ public virtual bool IsLeaf()
+ {
+ return this.isLeaf;
+ }
+
+
+ public void Set(IList<IQueryNode> children)
+ {
+
+ if (IsLeaf() || this.clauses == null)
+ {
+ //ResourceBundle bundle = ResourceBundle
+ // .getBundle("org.apache.lucene.queryParser.messages.QueryParserMessages");
+ //String message = bundle.getObject("Q0008E.NODE_ACTION_NOT_SUPPORTED")
+ // .toString();
+ string message = Lucene.Net.QueryParsers.Properties.Resources.NODE_ACTION_NOT_SUPPORTED;
+
+ throw new ArgumentException(message);
+
+ }
+
+ // reset parent value
+ foreach (IQueryNode child in children)
+ {
+ child.RemoveFromParent();
+ }
+
+ List<IQueryNode> existingChildren = new List<IQueryNode>(GetChildren());
+ foreach (IQueryNode existingChild in existingChildren)
+ {
+ existingChild.RemoveFromParent();
+ }
+
+ // allocate new children list
+ Allocate();
+
+ // add new children and set parent
+ Add(children);
+ }
+
+
+ public virtual IQueryNode CloneTree()
+ {
+ QueryNodeImpl clone = (QueryNodeImpl)this.MemberwiseClone();
+ clone.isLeaf = this.isLeaf;
+
+ // Reset all tags
+ clone.tags = new Dictionary<string, object>();
+
+ // copy children
+ if (this.clauses != null)
+ {
+ List<IQueryNode> localClauses = new List<IQueryNode>();
+ foreach (IQueryNode clause in this.clauses)
+ {
+ localClauses.Add(clause.CloneTree());
+ }
+ clone.clauses = localClauses;
+ }
+
+ return clone;
+ }
+
+
+ public virtual /*IQueryNode*/ object Clone()
+ {
+ return CloneTree();
+ }
+
+ protected virtual void SetLeaf(bool isLeaf)
+ {
+ this.isLeaf = isLeaf;
+ }
+
+ /**
+ * @return a List for QueryNode object. Returns null, for nodes that do not
+ * contain children. All leaf Nodes return null.
+ */
+
+ public IList<IQueryNode> GetChildren()
+ {
+ if (IsLeaf() || this.clauses == null)
+ {
+ return null;
+ }
+ return new List<IQueryNode>(this.clauses);
+ }
+
+
+ public virtual void SetTag(string tagName, object value)
+ {
+ this.tags[tagName.ToLower(CultureInfo.InvariantCulture)] = value;
+ }
+
+
+ public virtual void UnsetTag(string tagName)
+ {
+ this.tags.Remove(tagName.ToLower(CultureInfo.InvariantCulture));
+ }
+
+ /** verify if a node contains a tag */
+ public virtual bool ContainsTag(string tagName)
+ {
+ return this.tags.ContainsKey(tagName.ToLower(CultureInfo.InvariantCulture));
+ }
+
+ public virtual object GetTag(string tagName)
+ {
+ return this.tags[tagName.ToLower(CultureInfo.InvariantCulture)];
+ }
+
+ private IQueryNode parent = null;
+
+ private void SetParent(IQueryNode parent)
+ {
+ if (this.parent != parent)
+ {
+ this.RemoveFromParent();
+ this.parent = parent;
+ }
+ }
+
+
+ public virtual IQueryNode GetParent()
+ {
+ return this.parent;
+ }
+
+ protected bool IsRoot()
+ {
+ return GetParent() == null;
+ }
+
+ /**
+ * If set to true the the method toQueryString will not write field names
+ */
+ protected internal bool toQueryStringIgnoreFields = false;
+
+ /**
+ * This method is use toQueryString to detect if fld is the default field
+ *
+ * @param fld - field name
+ * @return true if fld is the default field
+ */
+ // TODO: remove this method, it's commonly used by {@link
+ // #toQueryString(org.apache.lucene.queryParser.core.parser.EscapeQuerySyntax)}
+ // to figure out what is the default field, however, {@link
+ // #toQueryString(org.apache.lucene.queryParser.core.parser.EscapeQuerySyntax)}
+ // should receive the default field value directly by parameter
+ protected bool IsDefaultField(string fld)
+ {
+ if (this.toQueryStringIgnoreFields)
+ return true;
+ if (fld == null)
+ return true;
+ if (QueryNodeImpl.PLAINTEXT_FIELD_NAME.Equals(StringUtils.ToString(fld)))
+ return true;
+ return false;
+ }
+
+ /**
+ * Every implementation of this class should return pseudo xml like this:
+ *
+ * For FieldQueryNode: <field start='1' end='2' field='subject' text='foo'/>
+ *
+ * @see org.apache.lucene.queryparser.flexible.core.nodes.QueryNode#toString()
+ */
+
+ public override string ToString()
+ {
+ return base.ToString();
+ }
+
+ /**
+ * Returns a map containing all tags attached to this query node.
+ *
+ * @return a map containing all tags attached to this query node
+ */
+ public virtual IDictionary<string, object> GetTagMap()
+ {
+ return new Dictionary<string, object>(this.tags);
+ }
+
+ public virtual void RemoveFromParent()
+ {
+ if (this.parent != null)
+ {
+ IList<IQueryNode> parentChildren = this.parent.GetChildren();
+ //IEnumerator<IQueryNode> it = parentChildren.GetEnumerator();
+
+ //while (it.MoveNext())
+ //{
+ // if (it.Current == this)
+ // {
+ // it.Remove();
+ // }
+ //}
+
+ // LUCENENET NOTE: Loop in reverse so we can remove items
+ // without screwing up our iterator.
+ for (int i = parentChildren.Count - 1; i >= 0; i--)
+ {
+ if (parentChildren[i] == this)
+ {
+ parentChildren.RemoveAt(i);
+ }
+ }
+
+ this.parent = null;
+ }
+ }
+
+ // LUCENENET specific - class must implement all members of IQueryNode
+ public abstract string ToQueryString(IEscapeQuerySyntax escapeSyntaxParser);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QuotedFieldQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QuotedFieldQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QuotedFieldQueryNode.cs
new file mode 100644
index 0000000..a60597b
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/QuotedFieldQueryNode.cs
@@ -0,0 +1,77 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Parser;
+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.Core.Nodes
+{
+ /// <summary>
+ /// A {@link QuotedFieldQueryNode} represents phrase query. Example:
+ /// "life is great"
+ /// </summary>
+ public class QuotedFieldQueryNode : FieldQueryNode
+ {
+ /**
+ * @param field
+ * - field name
+ * @param text
+ * - value
+ * @param begin
+ * - position in the query string
+ * @param end
+ * - position in the query string
+ */
+ // LUCENENET specific overload for text string
+ public QuotedFieldQueryNode(string field, string text, int begin,
+ int end)
+ : this(field, text.ToCharSequence(), begin, end)
+ {
+ }
+
+ /**
+ * @param field
+ * - field name
+ * @param text
+ * - value
+ * @param begin
+ * - position in the query string
+ * @param end
+ * - position in the query string
+ */
+ public QuotedFieldQueryNode(string field, ICharSequence text, int begin,
+ int end)
+ : base(field, text, begin, end)
+ {
+ }
+
+
+ public override string ToQueryString(IEscapeQuerySyntax escaper)
+ {
+ if (IsDefaultField(this.field))
+ {
+ return "\"" + GetTermEscapeQuoted(escaper) + "\"";
+ }
+ else
+ {
+ return this.field + ":" + "\"" + GetTermEscapeQuoted(escaper) + "\"";
+ }
+ }
+
+
+ public override string ToString()
+ {
+ return "<quotedfield start='" + this.begin + "' end='" + this.end
+ + "' field='" + this.field + "' term='" + this.text + "'/>";
+ }
+
+ public override IQueryNode CloneTree()
+ {
+ QuotedFieldQueryNode clone = (QuotedFieldQueryNode)base.CloneTree();
+ // nothing to do here
+ return clone;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/RangeQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/RangeQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/RangeQueryNode.cs
new file mode 100644
index 0000000..6e64892
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/RangeQueryNode.cs
@@ -0,0 +1,32 @@
+\ufeffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// This interface should be implemented by a {@link QueryNode} that represents
+ /// some kind of range query.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public interface IRangeQueryNode<T> : IRangeQueryNode, IFieldableNode
+ where T : IFieldableNode /*IFieldValuePairQueryNode<?>*/
+ {
+ T LowerBound { get; }
+
+ T UpperBound { get; }
+
+ bool IsLowerInclusive { get; }
+
+ bool IsUpperInclusive { get; }
+ }
+
+ /// <summary>
+ /// LUCENENET specific interface for identifying a
+ /// RangeQueryNode without specifying its generic closing type
+ /// </summary>
+ public interface IRangeQueryNode
+ { }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs
new file mode 100644
index 0000000..98fd5c1
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/SlopQueryNode.cs
@@ -0,0 +1,116 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Core.Parser;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// A {@link SlopQueryNode} represents phrase query with a slop.
+ ///
+ /// From Lucene FAQ: Is there a way to use a proximity operator (like near or
+ /// within) with Lucene? There is a variable called slop that allows you to
+ /// perform NEAR/WITHIN-like queries. By default, slop is set to 0 so that only
+ /// exact phrases will match. When using TextParser you can use this syntax to
+ /// specify the slop: "doug cutting"~2 will find documents that contain
+ /// "doug cutting" as well as ones that contain "cutting doug".
+ /// </summary>
+ public class SlopQueryNode : QueryNodeImpl, IFieldableNode
+ {
+ private int value = 0;
+
+ /**
+ * @param query
+ * - QueryNode Tree with the phrase
+ * @param value
+ * - slop value
+ */
+ public SlopQueryNode(IQueryNode query, int value)
+ {
+ if (query == null)
+ {
+ throw new QueryNodeError(new MessageImpl(
+ QueryParserMessages.NODE_ACTION_NOT_SUPPORTED, "query", "null"));
+ }
+
+ this.value = value;
+ SetLeaf(false);
+ Allocate();
+ Add(query);
+ }
+
+ public IQueryNode GetChild()
+ {
+ return GetChildren()[0];
+ }
+
+ public int GetValue()
+ {
+ return this.value;
+ }
+
+ private string GetValueString()
+ {
+ float f = this.value;
+ if (f == (long)f)
+ return "" + (long)f;
+ else
+ return "" + f;
+
+ }
+
+
+ public override string ToString()
+ {
+ return "<slop value='" + GetValueString() + "'>" + "\n"
+ + GetChild().ToString() + "\n</slop>";
+ }
+
+
+ public override string ToQueryString(IEscapeQuerySyntax escapeSyntaxParser)
+ {
+ if (GetChild() == null)
+ return "";
+ return GetChild().ToQueryString(escapeSyntaxParser) + "~"
+ + GetValueString();
+ }
+
+ public override IQueryNode CloneTree()
+ {
+ SlopQueryNode clone = (SlopQueryNode)base.CloneTree();
+
+ clone.value = this.value;
+
+ return clone;
+ }
+
+ public virtual string Field
+ {
+ get
+ {
+ IQueryNode child = GetChild();
+
+ if (child is IFieldableNode)
+ {
+ return ((IFieldableNode)child).Field;
+ }
+
+ return null;
+ }
+ set
+ {
+ IQueryNode child = GetChild();
+
+ if (child is IFieldableNode)
+ {
+ ((IFieldableNode)child).Field = value;
+ }
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TextableQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TextableQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TextableQueryNode.cs
new file mode 100644
index 0000000..317e060
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TextableQueryNode.cs
@@ -0,0 +1,17 @@
+\ufeffusing Lucene.Net.Support;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// Interface for a node that has text as a {@link CharSequence}
+ /// </summary>
+ public interface ITextableQueryNode
+ {
+ ICharSequence Text { get; set; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TokenizedPhraseQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TokenizedPhraseQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TokenizedPhraseQueryNode.cs
new file mode 100644
index 0000000..4cb5452
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/TokenizedPhraseQueryNode.cs
@@ -0,0 +1,103 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Parser;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// A {@link TokenizedPhraseQueryNode} represents a node created by a code that
+ /// tokenizes/lemmatizes/analyzes.
+ /// </summary>
+ public class TokenizedPhraseQueryNode : QueryNodeImpl, IFieldableNode
+ {
+ public TokenizedPhraseQueryNode()
+ {
+ SetLeaf(false);
+ Allocate();
+ }
+
+
+ public override string ToString()
+ {
+ if (GetChildren() == null || GetChildren().Count == 0)
+ return "<tokenizedphrase/>";
+ StringBuilder sb = new StringBuilder();
+ sb.Append("<tokenizedtphrase>");
+ foreach (IQueryNode child in GetChildren())
+ {
+ sb.Append("\n");
+ sb.Append(child.ToString());
+ }
+ sb.Append("\n</tokenizedphrase>");
+ return sb.ToString();
+ }
+
+ // This text representation is not re-parseable
+
+ public override string ToQueryString(IEscapeQuerySyntax escapeSyntaxParser)
+ {
+ if (GetChildren() == null || GetChildren().Count == 0)
+ return "";
+
+ StringBuilder sb = new StringBuilder();
+ string filler = "";
+ foreach (IQueryNode child in GetChildren())
+ {
+ sb.Append(filler).Append(child.ToQueryString(escapeSyntaxParser));
+ filler = ",";
+ }
+
+ return "[TP[" + sb.ToString() + "]]";
+ }
+
+ public override IQueryNode CloneTree()
+ {
+ TokenizedPhraseQueryNode clone = (TokenizedPhraseQueryNode)base
+ .CloneTree();
+
+ // nothing to do
+
+ return clone;
+ }
+
+ public string Field
+ {
+ get
+ {
+ IList<IQueryNode> children = GetChildren();
+
+ if (children == null || children.Count == 0)
+ {
+ return null;
+
+ }
+ else
+ {
+ return ((IFieldableNode)children[0]).Field;
+ }
+ }
+ set
+ {
+ IList<IQueryNode> children = GetChildren();
+
+ if (children != null)
+ {
+
+ foreach (IQueryNode child in GetChildren())
+ {
+
+ if (child is IFieldableNode)
+ {
+ ((IFieldableNode)child).Field = value;
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ValueQueryNode.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ValueQueryNode.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ValueQueryNode.cs
new file mode 100644
index 0000000..ee0dbd22
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Nodes/ValueQueryNode.cs
@@ -0,0 +1,18 @@
+\ufeffusing System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Nodes
+{
+ /// <summary>
+ /// This interface should be implemented by {@link QueryNode} that holds an
+ /// arbitrary value.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ public interface IValueQueryNode<T> : IQueryNode
+ {
+ T Value { get; set; }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Parser/EscapeQuerySyntax.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Parser/EscapeQuerySyntax.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Parser/EscapeQuerySyntax.cs
new file mode 100644
index 0000000..d0e6803
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Parser/EscapeQuerySyntax.cs
@@ -0,0 +1,39 @@
+\ufeffusing 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.Core.Parser
+{
+ /// <summary>
+ /// A parser needs to implement {@link EscapeQuerySyntax} to allow the QueryNode
+ /// to escape the queries, when the toQueryString method is called.
+ /// </summary>
+ public interface IEscapeQuerySyntax
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="text"> text to be escaped</param>
+ /// <param name="locale">locale for the current query</param>
+ /// <param name="type">select the type of escape operation to use</param>
+ /// <returns>escaped text</returns>
+ ICharSequence Escape(ICharSequence text, CultureInfo locale, EscapeQuerySyntax.Type type);
+ }
+
+ public static class EscapeQuerySyntax
+ {
+ /// <summary>
+ /// Type of escaping: String for escaping syntax,
+ /// NORMAL for escaping reserved words (like AND) in terms
+ /// </summary>
+ public enum Type
+ {
+ STRING,
+ NORMAL
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Parser/SyntaxParser.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Parser/SyntaxParser.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Parser/SyntaxParser.cs
new file mode 100644
index 0000000..387019d
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Parser/SyntaxParser.cs
@@ -0,0 +1,23 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Parser
+{
+ /// <summary>
+ /// A parser needs to implement {@link SyntaxParser} interface
+ /// </summary>
+ public interface ISyntaxParser
+ {
+ /// <summary>
+ ///
+ /// </summary>
+ /// <param name="query">query data to be parsed</param>
+ /// <param name="field">default field name</param>
+ /// <returns>QueryNode tree</returns>
+ IQueryNode Parse(string query, string field);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Processors/NoChildOptimizationQueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Processors/NoChildOptimizationQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/NoChildOptimizationQueryNodeProcessor.cs
new file mode 100644
index 0000000..862ad1f
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/NoChildOptimizationQueryNodeProcessor.cs
@@ -0,0 +1,73 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Processors
+{
+ /// <summary>
+ /// A {@link NoChildOptimizationQueryNodeProcessor} removes every
+ /// BooleanQueryNode, BoostQueryNode, TokenizedPhraseQueryNode or
+ /// ModifierQueryNode that do not have a valid children.
+ /// <para>
+ /// Example: When the children of these nodes are removed for any reason then the
+ /// nodes may become invalid.
+ /// </para>
+ /// </summary>
+ public class NoChildOptimizationQueryNodeProcessor : QueryNodeProcessorImpl
+ {
+ public NoChildOptimizationQueryNodeProcessor()
+ {
+ // empty constructor
+ }
+
+
+ protected override IQueryNode PostProcessNode(IQueryNode node)
+ {
+
+ if (node is BooleanQueryNode || node is BoostQueryNode
+ || node is TokenizedPhraseQueryNode
+ || node is ModifierQueryNode)
+ {
+
+ IList<IQueryNode> children = node.GetChildren();
+
+ if (children != null && children.Count > 0)
+ {
+
+ foreach (IQueryNode child in children)
+ {
+
+ if (!(child is DeletedQueryNode))
+ {
+ return node;
+ }
+
+ }
+
+ }
+
+ return new MatchNoDocsQueryNode();
+
+ }
+
+ 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/Core/Processors/QueryNodeProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessor.cs
new file mode 100644
index 0000000..df3a851
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessor.cs
@@ -0,0 +1,61 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Processors
+{
+ /// <summary>
+ /// A {@link QueryNodeProcessor} is an interface for classes that process a
+ /// {@link QueryNode} tree.
+ /// <para>
+ /// The implementor of this class should perform some operation on a query node
+ /// tree and return the same or another query node tree.
+ /// </para>
+ /// <para>
+ /// It also may carry a {@link QueryConfigHandler} object that contains
+ /// configuration about the query represented by the query tree or the
+ /// collection/index where it's intended to be executed.
+ /// </para>
+ /// <para>
+ /// In case there is any {@link QueryConfigHandler} associated to the query tree
+ /// to be processed, it should be set using
+ /// {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)} before
+ /// {@link QueryNodeProcessor#process(QueryNode)} is invoked.
+ /// </para>
+ /// </summary>
+ /// <seealso cref="IQueryNode"/>
+ /// <seealso cref="QueryNodeProcessor"/>
+ /// <seealso cref="QueryConfigHandler"/>
+ public interface IQueryNodeProcessor
+ {
+ /**
+ * Processes a query node tree. It may return the same or another query tree.
+ * I should never return <code>null</code>.
+ *
+ * @param queryTree
+ * tree root node
+ *
+ * @return the processed query tree
+ */
+ IQueryNode Process(IQueryNode queryTree);
+
+ /**
+ * Sets the {@link QueryConfigHandler} associated to the query tree.
+ */
+ void SetQueryConfigHandler(QueryConfigHandler queryConfigHandler);
+
+ /**
+ * Returns the {@link QueryConfigHandler} associated to the query tree if any,
+ * otherwise it returns <code>null</code>
+ *
+ * @return the {@link QueryConfigHandler} associated to the query tree if any,
+ * otherwise it returns <code>null</code>
+ */
+ QueryConfigHandler GetQueryConfigHandler();
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorImpl.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorImpl.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorImpl.cs
new file mode 100644
index 0000000..23aa179
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorImpl.cs
@@ -0,0 +1,202 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Processors
+{
+ public abstract class QueryNodeProcessorImpl : IQueryNodeProcessor
+ {
+ private List<ChildrenList> childrenListPool = new List<ChildrenList>();
+
+ private QueryConfigHandler queryConfig;
+
+ public QueryNodeProcessorImpl()
+ {
+ // empty constructor
+ }
+
+ public QueryNodeProcessorImpl(QueryConfigHandler queryConfigHandler)
+ {
+ this.queryConfig = queryConfigHandler;
+ }
+
+
+ public virtual IQueryNode Process(IQueryNode queryTree)
+ {
+ return ProcessIteration(queryTree);
+ }
+
+ private IQueryNode ProcessIteration(IQueryNode queryTree)
+ {
+ queryTree = PreProcessNode(queryTree);
+
+ ProcessChildren(queryTree);
+
+ queryTree = PostProcessNode(queryTree);
+
+ return queryTree;
+
+ }
+
+ /**
+ * This method is called every time a child is processed.
+ *
+ * @param queryTree
+ * the query node child to be processed
+ * @throws QueryNodeException
+ * if something goes wrong during the query node processing
+ */
+ protected virtual void ProcessChildren(IQueryNode queryTree)
+ {
+
+ IList<IQueryNode> children = queryTree.GetChildren();
+ ChildrenList newChildren;
+
+ if (children != null && children.Count > 0)
+ {
+
+ newChildren = AllocateChildrenList();
+
+ try
+ {
+
+ foreach (IQueryNode child in children)
+ {
+ var child2 = ProcessIteration(child);
+
+ if (child2 == null)
+ {
+ throw new NullReferenceException();
+
+ }
+
+ newChildren.Add(child2);
+
+ }
+
+ IList<IQueryNode> orderedChildrenList = SetChildrenOrder(newChildren);
+
+ queryTree.Set(orderedChildrenList);
+
+ }
+ finally
+ {
+ newChildren.beingUsed = false;
+ }
+
+ }
+
+ }
+
+ private ChildrenList AllocateChildrenList()
+ {
+ ChildrenList list = null;
+
+ foreach (ChildrenList auxList in this.childrenListPool)
+ {
+
+ if (!auxList.beingUsed)
+ {
+ list = auxList;
+ list.Clear();
+
+ break;
+
+ }
+
+ }
+
+ if (list == null)
+ {
+ list = new ChildrenList();
+ this.childrenListPool.Add(list);
+
+ }
+
+ list.beingUsed = true;
+
+ return list;
+
+ }
+
+ /**
+ * For reference about this method check:
+ * {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)}.
+ *
+ * @param queryConfigHandler
+ * the query configuration handler to be set.
+ *
+ * @see QueryNodeProcessor#getQueryConfigHandler()
+ * @see QueryConfigHandler
+ */
+
+ public virtual void SetQueryConfigHandler(QueryConfigHandler queryConfigHandler)
+ {
+ this.queryConfig = queryConfigHandler;
+ }
+
+ /**
+ * For reference about this method check:
+ * {@link QueryNodeProcessor#getQueryConfigHandler()}.
+ *
+ * @return QueryConfigHandler the query configuration handler to be set.
+ *
+ * @see QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)
+ * @see QueryConfigHandler
+ */
+ public virtual QueryConfigHandler GetQueryConfigHandler()
+ {
+ return this.queryConfig;
+ }
+
+ /**
+ * This method is invoked for every node when walking down the tree.
+ *
+ * @param node
+ * the query node to be pre-processed
+ *
+ * @return a query node
+ *
+ * @throws QueryNodeException
+ * if something goes wrong during the query node processing
+ */
+ protected abstract IQueryNode PreProcessNode(IQueryNode node);
+
+ /**
+ * This method is invoked for every node when walking up the tree.
+ *
+ * @param node
+ * node the query node to be post-processed
+ *
+ * @return a query node
+ *
+ * @throws QueryNodeException
+ * if something goes wrong during the query node processing
+ */
+ protected abstract IQueryNode PostProcessNode(IQueryNode node);
+
+ /**
+ * This method is invoked for every node that has at least on child. It's
+ * invoked right before {@link #postProcessNode(QueryNode)} is invoked.
+ *
+ * @param children
+ * the list containing all current node's children
+ *
+ * @return a new list containing all children that should be set to the
+ * current node
+ *
+ * @throws QueryNodeException
+ * if something goes wrong during the query node processing
+ */
+ protected abstract IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children);
+
+ private class ChildrenList : List<IQueryNode>
+ {
+ internal bool beingUsed;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorPipeline.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorPipeline.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorPipeline.cs
new file mode 100644
index 0000000..7ffdd1e
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/QueryNodeProcessorPipeline.cs
@@ -0,0 +1,425 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Config;
+using Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Collections;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Processors
+{
+ public class QueryNodeProcessorPipeline : IQueryNodeProcessor, IList<IQueryNodeProcessor>
+ {
+ //private LinkedList<IQueryNodeProcessor> processors = new LinkedList<IQueryNodeProcessor>();
+ private List<IQueryNodeProcessor> processors = new List<IQueryNodeProcessor>();
+
+ private QueryConfigHandler queryConfig;
+
+ /**
+ * Constructs an empty query node processor pipeline.
+ */
+ public QueryNodeProcessorPipeline()
+ {
+ // empty constructor
+ }
+
+ /**
+ * Constructs with a {@link QueryConfigHandler} object.
+ */
+ public QueryNodeProcessorPipeline(QueryConfigHandler queryConfigHandler)
+ {
+ this.queryConfig = queryConfigHandler;
+ }
+
+ /**
+ * For reference about this method check:
+ * {@link QueryNodeProcessor#getQueryConfigHandler()}.
+ *
+ * @return QueryConfigHandler the query configuration handler to be set.
+ *
+ * @see QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)
+ * @see QueryConfigHandler
+ */
+ public virtual QueryConfigHandler GetQueryConfigHandler()
+ {
+ return this.queryConfig;
+ }
+
+ /**
+ * For reference about this method check:
+ * {@link QueryNodeProcessor#process(QueryNode)}.
+ *
+ * @param queryTree the query node tree to be processed
+ *
+ * @throws QueryNodeException if something goes wrong during the query node
+ * processing
+ *
+ * @see QueryNode
+ */
+
+ public virtual IQueryNode Process(IQueryNode queryTree)
+ {
+
+ foreach (IQueryNodeProcessor processor in this.processors)
+ {
+ queryTree = processor.Process(queryTree);
+ }
+
+ return queryTree;
+
+ }
+
+ /**
+ * For reference about this method check:
+ * {@link QueryNodeProcessor#setQueryConfigHandler(QueryConfigHandler)}.
+ *
+ * @param queryConfigHandler the query configuration handler to be set.
+ *
+ * @see QueryNodeProcessor#getQueryConfigHandler()
+ * @see QueryConfigHandler
+ */
+
+ public virtual void SetQueryConfigHandler(QueryConfigHandler queryConfigHandler)
+ {
+ this.queryConfig = queryConfigHandler;
+
+ foreach (IQueryNodeProcessor processor in this.processors)
+ {
+ processor.SetQueryConfigHandler(this.queryConfig);
+ }
+
+ }
+
+ /**
+ * @see List#add(Object)
+ */
+
+ public virtual bool Add(IQueryNodeProcessor processor)
+ {
+ this.processors.Add(processor);
+ bool added = processors.Contains(processor);
+
+ if (added)
+ {
+ processor.SetQueryConfigHandler(this.queryConfig);
+ }
+
+ return added;
+
+ }
+
+ /**
+ * @see List#add(int, Object)
+ */
+
+ public virtual void Add(int index, IQueryNodeProcessor processor)
+ {
+ this.processors.Insert(index, processor);
+ processor.SetQueryConfigHandler(this.queryConfig);
+
+ }
+
+ // /**
+ // * @see List#addAll(Collection)
+ // */
+
+ //public virtual bool AddAll(Collection<? extends QueryNodeProcessor> c)
+ // {
+ // boolean anyAdded = this.processors.addAll(c);
+
+ // for (QueryNodeProcessor processor : c)
+ // {
+ // processor.setQueryConfigHandler(this.queryConfig);
+ // }
+
+ // return anyAdded;
+
+ // }
+
+ // /**
+ // * @see List#addAll(int, Collection)
+ // */
+ // @Override
+ //public boolean addAll(int index, Collection<? extends QueryNodeProcessor> c)
+ // {
+ // boolean anyAdded = this.processors.addAll(index, c);
+
+ // for (QueryNodeProcessor processor : c)
+ // {
+ // processor.setQueryConfigHandler(this.queryConfig);
+ // }
+
+ // return anyAdded;
+
+ // }
+
+ /**
+ * @see List#clear()
+ */
+
+ public virtual void Clear()
+ {
+ this.processors.Clear();
+ }
+
+ /**
+ * @see List#contains(Object)
+ */
+
+ public virtual bool Contains(object o)
+ {
+ return this.processors.Contains(o);
+ }
+
+ // /**
+ // * @see List#containsAll(Collection)
+ // */
+ // @Override
+ //public boolean containsAll(Collection<?> c)
+ // {
+ // return this.processors.containsAll(c);
+ // }
+
+ // /**
+ // * @see List#get(int)
+ // */
+ // @Override
+ //public QueryNodeProcessor Get(int index)
+ // {
+ // return this.processors.get(index);
+ // }
+
+ public virtual IQueryNodeProcessor this[int index]
+ {
+ get
+ {
+ return this.processors[index];
+ }
+ set
+ {
+ IQueryNodeProcessor oldProcessor = this.processors[index];
+ this.processors[index] = value;
+
+ if (oldProcessor != value)
+ {
+ value.SetQueryConfigHandler(this.queryConfig);
+ }
+
+ //return oldProcessor;
+ }
+ }
+
+ /**
+ * @see List#indexOf(Object)
+ */
+
+ public virtual int IndexOf(object o)
+ {
+ return this.processors.IndexOf(o as IQueryNodeProcessor);
+ }
+
+ public virtual int IndexOf(IQueryNodeProcessor o)
+ {
+ return this.processors.IndexOf(o);
+ }
+
+ // /**
+ // * @see List#isEmpty()
+ // */
+ // @Override
+ //public boolean isEmpty()
+ // {
+ // return this.processors.isEmpty();
+ // }
+
+ // /**
+ // * @see List#iterator()
+ // */
+ // @Override
+ //public Iterator<QueryNodeProcessor> iterator()
+ // {
+ // return this.processors.iterator();
+ // }
+
+ public virtual IEnumerator<IQueryNodeProcessor> GetEnumerator()
+ {
+ return this.processors.GetEnumerator();
+ }
+
+ // /**
+ // * @see List#lastIndexOf(Object)
+ // */
+ // @Override
+ //public int lastIndexOf(Object o)
+ // {
+ // return this.processors.lastIndexOf(o);
+ // }
+
+ // /**
+ // * @see List#listIterator()
+ // */
+ // @Override
+ //public ListIterator<QueryNodeProcessor> listIterator()
+ // {
+ // return this.processors.listIterator();
+ // }
+
+ // /**
+ // * @see List#listIterator(int)
+ // */
+ // @Override
+ //public ListIterator<QueryNodeProcessor> listIterator(int index)
+ // {
+ // return this.processors.listIterator(index);
+ // }
+
+ /**
+ * @see List#remove(Object)
+ */
+
+ public bool Remove(object o)
+ {
+ return this.processors.Remove(o as IQueryNodeProcessor);
+ }
+
+ public virtual bool Remove(IQueryNodeProcessor o)
+ {
+ return this.processors.Remove(o);
+ }
+
+ // /**
+ // * @see List#remove(int)
+ // */
+ // @Override
+ //public QueryNodeProcessor remove(int index)
+ // {
+ // return this.processors.remove(index);
+ // }
+
+ public virtual void RemoveAt(int index)
+ {
+ this.processors.RemoveAt(index);
+ }
+
+ // /**
+ // * @see List#removeAll(Collection)
+ // */
+ // @Override
+ //public boolean removeAll(Collection<?> c)
+ // {
+ // return this.processors.removeAll(c);
+ // }
+
+ public virtual void RemoveRange(int index, int count)
+ {
+ this.processors.RemoveRange(index, count);
+ }
+
+ // /**
+ // * @see List#retainAll(Collection)
+ // */
+ // @Override
+ //public boolean retainAll(Collection<?> c)
+ // {
+ // return this.processors.retainAll(c);
+ // }
+
+ /**
+ * @see List#set(int, Object)
+ */
+
+ public virtual IQueryNodeProcessor Set(int index, IQueryNodeProcessor processor)
+ {
+ IQueryNodeProcessor oldProcessor = this.processors[index];
+ this.processors[index] = processor;
+
+ if (oldProcessor != processor)
+ {
+ processor.SetQueryConfigHandler(this.queryConfig);
+ }
+
+ return oldProcessor;
+
+ }
+
+ // /**
+ // * @see List#size()
+ // */
+ // @Override
+ //public int size()
+ // {
+ // return this.processors.size();
+ // }
+
+ public int Count
+ {
+ get { return this.processors.Count; }
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ // /**
+ // * @see List#subList(int, int)
+ // */
+ // @Override
+ //public List<QueryNodeProcessor> subList(int fromIndex, int toIndex)
+ // {
+ // return this.processors.subList(fromIndex, toIndex);
+ // }
+
+ public virtual List<IQueryNodeProcessor> GetRange(int index, int count)
+ {
+ return this.processors.GetRange(index, count);
+ }
+
+ public void Insert(int index, IQueryNodeProcessor item)
+ {
+ this.processors.Insert(index, item);
+ }
+
+ void ICollection<IQueryNodeProcessor>.Add(IQueryNodeProcessor item)
+ {
+ this.processors.Add(item);
+ }
+
+ public bool Contains(IQueryNodeProcessor item)
+ {
+ return this.processors.Contains(item);
+ }
+
+ public void CopyTo(IQueryNodeProcessor[] array, int arrayIndex)
+ {
+ this.processors.CopyTo(array, arrayIndex);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ // /**
+ // * @see List#toArray(Object[])
+ // */
+ // @Override
+ //public <T> T[] toArray(T[] array)
+ // {
+ // return this.processors.toArray(array);
+ // }
+
+ // /**
+ // * @see List#toArray()
+ // */
+ // @Override
+ //public Object[] toArray()
+ // {
+ // return this.processors.toArray();
+ // }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/Processors/RemoveDeletedQueryNodesProcessor.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/Processors/RemoveDeletedQueryNodesProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/RemoveDeletedQueryNodesProcessor.cs
new file mode 100644
index 0000000..95214f9
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/Processors/RemoveDeletedQueryNodesProcessor.cs
@@ -0,0 +1,102 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Nodes;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core.Processors
+{
+ /// <summary>
+ /// A {@link QueryNodeProcessorPipeline} class removes every instance of
+ /// {@link DeletedQueryNode} from a query node tree. If the resulting root node
+ /// is a {@link DeletedQueryNode}, {@link MatchNoDocsQueryNode} is returned.
+ /// </summary>
+ public class RemoveDeletedQueryNodesProcessor : QueryNodeProcessorImpl
+ {
+ public RemoveDeletedQueryNodesProcessor()
+ {
+ // empty constructor
+ }
+
+
+ public override IQueryNode Process(IQueryNode queryTree)
+ {
+ queryTree = base.Process(queryTree);
+
+ if (queryTree is DeletedQueryNode
+ && !(queryTree is MatchNoDocsQueryNode))
+ {
+
+ return new MatchNoDocsQueryNode();
+
+ }
+
+ return queryTree;
+
+ }
+
+
+ protected override IQueryNode PostProcessNode(IQueryNode node)
+ {
+
+ if (!node.IsLeaf())
+ {
+ IList<IQueryNode> children = node.GetChildren();
+ bool removeBoolean = false;
+
+ if (children == null || children.Count == 0)
+ {
+ removeBoolean = true;
+
+ }
+ else
+ {
+ removeBoolean = true;
+
+ for (IEnumerator<IQueryNode> it = children.GetEnumerator(); it.MoveNext();)
+ {
+
+ if (!(it.Current is DeletedQueryNode))
+ {
+ removeBoolean = false;
+ break;
+
+ }
+
+ }
+
+ }
+
+ if (removeBoolean)
+ {
+ return new DeletedQueryNode();
+ }
+
+ }
+
+ return node;
+ }
+
+
+ protected override IList<IQueryNode> SetChildrenOrder(IList<IQueryNode> children)
+ {
+ for (int i = 0; i < children.Count; i++)
+ {
+
+ if (children[i] is DeletedQueryNode)
+ {
+ children.RemoveAt(i--);
+ }
+
+ }
+
+ return children;
+ }
+
+ protected override IQueryNode PreProcessNode(IQueryNode node)
+ {
+ return node;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs
new file mode 100644
index 0000000..e92e399
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeError.cs
@@ -0,0 +1,64 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core
+{
+ /// <summary>
+ /// Error class with NLS support
+ /// </summary>
+ /// <seealso cref="Messages.NLS"/>
+ /// <seealso cref="Messages.Message"/>
+ [Serializable]
+ public class QueryNodeError : Exception, INLSException
+ {
+ private IMessage message;
+
+ /**
+ * @param message
+ * - NLS Message Object
+ */
+ public QueryNodeError(IMessage message)
+ : base(message.Key)
+ {
+ this.message = message;
+
+ }
+
+ /**
+ * @param throwable
+ * - @see java.lang.Error
+ */
+ public QueryNodeError(Exception throwable)
+ : base(throwable.Message, throwable)
+ {
+ }
+
+ /**
+ * @param message
+ * - NLS Message Object
+ * @param throwable
+ * - @see java.lang.Error
+ */
+ public QueryNodeError(IMessage message, Exception throwable)
+ : base(message.Key, throwable)
+ {
+ this.message = message;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.lucene.messages.NLSException#getMessageObject()
+ */
+
+ public virtual IMessage MessageObject
+ {
+ get { return this.message; }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs
new file mode 100644
index 0000000..881f738
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeException.cs
@@ -0,0 +1,75 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core
+{
+ /// <summary>
+ /// This exception should be thrown if something wrong happens when dealing with
+ /// {@link QueryNode}s.
+ /// <para>
+ /// It also supports NLS messages.
+ /// </para>
+ /// </summary>
+ /// <seealso cref="Message"/>
+ /// <seealso cref="NLS"/>
+ /// <seealso cref="NLSException"/>
+ /// <seealso cref="IQueryNode"/>
+ [Serializable]
+ public class QueryNodeException : Exception, INLSException
+ {
+ protected IMessage message = new MessageImpl(QueryParserMessages.EMPTY_MESSAGE);
+
+ public QueryNodeException(IMessage message)
+ : base(message.Key)
+ {
+ this.message = message;
+
+ }
+
+ public QueryNodeException(Exception throwable)
+ : base(throwable.Message, throwable)
+ {
+ }
+
+ public QueryNodeException(IMessage message, Exception throwable)
+ : base(message.Key, throwable)
+ {
+ this.message = message;
+ }
+
+
+ public virtual IMessage MessageObject
+ {
+ get { return this.message; }
+ }
+
+
+ public override string Message
+ {
+ get { return GetLocalizedMessage(); }
+ }
+
+
+ public string GetLocalizedMessage()
+ {
+ return GetLocalizedMessage(CultureInfo.InvariantCulture);
+ }
+
+ public string GetLocalizedMessage(CultureInfo locale)
+ {
+ return this.message.GetLocalizedMessage(locale);
+ }
+
+
+ public override string ToString()
+ {
+ return this.message.Key + ": " + GetLocalizedMessage();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/c83be6be/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs
new file mode 100644
index 0000000..c6cd651
--- /dev/null
+++ b/src/Lucene.Net.QueryParser/Flexible/Core/QueryNodeParseException.cs
@@ -0,0 +1,117 @@
+\ufeffusing Lucene.Net.QueryParsers.Flexible.Core.Messages;
+using Lucene.Net.QueryParsers.Flexible.Messages;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Lucene.Net.QueryParsers.Flexible.Core
+{
+ /// <summary>
+ /// This should be thrown when an exception happens during the query parsing from
+ /// string to the query node tree.
+ /// </summary>
+ /// <seealso cref="QueryNodeException"/>
+ /// <seealso cref="ISyntaxParser"/>
+ /// <seealso cref="IQueryNode"/>
+ [Serializable]
+ public class QueryNodeParseException : QueryNodeException
+ {
+ private string query;
+
+ private int beginColumn = -1;
+
+ private int beginLine = -1;
+
+ private string errorToken = "";
+
+ public QueryNodeParseException(IMessage message)
+ : base(message)
+ {
+ }
+
+ public QueryNodeParseException(Exception throwable)
+ : base(throwable)
+ {
+ }
+
+ public QueryNodeParseException(IMessage message, Exception throwable)
+ : base(message, throwable)
+ {
+ }
+
+ public void SetQuery(string query)
+ {
+ this.query = query;
+ this.message = new MessageImpl(
+ QueryParserMessages.INVALID_SYNTAX_CANNOT_PARSE, query, "");
+ }
+
+ public string GetQuery()
+ {
+ return this.query;
+ }
+
+ /**
+ * @param errorToken
+ * the errorToken in the query
+ */
+ protected void SetErrorToken(string errorToken)
+ {
+ this.errorToken = errorToken;
+ }
+
+ public string GetErrorToken()
+ {
+ return this.errorToken;
+ }
+
+ public void SetNonLocalizedMessage(IMessage message)
+ {
+ this.message = message;
+ }
+
+ /**
+ * For EndOfLine and EndOfFile ("<EOF>") parsing problems the last char in the
+ * string is returned For the case where the parser is not able to figure out
+ * the line and column number -1 will be returned
+ *
+ * @return line where the problem was found
+ */
+ public int GetBeginLine()
+ {
+ return this.beginLine;
+ }
+
+ /**
+ * For EndOfLine and EndOfFile ("<EOF>") parsing problems the last char in the
+ * string is returned For the case where the parser is not able to figure out
+ * the line and column number -1 will be returned
+ *
+ * @return column of the first char where the problem was found
+ */
+ public int GetBeginColumn()
+ {
+ return this.beginColumn;
+ }
+
+ /**
+ * @param beginLine
+ * the beginLine to set
+ */
+ protected void SetBeginLine(int beginLine)
+ {
+ this.beginLine = beginLine;
+ }
+
+ /**
+ * @param beginColumn
+ * the beginColumn to set
+ */
+ protected void SetBeginColumn(int beginColumn)
+ {
+ this.beginColumn = beginColumn;
+ }
+ }
+}