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 2018/09/25 21:30:40 UTC

[2/2] tinkerpop git commit: TINKERPOP-2040 Hooked up Customizer for TypeTranslator

TINKERPOP-2040 Hooked up Customizer for TypeTranslator

Enables the Groovy GremlinScriptEngine to use custom TypeTranslators


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/93d99ef1
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/93d99ef1
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/93d99ef1

Branch: refs/heads/TINKERPOP-2040
Commit: 93d99ef1a0119b4c0994daeccaf312d45c894f45
Parents: 873609b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Sep 25 17:29:49 2018 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Sep 25 17:29:49 2018 -0400

----------------------------------------------------------------------
 .../gremlin/jsr223/TranslatorCustomizer.java    | 38 ++++++++++++++++++++
 .../groovy/jsr223/GroovyTranslatorTest.java     | 23 +++++++++++-
 .../jsr223/GremlinGroovyScriptEngine.java       | 15 ++++++--
 .../gremlin/groovy/jsr223/GroovyTranslator.java |  8 ++---
 4 files changed, 76 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/93d99ef1/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/TranslatorCustomizer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/TranslatorCustomizer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/TranslatorCustomizer.java
new file mode 100644
index 0000000..4468255
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/TranslatorCustomizer.java
@@ -0,0 +1,38 @@
+/*
+ * 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.jsr223;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Translator;
+
+/**
+ * Provides a way to customize and override {@link Bytecode} to script translation. Not all {@link GremlinScriptEngine}
+ * will support this capability as translation is optional.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public interface TranslatorCustomizer extends Customizer {
+
+    /**
+     * Construct a {@link Translator.ScriptTranslator.TypeTranslator} that will be used by a
+     * {@link Translator.ScriptTranslator} instance within the {@link GremlinScriptEngine} to translate
+     * {@link Bytecode} to a script.
+     */
+    public Translator.ScriptTranslator.TypeTranslator createTypeTranslator();
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/93d99ef1/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
index c224642..1622d3d 100644
--- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
+++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GroovyTranslatorTest.java
@@ -22,6 +22,7 @@ package org.apache.tinkerpop.gremlin.groovy.jsr223;
 import org.apache.commons.configuration.MapConfiguration;
 import org.apache.tinkerpop.gremlin.AbstractGremlinTest;
 import org.apache.tinkerpop.gremlin.LoadGraphWith;
