Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1489 1f00b7c9f -> 468bba639


TINKERPOP-1489 Added Nashorn ScriptEngine to gremlin-javascript


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

Branch: refs/heads/TINKERPOP-1489
Commit: 468bba6393b26e12fc314eda270b93ec12503dc8
Parents: 1f00b7c
Author: Stephen Mallette <[email protected]>
Authored: Tue Sep 5 12:36:12 2017 -0400
Committer: Stephen Mallette <[email protected]>
Committed: Tue Sep 5 12:36:12 2017 -0400

----------------------------------------------------------------------
 .../jsr223/GremlinJavaScriptScriptEngine.java   | 170 ++++++++++++++
 .../GremlinJavaScriptScriptEngineFactory.java   |  60 +++++
 .../javascript/jsr223/JavaScriptTranslator.java | 220 +++++++++++++++++++
 .../gremlin/javascript/jsr223/SymbolHelper.java |  51 +++++
 .../javascript/gremlin-javascript/package.json  |   2 +-
 ...op.gremlin.jsr223.GremlinScriptEngineFactory |   1 +
 .../JavaScriptGremlinScriptEngineTest.java      |  31 +++
 .../src/test/resources/log4j-silent.properties  |  23 ++
 .../src/test/resources/log4j-test.properties    |  23 ++
 .../jsr223/BindingsScriptEngineTest.java        |   4 +-
 .../jsr223/GremlinEnabledScriptEngineTest.java  |  15 +-
 .../gremlin/jsr223/ScriptEngineLambdaTest.java  |   8 +-
 12 files changed, 599 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngine.java
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngine.java
 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngine.java
