You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by jo...@apache.org on 2017/11/30 09:20:05 UTC
[21/33] tinkerpop git commit: Context parameters support
Context parameters support
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/69a710c8
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/69a710c8
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/69a710c8
Branch: refs/heads/TINKERPOP-1827
Commit: 69a710c813f4347365d8938df8f4b619ef531538
Parents: ee33016
Author: Jorge Bay Gondra <jo...@gmail.com>
Authored: Tue Oct 31 17:33:03 2017 +0100
Committer: Jorge Bay Gondra <jo...@gmail.com>
Committed: Thu Nov 30 10:00:08 2017 +0100
----------------------------------------------------------------------
.../Process/Traversal/Instruction.cs | 4 +-
.../Gherkin/CommonSteps.cs | 113 ++++++++++-----
.../Gherkin/GherkinTestRunner.cs | 32 +----
.../Gherkin/ScenarioData.cs | 59 ++++++++
.../ContextBasedParameter.cs | 84 +++++++++++
.../TraversalEvaluation/ITokenParameter.cs | 3 +-
.../TraversalEvaluation/NumericParameter.cs | 8 +-
.../StaticTraversalParameter.cs | 4 +-
.../TraversalEvaluation/StringParameter.cs | 3 +-
.../TraversalEnumParameter.cs | 2 +-
.../TraversalEvaluationTests.cs | 46 +++---
.../TraversalEvaluation/TraversalParser.cs | 143 +++++++++----------
.../TraversalPredicateParameter.cs | 5 +-
13 files changed, 330 insertions(+), 176 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
index 195b7bf..a9163be 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/Instruction.cs
@@ -28,6 +28,8 @@ namespace Gremlin.Net.Process.Traversal
/// </summary>
public class Instruction
{
+ private static readonly object[] EmptyArgs = new object[0];
+
/// <summary>
/// Initializes a new instance of the <see cref="Instruction" /> class.
/// </summary>
@@ -36,7 +38,7 @@ namespace Gremlin.Net.Process.Traversal
public Instruction(string operatorName, params dynamic[] arguments)
{
OperatorName = operatorName;
- Arguments = arguments;
+ Arguments = arguments ?? EmptyArgs;
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
index 16aef9d..235f1ba 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/CommonSteps.cs
@@ -25,15 +25,12 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
-using System.Net.Http.Headers;
-using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
using Gherkin.Ast;
using Gremlin.Net.IntegrationTest.Gherkin.Attributes;
using Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation;
using Gremlin.Net.Process.Traversal;
using Gremlin.Net.Structure;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using Xunit;
namespace Gremlin.Net.IntegrationTest.Gherkin
@@ -41,14 +38,26 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
internal class GeneralDefinitions : StepDefinition
{
private GraphTraversalSource _g;
+ private readonly IDictionary<string, object> _parameters = new Dictionary<string, object>();
private dynamic _traversal;
private object[] _result;
- private static readonly IDictionary<string, Func<GraphTraversalSource, ITraversal>> FixedTranslations =
- new Dictionary<string, Func<GraphTraversalSource, ITraversal>>
+ private static readonly IDictionary<Regex, Func<string, object>> Parsers =
+ new Dictionary<string, Func<string, object>>
{
- { "g.V().has(\"no\").count()", g => g.V().Has("no").Count() }
- };
+ {@"d\[(\d+)\]", x => Convert.ToInt64(x)},
+ {@"d\[(\d+(?:\.\d+)?)\]", x => Convert.ToDouble(x)},
+ {@"v\[(.+)\]", ToVertex},
+ {@"v\[(.+)\]\.id", x => ToVertex(x).Id},
+ {@"v\[(.+)\]\.sid", x => ToVertex(x).Id.ToString()},
+ {@"e\[(.+)\]", ToEdge},
+ {@"e\[(.+)\].id", s => ToEdge(s).Id},
+ {@"e\[(.+)\].sid", s => ToEdge(s).Id.ToString()},
+ {@"p\[(.+)\]", ToPath},
+ {@"l\[(.+)\]", ToList},
+ {@"s\[(.+)\]", ToSet},
+ {@"m\[(.+)\]", ToMap},
+ }.ToDictionary(kv => new Regex("^" + kv.Key + "$", RegexOptions.Compiled), kv => kv.Value);
[Given("the modern graph")]
public void ChooseModernGraph()
@@ -57,6 +66,22 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
_g = new Graph().Traversal().WithRemote(connection);
}
+ [Given("using the parameter (\\w+) defined as \"(.*)\"")]
+ public void UsingParameter(string name, string value)
+ {
+ _parameters.Add(name, ParseValue(value));
+ }
+
+ [Given("the traversal of")]
+ public void TranslateTraversal(string traversalText)
+ {
+ if (_g == null)
+ {
+ throw new InvalidOperationException("g should be a traversal source");
+ }
+ _traversal = TraversalParser.GetTraversal(traversalText, _g, _parameters);
+ }
+
[When("iterated to list")]
public void IterateToList()
{
@@ -78,16 +103,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
_result = _traversal.Next();
}
- [Given("the traversal of")]
- public void TranslateTraversal(string traversalText)
- {
- if (_g == null)
- {
- throw new InvalidOperationException("g should be a traversal source");
- }
- _traversal = TraversalParser.GetTraversal(traversalText, _g);
- }
-
[Then("the result should be (\\w+)")]
public void AssertResult(string characterizedAs, DataTable table)
{
@@ -104,9 +119,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{
var row = rows[i];
var cells = row.Cells.ToArray();
- var typeName = cells[0].Value;
- var expectedValue = ConvertExpectedToType(typeName, cells[1].Value);
- var resultItem = ConvertResultItem(typeName, _result[i]);
+ var expectedValue = ParseValue(cells[0].Value);
+ var resultItem = ConvertResultItem(null, _result[i]);
Assert.Equal(expectedValue, resultItem);
}
break;
@@ -116,10 +130,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
foreach (var row in rows)
{
var cells = row.Cells.ToArray();
- var typeName = cells[0].Value;
- var expectedValue = ConvertExpectedToType(typeName, cells[1].Value);
+ var expectedValue = ParseValue(cells[0].Value);
// Convert all the values in the result to the type
- var convertedResult = _result.Select(item => ConvertResultItem(typeName, item));
+ var convertedResult = _result.Select(item => ConvertResultItem(null, item));
Assert.Contains(expectedValue, convertedResult);
}
break;
@@ -149,19 +162,51 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
return result;
}
- private object ConvertExpectedToType(string typeName, string stringValue)
+ private static IDictionary ToMap(string arg)
+ {
+ throw new NotImplementedException();
+ }
+
+ private static ICollection ToSet(string arg)
+ {
+ throw new NotImplementedException();
+ }
+
+ private static IList ToList(string arg)
+ {
+ throw new NotImplementedException();
+ }
+
+ private static Vertex ToVertex(string name)
{
- switch (typeName)
+ return ScenarioData.Instance.ModernVertices[name];
+ }
+
+ private static Edge ToEdge(string s)
+ {
+ throw new NotImplementedException();
+ }
+
+ private static Path ToPath(string arg)
+ {
+ throw new NotImplementedException();
+ }
+
+ private static object ParseValue(string stringValue)
+ {
+ Func<string, object> parser = null;
+ string extractedValue = null;
+ foreach (var kv in Parsers)
{
- case "numeric":
- return Convert.ToInt64(stringValue);
- case "string":
- return stringValue;
- case "map":
- IDictionary<string, JToken> jsonObject = JObject.Parse(stringValue);
- return jsonObject.ToDictionary(item => item.Key, item => item.Value.ToString());
+ var match = kv.Key.Match(stringValue);
+ if (match.Success)
+ {
+ parser = kv.Value;
+ extractedValue = match.Groups[1].Value;
+ break;
+ }
}
- throw new NotSupportedException($"Data table result with subtype of {typeName} not supported");
+ return parser != null ? parser(extractedValue) : stringValue;
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index 7523b0b..d850d08 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -307,7 +307,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
var parser = new Parser();
WriteOutput("Parsing " + gherkinFile);
var doc = parser.Parse(gherkinFile);
- yield return doc.Feature;
+ yield return doc.Feature;
}
}
@@ -332,35 +332,5 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
}
return rootDir.FullName;
}
-
- private void PrintGherkin()
- {
- var gherkinFile = "/Users/jorge/workspace/temp/count.feature";
- var parser = new Parser();
- GherkinDocument doc = parser.Parse(gherkinFile);
- foreach (var scenario in doc.Feature.Children)
- {
- WriteOutput("--------");
- WriteOutput("Scenario: " + scenario.Name);
- foreach (var step in scenario.Steps)
- {
- WriteOutput(" Step");
- WriteOutput(" Keyword: " + step.Keyword);
- WriteOutput(" Text: " + step.Text);
- WriteOutput(" Argument: " + step.Argument);
- if (step.Argument is DocString)
- {
- WriteOutput(" " + ((DocString)step.Argument).Content);
- }
- if (step.Argument is DataTable)
- {
- foreach (var row in ((DataTable)step.Argument).Rows)
- {
- WriteOutput(" Row: " + string.Join(", ", row.Cells.Select(x => x.Value)));
- }
- }
- }
- }
- }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
new file mode 100644
index 0000000..c45ed12
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/ScenarioData.cs
@@ -0,0 +1,59 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Gremlin.Net.IntegrationTest.Process.Traversal.DriverRemoteConnection;
+using Gremlin.Net.Process.Traversal;
+using Gremlin.Net.Structure;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin
+{
+ public class ScenarioData
+ {
+ private static readonly Lazy<ScenarioData> Lazy = new Lazy<ScenarioData>(Load);
+
+ public static ScenarioData Instance => Lazy.Value;
+
+ public IDictionary<string, Vertex> ModernVertices { get; }
+
+ public IDictionary<string, Edge> ModernEdges { get; }
+
+ private ScenarioData(IDictionary<string, Vertex> modernVertices, IDictionary<string, Edge> modernEdges)
+ {
+ ModernVertices = modernVertices;
+ ModernEdges = modernEdges;
+ }
+
+ private static ScenarioData Load()
+ {
+ var connectionFactory = new RemoteConnectionFactory();
+ var g = new Graph().Traversal().WithRemote(connectionFactory.CreateRemoteConnection());
+ //TODO: Remove workaround once Group() is fixed TINKERPOP-1752
+ var vertices = g.V().ToList().ToDictionary(v => g.V(v.Id).Values<string>("name").Next(), v => v);
+ connectionFactory.Dispose();
+ return new ScenarioData(vertices, null);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ContextBasedParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ContextBasedParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ContextBasedParameter.cs
new file mode 100644
index 0000000..4f837d4
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ContextBasedParameter.cs
@@ -0,0 +1,84 @@
+#region License
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+ public class ContextBasedParameter : ITokenParameter, IEquatable<ContextBasedParameter>
+ {
+ public bool Equals(ContextBasedParameter other)
+ {
+ return string.Equals(_name, other._name) && Equals(_value, other._value);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != GetType()) return false;
+ return Equals((ContextBasedParameter) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return ((_name != null ? _name.GetHashCode() : 0) * 397) ^ (_value != null ? _value.GetHashCode() : 0);
+ }
+ }
+
+ private readonly string _name;
+ private object _value;
+
+ public ContextBasedParameter(string name)
+ {
+ _name = name;
+ }
+
+ private void SetValue(IDictionary<string, object> parameterValues)
+ {
+ if (parameterValues == null || !parameterValues.TryGetValue(_name, out var value))
+ {
+ throw new InvalidOperationException($"Parameter \"{_name}\" was not provided");
+ }
+ _value = value;
+ }
+
+ public object GetValue(IDictionary<string, object> contextParameterValues)
+ {
+ SetValue(contextParameterValues);
+ return _value;
+ }
+
+ public Type GetParameterType()
+ {
+ if (_value == null)
+ {
+ throw new NullReferenceException($"Value for parameter \"{_name}\" was not set");
+ }
+ return _value.GetType();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
index 5c8197f..9b06e80 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
@@ -22,6 +22,7 @@
#endregion
using System;
+using System.Collections.Generic;
namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
@@ -30,7 +31,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
/// <summary>
/// Gets the value of the parameter
/// </summary>
- object GetValue();
+ object GetValue(IDictionary<string, object> contextParameterValues);
/// <summary>
/// Gets the type of the parameter
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
index 378680c..7428cc2 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
@@ -22,6 +22,7 @@
#endregion
using System;
+using System.Collections.Generic;
namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
@@ -57,7 +58,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
return $"NumericParameter<{typeof(T).Name}>({Value})";
}
- public object GetValue()
+ public object GetValue(IDictionary<string, object> contextParameterValues)
{
return Value;
}
@@ -74,5 +75,10 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
return new NumericParameter<TType>(value);
}
+
+ public static NumericParameter<long> CreateLong(string value)
+ {
+ return NumericParameter.Create(Convert.ToInt64(value.Substring(0, value.Length - 1)));
+ }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
index dca691b..dd38dca 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
@@ -50,9 +50,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
return Tokens != null ? Tokens.GetHashCode() : 0;
}
- public object GetValue()
+ public object GetValue(IDictionary<string, object> contextParameterValues)
{
- return TraversalParser.GetTraversalFromTokens(Tokens, null, _traversalText);
+ return TraversalParser.GetTraversalFromTokens(Tokens, null, contextParameterValues, _traversalText);
}
public Type GetParameterType()
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
index 82f6cd9..430c2d2 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
@@ -22,6 +22,7 @@
#endregion
using System;
+using System.Collections.Generic;
namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
@@ -66,7 +67,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
return $"{GetType().Name}({Value})";
}
- public object GetValue()
+ public object GetValue(IDictionary<string, object> contextParameterValues)
{
return Value;
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEnumParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEnumParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEnumParameter.cs
index 663928a..c99fc95 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEnumParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEnumParameter.cs
@@ -85,7 +85,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
return _text.GetHashCode();
}
- public object GetValue()
+ public object GetValue(IDictionary<string, object> contextParameterValues)
{
return _value;
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
index 9cbceb9..be5f444 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
@@ -31,13 +31,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
public class TraversalEvaluationTests
{
- private readonly ITestOutputHelper _output;
-
- public TraversalEvaluationTests(ITestOutputHelper output)
- {
- _output = output;
- }
-
[Fact]
public void Traversal_Parser_Should_Parse_Into_Tokens()
{
@@ -48,6 +41,12 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
new[] {new Token("values", new StringParameter("name"))}),
Tuple.Create("g.V().constant(123l)",
new[] {new Token("constant", new[] {NumericParameter.Create(123L)})}),
+ Tuple.Create("g.V().constant(123)",
+ new[] {new Token("constant", new[] {NumericParameter.Create(123)})}),
+ Tuple.Create("g.V().constant(123.1)",
+ new[] {new Token("constant", new[] {NumericParameter.Create(123.1)})}),
+ Tuple.Create("g.V().constant(123.1f)",
+ new[] {new Token("constant", new[] {NumericParameter.Create(123.1f)})}),
Tuple.Create("g.V().has(\"no\").count()",
new[] {new Token("has", new StringParameter("no")), new Token("count")}),
Tuple.Create("g.V().has(\"lang\", \"java\")",
@@ -55,7 +54,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
Tuple.Create("g.V().where(__.in(\"knows\"))",
new[] {new Token("where", new[] {new StaticTraversalParameter(
new[] {new Token("__"), new Token("in", new StringParameter("knows"))}, "__.in(\"knows\")")})}),
- Tuple.Create("g.V().has(\"age\", P.gt(27)",
+ Tuple.Create("g.V().has(\"age\",P.gt(27))",
new[] {new Token("has", new ITokenParameter[] { new StringParameter("age"),
new TraversalPredicateParameter(
new[] { new Token("P"), new Token("gt", NumericParameter.Create(27)) }) })}),
@@ -65,14 +64,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
foreach (var item in items)
{
var parts = TraversalParser.ParseTraversal(item.Item1);
- _output.WriteLine("Parsing " + item.Item1);
- if (parts[parts.Count-1].Parameters != null)
- {
- _output.WriteLine("{0}", parts[parts.Count-1].Parameters.Count);
- _output.WriteLine("Values: " +
- string.Join(", ", parts[parts.Count - 1].Parameters.Select(p => p.ToString())));
- }
- Assert.Equal(new[] {new Token("g"), new Token("V")}.Concat(item.Item2), parts);
+ Assert.Equal(item.Item2, parts.Skip(2));
}
}
@@ -81,21 +73,21 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
var traversalTexts = new []
{
- "g.V().count()",
- //"g.V().constant(123L)", Can be parsed using the new type-safe API
- "g.V().has(\"no\").count()",
- "g.V().values(\"age\")",
- "g.V().valueMap(\"name\", \"age\")",
- "g.V().where(__.in(\"created\").count().is(1)).values(\"name\")",
- "g.V().count(Scope.local)",
- "g.V().values(\"age\").is(P.lte(30))"
+ Tuple.Create("g.V().count()", 2),
+// //"g.V().constant(123L)", Can be parsed using the new type-safe API
+ Tuple.Create("g.V().has(\"no\").count()", 3),
+ Tuple.Create("g.V().values(\"age\")", 2),
+ Tuple.Create("g.V().valueMap(\"name\", \"age\")", 2),
+ Tuple.Create("g.V().where(__.in(\"created\").count().is(1)).values(\"name\")", 3),
+ Tuple.Create("g.V().count(Scope.local)", 2),
+ Tuple.Create("g.V().values(\"age\").is(P.lte(30))", 3)
};
var g = new Graph().Traversal();
- foreach (var text in traversalTexts)
+ foreach (var tuple in traversalTexts)
{
- var traversal = TraversalParser.GetTraversal(text, g);
+ var traversal = TraversalParser.GetTraversal(tuple.Item1, g, null);
Assert.NotNull(traversal);
- Assert.True(traversal.Bytecode.StepInstructions.Count > 0);
+ Assert.Equal(tuple.Item2, traversal.Bytecode.StepInstructions.Count);
}
}
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
index 9880a64..4cf7b4a 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -36,71 +36,60 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
{ "g.V().fold().count(Scope.local)", g => g.V().Fold<object>().Count(Scope.Local)}
};
-
- private static readonly Regex RegexInteger = new Regex(@"\d+", RegexOptions.Compiled);
- private static readonly Regex RegexDouble = new Regex(@"\d+\.\d+", RegexOptions.Compiled);
- private static readonly Regex RegexFloat =
- new Regex(@"\d+\.\d+f", RegexOptions.Compiled | RegexOptions.IgnoreCase);
- private static readonly Regex RegexLong = new Regex(@"\d+l", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
+ private static readonly Regex RegexNumeric =
+ new Regex(@"\d+(\.\d+)?(?:l|f)?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
+
private static readonly Regex RegexEnum = new Regex(@"\w+\.\w+", RegexOptions.Compiled);
- internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g)
+ private static readonly Regex RegexParam = new Regex(@"\w+", RegexOptions.Compiled);
+
+ internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g,
+ IDictionary<string, object> contextParameterValues)
{
if (!FixedTranslations.TryGetValue(traversalText, out var traversalBuilder))
{
var tokens = ParseTraversal(traversalText);
- return GetTraversalFromTokens(tokens, g, traversalText);
+ return GetTraversalFromTokens(tokens, g, contextParameterValues, traversalText);
}
return traversalBuilder(g);
}
internal static ITraversal GetTraversalFromTokens(IList<Token> tokens, GraphTraversalSource g,
- string traversalText)
+ IDictionary<string, object> contextParameterValues,
+ string traversalText)
{
- ITraversal traversal;
- Type traversalType;
- var initialIndex = 2;
+ object instance;
+ Type instanceType;
if (tokens[0].Name == "g")
{
- switch (tokens[1].Name)
- {
- case "V":
- //TODO: support V() parameters
- traversal = g.V();
- break;
- case "E":
- traversal = g.E();
- break;
- default:
- throw BuildException(traversalText);
- }
- traversalType = traversal.GetType();
+ instance = g;
+ instanceType = g.GetType();
}
else if (tokens[0].Name == "__")
{
- traversal = null;
- traversalType = typeof(__);
- initialIndex = 1;
+ instance = null;
+ instanceType = typeof(__);
}
else
{
throw BuildException(traversalText);
}
- for (var i = initialIndex; i < tokens.Count; i++)
+ for (var i = 1; i < tokens.Count; i++)
{
var token = tokens[i];
var name = GetCsharpName(token.Name);
- var method = traversalType.GetMethod(name);
+ var method = instanceType.GetMethod(name);
if (method == null)
{
throw new InvalidOperationException($"Traversal method '{tokens[i]}' not found for testing");
}
- var parameterValues = BuildParameters(method, token, out var genericParameters);
+ var parameterValues = BuildParameters(method, token, contextParameterValues, out var genericParameters);
method = BuildGenericMethod(method, genericParameters, parameterValues);
- traversal = (ITraversal) method.Invoke(traversal, parameterValues);
- traversalType = traversal.GetType();
+ instance = method.Invoke(instance, parameterValues);
+ instanceType = instance.GetType();
}
- return traversal;
+ return (ITraversal) instance;
}
private static MethodInfo BuildGenericMethod(MethodInfo method, IDictionary<string, Type> genericParameters,
@@ -133,6 +122,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
}
private static object[] BuildParameters(MethodInfo method, Token token,
+ IDictionary<string, object> contextParameterValues,
out IDictionary<string, Type> genericParameterTypes)
{
var paramsInfo = method.GetParameters();
@@ -145,7 +135,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
if (token.Parameters.Count > i)
{
var tokenParameter = token.Parameters[i];
- value = tokenParameter.GetValue();
+ value = tokenParameter.GetValue(contextParameterValues);
if (info.ParameterType.IsGenericParameter)
{
// We've provided a value for parameter of a generic type, we can infer the
@@ -191,41 +181,40 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
var result = new List<Token>();
var startIndex = i;
var parsing = ParsingPart.Name;
- string name = null;
var parameters = new List<ITokenParameter>();
+ string name = null;
while (i < text.Length)
{
switch (text[i])
{
case '.':
- if (name == null)
+ if (parsing == ParsingPart.Name)
{
- name = text.Substring(startIndex, i - startIndex);
+ // The previous token was an object property, not a method
+ result.Add(new Token(text.Substring(startIndex, i - startIndex)));
}
startIndex = i + 1;
- result.Add(new Token(name, parameters));
- name = null;
parameters = new List<ITokenParameter>();
parsing = ParsingPart.Name;
break;
case '(':
{
name = text.Substring(startIndex, i - startIndex);
- i++;
parsing = ParsingPart.StartParameters;
+ // Start parsing from the next index
+ i++;
var param = ParseParameter(text, ref i);
if (param == null)
{
- parsing = ParsingPart.EndParameters;
- }
- else
- {
- parameters.Add(param);
+ // The next character was a ')', empty params
+ // Evaluate the current position
+ continue;
}
+ parameters.Add(param);
break;
}
case ',' when text[i+1] != ' ':
- case ' ' when text[i+1] != ' ':
+ case ' ' when text[i+1] != ' ' && text[i+1] != ')':
{
if (parsing != ParsingPart.StartParameters)
{
@@ -236,31 +225,33 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
var param = ParseParameter(text, ref i);
if (param == null)
{
- parsing = ParsingPart.EndParameters;
- }
- else
- {
- parameters.Add(param);
+ // The next character was a ')', empty params
+ // Evaluate the current position
+ continue;
}
+ parameters.Add(param);
break;
}
case ')' when parsing != ParsingPart.StartParameters:
- // The traversal already ended
- i--;
- if (name != null)
+ // The current nested object already ended
+ if (parsing == ParsingPart.Name)
{
- result.Add(new Token(name, parameters));
+ // The previous token was an object property, not a method and finished
+ result.Add(new Token(text.Substring(startIndex, i - startIndex)));
}
+ i--;
return result;
case ')':
parsing = ParsingPart.EndParameters;
+ result.Add(new Token(name, parameters));
break;
}
i++;
}
- if (name != null)
+ if (parsing == ParsingPart.Name)
{
- result.Add(new Token(name, parameters));
+ // The previous token was an object property, not a method and finished
+ result.Add(new Token(text.Substring(startIndex, i - startIndex)));
}
return result;
}
@@ -297,38 +288,40 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
}
if (RegexEnum.IsMatch(parameterText))
{
+ i += parameterText.Length - 1;
return new TraversalEnumParameter(parameterText);
}
+ if (RegexParam.IsMatch(parameterText))
+ {
+ i += parameterText.Length - 1;
+ return new ContextBasedParameter(parameterText);
+ }
throw new NotSupportedException($"Parameter {parameterText} not supported");
}
private static ITokenParameter ParseNumber(string text, ref int i)
{
- var match = RegexLong.Match(text.Substring(i));
- if (match.Success)
+ var match = RegexNumeric.Match(text, i);
+ if (!match.Success)
{
- i += match.Value.Length - 1;
- return NumericParameter.Create(Convert.ToInt64(match.Value.Substring(0, match.Value.Length-1)));
+ throw new InvalidOperationException(
+ $"Could not parse numeric value from the beginning of {text.Substring(i)}");
}
- match = RegexFloat.Match(text.Substring(i));
- if (match.Success)
+ var numericText = match.Value.ToUpper();
+ i += match.Value.Length - 1;
+ if (numericText.EndsWith("L"))
{
- i += match.Value.Length - 1;
- return NumericParameter.Create(Convert.ToSingle(match.Value.Substring(0, match.Value.Length-1)));
+ return NumericParameter.Create(Convert.ToInt64(match.Value.Substring(0, match.Value.Length - 1)));
}
- match = RegexDouble.Match(text.Substring(i));
- if (match.Success)
+ if (numericText.EndsWith("F"))
{
- i += match.Value.Length;
- return NumericParameter.Create(Convert.ToSingle(match.Value));
+ return NumericParameter.Create(Convert.ToSingle(match.Value.Substring(0, match.Value.Length-1)));
}
- match = RegexInteger.Match(text.Substring(i));
- if (!match.Success)
+ if (match.Groups[1].Value != "")
{
- throw new InvalidOperationException(
- $"Could not parse numeric value from the beginning of {text.Substring(i)}");
+ // Captured text with the decimal separator
+ return NumericParameter.Create(Convert.ToDouble(match.Value));
}
- i += match.Value.Length;
return NumericParameter.Create(Convert.ToInt32(match.Value));
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/69a710c8/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
index 0d0dc49..83060c7 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
@@ -52,7 +52,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
return Tokens != null ? Tokens.GetHashCode() : 0;
}
- public object GetValue()
+ public object GetValue(IDictionary<string, object> contextParameterValues)
{
var type = typeof(P);
object instance = null;
@@ -65,7 +65,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
{
throw new InvalidOperationException($"Predicate (P) method '{token}' not found for testing");
}
- instance = method.Invoke(instance, new object[] {token.Parameters.Select(p => p.GetValue()).ToArray()});
+ instance = method.Invoke(instance,
+ new object[] {token.Parameters.Select(p => p.GetValue(contextParameterValues)).ToArray()});
}
return instance;
}