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 19:34:12 UTC
[tinkerpop] 04/04: 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
commit 127821e36321ccf2544f62683abd4c7360051ede
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);
}