blob: fbd6f56c33ca76529dc929cc82e30d014c79f910 [file] [log] [blame]
/*
* 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.groovy.jsr223;
import org.apache.commons.configuration2.MapConfiguration;
import org.apache.tinkerpop.gremlin.jsr223.TranslatorCustomizer;
import org.apache.tinkerpop.gremlin.process.traversal.Compare;
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.Scope;
import org.apache.tinkerpop.gremlin.process.traversal.Script;
import org.apache.tinkerpop.gremlin.process.traversal.Translator;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
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.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
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.Graph;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.apache.tinkerpop.gremlin.util.function.Lambda;
import org.junit.Test;
import javax.script.Bindings;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
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.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* test {@link GroovyTranslator} which return parameterized result, covers:
* - parameterized script checking
* - binding checking
* - eval result checking
*
* <p>
* {@link GroovyTranslatorTest } is used to test {@link GroovyTranslator}, both test cases looks the same
* <p>
*
* @author Marko A. Rodriguez (http://markorodriguez.com)
* @author Stephen Mallette (http://stephen.genoprime.com)
* @author Stark Arya (sandszhou.zj@alibaba-inc.com)
*/
public class ParameterizedGroovyTranslatorTest {
private Graph graph = TinkerGraph.open();
private GraphTraversalSource g = graph.traversal();
private static final GremlinGroovyScriptEngine parameterizedEngine = new GremlinGroovyScriptEngine(new TranslatorCustomizer() {
@Override
public Translator.ScriptTranslator.TypeTranslator createTypeTranslator() {
return new GroovyTranslator.DefaultTypeTranslator(true);
}
});
@Test
public void shouldHandleStrategies() throws Exception {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal().withStrategies(SubgraphStrategy.create(new MapConfiguration(new HashMap<String, Object>() {{
put(SubgraphStrategy.VERTICES, __.has("name", "marko"));
}})));
final Bindings bindings = new SimpleBindings();
bindings.put("g", g);
Traversal.Admin<Vertex, Object> traversal = parameterizedEngine.eval(g.V().values("name").asAdmin().getBytecode(), bindings, "g");
assertEquals("marko", traversal.next());
assertFalse(traversal.hasNext());
//
traversal = parameterizedEngine.eval(g.withoutStrategies(SubgraphStrategy.class).V().count().asAdmin().getBytecode(), bindings, "g");
assertEquals(new Long(6), traversal.next());
assertFalse(traversal.hasNext());
//
traversal = parameterizedEngine.eval(g.withStrategies(SubgraphStrategy.create(new MapConfiguration(new HashMap<String, Object>() {{
put(SubgraphStrategy.VERTICES, __.has("name", "marko"));
}})), ReadOnlyStrategy.instance()).V().values("name").asAdmin().getBytecode(), bindings, "g");
assertEquals("marko", traversal.next());
assertFalse(traversal.hasNext());
}
@Test
public void shouldSupportStringSupplierLambdas() {
final TinkerGraph graph = TinkerFactory.createModern();
GraphTraversalSource g = graph.traversal();
g = g.withStrategies(new TranslationStrategy(g, GroovyTranslator.of("g", true), false));
final GraphTraversal.Admin<Vertex, Integer> t = g.withSideEffect("lengthSum", 0).withSack(1)
.V()
.filter(Lambda.predicate("it.get().label().equals('person')"))
.flatMap(Lambda.function("it.get().vertices(Direction.OUT)"))
.map(Lambda.<Traverser<Object>, Integer>function("it.get().value('name').length()"))
.sideEffect(Lambda.consumer("{ x -> x.sideEffects(\"lengthSum\", x.<Integer>sideEffects('lengthSum') + x.get()) }"))
.order().by(Lambda.comparator("a,b -> a <=> b"))
.sack(Lambda.biFunction("{ a,b -> a + b }"))
.asAdmin();
final List<Integer> sacks = new ArrayList<>();
final List<Integer> lengths = new ArrayList<>();
while (t.hasNext()) {
final Traverser.Admin<Integer> traverser = t.nextTraverser();
sacks.add(traverser.sack());
lengths.add(traverser.get());
}
assertFalse(t.hasNext());
//
assertEquals(6, lengths.size());
assertEquals(3, lengths.get(0).intValue());
assertEquals(3, lengths.get(1).intValue());
assertEquals(3, lengths.get(2).intValue());
assertEquals(4, lengths.get(3).intValue());
assertEquals(5, lengths.get(4).intValue());
assertEquals(6, lengths.get(5).intValue());
///
assertEquals(6, sacks.size());
assertEquals(4, sacks.get(0).intValue());
assertEquals(4, sacks.get(1).intValue());
assertEquals(4, sacks.get(2).intValue());
assertEquals(5, sacks.get(3).intValue());
assertEquals(6, sacks.get(4).intValue());
assertEquals(7, sacks.get(5).intValue());
//
assertEquals(24, t.getSideEffects().<Number>get("lengthSum").intValue());
final Script script = GroovyTranslator.of("g", true).translate(t.getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(9, bindings.size());
assertEquals("lengthSum", bindings.get("_args_0"));
assertEquals(Integer.valueOf(0), bindings.get("_args_1"));
assertEquals(Integer.valueOf(1), bindings.get("_args_2"));
assertEquals(Lambda.predicate("it.get().label().equals('person')"), bindings.get("_args_3"));
assertEquals(Lambda.function("it.get().vertices(Direction.OUT)"), bindings.get("_args_4"));
assertEquals(Lambda.<Traverser<Object>, Integer>function("it.get().value('name').length()"), bindings.get("_args_5"));
assertEquals(Lambda.consumer("{ x -> x.sideEffects(\"lengthSum\", x.<Integer>sideEffects('lengthSum') + x.get()) }"), bindings.get("_args_6"));
assertEquals(Lambda.comparator("a,b -> a <=> b"), bindings.get("_args_7"));
assertEquals(Lambda.biFunction("{ a,b -> a + b }"), bindings.get("_args_8"));
assertEquals("g.withStrategies(org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.TranslationStrategy.instance())" +
".withSideEffect(_args_0,_args_1).withSack(_args_2)" +
".V()" +
".filter(_args_3)" +
".flatMap(_args_4)" +
".map(_args_5)" +
".sideEffect(_args_6)" +
".order().by(_args_7)" +
".sack(_args_8)",
script.getScript());
}
@Test
public void shouldHandleArray() {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal();
final Script script = GroovyTranslator.of("g", true).translate(g.V().has(T.id, P.within(new ArrayList() {{
add(1);
add(2);
add(3);
add(4);
add(5);
}})).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(5, bindings.size());
assertEquals(Integer.valueOf(1), bindings.get("_args_0"));
assertEquals(Integer.valueOf(2), bindings.get("_args_1"));
assertEquals(Integer.valueOf(3), bindings.get("_args_2"));
assertEquals(Integer.valueOf(4), bindings.get("_args_3"));
assertEquals(Integer.valueOf(5), bindings.get("_args_4"));
assertEquals("g.V().has(T.id,P.within([_args_0, _args_1, _args_2, _args_3, _args_4]))", script.getScript());
final Script standard = GroovyTranslator.of("g").translate(g.V().has(T.id, P.within(new ArrayList() {{
add(1);
add(2);
add(3);
add(4);
add(5);
}})).asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
}
@Test
public void shouldHandleSet() {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal();
final Script script = GroovyTranslator.of("g", true).translate(g.V().id().is(new HashSet<Object>() {{
add(3);
add(Arrays.asList(1, 2, 3.1d));
add(3);
add("3");
}}).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(5, bindings.size());
assertEquals(Integer.valueOf(3), bindings.get("_args_0"));
assertEquals("3", bindings.get("_args_1"));
assertEquals(Integer.valueOf(1), bindings.get("_args_2"));
assertEquals(Integer.valueOf(2), bindings.get("_args_3"));
assertEquals(Double.valueOf(3.1), bindings.get("_args_4"));
assertEquals("g.V().id().is([_args_0, _args_1, [_args_2, _args_3, _args_4]] as Set)", script.getScript());
final Script standard = GroovyTranslator.of("g" ).translate(g.V().id().is(new HashSet<Object>() {{
add(3);
add(Arrays.asList(1, 2, 3.1d));
add(3);
add("3");
}}).asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
}
@Test
public void shouldHandleMaps() {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal();
final Script script = GroovyTranslator.of("g", true).translate(g.V().id().is(new LinkedHashMap<Object,Object>() {{
put(3, "32");
put(Arrays.asList(1, 2, 3.1d), 4);
}}).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(6, bindings.size());
assertEquals(Integer.valueOf(3), bindings.get("_args_0"));
assertEquals("32", bindings.get("_args_1"));
assertEquals(Integer.valueOf(1), bindings.get("_args_2"));
assertEquals(Integer.valueOf(2), bindings.get("_args_3"));
assertEquals(Double.valueOf(3.1), bindings.get("_args_4"));
assertEquals(Integer.valueOf(4), bindings.get("_args_5"));
assertEquals("g.V().id().is([(_args_0):(_args_1),([_args_2, _args_3, _args_4]):(_args_5)])", script.getScript());
final Script standard = GroovyTranslator.of("g").translate(g.V().id().is(new LinkedHashMap<Object,Object>() {{
put(3, "32");
put(Arrays.asList(1, 2, 3.1d), 4);
}}).asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
}
@Test
public void shouldHandleEmptyMaps() {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal();
final Function identity = new Lambda.OneArgLambda("it.get()", "gremlin-groovy");
final Script script = GroovyTranslator.of("g", true).translate(g.inject(Collections.emptyMap()).map(identity).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(1, bindings.size());
assertEquals(identity, bindings.get("_args_0"));
assertEquals("g.inject([]).map(_args_0)", script.getScript());
bindings.put("g", g);
assertThatScriptOk(script.getScript(), bindings);
}
@Test
public void shouldHandleDate() {
final Calendar c = Calendar.getInstance();
c.set(1975, Calendar.SEPTEMBER, 7);
final Date d = c.getTime();
assertParameterizedTranslation(String.format("new java.util.Date(%s)", d.getTime()), d);
}
@Test
public void shouldHandlePredicate() {
final P p = new P(Compare.eq, 10);
assertParameterizedTranslation(String.format("new java.util.Date(%s)", p.toString()), 10);
}
@Test
public void shouldHandleTimestamp() {
final Calendar c = Calendar.getInstance();
c.set(1975, Calendar.SEPTEMBER, 7);
final Timestamp t = new Timestamp(c.getTime().getTime());
assertParameterizedTranslation(String.format("new java.sql.Timestamp(%s)", t.getTime()), t);
}
@Test
public void shouldHandleUuid() {
final UUID uuid = UUID.fromString("ffffffff-fd49-1e4b-0000-00000d4b8a1d");
assertParameterizedTranslation(String.format("java.util.UUID.fromString('%s')", uuid), uuid);
}
@Test
public void shouldHandleClass() {
final Class cls = Vertex.class;
assertParameterizedTranslation(String.format("%s", cls), cls.getCanonicalName());
}
@Test
public void shouldHandleBarrier() {
final SackFunctions.Barrier barrier = SackFunctions.Barrier.normSack;
assertNonParameterizedTranslation(String.format("SackFunctions.Barrier.%s", barrier), barrier);
}
@Test
public void shouldHandleCardinality() {
final VertexProperty.Cardinality cardinality = VertexProperty.Cardinality.set;
assertNonParameterizedTranslation(String.format("VertexProperty.Cardinality.%s", cardinality), cardinality);
}
@Test
public void shouldHandlePick() {
final TraversalOptionParent.Pick pick = TraversalOptionParent.Pick.any;
assertNonParameterizedTranslation(String.format("TraversalOptionParent.Pick.%s", pick), pick);
}
@Test
public void shouldHandleColumn() {
assertNonParameterizedTranslation("Column.keys", Column.keys);
}
@Test
public void shouldHandleDirection() {
assertNonParameterizedTranslation("Direction.BOTH", Direction.BOTH);
}
@Test
public void shouldHandleOrder() {
assertNonParameterizedTranslation("Order.shuffle", Order.shuffle);
}
@Test
public void shouldHandlePop() {
assertNonParameterizedTranslation("Pop.last", Pop.last);
}
@Test
public void shouldHandleScope() {
assertNonParameterizedTranslation("Scope.local", Scope.local);
}
@Test
public void shouldIncludeCustomTypeTranslationForSomethingSilly() throws Exception {
final TinkerGraph graph = TinkerGraph.open();
final ParameterizedSillyClass notSillyEnough = ParameterizedSillyClass.from("not silly enough", 100);
final GraphTraversalSource g = graph.traversal();
// without type translation we get uglinesss
final Script parameterizedScriptBad = GroovyTranslator.of("g", true).
translate(g.inject(notSillyEnough).asAdmin().getBytecode());
Bindings bindings = new SimpleBindings();
parameterizedScriptBad.getParameters().ifPresent(bindings::putAll);
assertEquals(String.format("g.inject(%s)", "_args_0"), parameterizedScriptBad.getScript());
assertEquals(1, bindings.size());
assertEquals(notSillyEnough, bindings.get("_args_0"));
bindings.clear();
// with type translation we get valid gremlin
final Script parameterizedScriptGood = GroovyTranslator.of("g", new ParameterizedSillyClassTranslatorCustomizer().createTypeTranslator()).
translate(g.inject(notSillyEnough).asAdmin().getBytecode());
parameterizedScriptGood.getParameters().ifPresent(bindings::putAll);
assertEquals(2, bindings.size());
assertEquals(notSillyEnough.getX(), bindings.get("_args_0"));
assertEquals(notSillyEnough.getY(), bindings.get("_args_1"));
assertEquals("g.inject(org.apache.tinkerpop.gremlin.groovy.jsr223.ParameterizedGroovyTranslatorTest.ParameterizedSillyClass.from(_args_0,_args_1))", parameterizedScriptGood.getScript());
bindings.put("g", g);
assertThatScriptOk(parameterizedScriptGood.getScript(), bindings);
final GremlinGroovyScriptEngine customEngine = new GremlinGroovyScriptEngine(new ParameterizedSillyClassTranslatorCustomizer());
final Traversal t = customEngine.eval(g.inject(notSillyEnough).asAdmin().getBytecode(), bindings, "g");
final ParameterizedSillyClass sc = (ParameterizedSillyClass) t.next();
assertEquals(notSillyEnough.getX(), sc.getX());
assertEquals(notSillyEnough.getY(), sc.getY());
assertThat(t.hasNext(), is(false));
}
@Test
public void shouldHaveValidToString() {
assertEquals("translator[h:gremlin-groovy]", GroovyTranslator.of("h", true).toString());
}
@Test
public void shouldEscapeStrings() {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal();
final Script script = GroovyTranslator.of("g", true).translate(g.addV("customer")
.property("customer_id", 501L)
.property("name", "Foo\u0020Bar")
.property("age", 25)
.property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
.asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(9, bindings.size());
assertEquals("customer", bindings.get("_args_0"));
assertEquals("customer_id", bindings.get("_args_1"));
assertEquals(Long.valueOf(501), bindings.get("_args_2"));
assertEquals("name", bindings.get("_args_3"));
assertEquals("Foo\u0020Bar", bindings.get("_args_4"));
assertEquals("age", bindings.get("_args_5"));
assertEquals(Integer.valueOf(25), bindings.get("_args_6"));
assertEquals("special", bindings.get("_args_7"));
assertEquals("`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?", bindings.get("_args_8"));
assertEquals("g.addV(_args_0).property(_args_1,_args_2).property(_args_3,_args_4).property(_args_5,_args_6).property(_args_7,_args_8)", script.getScript());
final Script standard = GroovyTranslator.of("g").translate(g.addV("customer")
.property("customer_id", 501L)
.property("name", "Foo\u0020Bar")
.property("age", 25)
.property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
.asAdmin().getBytecode());
bindings.put("g", g);
//add vertex will return different vertex id
assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, false);
}
@Test
public void shouldHandleVertexAndEdge() {
final TinkerGraph graph = TinkerFactory.createModern();
final GraphTraversalSource g = graph.traversal();
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 Script script1 = GroovyTranslator.of("g", true).translate(g.inject(vertex1).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script1.getParameters().ifPresent(bindings::putAll);
assertEquals(2, bindings.size());
assertEquals(id1, bindings.get("_args_0"));
assertEquals("customer", bindings.get("_args_1"));
assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_0,_args_1, Collections.emptyMap()))", script1.getScript());
final Script standard1 = GroovyTranslator.of("g").translate(g.inject(vertex1).asAdmin().getBytecode());
bindings.put("g", g);
// TinkerGraph not support string id
assertParameterizedScriptOk(standard1.getScript(), script1.getScript(), bindings, false);
bindings.clear();
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 Script script2 = GroovyTranslator.of("g", true).translate(g.inject(vertex2).asAdmin().getBytecode());
script2.getParameters().ifPresent(bindings::putAll);
assertEquals(2, bindings.size());
assertEquals(id2, bindings.get("_args_0"));
assertEquals("user", bindings.get("_args_1"));
assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_0,_args_1, Collections.emptyMap()))", script2.getScript());
final Script standard2 = GroovyTranslator.of("g").translate(g.inject(vertex2).asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard2.getScript(), script2.getScript(), bindings, false);
bindings.clear();
final Object id3 = "knows:30:foo\u0020bar\u0020\u0024100:\\u0020\\u0024500#70";
final Edge edge = DetachedEdge.build().setLabel("knows").setId(id3)
.setOutV((DetachedVertex) vertex1)
.setInV((DetachedVertex) vertex2)
.create();
final Script script3 = GroovyTranslator.of("g", true).translate(g.inject(edge).asAdmin().getBytecode());
script3.getParameters().ifPresent(bindings::putAll);
assertEquals(6, bindings.size());
assertEquals(id3, bindings.get("_args_0"));
assertEquals("knows", bindings.get("_args_1"));
assertEquals(id1, bindings.get("_args_2"));
assertEquals("customer", bindings.get("_args_3"));
assertEquals(id2, bindings.get("_args_4"));
assertEquals("user", bindings.get("_args_5"));
assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(_args_0,_args_1,Collections.emptyMap(),_args_2,_args_3,_args_4,_args_5))", script3.getScript());
final Script standard3 = GroovyTranslator.of("g").translate(g.inject(edge).asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard3.getScript(), script3.getScript(), bindings, false);
bindings.clear();
final Script script4 = GroovyTranslator.of("g", true).translate(
g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
.asAdmin().getBytecode());
script4.getParameters().ifPresent(bindings::putAll);
assertEquals(7, bindings.size());
assertEquals("knows", bindings.get("_args_0"));
assertEquals(id1, bindings.get("_args_1"));
assertEquals("customer", bindings.get("_args_2"));
assertEquals(id2, bindings.get("_args_3"));
assertEquals("user", bindings.get("_args_4"));
assertEquals("when", bindings.get("_args_5"));
assertEquals("2018/09/21", bindings.get("_args_6"));
assertEquals("g.addE(_args_0).from(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_1,_args_2, Collections.emptyMap())).to(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(_args_3,_args_4, Collections.emptyMap())).property(_args_5,_args_6)", script4.getScript());
final Script standard4 = GroovyTranslator.of("g").translate(
g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
.asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard4.getScript(), script4.getScript(), bindings, false);
bindings.clear();
final Script script5 = GroovyTranslator.of("g", true).translate(g.V().has("age").asAdmin().getBytecode());
script5.getParameters().ifPresent(bindings::putAll);
assertEquals(1, bindings.size());
assertEquals("age", bindings.get("_args_0"));
assertEquals("g.V().has(_args_0)", script5.getScript());
final Script standard5 = GroovyTranslator.of("g").translate(g.V().has("age").asAdmin().getBytecode());
bindings.put("g", g);
// Ok, here we checking all the result
assertParameterizedScriptOk(standard5.getScript(), script5.getScript(), bindings, true);
bindings.clear();
}
private Object eval(final String s, final Bindings b) throws ScriptException {
return parameterizedEngine.eval(s, b);
}
private void assertParameterizedTranslation(final String expectedTranslation, final Object... objs) {
final Script script = GroovyTranslator.of("g", true).translate(g.inject(objs).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(1, bindings.size());
assertEquals(objs[0], bindings.get("_args_0"));
assertEquals(String.format("g.inject(_args_0)", expectedTranslation), script.getScript());
final Script standard = GroovyTranslator.of("g").translate(g.inject(objs).asAdmin().getBytecode());
bindings.put("g", g);
assertParameterizedScriptOk(standard.getScript(), script.getScript(), bindings, true);
}
private void assertNonParameterizedTranslation(final String expectedTranslation, final Object... objs) {
final Script script = GroovyTranslator.of("g", true).translate(g.inject(objs).asAdmin().getBytecode());
final Bindings bindings = new SimpleBindings();
script.getParameters().ifPresent(bindings::putAll);
assertEquals(0, bindings.size());
assertEquals(String.format("g.inject(%s)", expectedTranslation), script.getScript());
final Script standard = GroovyTranslator.of("g").translate(g.inject(objs).asAdmin().getBytecode());
assertEquals(standard.getScript(), script.getScript());
}
private void assertThatScriptOk(final String s, Bindings bindings) {
try {
assertNotNull(eval(s, bindings));
} catch (ScriptException se) {
se.printStackTrace();
fail("Script should have eval'd");
}
}
private void assertParameterizedScriptOk(final String standardScript, final String checkingScript, final Bindings bindings, final boolean resultChecking) {
try {
System.out.println(standardScript + " " + checkingScript);
assertTrue(!standardScript.equals(checkingScript));
assertThatScriptOk(checkingScript, bindings);
assertEquals(eval(standardScript, bindings), eval(checkingScript, bindings));
if (resultChecking) {
Traversal.Admin<Vertex, Object> standardTraversal = (Traversal.Admin) eval(standardScript, bindings);
Traversal.Admin<Vertex, Object> checkingTraversal = (Traversal.Admin) eval(checkingScript, bindings);
while (standardTraversal.hasNext() && checkingTraversal.hasNext()) {
// assertEquals(standardTraversal.next(), checkingTraversal.next());
System.out.println(standardTraversal.next() + " " + checkingTraversal.next());
}
assertEquals(standardTraversal.hasNext(), checkingTraversal.hasNext());
}
} catch (ScriptException se) {
se.printStackTrace();
fail("Script should have eval'd");
}
}
public static class ParameterizedSillyClass {
private final String x;
private final int y;
private ParameterizedSillyClass(final String x, final int y) {
this.x = x;
this.y = y;
}
public static ParameterizedSillyClass from(final String x, final int y) {
return new ParameterizedSillyClass(x, y);
}
public String getX() {
return x;
}
public int getY() {
return y;
}
public Object[] getArguments() {
return new Object[] {x,y};
}
@Override
public String toString() {
return String.format("org.apache.tinkerpop.gremlin.groovy.jsr223.ParameterizedGroovyTranslatorTest.ParameterizedSillyClass.from('%s', (int) %s)", getX(), getY());
}
}
public static class ParameterizedSillyClassTranslator extends GroovyTranslator.DefaultTypeTranslator {
public ParameterizedSillyClassTranslator(final boolean withParameters) {
super(withParameters);
}
@Override
protected Script convertToScript(final Object object) {
if (object instanceof ParameterizedSillyClass) {
ParameterizedSillyClass obj = (ParameterizedSillyClass) object;
script.append(obj.getClass().getCanonicalName());
if (0 == obj.getArguments().length) {
script.append(".").append("from").append("()");
} else {
script.append(".").append("from").append("(");
for (final Object argument: obj.getArguments()) {
convertToScript(argument);
script.append(",");
}
script.setCharAtEnd(')');
}
return script;
} else {
return super.convertToScript(object);
}
}
}
public static class ParameterizedSillyClassTranslatorCustomizer implements TranslatorCustomizer {
@Override
public Translator.ScriptTranslator.TypeTranslator createTypeTranslator() {
return new ParameterizedSillyClassTranslator(true);
}
}
}