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/23 08:16:08 UTC

[33/50] tinkerpop git commit: Invoke predicates and enums

Invoke predicates and enums


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

Branch: refs/heads/TINKERPOP-1827
Commit: fe6e61312d22c6620238ce0ca126816575e48033
Parents: 71c4a8f
Author: Jorge Bay Gondra <jo...@gmail.com>
Authored: Mon Oct 30 15:14:38 2017 +0100
Committer: Jorge Bay Gondra <jo...@gmail.com>
Committed: Thu Nov 23 09:08:06 2017 +0100

----------------------------------------------------------------------
 .../StaticTraversalParameter.cs                 | 15 +--
 .../TraversalEnumParameter.cs                   | 98 ++++++++++++++++++++
 .../TraversalEvaluationTests.cs                 | 16 +++-
 .../TraversalEvaluation/TraversalParser.cs      | 79 ++++++++++------
 .../TraversalPredicateParameter.cs              | 26 ++++--
 .../TraversalTokenParameter.cs                  | 71 --------------
 6 files changed, 188 insertions(+), 117 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe6e6131/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 8e0fbf9..dca691b 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/StaticTraversalParameter.cs
@@ -30,9 +30,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 {
     internal class StaticTraversalParameter : ITokenParameter, IEquatable<StaticTraversalParameter>
     {
+        private readonly string _traversalText;
+
         public bool Equals(StaticTraversalParameter other)
         {
-            return Parts.SequenceEqual(other.Parts);
+            return Tokens.SequenceEqual(other.Tokens);
         }
 
         public override bool Equals(object obj)
@@ -45,12 +47,12 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 
         public override int GetHashCode()
         {
-            return Parts != null ? Parts.GetHashCode() : 0;
+            return Tokens != null ? Tokens.GetHashCode() : 0;
         }
 
         public object GetValue()
         {
-            throw new NotImplementedException();
+            return TraversalParser.GetTraversalFromTokens(Tokens, null, _traversalText);
         }
 
         public Type GetParameterType()
@@ -58,11 +60,12 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return typeof(ITraversal);
         }
 
-        public IList<Token> Parts { get; }
+        public IList<Token> Tokens { get; }
         
-        public StaticTraversalParameter(IList<Token> parts)
+        public StaticTraversalParameter(IList<Token> tokens, string traversalText)
         {
-            Parts = parts;
+            _traversalText = traversalText;
+            Tokens = tokens;
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe6e6131/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
new file mode 100644
index 0000000..663928a
--- /dev/null
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEnumParameter.cs
@@ -0,0 +1,98 @@
+#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 System.Reflection;
+using Gremlin.Net.Process.Traversal;
+using TEnum = Gremlin.Net.Process.Traversal.T;
+
+namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
+{
+    /// <summary>
+    /// Represents a parameter for a traversal token (ie: T.label)
+    /// </summary>
+    internal class TraversalEnumParameter : ITokenParameter, IEquatable<TraversalEnumParameter>
+    {
+        private readonly string _text;
+
+        private static readonly IDictionary<string, Type> EnumTypesByName = typeof(Scope).GetTypeInfo().Assembly
+            .GetTypes().Where(t => t.GetTypeInfo().IsEnum && t.GetTypeInfo().IsPublic)
+            .ToDictionary(e => e.Name, e => e);
+        
+        private readonly object _value;
+        private readonly Type _type;
+        
+        public TraversalEnumParameter(string text)
+        {
+            _text = text;
+            var separatorIndex = text.IndexOf('.');
+            var enumTypeName = text.Substring(0, separatorIndex);
+            if (!EnumTypesByName.TryGetValue(enumTypeName, out var type))
+            {
+                throw new KeyNotFoundException($"Enum with name {enumTypeName} not found");
+            }
+            _type = type;
+            var valueName = text.Substring(separatorIndex + 1);
+            _value = Enum.Parse(type, GetCsharpName(valueName));
+        }
+
+        private string GetCsharpName(string valueText)
+        {
+            if (_type == typeof(Direction))
+            {
+                valueText = valueText.ToLower();
+            }
+            return TraversalParser.GetCsharpName(valueText);
+        }
+
+        public bool Equals(TraversalEnumParameter other)
+        {
+            return _text == other._text;
+        }
+
+        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((TraversalEnumParameter) obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return _text.GetHashCode();
+        }
+
+        public object GetValue()
+        {
+            return _value;
+        }
+
+        public Type GetParameterType()
+        {
+            return _type;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe6e6131/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 4e3ec42..9cbceb9 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalEvaluationTests.cs
@@ -54,11 +54,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
                     new[] {new Token("has", new[] {new StringParameter("lang"), new StringParameter("java")})}),
                 Tuple.Create("g.V().where(__.in(\"knows\"))",
                     new[] {new Token("where", new[] {new StaticTraversalParameter(
-                        new[] {new Token("__"), new Token("in", new StringParameter("knows"))})})}),
+                        new[] {new Token("__"), new Token("in", new StringParameter("knows"))}, "__.in(\"knows\")")})}),
                 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)) }) })})
