You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2020/11/06 16:59:59 UTC

[tinkerpop] branch TINKERPOP-2461 updated: TINKERPOP-2461 Added reference documentation for Translator

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-2461
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/TINKERPOP-2461 by this push:
     new 8043a7d  TINKERPOP-2461 Added reference documentation for Translator
8043a7d is described below

commit 8043a7dd15189103c2d0af65711acd75e45fa415
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Nov 6 11:59:15 2020 -0500

    TINKERPOP-2461 Added reference documentation for Translator
---
 docs/src/reference/gremlin-variants.asciidoc       |   4 +-
 docs/src/reference/the-traversal.asciidoc          |  63 +++++++++++++++++++++
 docs/static/images/gremlin-translator.png          | Bin 0 -> 998775 bytes
 .../traversal/translator/GroovyTranslatorTest.java |  30 +++++-----
 4 files changed, 80 insertions(+), 17 deletions(-)

diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index b3c13cb..4cdc783 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -626,8 +626,8 @@ Gremlin-Java constructs. Moreover, given its scripting nature, Gremlin-Groovy se
 
 [source,groovy]
 ----
-compile group: 'org.apache.tinkerpop', name: 'gremlin-core', version: '3.3.4'
-compile group: 'org.apache.tinkerpop', name: 'gremlin-driver', version: '3.3.4'
+compile group: 'org.apache.tinkerpop', name: 'gremlin-core', version: 'x.y.z'
+compile group: 'org.apache.tinkerpop', name: 'gremlin-driver', version: 'x.y.z'
 ----
 
 [[gremlin-groovy-differences]]
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 7fce8f1..a192993 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -4176,3 +4176,66 @@ social.persons("marko").youngestFriendsAge()
 
 Learn more about how to implement these DSLs in the <<gremlin-drivers-variants,Gremlin Language Variants>> section
 specific to the programming language of interest.
