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:19:57 UTC

[13/33] tinkerpop git commit: Invoke traversal methods with generic parameters

Invoke traversal methods with generic parameters


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/19105a75
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/19105a75
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/19105a75

Branch: refs/heads/TINKERPOP-1827
Commit: 19105a755353959d56359ef09757b52015c893bf
Parents: 6d8ff7d
Author: Jorge Bay Gondra <jo...@gmail.com>
Authored: Fri Oct 27 10:55:20 2017 +0200
Committer: Jorge Bay Gondra <jo...@gmail.com>
Committed: Thu Nov 30 10:00:07 2017 +0100

----------------------------------------------------------------------
 .../TraversalEvaluation/ITokenParameter.cs      | 13 ++-
 .../TraversalEvaluation/NumericParameter.cs     | 10 +++
 .../StaticTraversalParameter.cs                 | 11 +++
 .../TraversalEvaluation/StringParameter.cs      | 10 +++
 .../Gherkin/TraversalEvaluation/Token.cs        | 15 ++--
 .../TraversalEvaluationTests.cs                 | 23 ++++--
 .../TraversalEvaluation/TraversalParser.cs      | 86 ++++++++++++++++----
 .../TraversalPredicateParameter.cs              | 11 +++
 .../TraversalTokenParameter.cs                  | 11 +++
 .../Gremlin.Net.IntegrationTest.csproj          |  6 +-
 10 files changed, 164 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 1c940db..5c8197f 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/ITokenParameter.cs
@@ -21,10 +21,21 @@
 
 #endregion
 
+using System;
+
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
     public interface ITokenParameter
     {
-        
+        /// <summary>
+        /// Gets the value of the parameter 
+        /// </summary>
+        object GetValue();
+
+        /// <summary>
+        /// Gets the type of the parameter
+        /// </summary>
+        /// <returns></returns>
+        Type GetParameterType();
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 9effc17..378680c 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/NumericParameter.cs
@@ -56,6 +56,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
         {
             return $"NumericParameter<{typeof(T).Name}>({Value})";
         }
+
+        public object GetValue()
+        {
+            return Value;
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(T);
+        }
     }
 
     internal static class NumericParameter

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 b054cbc..8e0fbf9 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using Gremlin.Net.Process.Traversal;
 
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
@@ -47,6 +48,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return Parts != null ? Parts.GetHashCode() : 0;
         }
 
+        public object GetValue()
+        {
+            throw new NotImplementedException();
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(ITraversal);
+        }
+
         public IList<Token> Parts { get; }
         
         public StaticTraversalParameter(IList<Token> parts)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 ad182b5..82f6cd9 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StringParameter.cs
@@ -65,5 +65,15 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
         {
             return $"{GetType().Name}({Value})";
         }
