| /* |
| * 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. |
| */ |
| |
| import org.apache.tinkerpop.gremlin.jsr223.CoreImports |
| import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ConnectedComponent |
| import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PageRank |
| import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.PeerPressure |
| import org.apache.tinkerpop.gremlin.process.computer.traversal.step.map.ShortestPath |
| import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource |
| import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal |
| import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource |
| import org.apache.tinkerpop.gremlin.process.traversal.P |
| import org.apache.tinkerpop.gremlin.process.traversal.TextP |
| import org.apache.tinkerpop.gremlin.process.traversal.IO |
| import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__ |
| import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions |
| import org.apache.tinkerpop.gremlin.structure.Direction |
| import java.lang.reflect.Modifier |
| import java.lang.reflect.TypeVariable |
| import java.lang.reflect.GenericArrayType |
| |
| def toCSharpTypeMap = ["Long": "long", |
| "Double": "double", |
| "Integer": "int", |
| "String": "string", |
| "boolean": "bool", |
| "Object": "object", |
| "String[]": "string[]", |
| "Object[]": "object[]", |
| "Class": "Type", |
| "Class[]": "Type[]", |
| "java.util.Map<java.lang.String, java.lang.Object>": "IDictionary<string, object>", |
| "java.util.Map<java.lang.String, E2>": "IDictionary<string, E2>", |
| "java.util.Map<java.lang.String, B>": "IDictionary<string, E2>", |
| "java.util.Map<java.lang.Object, E2>": "IDictionary<object, E2>", |
| "java.util.Map<java.lang.Object, B>": "IDictionary<object, 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", |
| "Traversal": "ITraversal", |
| "Traversal[]": "ITraversal[]", |
| "Predicate": "IPredicate", |
| "P": "P", |
| "TextP": "TextP", |
| "TraversalStrategy": "ITraversalStrategy", |
| "TraversalStrategy[]": "ITraversalStrategy[]", |
| "Function": "IFunction", |
| "BiFunction": "IBiFunction", |
| "UnaryOperator": "IUnaryOperator", |
| "BinaryOperator": "IBinaryOperator", |
| "Consumer": "IConsumer", |
| "Supplier": "ISupplier", |
| "Comparator": "IComparator", |
| "VertexProgram": "object"] |
| |
| def useE2 = ["E2", "E2"] |
| def methodsWithSpecificTypes = ["constant": useE2, |
| "limit": useE2, |
| "mean": useE2, |
| "optional": useE2, |
| "range": useE2, |
| "skip": useE2, |
| "sum": useE2, |
| "tail": useE2, |
| "unfold": useE2, |
| "valueMap": ["IDictionary<TKey, TValue>", "TKey, TValue"],] |
| |
| def getCSharpGenericTypeParam = { typeName -> |
| def tParam = "" |
| if (typeName.contains("E2")) { |
| tParam = "<E2>" |
| } |
| else if (typeName.contains("<K, V>")) { |
| tParam = "<K, V>" |
| } |
| else if (typeName.contains("<K, ")) { |
| tParam = "<K>" |
| } |
| else if (typeName.contains("S")) { |
| tParam = "<S>" |
| } |
| else if (typeName.contains("A")) { |
| tParam = "<A>" |
| } |
| return tParam |
| } |
| |
| def toCSharpType = { name -> |
| String typeName = toCSharpTypeMap.getOrDefault(name, name) |
| if (typeName.equals(name) && (typeName.contains("? extends") || typeName.equals("Tree"))) { |
| typeName = "E2" |
| } |
| return typeName |
| } |
| |
| def toCSharpMethodName = { symbol -> (String) Character.toUpperCase(symbol.charAt(0)) + symbol.substring(1) } |
| |
| def toCSharpValue = { type, value -> |
| type == String.class && value != null ? ('"' + value + '"') : value |
| } |
| |
| def getJavaGenericTypeParameterTypeNames = { method -> |
| def typeArguments = method.genericReturnType.actualTypeArguments |
| return typeArguments. |
| collect { (it instanceof Class) ? ((Class)it).simpleName : it.typeName }. |
| collect { name -> |
| if (name.equals("A")) { |
| name = "object" |
| } |
| else if (name.equals("B")) { |
| name = "E2" |
| } |
| name |
| } |
| } |
| |
| def getJavaParameterTypeNames = { method -> |
| return method.parameters. |
| collect { param -> |
| param.type.simpleName |
| } |
| } |
| |
| def toCSharpParamString = { param, genTypeName -> |
| String csharpParamTypeName = genTypeName |
| if (csharpParamTypeName == null){ |
| csharpParamTypeName = toCSharpType(param.type.simpleName) |
| } |
| else if (csharpParamTypeName == "M") { |
| csharpParamTypeName = "object" |
| } |
| else if (csharpParamTypeName == "A[]") { |
| csharpParamTypeName = "object[]" |
| } |
| else if (csharpParamTypeName == "A" || csharpParamTypeName == "B") { |
| csharpParamTypeName = "E2" |
| } |
| "${csharpParamTypeName} ${param.name}" |
| } |
| |
| def getJavaParamTypeString = { method -> |
| getJavaParameterTypeNames(method).join(",") |
| } |
| |
| def getCSharpParamTypeString = { method -> |
| return method.parameters. |
| collect { param -> |
| toCSharpType(param.type.simpleName) |
| }.join(",") |
| } |
| |
| def getCSharpParamString = { method, useGenericParams -> |
| def parameters = method.parameters |
| if (parameters.length == 0) |
| return "" |
| |
| def genericTypes = method.getGenericParameterTypes() |
| def csharpParameters = parameters. |
| toList().indexed(). |
| collect { index, param -> |
| String genTypeName = null |
| if (useGenericParams) { |
| def genType = genericTypes[index] |
| if (genType instanceof TypeVariable<?>) { |
| genTypeName = ((TypeVariable<?>)genType).name |
| } |
| else if (genType instanceof GenericArrayType) { |
| if (((GenericArrayType)genType).getGenericComponentType() instanceof TypeVariable<?>) { |
| genTypeName = ((TypeVariable<?>)((GenericArrayType)genType).getGenericComponentType()).name + "[]" |
| } |
| } |
| } |
| toCSharpParamString(param, genTypeName) |
| }. |
| toArray() |
| |
| if (method.isVarArgs()) { |
| def lastIndex = csharpParameters.length-1 |
| csharpParameters[lastIndex] = "params " + csharpParameters[lastIndex] |
| } |
| |
| csharpParameters.join(", ") |
| } |
| |
| def getParamNames = { parameters -> |
| return parameters. |
| collect { param -> |
| param.name |
| } |
| } |
| |
| def isParamsArgCastNecessary = { parameterString -> |
| if (parameterString.contains("params ")) { |
| def paramsType = parameterString.substring(parameterString.indexOf("params ") + "params ".length(), parameterString.indexOf("[]")) |
| return paramsType == "E" || paramsType == "S" |
| } |
| return false |
| } |
| |
| def hasMethodNoGenericCounterPartInGraphTraversal = { method -> |
| def parameterTypeNames = getJavaParameterTypeNames(method) |
| if (method.name.equals("fold")) { |
| return parameterTypeNames.size() == 0 |
| } |
| return false |
| } |
| |
| def t2withSpecialGraphTraversalt2 = ["IList<E2>": "E2"] |
| |
| def getGraphTraversalT2ForT2 = { t2 -> |
| if (t2withSpecialGraphTraversalt2.containsKey(t2)) { |
| return t2withSpecialGraphTraversalt2.get(t2) |
| } |
| return t2 |
| } |
| |
| def gatherTokensFrom = { tokenClasses -> |
| def m = [:] |
| tokenClasses.each { tc -> m << [(tc.simpleName) : tc.getFields().sort{ a, b -> a.name <=> b.name }.collectEntries{ f -> [(f.name) : f.get(null)]}]} |
| return m |
| } |
| |
| def binding = ["pmethods": P.class.getMethods(). |
| findAll { Modifier.isStatic(it.getModifiers()) }. |
| findAll { P.class.isAssignableFrom(it.returnType) }. |
| collect { it.name }. |
| unique(). |
| sort { a, b -> a <=> b }, |
| "tpmethods": TextP.class.getMethods(). |
| findAll { Modifier.isStatic(it.getModifiers()) }. |
| findAll { TextP.class.isAssignableFrom(it.returnType) }. |
| collect { it.name }. |
| unique(). |
| sort { a, b -> a <=> b }, |
| "sourceStepMethods": GraphTraversalSource.getMethods(). // SOURCE STEPS |
| findAll { GraphTraversalSource.class.equals(it.returnType) }. |
| findAll { |
| !it.name.equals("clone") && |
| !it.name.equals(TraversalSource.Symbols.withRemote) && |
| !it.name.equals(TraversalSource.Symbols.withComputer) |
| }. |
| // Select unique combination of C# parameter types and sort by Java parameter type combination |
| sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }. |
| unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }. |
| collect { javaMethod -> |
| def parameters = getCSharpParamString(javaMethod, false) |
| def paramNames = getParamNames(javaMethod.parameters) |
| return ["methodName": javaMethod.name, "parameters":parameters, "paramNames":paramNames] |
| }, |
| "sourceSpawnMethods": GraphTraversalSource.getMethods(). // SPAWN STEPS |
| findAll { GraphTraversal.class.equals(it.returnType) }. |
| // Select unique combination of C# parameter types and sort by Java parameter type combination |
| sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }. |
| unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }. |
| collect { javaMethod -> |
| def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod) |
| def t1 = toCSharpType(typeNames[0]) |
| def t2 = toCSharpType(typeNames[1]) |
| def tParam = getCSharpGenericTypeParam(t2) |
| def parameters = getCSharpParamString(javaMethod, true) |
| def paramNames = getParamNames(javaMethod.parameters) |
| def isArgsCastNecessary = isParamsArgCastNecessary(parameters) |
| return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "isArgsCastNecessary":isArgsCastNecessary] |
| }, |
| "graphStepMethods": GraphTraversal.getMethods(). |
| findAll { GraphTraversal.class.equals(it.returnType) }. |
| findAll { !it.name.equals("clone") && !it.name.equals("iterate") }. |
| // Select unique combination of C# parameter types and sort by Java parameter type combination |
| sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }. |
| unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }. |
| collect { javaMethod -> |
| def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod) |
| def t1 = toCSharpType(typeNames[0]) |
| def t2 = toCSharpType(typeNames[1]) |
| def tParam = getCSharpGenericTypeParam(t2) |
| def specificTypes = methodsWithSpecificTypes.get(javaMethod.name) |
| if (specificTypes) { |
| t2 = specificTypes[0] |
| tParam = specificTypes.size() > 1 ? "<" + specificTypes[1] + ">" : "" |
| } |
| def parameters = getCSharpParamString(javaMethod, true) |
| def paramNames = getParamNames(javaMethod.parameters) |
| def isArgsCastNecessary = isParamsArgCastNecessary(parameters) |
| return ["methodName": javaMethod.name, "t1":t1, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "isArgsCastNecessary":isArgsCastNecessary] |
| }, |
| "anonStepMethods": __.class.getMethods(). |
| findAll { GraphTraversal.class.equals(it.returnType) }. |
| findAll { Modifier.isStatic(it.getModifiers()) }. |
| findAll { !it.name.equals("__") && !it.name.equals("start") }. |
| // Select unique combination of C# parameter types and sort by Java parameter type combination |
| sort { a, b -> a.name <=> b.name ?: getJavaParamTypeString(a) <=> getJavaParamTypeString(b) }. |
| unique { a,b -> a.name <=> b.name ?: getCSharpParamTypeString(a) <=> getCSharpParamTypeString(b) }. |
| collect { javaMethod -> |
| def typeNames = getJavaGenericTypeParameterTypeNames(javaMethod) |
| def t2 = toCSharpType(typeNames[1]) |
| def tParam = getCSharpGenericTypeParam(t2) |
| def specificTypes = methodsWithSpecificTypes.get(javaMethod.name) |
| if (specificTypes) { |
| t2 = specificTypes[0] |
| tParam = specificTypes.size() > 1 ? "<" + specificTypes[1] + ">" : "" |
| } |
| def parameters = getCSharpParamString(javaMethod, true) |
| def paramNames = getParamNames(javaMethod.parameters) |
| def callGenericTypeArg = hasMethodNoGenericCounterPartInGraphTraversal(javaMethod) ? "" : tParam |
| def graphTraversalT2 = getGraphTraversalT2ForT2(t2) |
| return ["methodName": javaMethod.name, "t2":t2, "tParam":tParam, "parameters":parameters, "paramNames":paramNames, "callGenericTypeArg":callGenericTypeArg, "graphTraversalT2":graphTraversalT2] |
| }, |
| "tokens": gatherTokensFrom([IO, ConnectedComponent, ShortestPath, PageRank, PeerPressure]), |
| "toCSharpMethodName": toCSharpMethodName, |
| "withOptions": WithOptions.getDeclaredFields(). |
| collect {["type": toCSharpType(it.type.simpleName), "name": toCSharpMethodName(it.name), "value": toCSharpValue(it.type, it.get(null))]}] |
| |
| def engine = new groovy.text.GStringTemplateEngine() |
| def traversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversal.template")).make(binding) |
| def traversalFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs") |
| traversalFile.newWriter().withWriter{ it << traversalTemplate } |
| |
| def graphTraversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/GraphTraversalSource.template")).make(binding) |
| def graphTraversalFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/GraphTraversalSource.cs") |
| graphTraversalFile.newWriter().withWriter{ it << graphTraversalTemplate } |
| |
| def anonymousTraversalTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/AnonymousTraversal.template")).make(binding) |
| def anonymousTraversalFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/__.cs") |
| anonymousTraversalFile.newWriter().withWriter{ it << anonymousTraversalTemplate } |
| |
| def pTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/P.template")).make(binding) |
| def pFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/P.cs") |
| pFile.newWriter().withWriter{ it << pTemplate } |
| |
| def tpTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/TextP.template")).make(binding) |
| def tpFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/TextP.cs") |
| tpFile.newWriter().withWriter{ it << tpTemplate } |
| |
| def withOptionsTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/WithOptions.template")).make(binding) |
| def withOptionsFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/WithOptions.cs") |
| withOptionsFile.newWriter().withWriter{ it << withOptionsTemplate } |
| |
| binding.tokens.each {k,v -> |
| def tokenTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Token.template")).make([tokenFields: v, tokenName: k]) |
| def tokenFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/${k}.cs") |
| tokenFile.newWriter().withWriter{ it << tokenTemplate } |
| } |
| |
| def createEnum = { enumClass -> |
| def b = ["enumClass": enumClass, |
| "implementedTypes": enumClass.getInterfaces(). |
| collect { it.getSimpleName() }. |
| findAll { toCSharpTypeMap.containsKey(it) }. |
| findAll { toCSharpTypeMap[it] != "object" }. |
| sort { a, b -> a <=> b }. |
| collect(["EnumWrapper"]) { typeName -> |
| return toCSharpTypeMap[typeName] |
| }.join(", "), |
| "constants": enumClass.getEnumConstants(). |
| sort { a, b -> a.name() <=> b.name() }, |
| "directionClass": Direction.class ] |
| |
| def enumTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Enum.template")).make(b) |
| def enumFile = new File("${projectBaseDir}/src/Gremlin.Net/Process/Traversal/" + enumClass.getSimpleName() + ".cs") |
| enumFile.newWriter().withWriter{ it << enumTemplate } |
| } |
| |
| CoreImports.getClassImports().findAll { Enum.class.isAssignableFrom(it) }. |
| sort { a, b -> a.getSimpleName() <=> b.getSimpleName() }. |
| each { createEnum(it) } |
| |
| def determineVersion = { |
| def env = System.getenv() |
| def mavenVersion = env.containsKey("TP_RELEASE_VERSION") ? env.get("DOTNET_RELEASE_VERSION") : "${projectVersion}" |
| |
| // only want to generate a timestamp for the version if this is a nuget deploy |
| if (!mavenVersion.endsWith("-SNAPSHOT") || null == System.getProperty("nuget")) return mavenVersion |
| |
| return mavenVersion.replace("-SNAPSHOT", "-dev-" + System.currentTimeMillis()) |
| } |
| |
| def versionToUse = determineVersion() |
| def csprojTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.csproj.template")).make(["projectVersion":versionToUse]) |
| def csprojFile = new File("${projectBaseDir}/src/Gremlin.Net/Gremlin.Net.csproj") |
| csprojFile.newWriter().withWriter{ it << csprojTemplate } |
| def templateCsprojTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.Template.csproj.template")).make(["projectVersion":versionToUse]) |
| def templateCsprojFile = new File("${projectBaseDir}/src/Gremlin.Net.Template/Gremlin.Net.Template.csproj") |
| templateCsprojFile.newWriter().withWriter{ it << templateCsprojTemplate } |
| def nuspecTemplate = engine.createTemplate(new File("${projectBaseDir}/glv/Gremlin.Net.Template.nuspec.template")).make(["projectVersion":versionToUse]) |
| def nuspecFile = new File("${projectBaseDir}/src/Gremlin.Net.Template/Gremlin.Net.Template.nuspec") |
| nuspecFile.newWriter().withWriter{ it << nuspecTemplate } |