+                            new[] { new Token("P"), new Token("gt", NumericParameter.Create(27)) }) })}),
+                Tuple.Create("g.V().count(Scope.local)", 
+                    new[] { new Token("count", new TraversalEnumParameter("Scope.local"))})
             };
             foreach (var item in items)
             {
@@ -80,16 +82,20 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             var traversalTexts = new []
             {
                 "g.V().count()",
-                "g.V().constant(123)",
+                //"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().repeat(__.both()).times(5)"
+                "g.V().where(__.in(\"created\").count().is(1)).values(\"name\")",
+                "g.V().count(Scope.local)",
+                "g.V().values(\"age\").is(P.lte(30))"
             };
             var g = new Graph().Traversal();
             foreach (var text in traversalTexts)
             {
-                Assert.NotNull(TraversalParser.GetTraversal(text, g));
+                var traversal = TraversalParser.GetTraversal(text, g);
+                Assert.NotNull(traversal);
+                Assert.True(traversal.Bytecode.StepInstructions.Count > 0);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe6e6131/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 11283c1..9880a64 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalParser.cs
@@ -42,49 +42,63 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
         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 RegexEnum = new Regex(@"\w+\.\w+", RegexOptions.Compiled);
 
         internal static ITraversal GetTraversal(string traversalText, GraphTraversalSource g)
         {
-            Func<GraphTraversalSource, ITraversal> traversalBuilder;
-            if (!FixedTranslations.TryGetValue(traversalText, out traversalBuilder))
+            if (!FixedTranslations.TryGetValue(traversalText, out var traversalBuilder))
             {
-                return BuildFromMethods(traversalText, g);
+                var tokens = ParseTraversal(traversalText);
+                return GetTraversalFromTokens(tokens, g, traversalText);
             }
             return traversalBuilder(g);
         }
 
-        private static ITraversal BuildFromMethods(string traversalText, GraphTraversalSource g)
+        internal static ITraversal GetTraversalFromTokens(IList<Token> tokens, GraphTraversalSource g,
+                                                         string traversalText)
         {
-            var parts = ParseTraversal(traversalText);
-            if (parts[0].Name != "g")
+            ITraversal traversal;
+            Type traversalType;
+            var initialIndex = 2;
+            if (tokens[0].Name == "g")
             {
-                throw BuildException(traversalText);
+                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();
             }
-            ITraversal traversal;
-            switch (parts[1].Name)
+            else if (tokens[0].Name == "__")
             {
-                case "V":
-                    //TODO: support V() parameters
-                    traversal = g.V();
-                    break;
-                case "E":
-                    traversal = g.E();
-                    break;
-                default:
-                    throw BuildException(traversalText);
+                traversal = null;
+                traversalType = typeof(__);
+                initialIndex = 1;
             }
-            for (var i = 2; i < parts.Count; i++)
+            else
             {
-                var token = parts[i];
+                throw BuildException(traversalText);
+            }
+            for (var i = initialIndex; i < tokens.Count; i++)
+            {
+                var token = tokens[i];
                 var name = GetCsharpName(token.Name);
-                var method = traversal.GetType().GetMethod(name);
+                var method = traversalType.GetMethod(name);
                 if (method == null)
                 {
-                    throw new InvalidOperationException($"Traversal method '{parts[i]}' not found for testing");
+                    throw new InvalidOperationException($"Traversal method '{tokens[i]}' not found for testing");
                 }
                 var parameterValues = BuildParameters(method, token, out var genericParameters);
                 method = BuildGenericMethod(method, genericParameters, parameterValues);
                 traversal = (ITraversal) method.Invoke(traversal, parameterValues);
+                traversalType = traversal.GetType();
             }
             return traversal;
         }
@@ -155,7 +169,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) : null;
         }
 