+
+        public object GetValue()
+        {
+            return Value;
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(string);
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
index 633e2b5..539be89 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/Token.cs
@@ -23,13 +23,15 @@
 
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Linq;
 
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
     internal class Token : IEquatable<Token>
     {
-        private static readonly IList<ITokenParameter> EmptyParameters = new ITokenParameter[0];
+        private static readonly IList<ITokenParameter> EmptyParameters =
+            new ReadOnlyCollection<ITokenParameter>(new ITokenParameter[0]);
         
         public bool Equals(Token other)
         {
@@ -37,7 +39,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             {
                 return false;
             }
-            return  (Parameters ?? EmptyParameters).SequenceEqual(other.Parameters ?? EmptyParameters);
+            return  (Parameters).SequenceEqual(other.Parameters);
         }
 
         public override bool Equals(object obj)
@@ -59,12 +61,15 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 
         public string Name { get; }
 
-        public ICollection<ITokenParameter> Parameters { get; }
+        /// <summary>
+        /// Returns the collection of parameters, can not be null.
+        /// </summary>
+        public IList<ITokenParameter> Parameters { get; }
             
-        public Token(string name, ICollection<ITokenParameter> parameters = null)
+        public Token(string name, IList<ITokenParameter> parameters = null)
         {
             Name = name;
-            Parameters = parameters;
+            Parameters = parameters ?? EmptyParameters;
         }
             
         public Token(string name, ITokenParameter parameter)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 ea65cd2..0949ad5 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
@@ -22,12 +22,10 @@
 #endregion
 
 using System;
-using System.Collections.Generic;
-using System.Diagnostics;
 using System.Linq;
+using Gremlin.Net.Structure;
 using Xunit;
 using Xunit.Abstractions;
-using Xunit.Sdk;
 
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
@@ -41,7 +39,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
         }
         
         [Fact]
-        public void Traversal_Parser_Should_Parse_Parts()
+        public void Traversal_Parser_Should_Parse_Into_Tokens()
         {
             var items = new[]
             {
@@ -64,7 +62,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             };
             foreach (var item in items)
             {
-                var parts = TraversalParser.ParseParts(item.Item1);
+                var parts = TraversalParser.ParseTraversal(item.Item1);
                 _output.WriteLine("Parsing " + item.Item1);
                 if (parts[parts.Count-1].Parameters != null)
                 {
@@ -75,5 +73,20 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                 Assert.Equal(new[] {new Token("g"), new Token("V")}.Concat(item.Item2), parts);
             }
         }
+
+        [Fact]
+        public void GetTraversal_Should_Invoke_Traversal_Methods()
+        {
+            var traversalTexts = new string[]
+            {
+                "g.V().count()",
+                "g.V().constant(123)"
+            };
+            var g = new Graph().Traversal();
+            foreach (var text in traversalTexts)
+            {
+                TraversalParser.GetTraversal(text, g);
+            }
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 0ac97ff..65ca103 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -56,49 +56,103 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 
         private static ITraversal BuildFromMethods(string traversalText, GraphTraversalSource g)
         {
-            var parts = traversalText.Split('.');
-            if (parts[0] != "g")
+            var parts = ParseTraversal(traversalText);
+            if (parts[0].Name != "g")
             {
                 throw BuildException(traversalText);
             }
             ITraversal traversal;
-            switch (parts[1])
+            switch (parts[1].Name)
             {
-                case "V()":
+                case "V":
+                    //TODO: support V() parameters
                     traversal = g.V();
                     break;
-                case "E()":
+                case "E":
                     traversal = g.E();
                     break;
                 default:
                     throw BuildException(traversalText);
             }
-            for (var i = 2; i < parts.Length; i++)
+            for (var i = 2; i < parts.Count; i++)
             {
-                var name = GetCsharpName(parts[i], traversalText);
+                var token = parts[i];
+                var name = GetCsharpName(token.Name);
                 var method = traversal.GetType().GetMethod(name);
                 if (method == null)
                 {
                     throw new InvalidOperationException($"Traversal method '{parts[i]}' not found for testing");
                 }
-                if (method.IsGenericMethod)
+                var parameters = BuildParameters(method, token, out var genericParameters);
+                method = BuildGenericMethod(method, genericParameters);
+                traversal = (ITraversal) method.Invoke(traversal, parameters);
+            }
+            return traversal;
+        }
+
+        private static MethodInfo BuildGenericMethod(MethodInfo method, IDictionary<string, Type> genericParameters)
+        {
+            if (!method.IsGenericMethod)
+            {
+                return method;
+            }
+            var genericArgs = method.GetGenericArguments();
+            var types = new Type[genericArgs.Length];
+            for (var i = 0; i < genericArgs.Length; i++)
+            {
+                var name = genericArgs[i].Name;
+                if (genericParameters.TryGetValue(name, out var type))
+                {
+                    types[i] = type;
+                }
+                //TODO: Try to infer it from the name based on modern schema
+                else
                 {
                     throw new InvalidOperationException(
-                        $"Can not build traversal to test as '{name}()' method is generic");
+                        $"Can not build traversal to test as '{method.Name}()' method is generic and type '{name}'" +
+                        $" can not be inferred");
                 }
-                traversal = (ITraversal) method.Invoke(traversal, new object[] { new object[0]});
             }
-            return traversal;
+            return method.MakeGenericMethod(types);
         }
 
-        private static string GetCsharpName(string part, string traversalText)
+        private static object[] BuildParameters(MethodInfo method, Token token,
+                                                out IDictionary<string, Type> genericParameterTypes)
         {
-            if (!part.EndsWith("()"))
+            var paramsInfo = method.GetParameters();
+            var parameters = new object[paramsInfo.Length];
+            genericParameterTypes = new Dictionary<string, Type>();
+            for (var i = 0; i < paramsInfo.Length; i++)
             {
-                throw BuildException(traversalText);
+                var info = paramsInfo[i];
+                object value = null;
+                if (token.Parameters.Count > i)
+                {
+                    var tokenParameter = token.Parameters[i];
+                    value =  tokenParameter.GetValue();
+                    if (info.ParameterType.IsGenericParameter)
+                    {
+                        // We've provided a value for parameter of a generic type, we can infer the
+                        // type of the generic argument based on the parameter.
+                        // For example, in the case of `Constant<E2>(E2 value)`
+                        // if we have the type of value we have the type of E2. 
+                        genericParameterTypes.Add(info.ParameterType.Name, tokenParameter.GetParameterType());
+                    }
+                }
+                parameters[i] = value ?? GetDefault(info.ParameterType);
             }
+            return parameters;
+        }
+
+        public static object GetDefault(Type type)
+        {
+            return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) : null;
+        }
+
+        private static string GetCsharpName(string part)
+        {
             // Transform to PascalCasing and remove the parenthesis
-            return char.ToUpper(part[0]) + part.Substring(1, part.Length - 3);
+            return char.ToUpper(part[0]) + part.Substring(1);
         }
 
         private static Exception BuildException(string traversalText)
@@ -106,7 +160,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return new InvalidOperationException($"Can not build a traversal to test from '{traversalText}'");
         }
 