new file mode 100644
index 0000000..4268e2a
--- /dev/null
+++ 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngine.java
@@ -0,0 +1,170 @@
+/*
+ * 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.javascript.jsr223;
+
+import jdk.nashorn.api.scripting.NashornScriptEngine;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.apache.tinkerpop.gremlin.jsr223.CoreGremlinPlugin;
+import org.apache.tinkerpop.gremlin.jsr223.Customizer;
+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.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptException;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GremlinJavaScriptScriptEngine implements GremlinScriptEngine {
+
+    private final NashornScriptEngine scriptEngine;
+
+    public GremlinJavaScriptScriptEngine(final Customizer... customizers) {
+        this.scriptEngine = (NashornScriptEngine) new 
NashornScriptEngineFactory().getScriptEngine();
+        final List<Customizer> listOfCustomizers = new 
ArrayList<>(Arrays.asList(customizers));
+
+        // always need this plugin for a scriptengine to be "Gremlin-enabled"
+        
CoreGremlinPlugin.instance().getCustomizers("gremlin-javascript").ifPresent(c 
-> listOfCustomizers.addAll(Arrays.asList(c)));
+
+        final List<ImportCustomizer> importCustomizers = 
listOfCustomizers.stream()
+                .filter(p -> p instanceof ImportCustomizer)
+                .map(p -> (ImportCustomizer) p)
+                .collect(Collectors.toList());
+
+        try {
+            for (ImportCustomizer ic : importCustomizers) {
+                for (Class<?> c : ic.getClassImports()) {
+                    if (null == c.getDeclaringClass())
+                        this.scriptEngine.eval(c.getSimpleName() + " = 
Java.type(\"" + c.getName() + "\")");
+                    else
+                        this.scriptEngine.eval(c.getSimpleName() + " = 
Java.type(\"" + c.getDeclaringClass().getName() + "\")");
+                }
+
+                for (Method m : ic.getMethodImports()) {
+                    
this.scriptEngine.eval(SymbolHelper.toJavaScript(m.getName()) + " = 
Java.type(\"" + m.getDeclaringClass().getName() + "\")." + m.getName());
+                }
+
+                // enums need to import after methods for some reason or else 
label comes in as a PyReflectedFunction
+                for (Enum e : ic.getEnumImports()) {
+                    this.scriptEngine.eval(SymbolHelper.toJavaScript(e.name()) 
+ " = Java.type(\"" + e.getDeclaringClass().getName() + "\")." + e.name());
+                }
+            }
+
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    @Override
+    public Traversal.Admin eval(final Bytecode bytecode, final Bindings 
bindings) throws ScriptException {
+        bindings.putAll(bytecode.getBindings());
+        String traversalSource = "g";
+        for (final Map.Entry<String, Object> entry : bindings.entrySet()) {
+            if (entry.getValue() instanceof TraversalSource) {
+                traversalSource = entry.getKey();
+                break;
+            }
+        }
+        return (Traversal.Admin) 
this.eval(JavaScriptTranslator.of(traversalSource).translate(bytecode), 
bindings);
+    }
+
+    @Override
+    public Object eval(final String script, final ScriptContext context) 
throws ScriptException {
+        return this.scriptEngine.eval(script, context);
+    }
+
+    @Override
+    public Object eval(final Reader reader, final ScriptContext context) 
throws ScriptException {
+        return this.scriptEngine.eval(reader, context);
+    }
+
+    @Override
+    public Object eval(final String script) throws ScriptException {
+        return this.scriptEngine.eval(script);
+    }
+
+    @Override
+    public Object eval(final Reader reader) throws ScriptException {
+        return this.scriptEngine.eval(reader);
+    }
+
+    @Override
+    public Object eval(final String script, final Bindings n) throws 
ScriptException {
+        this.scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(n); 
// TODO: groovy and jython act different
+        return this.scriptEngine.eval(script);
+    }
+
+    @Override
+    public Object eval(final Reader reader, final Bindings n) throws 
ScriptException {
+        this.scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(n); 
// TODO: groovy and jython act different
+        return this.scriptEngine.eval(reader);
+    }
+
+    @Override
+    public void put(final String key, final Object value) {
+        this.scriptEngine.put(key, value);
+    }
+
+    @Override
+    public Object get(final String key) {
+        return this.scriptEngine.get(key);
+    }
+
+    @Override
+    public Bindings getBindings(final int scope) {
+        return this.scriptEngine.getBindings(scope);
+    }
+
+    @Override
+    public void setBindings(final Bindings bindings, final int scope) {
+        this.scriptEngine.setBindings(bindings, scope);
+    }
+
+    @Override
+    public Bindings createBindings() {
+        return this.scriptEngine.createBindings();
+    }
+
+    @Override
+    public ScriptContext getContext() {
+        return this.scriptEngine.getContext();
+    }
+
+    @Override
+    public void setContext(final ScriptContext context) {
+        this.scriptEngine.setContext(context);
+    }
+
+    @Override
+    public GremlinScriptEngineFactory getFactory() {
+        return new GremlinJavaScriptScriptEngineFactory();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngineFactory.java
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngineFactory.java
 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngineFactory.java
new file mode 100644
index 0000000..f1309be
--- /dev/null
+++ 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/GremlinJavaScriptScriptEngineFactory.java
@@ -0,0 +1,60 @@
+/*
+ * 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.javascript.jsr223;
+
+import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinScriptEngineFactory;
+import org.apache.tinkerpop.gremlin.jsr223.Customizer;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A {@link GremlinScriptEngineFactory} implementation that creates {@link 
GremlinJavaScriptScriptEngine} instances.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GremlinJavaScriptScriptEngineFactory extends 
AbstractGremlinScriptEngineFactory {
+    private static final String ENGINE_NAME = "gremlin-javascript";
+    private static final String LANGUAGE_NAME = "gremlin-javascript";
+    private static final String PLAIN = "plain";
+    private static final List<String> EXTENSIONS = 
Collections.singletonList("js");
+
+    public GremlinJavaScriptScriptEngineFactory() {
+        super(ENGINE_NAME, LANGUAGE_NAME, EXTENSIONS, 
Collections.singletonList(PLAIN));
+    }
+
+    @Override
+    public String getMethodCallSyntax(final String obj, final String m, final 
String... args) {
+        return null;
+    }
+
+    @Override
+    public String getOutputStatement(final String toDisplay) {
+        return "println " + toDisplay;
+    }
+
+    @Override
+    public GremlinScriptEngine getScriptEngine() {
+        final List<Customizer> customizers =  
manager.getCustomizers(ENGINE_NAME);
+        return (customizers.isEmpty()) ? new GremlinJavaScriptScriptEngine() :
+                new GremlinJavaScriptScriptEngine(customizers.toArray(new 
Customizer[customizers.size()]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptTranslator.java
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptTranslator.java
 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptTranslator.java
new file mode 100644
index 0000000..aeafd6e
--- /dev/null
+++ 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptTranslator.java
@@ -0,0 +1,220 @@
+/*
+ *  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.javascript.jsr223;
+
+import org.apache.commons.configuration.ConfigurationConverter;
+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.SackFunctions;
+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.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+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.Element;
+import org.apache.tinkerpop.gremlin.structure.T;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
+import org.apache.tinkerpop.gremlin.util.function.Lambda;
+import org.apache.tinkerpop.gremlin.util.iterator.ArrayIterator;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class JavaScriptTranslator implements Translator.ScriptTranslator {
+
+    private static final boolean IS_TESTING = 
Boolean.valueOf(System.getProperty("is.testing", "false"));
+    private static final Set<String> STEP_NAMES = 
Stream.of(GraphTraversal.class.getMethods()).filter(method -> 
Traversal.class.isAssignableFrom(method.getReturnType())).map(Method::getName).collect(Collectors.toSet());
+    private static final Set<String> NO_STATIC = Stream.of(T.values(), 
Operator.values())
+            .flatMap(arg -> IteratorUtils.stream(new ArrayIterator<>(arg)))
+            .map(arg -> ((Enum) arg).name())
+            .collect(Collectors.toCollection(() -> new 
HashSet<>(Collections.singleton("not"))));
+
+    private final String traversalSource;
+    private final boolean importStatics;
+
+    JavaScriptTranslator(final String traversalSource, final boolean 
importStatics) {
+        this.traversalSource = traversalSource;
+        this.importStatics = importStatics;
+    }
+
+    public static JavaScriptTranslator of(final String traversalSource, final 
boolean importStatics) {
+        return new JavaScriptTranslator(traversalSource, importStatics);
+    }
+
+    public static JavaScriptTranslator of(final String traversalSource) {
+        return new JavaScriptTranslator(traversalSource, false);
+    }
+
+    @Override
+    public String getTraversalSource() {
+        return this.traversalSource;
+    }
+
+    @Override
+    public String translate(final Bytecode bytecode) {
+        return this.internalTranslate(this.traversalSource, bytecode);
+    }
+
+    @Override
+    public String getTargetLanguage() {
+        return "gremlin-python";
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.translatorString(this);
+    }
+
+    ///////
+
+    private String internalTranslate(final String start, final Bytecode 
bytecode) {
+        final StringBuilder traversalScript = new StringBuilder(start);
+        for (final Bytecode.Instruction instruction : 
bytecode.getInstructions()) {
+            final String methodName = instruction.getOperator();
+            final Object[] arguments = instruction.getArguments();
+            if (IS_TESTING &&
+                    
instruction.getOperator().equals(TraversalSource.Symbols.withStrategies) &&
+                    
instruction.getArguments()[0].toString().contains("TranslationStrategy"))
+                continue;
+            else if (0 == arguments.length)
+                
traversalScript.append(".").append(SymbolHelper.toJavaScript(methodName)).append("()");
+            else if (methodName.equals("values") && 1 == arguments.length && 
traversalScript.length() > 3 && !STEP_NAMES.contains(arguments[0].toString()))
+                traversalScript.append(".").append(arguments[0]);
+            else {
+                traversalScript.append(".");
+                String temp = SymbolHelper.toJavaScript(methodName) + "(";
+                for (final Object object : arguments) {
+                    temp = temp + convertToString(object) + ",";
+                }
+                traversalScript.append(temp.substring(0, temp.length() - 
1)).append(")");
+            }
+            // clip off __.
+            if (this.importStatics && traversalScript.substring(0, 
3).startsWith("__.")
+                    && !NO_STATIC.stream().filter(name -> 
traversalScript.substring(3).startsWith(SymbolHelper.toJavaScript(name))).findAny().isPresent())
 {
+                traversalScript.delete(0, 3);
+            }
+        }
+        return traversalScript.toString();
+    }
+
+    private String convertToString(final Object object) {
+        if (object instanceof Bytecode.Binding)
+            return ((Bytecode.Binding) object).variable();
+        else if (object instanceof Bytecode)
+            return this.internalTranslate("__", (Bytecode) object);
+        else if (object instanceof Traversal)
+            return convertToString(((Traversal) 
object).asAdmin().getBytecode());
+        else if (object instanceof String)
+            return ((String) object).contains("\"") ? "\"\"\"" + object + 
"\"\"\"" : "\"" + object + "\"";
+        else if (object instanceof Set) {
+            final Set<String> set = new LinkedHashSet<>(((Set) object).size());
+            for (final Object item : (Set) object) {
+                set.add(convertToString(item));
+            }
+            return "new Set(" + set.toString() + ")"; // supported in ECMA 
Script 6 and JDK 9
+        } else if (object instanceof List) {
+            final List<String> list = new ArrayList<>(((List) object).size());
+            for (final Object item : (List) object) {
+                list.add(convertToString(item));
+            }
+            return list.toString();
+        } else if (object instanceof Map) {
+            final StringBuilder map = new StringBuilder("{");
+            for (final Map.Entry<?, ?> entry : ((Map<?, ?>) 
object).entrySet()) {
+                map.append(convertToString(entry.getKey())).
+                        append(":").
+                        append(convertToString(entry.getValue())).
+                        append(",");
+            }
+            return map.length() > 1 ? map.substring(0, map.length() - 1) + "}" 
: map.append("}").toString();
+        } else if (object instanceof Long)
+            return object + "L";
+        else if (object instanceof TraversalStrategyProxy) {
+            final TraversalStrategyProxy proxy = (TraversalStrategyProxy) 
object;
+            if (proxy.getConfiguration().isEmpty())
+                return "TraversalStrategy(\"" + 
proxy.getStrategyClass().getSimpleName() + "\")";
+            else
+                return "TraversalStrategy(\"" + 
proxy.getStrategyClass().getSimpleName() + "\"," + 
convertToString(ConfigurationConverter.getMap(proxy.getConfiguration())) + ")";
+        } else if (object instanceof TraversalStrategy) {
+            return convertToString(new 
TraversalStrategyProxy((TraversalStrategy) object));
+        } else if (object instanceof Boolean)
+            return object.equals(Boolean.TRUE) ? "true" : "false";
+        else if (object instanceof Class)
+            return ((Class) object).getCanonicalName();
+        else if (object instanceof VertexProperty.Cardinality)
+            return "Cardinality." + 
SymbolHelper.toJavaScript(object.toString());
+        else if (object instanceof SackFunctions.Barrier)
+            return "Barrier." + SymbolHelper.toJavaScript(object.toString());
+        else if (object instanceof TraversalOptionParent.Pick)
+            return "Pick." + SymbolHelper.toJavaScript(object.toString());
+        else if (object instanceof Enum)
+            return convertStatic(((Enum) 
object).getDeclaringClass().getSimpleName() + ".") + 
SymbolHelper.toJavaScript(object.toString());
+        else if (object instanceof P)
+            return convertPToString((P) object, new 
StringBuilder()).toString();
+        else if (object instanceof Element)
+            return convertToString(((Element) object).id()); // hack
+        else if (object instanceof Lambda)
+            return convertLambdaToString((Lambda) object);
+        else
+            return null == object ? "undefined" : object.toString();
+    }
+
+    private String convertStatic(final String name) {
+        return this.importStatics ? "" : name;
+    }
+
+    private StringBuilder convertPToString(final P p, final StringBuilder 
current) {
+        if (p instanceof ConnectiveP) {
+            final List<P<?>> list = ((ConnectiveP) p).getPredicates();
+            for (int i = 0; i < list.size(); i++) {
+                convertPToString(list.get(i), current);
+                if (i < list.size() - 1)
+                    current.append(p instanceof OrP ? ".or(" : ".and(");
+            }
+            current.append(")");
+        } else
+            
current.append(convertStatic("P.")).append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
+        return current;
+    }
+
+    protected String convertLambdaToString(final Lambda lambda) {
+        final String lambdaString = lambda.getLambdaScript().trim();
+        return lambdaString.startsWith("lambda") ? lambdaString : "lambda " + 
lambdaString;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java
 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java
new file mode 100644
index 0000000..204ec4b
--- /dev/null
+++ 
b/gremlin-javascript/src/main/java/org/apache/tinkerpop/gremlin/javascript/jsr223/SymbolHelper.java
@@ -0,0 +1,51 @@
+/*
+ *  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.javascript.jsr223;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class SymbolHelper {
+
+    private final static Map<String, String> TO_JS_MAP = new HashMap<>();
+    private final static Map<String, String> FROM_JS_MAP = new HashMap<>();
+
+    static {
+        //
+        TO_JS_MAP.put("in", "in_");
+        TO_JS_MAP.forEach((k, v) -> FROM_JS_MAP.put(v, k));
+    }
+
+    private SymbolHelper() {
+        // static methods only, do not instantiate
+    }
+
+    public static String toJavaScript(final String symbol) {
+        return TO_JS_MAP.getOrDefault(symbol, symbol);
+    }
+
+    public static String toJava(final String symbol) {
+        return FROM_JS_MAP.getOrDefault(symbol, symbol);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
index 514663b..1228dd4 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/package.json
@@ -1,6 +1,6 @@
 {
   "name": "gremlin-javascript",
-  "version": "3.2.6-alpha1",
+  "version": "3.2.7-alpha1",
   "description": "JavaScript Gremlin Language Variant",
   "author": "Apache TinkerPop team",
   "keywords": [

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
 
b/gremlin-javascript/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
new file mode 100644
index 0000000..0363752
--- /dev/null
+++ 
b/gremlin-javascript/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
@@ -0,0 +1 @@
+org.apache.tinkerpop.gremlin.javascript.jsr223.GremlinJavaScriptScriptEngineFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/test/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptGremlinScriptEngineTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-javascript/src/test/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptGremlinScriptEngineTest.java
 
b/gremlin-javascript/src/test/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptGremlinScriptEngineTest.java
new file mode 100644
index 0000000..0956aa9
--- /dev/null
+++ 
b/gremlin-javascript/src/test/java/org/apache/tinkerpop/gremlin/javascript/jsr223/JavaScriptGremlinScriptEngineTest.java
@@ -0,0 +1,31 @@
+/*
+ *  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.javascript.jsr223;
+
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineSuite;
+import org.apache.tinkerpop.gremlin.jsr223.ScriptEngineToTest;
+import org.junit.runner.RunWith;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(GremlinScriptEngineSuite.class)
+@ScriptEngineToTest(scriptEngineName = "gremlin-javascript")
+public class JavaScriptGremlinScriptEngineTest {
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/test/resources/log4j-silent.properties
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/test/resources/log4j-silent.properties 
b/gremlin-javascript/src/test/resources/log4j-silent.properties
new file mode 100644
index 0000000..1825bb0
--- /dev/null
+++ b/gremlin-javascript/src/test/resources/log4j-silent.properties
@@ -0,0 +1,23 @@
+# 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.
+
+# this file should always have logging set to OFF.  it seems, however, that an 
appender of some sort is
+# required or else some logs throw error and use other log4j.properties files 
on the path.
+log4j.rootLogger=OFF, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%p] %C - %m%n
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-javascript/src/test/resources/log4j-test.properties
----------------------------------------------------------------------
diff --git a/gremlin-javascript/src/test/resources/log4j-test.properties 
b/gremlin-javascript/src/test/resources/log4j-test.properties
new file mode 100644
index 0000000..79038b1
--- /dev/null
+++ b/gremlin-javascript/src/test/resources/log4j-test.properties
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+log4j.rootLogger=WARN, stdout
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%p] %C - %m%n
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
index 8886de9..ae3735e 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
@@ -62,7 +62,7 @@ public class BindingsScriptEngineTest {
 
         final GremlinScriptEngine engine1 = 
manager.getEngineByName(ENGINE_TO_TEST);
         assertThat(engine1.getBindings(ScriptContext.GLOBAL_SCOPE).size(), 
is(1));
-        assertEquals(101, (int) engine1.eval("x+1"));
+        assertEquals(101, ((Number) engine1.eval("x+1")).intValue());
 
         manager.getBindings().remove("x");
         final GremlinScriptEngine engine2 = 
manager.getEngineByName(ENGINE_TO_TEST);
@@ -79,7 +79,7 @@ public class BindingsScriptEngineTest {
         manager.addPlugin(plugin);
         final GremlinScriptEngine engine = 
manager.getEngineByName(ENGINE_TO_TEST);
         assertThat(engine.getBindings(ScriptContext.GLOBAL_SCOPE).size(), 
is(1));
-        assertEquals(101, (int) engine.eval("x+1"));
+        assertEquals(101, ((Number) engine.eval("x+1")).intValue());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
index 5a880f8..6a0e5bc 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinEnabledScriptEngineTest.java
@@ -30,7 +30,9 @@ import java.util.List;
 import java.util.Optional;
 
 import static 
org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineSuite.ENGINE_TO_TEST;
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.hamcrest.core.Is.is;
 
 /**
  * This is an important test case in that it validates that core features of 
{@code ScriptEngine} instances that claim
@@ -52,7 +54,7 @@ public class GremlinEnabledScriptEngineTest {
         final GremlinScriptEngine scriptEngine = 
manager.getEngineByName(ENGINE_TO_TEST);
         final List<Class> classesToCheck = Arrays.asList(Vertex.class, 
Edge.class, Graph.class, VertexProperty.class);
         for (Class clazz : classesToCheck) {
-            assertEquals(clazz, scriptEngine.eval(clazz.getSimpleName()));
+            assertClassEquality(scriptEngine.eval(clazz.getSimpleName()), 
clazz);
         }
     }
 
@@ -77,7 +79,7 @@ public class GremlinEnabledScriptEngineTest {
         final GremlinScriptEngine scriptEngine = 
mgr.getEngineByName(ENGINE_TO_TEST);
         final List<Class> classesToCheck = Arrays.asList(java.awt.Color.class, 
java.sql.CallableStatement.class);
         for (Class clazz : classesToCheck) {
-            assertEquals(clazz, scriptEngine.eval(clazz.getSimpleName()));
+            assertClassEquality(scriptEngine.eval(clazz.getSimpleName()), 
clazz);
         }
     }
 
@@ -89,4 +91,13 @@ public class GremlinEnabledScriptEngineTest {
                 
.appliesTo(Collections.singletonList("fake-script-engine")).create());
         assertEquals(0, mgr.getCustomizers(ENGINE_TO_TEST).size());
     }
+
+    private void assertClassEquality(final Object fromScriptEngine, final 
Class<?> expected) {
+        // this should typically equal the Class, but some scriptengines like 
nashorn create a synthetic class
+        // to wrap it in.
+        final boolean matches = fromScriptEngine.equals(expected) || 
fromScriptEngine.toString().contains(expected.getName());
+
+        assertThat("Doesn't match for " + fromScriptEngine, matches, is(true));
+
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/468bba63/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineLambdaTest.java
----------------------------------------------------------------------
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineLambdaTest.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineLambdaTest.java
index a1509cb..80998b2 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineLambdaTest.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ScriptEngineLambdaTest.java
@@ -37,7 +37,7 @@ public class ScriptEngineLambdaTest {
     public void shouldCallAsFunction() {
         // Function.apply
         final ScriptEngineLambda lambda = newLambda("1+a");
-        assertEquals(11, Integer.parseInt(lambda.apply(10).toString()));
+        assertEquals(11, ((Number) lambda.apply(10)).intValue());
     }
 
     @Test(expected = IllegalArgumentException.class)
@@ -130,14 +130,14 @@ public class ScriptEngineLambdaTest {
     @Test
     public void shouldCallTrivialFunction() {
         final ScriptEngineLambda lambda = newLambda("2 + 2");
-        assertEquals(lambda.apply("foo"), 4);
+        assertEquals(4, lambda.apply("foo"));
     }
 
     @Test
     public void shouldCallAsOneArgFunction() {
         final ScriptEngineLambda lambda = newLambda("a + 2");
-        assertEquals(lambda.apply(3), 5);
-        assertEquals(lambda.apply(10), 12);
+        assertEquals(5, ((Number) lambda.apply(3)).intValue());
+        assertEquals(12, ((Number) lambda.apply(10)).intValue());
     }
 
     private static ScriptEngineLambda newLambda(final String script) {

Reply via email to