+
+[[translators]]
+== Translators
+
+image::gremlin-translator.png[width=1024]
+
+There are times when is helpful to translate Gremlin from one programming language to another. Perhaps a large Gremlin
+example is found on StackOverflow written in Java, but the programming language the developer has chosen is Python.
+Fortunately, TinkerPop has developed `Translator` infrastructure that will convert Gremlin from one programming
+language syntax to another.
+
+The functionality relevant to most users is actually a sub-function of `Translator` infrastructure and is more
+specifically a `ScriptTranslator` which takes Gremlin `Bytecode` of a traversal and generates a `String` representation
+of that `Bytecode` in the programming language syntax that the `ScriptTranslator` instance supports. The translation
+therefore allows Gremlin to be converted from the host programming language of the `Translator` to another.
+
+The following translators are available:
+
+[width="100%",cols="<,^,^,^,^,^",options="header"]
+|=========================================================
+| |Java |Groovy |Javascript |.NET |Python
+|*Java* |- |X | | |X
+|*Groovy* | |- | | |X
+|*Javascript* | |X |- | |
+|*.NET* | | | |- |
+|*Python*  | | | | |-
+|=========================================================
+
+Each programming language has its own API for translation, but the pattern is quite similar from one to the next:
+
+WARN: While `Translator` implementations have been around for some time, they are still in their early stages from
+an interface perspective. API changes may occur in the near future.
+
+[source,java,tab]
+----
+// gremlin-core module
+import org.apache.tinkerpop.gremlin.process.traversal.translator.*;
+GraphTraversalSource g = ...;
+Traversal<Vertex,Integer> t = g.V().has("person","name","marko").
+                                where(in("knows")).
+                                values("age").
+                                map(Lambda.Function("it.get() + 1");
+
+Translator.ScriptTranslator groovyTranslator = GroovyTranslator.of("g");
+System.out.println(groovyTranslator.translate(t);
+// OUTPUT: g.V().has("person","name","marko").where(__.in("knows")).values("age").map({it.get() + 1})
+
+Translator.ScriptTranslator pythonTranslator = PythonTranslator.of("g");
+// OUTPUT: g.V().has('person','name','marko').where(__.in_('knows')).age.map(lambda it.get() + 1)
+----
+[source,javascript]
+----
+const g = ...;
+const t = g.V().has("person","name","marko").
+            where(in_("knows")).
+            values("age");
+
+// groovy
+const translator = new gremlin.process.Translator('g');
+console.log(translator.translate(t));
+// OUTPUT: g.V().has('person','name','marko').where(__.in('knows')).values('age')
+----
+
diff --git a/docs/static/images/gremlin-translator.png b/docs/static/images/gremlin-translator.png
new file mode 100644
index 0000000..ce42425
Binary files /dev/null and b/docs/static/images/gremlin-translator.png differ
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslatorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslatorTest.java
index 2575b3a..8455293 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslatorTest.java
@@ -66,25 +66,25 @@ public class GroovyTranslatorTest {
         assertEquals("g.withStrategies(ReadOnlyStrategy,new SubgraphStrategy(checkAdjacentVertices: false, vertices: __.hasLabel(\"person\"))).V().has(\"name\")",
                 translator.translate(g.withStrategies(ReadOnlyStrategy.instance(),
                         SubgraphStrategy.build().checkAdjacentVertices(false).vertices(hasLabel("person")).create()).
-                        V().has("name").asAdmin().getBytecode()));
+                        V().has("name")));
     }
 
     @Test
     public void shouldTranslateConfusingSacks() {
         final Traversal<Vertex,Double> tConstantUnary = g.withSack(1.0, Lambda.unaryOperator("it + 1")).V().sack();
-        final String scriptConstantUnary = translator.translate(tConstantUnary.asAdmin().getBytecode());
+        final String scriptConstantUnary = translator.translate(tConstantUnary);
         assertEquals("g.withSack(1.0d, (java.util.function.UnaryOperator) {it + 1}).V().sack()", scriptConstantUnary);
 
         final Traversal<Vertex,Double> tSupplierUnary = g.withSack(Lambda.supplier("1.0d"), Lambda.<Double>unaryOperator("it + 1")).V().sack();
-        final String scriptSupplierUnary = translator.translate(tSupplierUnary.asAdmin().getBytecode());
+        final String scriptSupplierUnary = translator.translate(tSupplierUnary);
         assertEquals("g.withSack((java.util.function.Supplier) {1.0d}, (java.util.function.UnaryOperator) {it + 1}).V().sack()", scriptSupplierUnary);
 
         final Traversal<Vertex,Double> tConstantBinary = g.withSack(1.0, Lambda.binaryOperator("x,y -> x + y + 1")).V().sack();
-        final String scriptConstantBinary = translator.translate(tConstantBinary.asAdmin().getBytecode());
+        final String scriptConstantBinary = translator.translate(tConstantBinary);
         assertEquals("g.withSack(1.0d, (java.util.function.BinaryOperator) {x,y -> x + y + 1}).V().sack()", scriptConstantBinary);
 
         final Traversal<Vertex,Double> tSupplierBinary = g.withSack(Lambda.supplier("1.0d"), Lambda.<Double>binaryOperator("x,y -> x + y + 1")).V().sack();
-        final String scriptSupplierBinary = translator.translate(tSupplierBinary.asAdmin().getBytecode());
+        final String scriptSupplierBinary = translator.translate(tSupplierBinary);
         assertEquals("g.withSack((java.util.function.Supplier) {1.0d}, (java.util.function.BinaryOperator) {x,y -> x + y + 1}).V().sack()", scriptSupplierBinary);
     }
 
@@ -117,14 +117,14 @@ public class GroovyTranslatorTest {
         final String script = translator.translate(g.V().id().is(new LinkedHashMap<Object,Object>() {{
             put(3, "32");
             put(Arrays.asList(1, 2, 3.1d), 4);
-        }}).asAdmin().getBytecode());
+        }}));
         assertEquals("g.V().id().is([((int) 3):(\"32\"),([(int) 1, (int) 2, 3.1d]):((int) 4)])", script);
     }
 
     @Test
     public void shouldTranslateEmptyMaps() {
         final Function identity = new Lambda.OneArgLambda("it.get()", "gremlin-groovy");
-        final String script = translator.translate(g.inject(Collections.emptyMap()).map(identity).asAdmin().getBytecode());
+        final String script = translator.translate(g.inject(Collections.emptyMap()).map(identity));
         assertEquals("g.inject([]).map({it.get()})", script);
     }
 
