You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2016/07/05 18:13:49 UTC
tinkerpop git commit: Created ReflectionTranslator which uses Java
reflection to generate a Traversal from ByteCode in Java. If ByteCode does
not have lambdas,
then translators can default to this translator when evaluating on the JVM.
This is all settin
Repository: tinkerpop
Updated Branches:
refs/heads/TINKERPOP-1278 539a4fc14 -> 756b2806b
Created ReflectionTranslator which uses Java reflection to generate a Traversal from ByteCode in Java. If ByteCode does not have lambdas, then translators can default to this translator when evaluating on the JVM. This is all setting up to instead of sending the Script string, drivers will just send ByteCode as it can be translated remotely into a Script string or (via ReflectionTranslator) into a Traversal directly without using a ScriptEngine. --- might rename ReflectionTranslator to JavaTranslator to keep with the target language naming convention.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/756b2806
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/756b2806
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/756b2806
Branch: refs/heads/TINKERPOP-1278
Commit: 756b2806b939d5e13204724d313a6fad0b4f0da1
Parents: 539a4fc
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Jul 5 12:13:42 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Jul 5 12:13:42 2016 -0600
----------------------------------------------------------------------
.../gremlin/process/traversal/ByteCode.java | 25 +++-
.../traversal/util/ReflectionTranslator.java | 117 +++++++++++++++++++
.../java/translator/GroovyTranslator.java | 5 +-
.../java/translator/PythonTranslator.java | 4 +-
.../structure/TinkerGraphPlayTest.java | 12 +-
5 files changed, 154 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/756b2806/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 d5fab83..09a8bc1 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
@@ -42,11 +42,11 @@ public final class ByteCode implements Cloneable, Serializable {
private List<Instruction> stepInstructions = new ArrayList<>();
public void addSource(final String sourceName, final Object... arguments) {
- this.sourceInstructions.add(new Instruction(sourceName, arguments));
+ this.sourceInstructions.add(new Instruction(sourceName, flattenArguments(arguments).toArray()));
}
public void addStep(final String stepName, final Object... arguments) {
- this.stepInstructions.add(new Instruction(stepName, arguments));
+ this.stepInstructions.add(new Instruction(stepName, flattenArguments(arguments).toArray()));
}
public List<Instruction> getSourceInstructions() {
@@ -152,4 +152,25 @@ public final class ByteCode implements Cloneable, Serializable {
}
}
+
+ /////
+
+ private static List<Object> flattenArguments(final Object... arguments) {
+ if (arguments.length == 0)
+ return Collections.emptyList();
+ final List<Object> flatArguments = new ArrayList<>();
+ for (final Object object : arguments) {
+ if (object instanceof Object[]) {
+ Collections.addAll(flatArguments, (Object[]) object);
+ } else
+ flatArguments.add(convertArgument(object));
+ }
+ return flatArguments;
+ }
+
+ private static Object convertArgument(final Object argument) {
+ if(argument instanceof Traversal.Admin)
+ return ((Traversal.Admin) argument).getByteCode();
+ return argument;
+ }
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/756b2806/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReflectionTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReflectionTranslator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReflectionTranslator.java
new file mode 100644
index 0000000..a640c49
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ReflectionTranslator.java
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+package org.apache.tinkerpop.gremlin.process.traversal.util;
+
+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.dsl.graph.__;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.Arrays;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class ReflectionTranslator implements Translator<Traversal.Admin<?, ?>> {
+
+ private final TraversalSource source;
+
+ public ReflectionTranslator(final TraversalSource source) {
+ this.source = source;
+ }
+
+ @Override
+ public String getAlias() {
+ return null;
+ }
+
+ @Override
+ public Traversal.Admin<?, ?> translate(final ByteCode byteCode) {
+ TraversalSource tempSource = this.source;
+ Traversal.Admin<?, ?> traversal = null == this.source ? __.start().asAdmin() : null;
+ boolean fromSource = null == traversal;
+ if (null != tempSource) {
+ for (final ByteCode.Instruction instruction : byteCode.getSourceInstructions()) {
+ tempSource = (TraversalSource) invokeMethod(tempSource, TraversalSource.class, instruction.getOperator(), instruction.getArguments());
+ }
+ }
+ for (final ByteCode.Instruction instruction : byteCode.getStepInstructions()) {
+ if (fromSource) {
+ traversal = (Traversal.Admin) invokeMethod(tempSource, Traversal.class, instruction.getOperator(), instruction.getArguments());
+ fromSource = false;
+ } else
+ invokeMethod(traversal, Traversal.class, instruction.getOperator(), instruction.getArguments());
+ }
+ return traversal;
+ }
+
+ @Override
+ public String getSourceLanguage() {
+ return null;
+ }
+
+ @Override
+ public String getTargetLanguage() {
+ return "gremlin-java";
+ }
+
+ ////
+
+ private static Object invokeMethod(final Object delegate, final Class returnType, final String methodName, final Object... arguments) {
+ try {
+ for (final Method method : delegate.getClass().getMethods()) {
+ if (method.getName().equals(methodName)) {
+ if (returnType.isAssignableFrom(method.getReturnType())) {
+ if (method.getParameterCount() == arguments.length || method.getParameters()[method.getParameters().length - 1].isVarArgs()) {
+ final Parameter[] parameters = method.getParameters();
+ final Object[] newArguments = new Object[parameters.length];
+ boolean found = true;
+ for (int i = 0; i < parameters.length; i++) {
+ if (parameters[i].isVarArgs()) {
+ newArguments[i] = Arrays.copyOfRange(arguments, i, arguments.length, (Class) parameters[i].getType());
+ break;
+ } else {
+ if (arguments.length > 0 && (parameters[i].getType().isPrimitive() ||
+ parameters[i].getType().isAssignableFrom(arguments[i].getClass()) ||
+ parameters[i].getType().isAssignableFrom(Traversal.Admin.class) && arguments[i] instanceof ByteCode)) {
+ newArguments[i] = arguments[i] instanceof ByteCode ?
+ new ReflectionTranslator(null).translate((ByteCode) arguments[i]) :
+ arguments[i];
+ } else {
+ found = false;
+ break;
+ }
+ }
+ }
+ if (found)
+ return 0 == newArguments.length ? method.invoke(delegate) : method.invoke(delegate, newArguments);
+ }
+ }
+ }
+ }
+ } catch (Throwable e) {
+ throw new IllegalStateException(e.getMessage() + methodName, e);
+ }
+ throw new IllegalStateException("could not find method: " + methodName + "--" + Arrays.toString(arguments));
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/756b2806/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/java/translator/GroovyTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/java/translator/GroovyTranslator.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/java/translator/GroovyTranslator.java
index 2fd13ee..a1db4db 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/java/translator/GroovyTranslator.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/java/translator/GroovyTranslator.java
@@ -24,7 +24,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.ByteCode;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
import org.apache.tinkerpop.gremlin.process.traversal.Translator;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
@@ -133,8 +132,8 @@ public final class GroovyTranslator implements Translator<String> {
} else if (object instanceof Lambda) {
final String lambdaString = ((Lambda) object).getLambdaScript();
return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
- } else if (object instanceof Traversal)
- return new GroovyTranslator("__").translate(((Traversal.Admin) object).getByteCode()).toString(); // TODO: make a static GroovyTranslator(__) object
+ } else if (object instanceof ByteCode)
+ return new GroovyTranslator("__").translate((ByteCode) object).toString(); // TODO: make a static GroovyTranslator(__) object
else
return null == object ? "null" : object.toString();
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/756b2806/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/java/translator/PythonTranslator.java
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/java/translator/PythonTranslator.java b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/java/translator/PythonTranslator.java
index 7af5f1d..8159a9d 100644
--- a/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/java/translator/PythonTranslator.java
+++ b/gremlin-python/src/main/java/org/apache/tinkerpop/gremlin/java/translator/PythonTranslator.java
@@ -161,8 +161,8 @@ public class PythonTranslator implements Translator<String> {
return convertPToString((P) object, new StringBuilder()).toString();
else if (object instanceof Element)
return convertToString(((Element) object).id()); // hack
- else if (object instanceof Traversal)
- return new PythonTranslator("__", this.importStatics).translate(((Traversal.Admin) object).getByteCode());
+ else if (object instanceof ByteCode)
+ return new PythonTranslator("__", this.importStatics).translate(((ByteCode) object));
else if (object instanceof Computer) {
return "";
} else if (object instanceof Lambda) {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/756b2806/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index 96d11e3..f44ad96 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -18,10 +18,12 @@
*/
package org.apache.tinkerpop.gremlin.tinkergraph.structure;
+import org.apache.tinkerpop.gremlin.process.traversal.ByteCode;
import org.apache.tinkerpop.gremlin.process.traversal.Operator;
import org.apache.tinkerpop.gremlin.process.traversal.P;
import org.apache.tinkerpop.gremlin.process.traversal.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.ReflectionTranslator;
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.dsl.graph.__;
@@ -63,8 +65,14 @@ public class TinkerGraphPlayTest {
@Ignore
public void testPlay8() throws Exception {
Graph graph = TinkerFactory.createModern();
- GraphTraversalSource g = graph.traversal().withComputer();//GraphTraversalSource.computer());
- System.out.println(g.V().as("a").out().repeat(both("created")).times(10).as("b").values("name").dedup().select("a", "b").by("name").asAdmin().getByteCode());
+ GraphTraversalSource g = graph.traversal();//GraphTraversalSource.computer());
+ System.out.println(g.V().as("a").repeat(out("created", "knows")).times(2).as("b").dedup().select("a", "b").toList());
+ final ByteCode byteCode = g.withComputer().V().as("a").repeat(out("created", "knows")).times(2).as("b").dedup().select("a", "b").asAdmin().getByteCode();
+ ReflectionTranslator translator = new ReflectionTranslator(g);
+ Traversal.Admin<?, ?> traversal = translator.translate(byteCode);
+ System.out.println(traversal);
+ System.out.println(traversal.toList());
+ System.out.println(traversal);
}
@Test