-        internal static IList<Token> ParseParts(string traversalText)
+        internal static IList<Token> ParseTraversal(string traversalText)
         {
             var index = 0;
             return ParseTokens(traversalText, ref index);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/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 d9bf061..8c040b9 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalPredicateParameter.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using Gremlin.Net.Process.Traversal;
 
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
@@ -50,6 +51,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return Parts != null ? Parts.GetHashCode() : 0;
         }
 
+        public object GetValue()
+        {
+            throw new NotImplementedException();
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(TraversalPredicate);
+        }
+
         public IList<Token> Parts { get; }
         
         public TraversalPredicateParameter(IList<Token> parts)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
index 5a5e8c1..9291cd6 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
@@ -24,6 +24,7 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using TEnum = Gremlin.Net.Process.Traversal.T;
 
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
@@ -50,6 +51,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return Parts != null ? Parts.GetHashCode() : 0;
         }
 
+        public object GetValue()
+        {
+            throw new NotImplementedException();
+        }
+
+        public Type GetParameterType()
+        {
+            return typeof(TEnum);
+        }
+
         public IList<Token> Parts { get; }
         
         public TraversalTokenParameter(IList<Token> parts)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/19105a75/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
index 40552ad..c929575 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gremlin.Net.IntegrationTest.csproj
@@ -18,6 +18,7 @@
     <ProjectReference Include="..\..\src\Gremlin.Net\Gremlin.Net.csproj" />
   </ItemGroup>
   <ItemGroup>
+    <PackageReference Include="gherkin" Version="5.0.0" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
     <PackageReference Include="xunit" Version="2.2.0" />
@@ -30,9 +31,4 @@
   <ItemGroup>
     <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
   </ItemGroup>
-  <ItemGroup>
-    <Reference Include="Gherkin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
-      <HintPath>..\..\..\..\temp\Gherkin.dll</HintPath>
-    </Reference>
-  </ItemGroup>
 </Project>
\ No newline at end of file