Repository: tinkerpop Updated Branches: refs/heads/TINKERPOP-1278 c3ec2f09a -> b11bf2077
Added the much needed Bytecode.getInstructions() method. Was able to really make GroovyTranslator and PythonTranslator more compact and easy to reason about. Optimized a few things in those respective translators. TranslationStrategy (used in testing) inserts bindings for various arguments like knows/created so we know that bindings in the various translations are working as expected. Bytecode.getStep/SourceInstructions() now returns Iterable, not List. Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/b11bf207 Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/b11bf207 Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/b11bf207 Branch: refs/heads/TINKERPOP-1278 Commit: b11bf2077036a7d0b4b7e7d06b2cfe870122e1a1 Parents: c3ec2f0 Author: Marko A. Rodriguez <okramma...@gmail.com> Authored: Wed Aug 10 08:53:57 2016 -0600 Committer: Marko A. Rodriguez <okramma...@gmail.com> Committed: Wed Aug 10 08:54:37 2016 -0600 ---------------------------------------------------------------------- .../gremlin/process/traversal/Bytecode.java | 61 ++++++++++++++++---- .../process/traversal/util/BytecodeHelper.java | 13 +---- .../graphson/GraphSONTraversalSerializers.java | 4 +- .../gremlin/groovy/jsr223/GroovyTranslator.java | 39 +++++-------- .../jsr223/GremlinJythonScriptEngine.java | 2 +- .../gremlin/python/jsr223/PythonTranslator.java | 41 +++++-------- .../jsr223/PythonGraphSONJavaTranslator.java | 12 +--- .../gremlin/python/jsr223/PythonProvider.java | 2 +- .../decoration/TranslationStrategy.java | 32 +++++++++- 9 files changed, 114 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java index 0be140c..ef82d8e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Bytecode.java @@ -20,21 +20,24 @@ package org.apache.tinkerpop.gremlin.process.traversal; import org.apache.tinkerpop.gremlin.structure.util.StringFactory; +import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; /** - * When a {@link TraversalSource} is manipulated, a {@link Traversal} is spawned and then mutated, a language - * agnostic representation of those mutations is recorded in a byte code instance. Byte code is simply a list - * of ordered instructions where an instruction is a string operator and an array of arguments. Byte code is used by - * {@link Translator} instances which translate a traversal to another language by analyzing the - * byte code as opposed to the Java traversal object representation on heap. + * When a {@link TraversalSource} is manipulated and then a {@link Traversal} is spawned and mutated, a language + * agnostic representation of those mutations is recorded in a bytecode instance. Bytecode is simply a list + * of ordered instructions where an instruction is a string operator and a (flattened) array of arguments. + * Bytecode is used by {@link Translator} instances which are able to translate a traversal in one language to another + * by analyzing the bytecode as opposed to the Java traversal object representation on heap. + * <p> + * Bytecode can be serialized between environments and machines by way of a GraphSON representation. + * Thus, Gremlin-Python can create bytecode in Python and ship it to Gremlin-Java for evaluation in Java. * * @author Marko A. Rodriguez (http://markorodriguez.com) */ @@ -42,9 +45,14 @@ public final class Bytecode implements Cloneable, Serializable { private List<Instruction> sourceInstructions = new ArrayList<>(); private List<Instruction> stepInstructions = new ArrayList<>(); - // required for Gremlin-Java private transient Bindings bindings = null; + /** + * Add a {@link TraversalSource} instruction to the bytecode. + * + * @param sourceName the traversal source method name (e.g. withSack()) + * @param arguments the traversal source method arguments + */ public void addSource(final String sourceName, final Object... arguments) { if (sourceName.equals(TraversalSource.Symbols.withBindings)) { this.bindings = (Bindings) arguments[0]; @@ -55,19 +63,50 @@ public final class Bytecode implements Cloneable, Serializable { } } + /** + * Add a {@link Traversal} instruction to the bytecode. + * + * @param stepName the traversal method name (e.g. out()) + * @param arguments the traversal method arguments + */ public void addStep(final String stepName, final Object... arguments) { this.stepInstructions.add(new Instruction(stepName, flattenArguments(arguments))); if (null != this.bindings) this.bindings.clear(); } - public List<Instruction> getSourceInstructions() { - return Collections.unmodifiableList(this.sourceInstructions); + /** + * Get the {@link TraversalSource} instructions associated with this bytecode. + * + * @return an iterable of instructions + */ + public Iterable<Instruction> getSourceInstructions() { + return this.sourceInstructions; } - public List<Instruction> getStepInstructions() { - return Collections.unmodifiableList(this.stepInstructions); + /** + * Get the {@link Traversal} instructions associated with this bytecode. + * + * @return an iterable of instructions + */ + public Iterable<Instruction> getStepInstructions() { + return this.stepInstructions; } + /** + * Get both the {@link TraversalSource} and {@link Traversal} instructions of this bytecode. + * The traversal source instructions are provided prior to the traversal instructions. + * + * @return an interable of all the instructions in this bytecode + */ + public Iterable<Instruction> getInstructions() { + return () -> IteratorUtils.concat(this.sourceInstructions.iterator(), this.stepInstructions.iterator()); + } + + /** + * Get all the bindings (in a nested, recurssive manner) from all the arguments of all the instructions of this bytecode. + * + * @return a map of string variable and object value bindings + */ public Map<String, Object> getBindings() { final Map<String, Object> bindingsMap = new HashMap<>(); for (final Instruction instruction : this.sourceInstructions) { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java index 43f3828..dc611d6 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/BytecodeHelper.java @@ -48,18 +48,7 @@ public final class BytecodeHelper { } public static Optional<String> getLambdaLanguage(final Bytecode bytecode) { - for (final Bytecode.Instruction instruction : bytecode.getSourceInstructions()) { - for (Object object : instruction.getArguments()) { - if (object instanceof Lambda) - return Optional.of(((Lambda) object).getLambdaLanguage()); - else if (object instanceof Bytecode) { - final Optional<String> temp = BytecodeHelper.getLambdaLanguage((Bytecode) object); - if (temp.isPresent()) - return temp; - } - } - } - for (final Bytecode.Instruction instruction : bytecode.getStepInstructions()) { + for (final Bytecode.Instruction instruction : bytecode.getInstructions()) { for (Object object : instruction.getArguments()) { if (object instanceof Lambda) return Optional.of(((Lambda) object).getLambdaLanguage()); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializers.java ---------------------------------------------------------------------- diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializers.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializers.java index 037ce96..89f0b42 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializers.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONTraversalSerializers.java @@ -88,7 +88,7 @@ public final class GraphSONTraversalSerializers { throws IOException { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("@type", "Bytecode"); - if (!bytecode.getSourceInstructions().isEmpty()) { + if (bytecode.getSourceInstructions().iterator().hasNext()) { jsonGenerator.writeArrayFieldStart("source"); for (final Bytecode.Instruction instruction : bytecode.getSourceInstructions()) { jsonGenerator.writeStartArray(); @@ -100,7 +100,7 @@ public final class GraphSONTraversalSerializers { } jsonGenerator.writeEndArray(); } - if (!bytecode.getStepInstructions().isEmpty()) { + if (bytecode.getStepInstructions().iterator().hasNext()) { jsonGenerator.writeArrayFieldStart("step"); for (final Bytecode.Instruction instruction : bytecode.getStepInstructions()) { jsonGenerator.writeStartArray(); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslator.java ---------------------------------------------------------------------- diff --git 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 index fdb3ece..9349c90 100644 --- 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 @@ -33,7 +33,6 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory; import org.apache.tinkerpop.gremlin.util.function.Lambda; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -88,31 +87,23 @@ public final class GroovyTranslator implements Translator.ScriptTranslator { private String internalTranslate(final String start, final Bytecode bytecode) { final StringBuilder traversalScript = new StringBuilder(start); - for (final Bytecode.Instruction instruction : bytecode.getSourceInstructions()) { - processInstruction(traversalScript, instruction); - } - for (final Bytecode.Instruction instruction : bytecode.getStepInstructions()) { - processInstruction(traversalScript, instruction); - } - return traversalScript.toString(); - } - - private void processInstruction(final StringBuilder traversalScript, final Bytecode.Instruction instruction) { - final String methodName = instruction.getOperator(); - if (methodName.equals(TraversalSource.Symbols.withStrategies)) - return; - final Object[] arguments = instruction.getArguments(); - final List<Object> objects = Arrays.asList(arguments); - if (objects.isEmpty()) - traversalScript.append(".").append(methodName).append("()"); - else { - traversalScript.append("."); - String temp = methodName + "("; - for (final Object object : objects) { - temp = temp + convertToString(object) + ","; + for (final Bytecode.Instruction instruction : bytecode.getInstructions()) { + final String methodName = instruction.getOperator(); + if (methodName.equals(TraversalSource.Symbols.withStrategies)) + continue; + final Object[] arguments = instruction.getArguments(); + if (0 == arguments.length) + traversalScript.append(".").append(methodName).append("()"); + else { + traversalScript.append("."); + String temp = methodName + "("; + for (final Object object : arguments) { + temp = temp + convertToString(object) + ","; + } + traversalScript.append(temp.substring(0, temp.length() - 1)).append(")"); } - traversalScript.append(temp.substring(0, temp.length() - 1)).append(")"); } + return traversalScript.toString(); } private String convertToString(final Object object) { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java index 3ea21e4..a10cb3f 100644 --- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java +++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/GremlinJythonScriptEngine.java @@ -119,7 +119,7 @@ public class GremlinJythonScriptEngine implements GremlinScriptEngine { public Traversal.Admin eval(final Bytecode bytecode, final Bindings bindings) throws ScriptException { bindings.putAll(bytecode.getBindings()); // TODO: this is kinda bad because it makes the assumption that we will always alias to "g" (which is generally true, but maybe better to not hardcode?) - return (Traversal.Admin) this.eval(new PythonTranslator("g", "__").translate(bytecode), bindings); + return (Traversal.Admin) this.eval(PythonTranslator.of("g", "__").translate(bytecode), bindings); } @Override http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java index 70bb38b..20cc21b 100644 --- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java +++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonTranslator.java @@ -62,14 +62,22 @@ public final class PythonTranslator implements Translator.ScriptTranslator { private String anonymousTraversal; private final boolean importStatics; - public PythonTranslator(final String traversalSource, final String anonymousTraversal, final boolean importStatics) { + private PythonTranslator(final String traversalSource, final String anonymousTraversal, final boolean importStatics) { this.traversalSource = traversalSource; this.anonymousTraversal = anonymousTraversal; this.importStatics = importStatics; } - public PythonTranslator(final String traversalSource, final String anonymousTraversal) { - this(traversalSource, anonymousTraversal, false); + public static final PythonTranslator of(final String traversalSource, final String anonymousTraversal, final boolean importStatics) { + return new PythonTranslator(traversalSource, anonymousTraversal, importStatics); + } + + public static final PythonTranslator of(final String traversalSource, final String anonymousTraversal) { + return new PythonTranslator(traversalSource, anonymousTraversal, false); + } + + public static final PythonTranslator of(final String traversalSource) { + return new PythonTranslator(traversalSource, "__", false); } @Override @@ -104,32 +112,12 @@ public final class PythonTranslator implements Translator.ScriptTranslator { private String internalTranslate(final String start, final Bytecode bytecode) { final StringBuilder traversalScript = new StringBuilder(start); - for (final Bytecode.Instruction instruction : bytecode.getSourceInstructions()) { + for (final Bytecode.Instruction instruction : bytecode.getInstructions()) { final String methodName = instruction.getOperator(); + final Object[] arguments = instruction.getArguments(); if (methodName.equals(TraversalSource.Symbols.withStrategies)) continue; - final Object[] arguments = instruction.getArguments(); - if (0 == arguments.length) - traversalScript.append(".").append(SymbolHelper.toPython(methodName)).append("()"); - else { - traversalScript.append("."); - String temp = SymbolHelper.toPython(methodName) + "("; - for (final Object object : arguments) { - temp = temp + convertToString(object) + ","; - } - traversalScript.append(temp.substring(0, temp.length() - 1)).append(")"); - } - - // clip off __. - if (this.importStatics && traversalScript.substring(0, 3).startsWith(this.anonymousTraversal + ".") - && !NO_STATIC.stream().filter(name -> traversalScript.substring(3).startsWith(SymbolHelper.toPython(name))).findAny().isPresent()) { - traversalScript.delete(0, 3); - } - } - for (final Bytecode.Instruction instruction : bytecode.getStepInstructions()) { - final String methodName = instruction.getOperator(); - final Object[] arguments = instruction.getArguments(); - if (0 == arguments.length) + else if (0 == arguments.length) traversalScript.append(".").append(SymbolHelper.toPython(methodName)).append("()"); else if (methodName.equals("range") && 2 == arguments.length) traversalScript.append("[").append(arguments[0]).append(":").append(arguments[1]).append("]"); @@ -145,7 +133,6 @@ public final class PythonTranslator implements Translator.ScriptTranslator { } traversalScript.append(temp.substring(0, temp.length() - 1)).append(")"); } - // clip off __. if (this.importStatics && traversalScript.substring(0, 3).startsWith(this.anonymousTraversal + ".") && !NO_STATIC.stream().filter(name -> traversalScript.substring(3).startsWith(SymbolHelper.toPython(name))).findAny().isPresent()) { http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java index 2a55228..f4e5cc7 100644 --- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java +++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonGraphSONJavaTranslator.java @@ -24,8 +24,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; import org.apache.tinkerpop.gremlin.process.traversal.Translator; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource; -import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException; -import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONReader; import org.apache.tinkerpop.gremlin.util.ScriptEngineCache; @@ -37,7 +35,7 @@ import java.io.ByteArrayInputStream; /** * @author Marko A. Rodriguez (http://markorodriguez.com) */ -public class PythonGraphSONJavaTranslator<S extends TraversalSource, T extends Traversal.Admin<?, ?>> implements Translator.StepTranslator<S, T> { +final class PythonGraphSONJavaTranslator<S extends TraversalSource, T extends Traversal.Admin<?, ?>> implements Translator.StepTranslator<S, T> { private final PythonTranslator pythonTranslator; private final JavaTranslator<S, T> javaTranslator; @@ -65,14 +63,6 @@ public class PythonGraphSONJavaTranslator<S extends TraversalSource, T extends T @Override public T translate(final Bytecode bytecode) { - - for (final Bytecode.Instruction instruction : bytecode.getStepInstructions()) { - for (final Object argument : instruction.getArguments()) { - if (argument.toString().contains("$")) - throw new VerificationException("Lambdas are currently not supported: " + bytecode, EmptyTraversal.instance()); - } - } - try { final ScriptEngine jythonEngine = ScriptEngineCache.get("jython"); final Bindings bindings = jythonEngine.createBindings(); http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java ---------------------------------------------------------------------- diff --git a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java index 56b0963..1414f8b 100644 --- a/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java +++ b/gremlin-python/src/test/java/org/apache/tinkerpop/gremlin/python/jsr223/PythonProvider.java @@ -157,7 +157,7 @@ public class PythonProvider extends AbstractGraphProvider { throw new IllegalStateException(e.getMessage(), e); } final GraphTraversalSource g = graph.traversal(); - return g.withStrategies(new TranslationStrategy(g, new PythonGraphSONJavaTranslator<>(new PythonTranslator("g", "__", IMPORT_STATICS), JavaTranslator.of(g)))); + return g.withStrategies(new TranslationStrategy(g, new PythonGraphSONJavaTranslator<>(PythonTranslator.of("g", "__", IMPORT_STATICS), JavaTranslator.of(g)))); } } http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b11bf207/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java ---------------------------------------------------------------------- diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java index 5ad7401..92c9483 100644 --- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java +++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/TranslationStrategy.java @@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration; import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine; import org.apache.tinkerpop.gremlin.jsr223.SingleGremlinScriptEngineManager; import org.apache.tinkerpop.gremlin.process.remote.traversal.strategy.decoration.RemoteStrategy; +import org.apache.tinkerpop.gremlin.process.traversal.Bytecode; import org.apache.tinkerpop.gremlin.process.traversal.Step; import org.apache.tinkerpop.gremlin.process.traversal.Translator; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; @@ -71,13 +72,16 @@ public final class TranslationStrategy extends AbstractTraversalStrategy<Travers // verifications to ensure unsupported steps do not exist in the traversal if (Boolean.valueOf(System.getProperty("is.testing", "false")) && (traversal.getBytecode().toString().contains("$") || traversal.getBytecode().toString().contains("HashSetSupplier"))) - throw new VerificationException("Test suite does not support profiling nor lambdas", traversal); + throw new VerificationException("Test suite does not support lambdas", traversal); final Traversal.Admin<?, ?> translatedTraversal; + final Bytecode bytecode = Boolean.valueOf(System.getProperty("is.testing", "false")) ? + insertBindingsForTesting(traversal.getBytecode()) : + traversal.getBytecode(); //////////////// if (this.translator instanceof Translator.StepTranslator) { // reflection based translation - translatedTraversal = (Traversal.Admin<?, ?>) this.translator.translate(traversal.getBytecode()); + translatedTraversal = (Traversal.Admin<?, ?>) this.translator.translate(bytecode); } else if (this.translator instanceof Translator.ScriptTranslator) { try { // script based translation @@ -85,7 +89,7 @@ public final class TranslationStrategy extends AbstractTraversalStrategy<Travers final Bindings bindings = scriptEngine.createBindings(); bindings.putAll(scriptEngine.getContext().getBindings(ScriptContext.ENGINE_SCOPE)); bindings.put(this.translator.getTraversalSource().toString(), this.traversalSource); - translatedTraversal = (Traversal.Admin<?, ?>) scriptEngine.eval(traversal.getBytecode(), bindings); + translatedTraversal = (Traversal.Admin<?, ?>) scriptEngine.eval(bytecode, bindings); } catch (final Exception e) { throw new IllegalArgumentException(e.getMessage(), e); } @@ -106,4 +110,26 @@ public final class TranslationStrategy extends AbstractTraversalStrategy<Travers return POSTS; } + private static final Bytecode insertBindingsForTesting(final Bytecode bytecode) { + final Bytecode newBytecode = new Bytecode(); + bytecode.getSourceInstructions().forEach(instruction -> newBytecode.addSource(instruction.getOperator(), instruction.getArguments())); + for (final Bytecode.Instruction instruction : bytecode.getStepInstructions()) { + final Object[] args = instruction.getArguments(); + final Object[] newArgs = new Object[args.length]; + + for (int i = 0; i < args.length; i++) { + if (args[i].equals("knows")) + newArgs[i] = new Bytecode.Binding<>("a", "knows"); + else if (args[i].equals("created")) + newArgs[i] = new Bytecode.Binding<>("b", "created"); + else if (args[i].equals(10)) + newArgs[i] = new Bytecode.Binding<>("c", 10); + else + newArgs[i] = args[i]; + } + newBytecode.addStep(instruction.getOperator(), newArgs); + } + return newBytecode; + } + }