-        private static string GetCsharpName(string part)
+        internal static string GetCsharpName(string part)
         {
             // Transform to PascalCasing and remove the parenthesis
             return char.ToUpper(part[0]) + part.Substring(1);
@@ -268,17 +282,24 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             }
             if (text.Substring(i, 3).StartsWith("__."))
             {
-                return new StaticTraversalParameter(ParseTokens(text, ref i));
-            }
-            if (text.Substring(i, 2).StartsWith("T."))
-            {
-                return new TraversalTokenParameter(ParseTokens(text, ref i));
+                var startIndex = i;
+                var tokens = ParseTokens(text, ref i);
+                return new StaticTraversalParameter(tokens, text.Substring(startIndex, i - startIndex));
             }
             if (text.Substring(i, 2).StartsWith("P."))
             {
                 return new TraversalPredicateParameter(ParseTokens(text, ref i));
             }
-            return null;
+            var parameterText = text.Substring(i, text.IndexOf(')', i) - i);
+            if (string.IsNullOrWhiteSpace(parameterText))
+            {
+                return null;
+            }
+            if (RegexEnum.IsMatch(parameterText))
+            {
+                return new TraversalEnumParameter(parameterText);
+            }
+            throw new NotSupportedException($"Parameter {parameterText} not supported");
         }
         
         private static ITokenParameter ParseNumber(string text, ref int i)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe6e6131/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 8c040b9..0d0dc49 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 System.Reflection;
 using Gremlin.Net.Process.Traversal;
 
 namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
@@ -35,7 +36,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
     {
         public bool Equals(TraversalPredicateParameter other)
         {
-            return Parts.SequenceEqual(other.Parts);
+            return Tokens.SequenceEqual(other.Tokens);
         }
 
         public override bool Equals(object obj)
@@ -48,12 +49,25 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
 
         public override int GetHashCode()
         {
-            return Parts != null ? Parts.GetHashCode() : 0;
+            return Tokens != null ? Tokens.GetHashCode() : 0;
         }
 
         public object GetValue()
         {
-            throw new NotImplementedException();
+            var type = typeof(P);
+            object instance = null;
+            for (var i = 1; i < Tokens.Count; i++)
+            {
+                var token = Tokens[i];
+                var method = type.GetMethod(TraversalParser.GetCsharpName(token.Name),
+                    BindingFlags.Static | BindingFlags.Public);
+                if (method == null)
+                {
+                    throw new InvalidOperationException($"Predicate (P) method '{token}' not found for testing");
+                }
+                instance = method.Invoke(instance, new object[] {token.Parameters.Select(p => p.GetValue()).ToArray()});
+            }
+            return instance;
         }
 
         public Type GetParameterType()
@@ -61,11 +75,11 @@ namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
             return typeof(TraversalPredicate);
         }
 
-        public IList<Token> Parts { get; }
+        public IList<Token> Tokens { get; }
         
-        public TraversalPredicateParameter(IList<Token> parts)
+        public TraversalPredicateParameter(IList<Token> tokens)
         {
-            Parts = parts;
+            Tokens = tokens;
         }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/fe6e6131/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
deleted file mode 100644
index 9291cd6..0000000
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/TraversalEvaluation/TraversalTokenParameter.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-#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 TEnum = Gremlin.Net.Process.Traversal.T;
-
-namespace Gremlin.Net.IntegrationTest.Gherkin.TraversalEvaluation
-{
-    /// <summary>
-    /// Represents a parameter for a traversal token (ie: T.label)
-    /// </summary>
-    internal class TraversalTokenParameter : ITokenParameter, IEquatable<TraversalTokenParameter>
-    {
-        public bool Equals(TraversalTokenParameter other)
-        {
-            return Parts.SequenceEqual(other.Parts);
-        }
-
-        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((TraversalTokenParameter) obj);
-        }
-
-        public override int GetHashCode()
-        {
-            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)
-        {
-            Parts = parts;
-        }
-    }
-}
\ No newline at end of file