+import org.apache.tinkerpop.gremlin.jsr223.TranslatorCustomizer;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.Scope;
@@ -59,9 +60,11 @@ import java.util.List;
 import java.util.UUID;
 import java.util.function.Function;
 
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 
 /**
@@ -224,7 +227,7 @@ public class GroovyTranslatorTest extends AbstractGremlinTest {
     }
 
     @Test
-    public void shouldIncludeCustomTypeTranslationForSomethingSilly() {
+    public void shouldIncludeCustomTypeTranslationForSomethingSilly() throws Exception {
         final SillyClass notSillyEnough = SillyClass.from("not silly enough", 100);
         final GraphTraversalSource g = graph.traversal();
 
@@ -241,6 +244,15 @@ public class GroovyTranslatorTest extends AbstractGremlinTest {
                 translate(g.inject(notSillyEnough).asAdmin().getBytecode());
         assertEquals(String.format("g.inject(org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslatorTest.SillyClass.from('%s', (int) %s))", notSillyEnough.getX(), notSillyEnough.getY()), scriptGood);
         assertThatScriptOk(scriptGood, "g", g);
+
+        final GremlinGroovyScriptEngine customEngine = new GremlinGroovyScriptEngine(new SillyClassTranslatorCustomizer());
+        final Bindings b = new SimpleBindings();
+        b.put("g", g);
+        final Traversal t = customEngine.eval(g.inject(notSillyEnough).asAdmin().getBytecode(), b, "g");
+        final SillyClass sc = (SillyClass) t.next();
+        assertEquals(notSillyEnough.getX(), sc.getX());
+        assertEquals(notSillyEnough.getY(), sc.getY());
+        assertThat(t.hasNext(), is(false));
     }
 
     @Test
@@ -344,4 +356,13 @@ public class GroovyTranslatorTest extends AbstractGremlinTest {
         }
     }
 
+    public static class SillyClassTranslatorCustomizer implements TranslatorCustomizer {
+
+        @Override
+        public Translator.ScriptTranslator.TypeTranslator createTypeTranslator() {
+            return x -> x instanceof SillyClass ?
+                    new Translator.ScriptTranslator.Handled(String.format("org.apache.tinkerpop.gremlin.groovy.jsr223.GroovyTranslatorTest.SillyClass.from('%s', (int) %s)",
+                            ((SillyClass) x).getX(), ((SillyClass) x).getY())) : x;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/93d99ef1/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
index 381dd88..b96b8b9 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java
@@ -30,7 +30,6 @@ import groovy.lang.MissingMethodException;
 import groovy.lang.MissingPropertyException;
 import groovy.lang.Script;
 import groovy.lang.Tuple;
-import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider;
 import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider;
 import org.apache.tinkerpop.gremlin.groovy.EmptyImportCustomizerProvider;
@@ -49,7 +48,9 @@ import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptContext;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory;
 import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer;
+import org.apache.tinkerpop.gremlin.jsr223.TranslatorCustomizer;
 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.codehaus.groovy.ast.ClassHelper;
@@ -241,6 +242,7 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl
     private final Set<Artifact> artifactsToUse = new HashSet<>();
     private final boolean interpreterModeEnabled;
     private final long expectedCompilationTime;
+    private final Translator.ScriptTranslator.TypeTranslator typeTranslator;
 
     /**
      * Creates a new instance using the {@link DefaultImportCustomizerProvider}.
@@ -287,6 +289,12 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl
         interpreterModeEnabled = groovyCustomizers.stream()
                 .anyMatch(p -> p.getClass().equals(InterpreterModeGroovyCustomizer.class));
 
+        final Optional<TranslatorCustomizer> translatorCustomizer = listOfCustomizers.stream().
+                filter(p -> p instanceof TranslatorCustomizer).
+                map(p -> (TranslatorCustomizer) p).findFirst();
+        typeTranslator = translatorCustomizer.isPresent() ? translatorCustomizer.get().createTypeTranslator() :
+                Translator.ScriptTranslator.TypeTranslator.identity();
+
         // not using the old provider model so set that to empty list so that when createClassLoader is called
         // it knows to use groovyCustomizers instead
         customizerProviders = Collections.emptyList();
@@ -330,6 +338,9 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl
         groovyCustomizers = Collections.emptyList();
         importGroovyCustomizer = null;
 
+        // TypeTranslator can only be set by a Customizer - use this old deprecated stuff and you're outta luck
+        typeTranslator = Translator.ScriptTranslator.TypeTranslator.identity();
+
         createClassLoader();
     }
 
@@ -464,7 +475,7 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl
         inner.putAll(bytecode.getBindings());
         inner.put(HIDDEN_G, b);
 
-        return (Traversal.Admin) this.eval(GroovyTranslator.of(HIDDEN_G).translate(bytecode), inner);
+        return (Traversal.Admin) this.eval(GroovyTranslator.of(HIDDEN_G, typeTranslator).translate(bytecode), inner);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/93d99ef1/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 9cd7791..949fcac 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
@@ -22,9 +22,7 @@ package org.apache.tinkerpop.gremlin.groovy.jsr223;
 import groovy.json.StringEscapeUtils;
 import org.apache.commons.configuration.ConfigurationConverter;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
-import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Pop;
 import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
 import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
@@ -34,8 +32,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.TraversalStrategyProxy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -52,10 +48,12 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
-import java.util.function.UnaryOperator;
 
 /**
+ * Converts bytecode to a Groovy string of Gremlin.
+ *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class GroovyTranslator implements Translator.ScriptTranslator {