This is an automated email from the ASF dual-hosted git repository. spmallette pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 0da112f9eb94ee35b39e5d3d73f5507b83b0a5b0 Merge: 9b84456 9f500ec Author: Stephen Mallette <sp...@genoprime.com> AuthorDate: Mon Sep 23 10:11:46 2019 -0400 Merge branch 'tp34' CHANGELOG.asciidoc | 1 + docs/src/reference/gremlin-variants.asciidoc | 8 +++++ .../tinkerpop/gremlin/util/function/Lambda.java | 31 ++++++++++++++++++ .../src/Gremlin.Net/Process/Traversal/Lambda.cs | 4 +-- .../Process/Traversal/StringBasedLambda.cs | 21 +++++++++++- .../GraphTraversalSourceTests.cs | 12 +++++++ .../gremlin/groovy/jsr223/GroovyTranslator.java | 37 +++++++++++++++++++--- .../groovy/jsr223/GroovyTranslatorTest.java | 27 ++++++++++++++++ .../gremlin_python/structure/io/graphsonV2d0.py | 8 +++-- .../gremlin_python/structure/io/graphsonV3d0.py | 8 +++-- .../tests/driver/test_driver_remote_connection.py | 11 +++++++ 11 files changed, 156 insertions(+), 12 deletions(-) diff --cc gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java index 9cd06e7,505f88a..1c21d59 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java @@@ -41,16 -41,17 +42,16 @@@ import org.apache.tinkerpop.gremlin.str import org.apache.tinkerpop.gremlin.util.function.Lambda; import java.sql.Timestamp; --import java.util.ArrayList; import java.util.Date; --import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; --import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; + import java.util.function.BinaryOperator; + import java.util.function.Supplier; + import java.util.function.UnaryOperator; /** * Converts bytecode to a Groovy string of Gremlin. @@@ -281,46 -203,62 +282,72 @@@ public final class GroovyTranslator imp } } else if (object instanceof Lambda) { final String lambdaString = ((Lambda) object).getLambdaScript().trim(); - return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}"; + final String wrapper = lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}"; + return script.getBoundKeyOrAssign(withParameters, withParameters ? object : wrapper); } else if (object instanceof TraversalStrategyProxy) { final TraversalStrategyProxy proxy = (TraversalStrategyProxy) object; - if (proxy.getConfiguration().isEmpty()) - return proxy.getStrategyClass().getCanonicalName() + ".instance()"; - else - return proxy.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration.MapConfiguration(" + convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + "))"; + if (proxy.getConfiguration().isEmpty()) { + return script.append(proxy.getStrategyClass().getCanonicalName() + ".instance()"); + } else { + script.append(proxy.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration2.MapConfiguration("); + convertToScript(ConfigurationConverter.getMap(proxy.getConfiguration())); + return script.append("))"); + } } else if (object instanceof TraversalStrategy) { - return convertToString(new TraversalStrategyProxy(((TraversalStrategy) object))); - } else - return null == object ? "null" : object.toString(); + return convertToScript(new TraversalStrategyProxy(((TraversalStrategy) object))); + } else { + return null == object ? script.append("null") : script.getBoundKeyOrAssign(withParameters, object); + } } - protected String internalTranslate(final String start, final Bytecode bytecode) { - final StringBuilder traversalScript = new StringBuilder(start); + protected Script internalTranslate(final String start, final Bytecode bytecode) { + script.append(start); for (final Bytecode.Instruction instruction : bytecode.getInstructions()) { final String methodName = instruction.getOperator(); - if (0 == instruction.getArguments().length) - traversalScript.append(".").append(methodName).append("()"); - else { - traversalScript.append("."); - String temp = methodName + "("; + if (0 == instruction.getArguments().length) { + script.append(".").append(methodName).append("()"); + } else { + script.append(".").append(methodName).append("("); - for (final Object object : instruction.getArguments()) { - convertToScript(object); + + // have to special case withSack() for Groovy because UnaryOperator and BinaryOperator signatures + // make it impossible for the interpreter to figure out which function to call. specifically we need + // to discern between: + // withSack(A initialValue, UnaryOperator<A> splitOperator) + // withSack(A initialValue, BinaryOperator<A> splitOperator) + // and: + // withSack(Supplier<A> initialValue, UnaryOperator<A> mergeOperator) + // withSack(Supplier<A> initialValue, BinaryOperator<A> mergeOperator) + if (methodName.equals(TraversalSource.Symbols.withSack) && + instruction.getArguments().length == 2 && instruction.getArguments()[1] instanceof Lambda) { + final String castFirstArgTo = instruction.getArguments()[0] instanceof Lambda ? + Supplier.class.getName() : ""; + final Lambda secondArg = (Lambda) instruction.getArguments()[1]; + final String castSecondArgTo = secondArg.getLambdaArguments() == 1 ? UnaryOperator.class.getName() : + BinaryOperator.class.getName(); + if (!castFirstArgTo.isEmpty()) - temp = temp + String.format("(%s) ", castFirstArgTo); - temp = temp + String.format("%s, (%s) %s,", - convertToString(instruction.getArguments()[0]), castSecondArgTo, - convertToString(instruction.getArguments()[1])); ++ script.append(String.format("(%s) ", castFirstArgTo)); ++ convertToScript(instruction.getArguments()[0]); ++ script.append(", ("); ++ script.append(castSecondArgTo); ++ script.append(") "); ++ convertToScript(instruction.getArguments()[1]); + script.append(","); + } else { + for (final Object object : instruction.getArguments()) { - temp = temp + convertToString(object) + ","; ++ convertToScript(object); ++ script.append(","); + } } - traversalScript.append(temp.substring(0, temp.length() - 1)).append(")"); + script.setCharAtEnd(')'); } } - return traversalScript.toString(); + return script; } - protected StringBuilder convertPToString(final P p, final StringBuilder current) { - if (p instanceof TextP) return convertTextPToString((TextP) p, current); + protected Script convertPToScript(final P p) { + if (p instanceof TextP) { + return convertTextPToScript((TextP) p); + } if (p instanceof ConnectiveP) { final List<P<?>> list = ((ConnectiveP) p).getPredicates(); for (int i = 0; i < list.size(); i++) { diff --cc gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java index 420d7fe,71f79ec..523c19f --- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java +++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java @@@ -102,6 -102,32 +103,32 @@@ public class GroovyTranslatorTest } @Test + public void shouldHandleConfusingSacks() { + final TinkerGraph graph = TinkerFactory.createModern(); + final GraphTraversalSource g = graph.traversal(); + + final Traversal<Vertex,Double> tConstantUnary = g.withSack(1.0, Lambda.unaryOperator("it + 1")).V().sack(); - final String scriptConstantUnary = GroovyTranslator.of("g").translate(tConstantUnary.asAdmin().getBytecode()); ++ final String scriptConstantUnary = GroovyTranslator.of("g").translate(tConstantUnary.asAdmin().getBytecode()).getScript(); + assertEquals("g.withSack(1.0d, (java.util.function.UnaryOperator) {it + 1}).V().sack()", scriptConstantUnary); + assertThatScriptOk(scriptConstantUnary, "g", g); + + final Traversal<Vertex,Double> tSupplierUnary = g.withSack(Lambda.supplier("1.0d"), Lambda.<Double>unaryOperator("it + 1")).V().sack(); - final String scriptSupplierUnary = GroovyTranslator.of("g").translate(tSupplierUnary.asAdmin().getBytecode()); ++ final String scriptSupplierUnary = GroovyTranslator.of("g").translate(tSupplierUnary.asAdmin().getBytecode()).getScript(); + assertEquals("g.withSack((java.util.function.Supplier) {1.0d}, (java.util.function.UnaryOperator) {it + 1}).V().sack()", scriptSupplierUnary); + assertThatScriptOk(scriptSupplierUnary, "g", g); + + final Traversal<Vertex,Double> tConstantBinary = g.withSack(1.0, Lambda.binaryOperator("x,y -> x + y + 1")).V().sack(); - final String scriptConstantBinary = GroovyTranslator.of("g").translate(tConstantBinary.asAdmin().getBytecode()); ++ final String scriptConstantBinary = GroovyTranslator.of("g").translate(tConstantBinary.asAdmin().getBytecode()).getScript(); + assertEquals("g.withSack(1.0d, (java.util.function.BinaryOperator) {x,y -> x + y + 1}).V().sack()", scriptConstantBinary); + assertThatScriptOk(scriptConstantBinary, "g", g); + + final Traversal<Vertex,Double> tSupplierBinary = g.withSack(Lambda.supplier("1.0d"), Lambda.<Double>binaryOperator("x,y -> x + y + 1")).V().sack(); - final String scriptSupplierBinary = GroovyTranslator.of("g").translate(tSupplierBinary.asAdmin().getBytecode()); ++ final String scriptSupplierBinary = GroovyTranslator.of("g").translate(tSupplierBinary.asAdmin().getBytecode()).getScript(); + assertEquals("g.withSack((java.util.function.Supplier) {1.0d}, (java.util.function.BinaryOperator) {x,y -> x + y + 1}).V().sack()", scriptSupplierBinary); + assertThatScriptOk(scriptSupplierBinary, "g", g); + } + + @Test public void shouldSupportStringSupplierLambdas() { final TinkerGraph graph = TinkerFactory.createModern(); GraphTraversalSource g = graph.traversal();