First attempt at completely type safe Gremlin.Net
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/5f327312 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5f327312 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5f327312 Branch: refs/heads/TINKERPOP-1752 Commit: 5f3273125805457c6535a9ab0d939603b49f7953 Parents: c59393f Author: Florian Hockmann <[email protected]> Authored: Thu Aug 17 22:57:07 2017 +0200 Committer: florianhockmann <[email protected]> Committed: Tue Sep 12 16:39:37 2017 +0200 ---------------------------------------------------------------------- gremlin-dotnet/glv/AnonymousTraversal.template | 4 +- gremlin-dotnet/glv/GraphTraversal.template | 3 +- .../glv/GraphTraversalSource.template | 8 +- gremlin-dotnet/pom.xml | 87 +- .../Process/Traversal/GraphTraversal.cs | 1034 ++++++++++++++++-- .../Process/Traversal/GraphTraversalSource.cs | 141 ++- .../src/Gremlin.Net/Process/Traversal/__.cs | 836 +++++++++++--- 7 files changed, 1800 insertions(+), 313 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f327312/gremlin-dotnet/glv/AnonymousTraversal.template ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/glv/AnonymousTraversal.template b/gremlin-dotnet/glv/AnonymousTraversal.template index 9bc7257..64a6dbf 100644 --- a/gremlin-dotnet/glv/AnonymousTraversal.template +++ b/gremlin-dotnet/glv/AnonymousTraversal.template @@ -43,9 +43,9 @@ namespace Gremlin.Net.Process.Traversal /// <summary> /// Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the <%= method.methodName %> step to that traversal. /// </summary> - public static GraphTraversal<object, <%= method.t2 %>> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(params object[] args) + public static GraphTraversal<object, <%= method.t2 %>> <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(<%= method.parameters %>) { - return new GraphTraversal<object, object>().<%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(args); + return new GraphTraversal<object, <%= method.t2 %>>().<%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %>(<%= method.paramNames %>); } <% } %> } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f327312/gremlin-dotnet/glv/GraphTraversal.template ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/glv/GraphTraversal.template b/gremlin-dotnet/glv/GraphTraversal.template index 5c3e03e..9c4a88c 100644 --- a/gremlin-dotnet/glv/GraphTraversal.template +++ b/gremlin-dotnet/glv/GraphTraversal.template @@ -65,8 +65,9 @@ namespace Gremlin.Net.Process.Traversal /// <summary> /// Adds the <%= method.methodName %> step to this <see cref="GraphTraversal{SType, EType}" />. /// </summary> - public GraphTraversal< <%= method.t1 %> , <%= method.t2 %> > <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %> (params object[] args) + public GraphTraversal< <%= method.t1 %> , <%= method.t2 %> > <%= toCSharpMethodName.call(method.methodName) %><%= method.tParam %> (<%= method.parameters %>) { + var args = new List<object> { <%= method.paramNames %> }; Bytecode.AddStep("<%= method.methodName %>", args); return Wrap< <%= method.t1 %> , <%= method.t2 %> >(this); } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f327312/gremlin-dotnet/glv/GraphTraversalSource.template ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/glv/GraphTraversalSource.template b/gremlin-dotnet/glv/GraphTraversalSource.template index 0d98433..c3d1c99 100644 --- a/gremlin-dotnet/glv/GraphTraversalSource.template +++ b/gremlin-dotnet/glv/GraphTraversalSource.template @@ -72,11 +72,12 @@ namespace Gremlin.Net.Process.Traversal } <% sourceStepMethods.each{ method -> %> - public GraphTraversalSource <%= toCSharpMethodName.call(method) %>(params object[] args) + public GraphTraversalSource <%= toCSharpMethodName.call(method.methodName) %>(<%= method.parameters %>) { var source = new GraphTraversalSource(new List<ITraversalStrategy>(TraversalStrategies), new Bytecode(Bytecode)); - source.Bytecode.AddSource("<%= method %>", args); + var args = new List<object> { <%= method.paramNames %> }; + source.Bytecode.AddSource("<%= method.methodName %>", args); return source; } <% } %> @@ -119,9 +120,10 @@ namespace Gremlin.Net.Process.Traversal /// Spawns a <see cref="GraphTraversal{SType, EType}" /> off this graph traversal source and adds the <%= method.methodName %> step to that /// traversal. /// </summary> - public GraphTraversal< <%= method.typeArguments.join(",") %> > <%= toCSharpMethodName.call(method.methodName) %>(params object[] args) + public GraphTraversal< <%= method.typeArguments.join(",") %> > <%= toCSharpMethodName.call(method.methodName) %>(<%= method.parameters %>) { var traversal = new GraphTraversal< <%= method.typeArguments.join(",") %> >(TraversalStrategies, new Bytecode(Bytecode)); + var args = new List<object> { <%= method.paramNames %> }; traversal.Bytecode.AddStep("<%= method.methodName %>", args); return traversal; } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5f327312/gremlin-dotnet/pom.xml ---------------------------------------------------------------------- diff --git a/gremlin-dotnet/pom.xml b/gremlin-dotnet/pom.xml index d2ab17c..8b869ec 100644 --- a/gremlin-dotnet/pom.xml +++ b/gremlin-dotnet/pom.xml @@ -85,15 +85,33 @@ import java.lang.reflect.Modifier def toCSharpTypeMap = ["Long": "long", "Integer": "int", "String": "string", + "boolean": "bool", "Object": "object", + "String[]": "string[]", + "Object[]": "object[]", "java.util.Map<java.lang.String, E2>": "IDictionary<string, E2>", "java.util.Map<java.lang.String, B>": "IDictionary<string, E2>", "java.util.List<E>": "IList<E>", + "java.util.List<A>": "IList<E2>", "java.util.Map<K, V>": "IDictionary<K, V>", "java.util.Collection<E2>": "ICollection<E2>", "java.util.Collection<B>": "ICollection<E2>", "java.util.Map<K, java.lang.Long>": "IDictionary<K, long>", - "TraversalMetrics": "E2"] + "TraversalMetrics": "E2", + "Traversal": "ITraversal", + "Traversal[]": "ITraversal[]", + "Predicate": "TraversalPredicate", + "P": "TraversalPredicate", + "TraversalStrategy": "ITraversalStrategy", + "TraversalStrategy[]": "ITraversalStrategy[]", + "Function": "object", + "BiFunction": "object", + "UnaryOperator": "object", + "BinaryOperator": "object", + "Consumer": "object", + "Supplier": "object", + "Comparator": "object", + "VertexProgram": "object"] def useE2 = ["E2", "E2"]; def methodsWithSpecificTypes = ["constant": useE2, @@ -101,10 +119,8 @@ def methodsWithSpecificTypes = ["constant": useE2, "mean": useE2, "optional": useE2, "range": useE2, - "select": ["IDictionary<string, E2>", "E2"], "sum": useE2, "tail": useE2, - "tree": ["object"], "unfold": useE2] def getCSharpGenericTypeParam = { typeName -> @@ -146,6 +162,36 @@ def getJavaParameterTypeNames = { method -> } } +def toCSharpParamString = { param -> + csharpParamTypeName = toCSharpType(param.type.simpleName) + "${csharpParamTypeName} ${param.name}" + } + +def getCSharpParamString = { method -> + def parameters = method.parameters; + if (parameters.length == 0) + return "" + def csharpParameters = parameters. + init(). + collect { param -> + toCSharpParamString(param) + }; + def lastCSharpParam = ""; + if (method.isVarArgs()) + lastCSharpParam += "params "; + lastCSharpParam += toCSharpParamString(parameters.last()) + csharpParameters += lastCSharpParam + csharpParamString = csharpParameters.join(", ") + csharpParamString +} + +def getParamNames = { parameters -> + return parameters. + collect { param -> + param.name + } +} + def binding = ["pmethods": P.class.getMethods(). findAll { Modifier.isStatic(it.getModifiers()) }. findAll { P.class.isAssignableFrom(it.returnType) }. @@ -160,35 +206,38 @@ def binding = ["pmethods": P.class.getMethods(). !it.name.equals(TraversalSource.Symbols.withRemote) && !it.name.equals(TraversalSource.Symbols.withComputer) }. - collect { it.name }. - unique(). - sort { a, b -> a <=> b }, + sort { a, b -> a.name <=> b.name }. + collect { javaMethod -> + def parameters = getCSharpParamString(javaMethod) + def paramNames = getParamNames(javaMethod.parameters).join(", ") + return ["methodName": javaMethod.name, "parameters":parameters, "paramNames":paramNames] + }, "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS - findAll { GraphTraversal.class.equals(it.returnType) && !it.name.equals('inject')}. - collect { [methodName: it.name, typeArguments: it.genericReturnType.actualTypeArguments.collect{t -> ((java.lang.Class)t).simpleName}] }. - unique(). - sort { a, b -> a.methodName <=> b.methodName }, + findAll { GraphTraversal.class.equals(it.returnType) && !it.name.equals('inject')}. + sort { a, b -> a.name <=> b.name }. + collect { javaMethod -> + def typeArguments = javaMethod.genericReturnType.actualTypeArguments.collect{t -> ((java.lang.Class)t).simpleName} + def parameters = getCSharpParamString(javaMethod) + def paramNames = getParamNames(javaMethod.parameters).join(", ") + return ["methodName": javaMethod.name, "typeArguments": typeArguments, "parameters":parameters, "paramNames":paramNames] + }, "graphStepMethods": GraphTraversal.getMethods(). findAll { GraphTraversal.class.equals(it.returnType) }. findAll { !it.name.equals("clone") && !it.name.equals("iterate") }. - groupBy { it.name }. - // Select unique by name, with the most amount of parameters - collect { it.value.sort { a, b -> b.parameterCount <=> a.parameterCount }.first() }. sort { a, b -> a.name <=> b.name }. collect { javaMethod -> def typeNames = getJavaParameterTypeNames(javaMethod) def t1 = toCSharpType(typeNames[0]) def t2 = toCSharpType(typeNames[1]) def tParam = getCSharpGenericTypeParam(t2) - return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam] + def parameters = getCSharpParamString(javaMethod) + def paramNames = getParamNames(javaMethod.parameters).join(", ") + return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames] }, "anonStepMethods": __.class.getMethods(). findAll { GraphTraversal.class.equals(it.returnType) }. findAll { Modifier.isStatic(it.getModifiers()) }. findAll { !it.name.equals("__") && !it.name.equals("start") }. - groupBy { it.name }. - // Select unique by name, with the most amount of parameters - collect { it.value.sort { a, b -> b.parameterCount <=> a.parameterCount }.first() }. sort { it.name }. collect { javaMethod -> def typeNames = getJavaParameterTypeNames(javaMethod) @@ -199,7 +248,9 @@ def binding = ["pmethods": P.class.getMethods(). t2 = specificTypes[0] tParam = specificTypes.size() > 1 ? "<" + specificTypes[1] + ">" : "" } - return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam] + def parameters = getCSharpParamString(javaMethod) + def paramNames = getParamNames(javaMethod.parameters).join(", ") + return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames] }, "toCSharpMethodName": toCSharpMethodName]