@@ -181,12 +181,12 @@ public class GroovyTranslatorTest {
 
         // without type translation we get uglinesss
         final String scriptBad = translator.
-                translate(g.inject(notSillyEnough).asAdmin().getBytecode());
+                translate(g.inject(notSillyEnough));
         assertEquals(String.format("g.inject(%s)", "not silly enough:100"), scriptBad);
 
         // with type translation we get valid gremlin
         final String scriptGood = GroovyTranslator.of("g", new SillyClassTranslator()).
-                translate(g.inject(notSillyEnough).asAdmin().getBytecode());
+                translate(g.inject(notSillyEnough));
         assertEquals(String.format("g.inject(org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslatorTest.SillyClass.from('%s', (int) %s))", notSillyEnough.getX(), notSillyEnough.getY()), scriptGood);
     }
 
@@ -202,7 +202,7 @@ public class GroovyTranslatorTest {
                 .property("name", "Foo\u0020Bar")
                 .property("age", 25)
                 .property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
-                .asAdmin().getBytecode());
+                );
 
         assertEquals("g.addV(\"customer\")" +
                         ".property(\"customer_id\",501L)" +
@@ -217,7 +217,7 @@ public class GroovyTranslatorTest {
         final Object id1 = "customer:10:foo\u0020bar\u0020\u0024100#90"; // customer:10:foo bar $100#90
         final Vertex vertex1 = DetachedVertex.build().setLabel("customer").setId(id1)
                 .create();
-        final String script1 = translator.translate(g.inject(vertex1).asAdmin().getBytecode());
+        final String script1 = translator.translate(g.inject(vertex1));
         assertEquals("g.inject(new ReferenceVertex(" +
                         "\"customer:10:foo bar \\$100#90\"," +
                         "\"customer\"))",
@@ -226,7 +226,7 @@ public class GroovyTranslatorTest {
         final Object id2 = "user:20:foo\\u0020bar\\u005c\\u0022mr\\u005c\\u0022\\u00241000#50"; // user:20:foo\u0020bar\u005c\u0022mr\u005c\u0022\u00241000#50
         final Vertex vertex2 = DetachedVertex.build().setLabel("user").setId(id2)
                 .create();
-        final String script2 = translator.translate(g.inject(vertex2).asAdmin().getBytecode());
+        final String script2 = translator.translate(g.inject(vertex2));
         assertEquals("g.inject(new ReferenceVertex(" +
                         "\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\"," +
                         "\"user\"))",
@@ -237,7 +237,7 @@ public class GroovyTranslatorTest {
                 .setOutV((DetachedVertex) vertex1)
                 .setInV((DetachedVertex) vertex2)
                 .create();
-        final String script3 = translator.translate(g.inject(edge).asAdmin().getBytecode());
+        final String script3 = translator.translate(g.inject(edge));
         assertEquals("g.inject(new ReferenceEdge(" +
                         "\"knows:30:foo bar \\$100:\\\\u0020\\\\u0024500#70\"," +
                         "\"knows\"," +
@@ -247,7 +247,7 @@ public class GroovyTranslatorTest {
 
         final String script4 = translator.translate(
                 g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
-                        .asAdmin().getBytecode());
+                        );
         assertEquals("g.addE(\"knows\")" +
                         ".from(new ReferenceVertex(\"customer:10:foo bar \\$100#90\",\"customer\"))" +
                         ".to(new ReferenceVertex(\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\",\"user\"))" +
@@ -256,7 +256,7 @@ public class GroovyTranslatorTest {
     }
 
     private void assertTranslation(final String expectedTranslation, final Object... objs) {
-        final String script = translator.translate(g.inject(objs).asAdmin().getBytecode());
+        final String script = translator.translate(g.inject(objs));
         assertEquals(String.format("g.inject(%s)", expectedTranslation), script);
     }