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/13 19:11:54 UTC

[tinkerpop] branch master updated (a6d90ea -> 88704e9)

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

spmallette pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git.


    from a6d90ea  Merge branch '3.4-dev'
     add 19411e2  TINKERPOP-2466 Provided more succinct syntax for withStrategies()
     add c666e0b  TINKERPOP-2461 Aligned CoreImports with GroovyTranslator
     add 9145537  TINKERPOP-2461 Added upgrade docs
     add 127821e  TINKERPOP-2461 Added reference documentation for Translator
     add 89529de  Merge branch 'TINKERPOP-2461' into 3.4-dev
     new 88704e9  Merge branch '3.4-dev'

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 CHANGELOG.asciidoc                                 |   2 +
 docs/src/reference/gremlin-variants.asciidoc       |   4 +-
 docs/src/reference/the-traversal.asciidoc          |  63 ++++++++++++++
 docs/src/upgrade/release-3.4.x.asciidoc            |  77 +++++++++++++++--
 docs/static/images/gremlin-translator.png          | Bin 0 -> 998775 bytes
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |  13 +++
 .../gremlin/process/traversal/Translator.java      |  16 +++-
 .../strategy/decoration/EventStrategy.java         |  12 +--
 .../strategy/decoration/SackStrategy.java          |   4 +
 .../traversal/translator/GroovyTranslator.java     |  70 ++++++++++------
 .../traversal/translator/GroovyTranslatorTest.java |  58 ++++++-------
 .../ParameterizedGroovyTranslatorTest.java         |  18 ++--
 .../gremlin/groovy/loaders/GremlinLoader.groovy    |   4 +-
 .../gremlin/groovy/loaders/ObjectLoader.groovy     |   2 +-
 .../gremlin/groovy/loaders/StepLoader.groovy       |  22 ++++-
 .../gremlin/groovy/loaders/StrategyLoader.groovy   |  92 +++++++++++++++++++++
 .../gremlin/groovy/loaders/SugarLoader.groovy      |   2 +-
 .../jsr223/GremlinGroovyScriptEngineTest.java      |  31 +++++++
 18 files changed, 402 insertions(+), 88 deletions(-)
 create mode 100644 docs/static/images/gremlin-translator.png
 create mode 100644 gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy


[tinkerpop] 01/01: Merge branch '3.4-dev'

Posted by sp...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 88704e926fdb8beb1fa4d29aea62a7b605ff21e9
Merge: a6d90ea 89529de
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Nov 13 14:11:32 2020 -0500

    Merge branch '3.4-dev'

 CHANGELOG.asciidoc                                 |   2 +
 docs/src/reference/gremlin-variants.asciidoc       |   4 +-
 docs/src/reference/the-traversal.asciidoc          |  63 ++++++++++++++
 docs/src/upgrade/release-3.4.x.asciidoc            |  77 +++++++++++++++--
 docs/static/images/gremlin-translator.png          | Bin 0 -> 998775 bytes
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |  13 +++
 .../gremlin/process/traversal/Translator.java      |  16 +++-
 .../strategy/decoration/EventStrategy.java         |  12 +--
 .../strategy/decoration/SackStrategy.java          |   4 +
 .../traversal/translator/GroovyTranslator.java     |  70 ++++++++++------
 .../traversal/translator/GroovyTranslatorTest.java |  58 ++++++-------
 .../ParameterizedGroovyTranslatorTest.java         |  18 ++--
 .../gremlin/groovy/loaders/GremlinLoader.groovy    |   4 +-
 .../gremlin/groovy/loaders/ObjectLoader.groovy     |   2 +-
 .../gremlin/groovy/loaders/StepLoader.groovy       |  22 ++++-
 .../gremlin/groovy/loaders/StrategyLoader.groovy   |  92 +++++++++++++++++++++
 .../gremlin/groovy/loaders/SugarLoader.groovy      |   2 +-
 .../jsr223/GremlinGroovyScriptEngineTest.java      |  31 +++++++
 18 files changed, 402 insertions(+), 88 deletions(-)

diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
index fb7c487,c2efdca..30dccc4
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Translator.java
@@@ -48,22 -33,22 +48,30 @@@ public interface Translator<S, T> 
      /**
       * Get the {@link TraversalSource} representation rooting this translator.
       * For string-based translators ({@link ScriptTranslator}), this is typically a "g".
--     * For java-based translators ({@link StepTranslator}), this is typically the {@link TraversalSource} instance which the {@link Traversal} will be built from.
++     * For java-based translators ({@link StepTranslator}), this is typically the {@link TraversalSource} instance
++     * which the {@link Traversal} will be built from.
       *
       * @return the traversal source representation
       */
      public S getTraversalSource();
  
      /**
--     * Translate {@link Bytecode} into a new representation.
--     * Typically, for language translations, the translation is to a string represenging the traversal in the respective scripting language.
++     * Translate {@link Bytecode} into a new representation. Typically, for language translations, the translation is
++     * to a string representing the traversal in the respective scripting language.
       *
--     * @param bytecode the byte code representing traversal source and traversal manipulations.
++     * @param bytecode the bytecode representing traversal source and traversal manipulations.
       * @return the translated object
       */
      public T translate(final Bytecode bytecode);
  
      /**
++     * Translates a {@link Traversal} into the specified form
++     */
++    public default T translate(final Traversal<?,?> t) {
++        return translate(t.asAdmin().getBytecode());
++    }
++
++    /**
       * Get the language that the translator is converting the traversal byte code to.
       *
       * @return the language of the translation
diff --cc gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
index b902ef0,6e8dc48..b57ffc7
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslator.java
@@@ -1,26 -1,26 +1,27 @@@
  /*
 - * 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
 + *  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
 + *  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.
 + *  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.process.traversal.translator;
  
 -import org.apache.commons.configuration.ConfigurationConverter;
 -import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.configuration2.ConfigurationConverter;
 +import org.apache.commons.text.StringEscapeUtils;
+ import org.apache.tinkerpop.gremlin.jsr223.CoreImports;
  import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
  import org.apache.tinkerpop.gremlin.process.traversal.P;
  import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions;
@@@ -116,194 -103,124 +118,210 @@@ public final class GroovyTranslator imp
      /**
       * Performs standard type translation for the TinkerPop types to Groovy.
       */
 -    public static class DefaultTypeTranslator implements TypeTranslator {
 +    public static class DefaultTypeTranslator extends AbstractTypeTranslator {
 +
 +        public DefaultTypeTranslator(final boolean withParameters) {
 +            super(withParameters);
 +        }
 +
 +        @Override
 +        protected String getNullSyntax() {
 +            return "null";
 +        }
 +
 +        @Override
 +        protected String getSyntax(final String o) {
 +            return (o.contains("\"") ? "\"\"\"" + StringEscapeUtils.escapeJava(o) + "\"\"\"" : "\"" + StringEscapeUtils.escapeJava(o) + "\"")
 +                    .replace("$", "\\$");
 +        }
 +
 +        @Override
 +        protected String getSyntax(final Boolean o) {
 +            return o.toString();
 +        }
 +
 +        @Override
 +        protected String getSyntax(final Date o) {
-             return "new java.util.Date(" + o.getTime() + ")";
++            return "new Date(" + o.getTime() + ")";
 +        }
 +
 +        @Override
 +        protected String getSyntax(final Timestamp o) {
-             return "new java.sql.Timestamp(" + o.getTime() + ")";
++            return "new Timestamp(" + o.getTime() + ")";
 +        }
  
          @Override
 -        public Object apply(final String traversalSource, final Object o) {
 -            if (o instanceof Bytecode)
 -                return internalTranslate(traversalSource, (Bytecode) o);
 +        protected String getSyntax(final UUID o) {
-             return "java.util.UUID.fromString('" + o.toString() + "')";
++            return "UUID.fromString('" + o.toString() + "')";
 +        }
 +
 +        @Override
 +        protected String getSyntax(final Lambda o) {
 +            final String lambdaString = o.getLambdaScript().trim();
 +            return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
 +        }
 +
 +        @Override
 +        protected String getSyntax(final SackFunctions.Barrier o) {
 +            return "SackFunctions.Barrier." + o.toString();
 +        }
 +
 +        @Override
 +        protected String getSyntax(final VertexProperty.Cardinality o) {
 +            return "VertexProperty.Cardinality." + o.toString();
 +        }
 +
 +        @Override
 +        protected String getSyntax(final TraversalOptionParent.Pick o) {
 +            return "TraversalOptionParent.Pick." + o.toString();
 +        }
 +
 +        @Override
 +        protected String getSyntax(final Number o) {
 +            if (o instanceof Long)
 +                return o + "L";
 +            else if (o instanceof Double)
 +                return o + "d";
 +            else if (o instanceof Float)
 +                return o + "f";
 +            else if (o instanceof Integer)
 +                return "(int) " + o;
 +            else if (o instanceof Byte)
 +                return "(byte) " + o;
 +            if (o instanceof Short)
 +                return "(short) " + o;
 +            else if (o instanceof BigInteger)
-                 return "new java.math.BigInteger('" + o.toString() + "')";
++                return "new BigInteger('" + o.toString() + "')";
 +            else if (o instanceof BigDecimal)
-                 return "new java.math.BigDecimal('" + o.toString() + "')";
++                return "new BigDecimal('" + o.toString() + "')";
              else
 -                return convertToString(o);
 +                return o.toString();
          }
  
 -        protected String convertToString(final Object object) {
 -            if (object instanceof Bytecode.Binding)
 -                return ((Bytecode.Binding) object).variable();
 -            else if (object instanceof Bytecode)
 -                return internalTranslate("__", (Bytecode) object);
 -            else if (object instanceof Traversal)
 -                return convertToString(((Traversal) object).asAdmin().getBytecode());
 -            else if (object instanceof String) {
 -                return (((String) object).contains("\"") ? "\"\"\"" + StringEscapeUtils.escapeJava((String) object) + "\"\"\"" : "\"" + StringEscapeUtils.escapeJava((String) object) + "\"")
 -                        .replace("$", "\\$");
 -            } else if (object instanceof Set) {
 -                final Set<String> set = new HashSet<>(((Set) object).size());
 -                for (final Object item : (Set) object) {
 -                    set.add(convertToString(item));
 -                }
 -                return set.toString() + " as Set";
 -            } 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("(").
 -                            append(convertToString(entry.getKey())).
 -                            append("):(").
 -                            append(convertToString(entry.getValue())).
 -                            append("),");
 +        @Override
 +        protected Script produceScript(final Set<?> o) {
 +            return produceScript(new ArrayList<>(o)).append(" as Set");
 +        }
 +
 +        @Override
 +        protected Script produceScript(final List<?> o) {
 +            final Iterator<?> iterator = ((List<?>) o).iterator();
 +            script.append("[");
 +
 +            while (iterator.hasNext()) {
 +                final Object nextItem = iterator.next();
 +                convertToScript(nextItem);
 +                if (iterator.hasNext())
 +                    script.append(",").append(" ");
 +            }
 +
 +            return script.append("]");
 +        }
 +
 +        @Override
 +        protected Script produceScript(final Map<?, ?> o) {
 +            script.append("[");
 +            final Iterator<? extends Map.Entry<?, ?>> itty = ((Map<?, ?>) o).entrySet().iterator();
 +            while (itty.hasNext()) {
 +                final Map.Entry<?,?> entry = itty.next();
 +                script.append("(");
 +                convertToScript(entry.getKey());
 +                script.append("):(");
 +                convertToScript(entry.getValue());
 +                script.append(")");
 +                if (itty.hasNext())
 +                    script.append(",");
 +            }
 +            return script.append("]");
 +        }
 +
++        /**
++         * Gets the string representation of a class with the default implementation simply checking to see if the
++         * {@code Class} is in {@link CoreImports} or not. If it is present that means it can be referenced using the
++         * simple name otherwise it uses the canonical name.
++         * <p/>
++         * Those building custom {@link ScriptTranslator} instances might override this if they have other classes
++         * that are not in {@link CoreImports} by default.
++         */
 +        @Override
 +        protected Script produceScript(final Class<?> o) {
-             return script.append(o.getCanonicalName());
++            return script.append(CoreImports.getClassImports().contains(o) ? o.getSimpleName() : o.getCanonicalName());
 +        }
 +
 +        @Override
 +        protected Script produceScript(final Enum<?> o) {
 +            return script.append(o.getDeclaringClass().getSimpleName() + "." + o.toString());
 +        }
 +
 +        @Override
 +        protected Script produceScript(final Vertex o) {
-             script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(");
++            script.append("new ReferenceVertex(");
 +            convertToScript(o.id());
 +            script.append(",");
 +            convertToScript(o.label());
-             return script.append(", Collections.emptyMap())");
++            return script.append(")");
 +        }
 +
 +        @Override
 +        protected Script produceScript(final Edge o) {
-             script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(");
++            script.append("new ReferenceEdge(");
 +            convertToScript(o.id());
 +            script.append(",");
 +            convertToScript(o.label());
++            script.append(",new ReferenceVertex(");
++            convertToScript(o.inVertex().id());
 +            script.append(",");
-             script.append("Collections.emptyMap(),");
++            convertToScript(o.inVertex().label());
++            script.append("),new ReferenceVertex(");
 +            convertToScript(o.outVertex().id());
 +            script.append(",");
 +            convertToScript(o.outVertex().label());
-             script.append(",");
-             convertToScript(o.inVertex().id());
-             script.append(",");
-             convertToScript(o.inVertex().label());
-             return script.append(")");
++            return script.append("))");
 +        }
 +
 +        @Override
 +        protected Script produceScript(final VertexProperty<?> o) {
-             script.append("new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty(");
++            script.append("new ReferenceVertexProperty(");
 +            convertToScript(o.id());
 +            script.append(",");
 +            convertToScript(o.label());
 +            script.append(",");
 +            convertToScript(o.value());
-             script.append(",");
-             script.append("Collections.emptyMap(),");
-             convertToScript(o.element());
 +            return script.append(")");
 +        }
 +
 +        @Override
 +        protected Script produceScript(final TraversalStrategyProxy<?> o) {
 +            if (o.getConfiguration().isEmpty()) {
-                 return script.append(o.getStrategyClass().getCanonicalName() + ".instance()");
++                return produceScript(o.getStrategyClass());
 +            } else {
-                 script.append(o.getStrategyClass().getCanonicalName() + ".create(new org.apache.commons.configuration2.MapConfiguration(");
-                 convertToScript(ConfigurationConverter.getMap(o.getConfiguration()));
-                 return script.append("))");
++                script.append("new ");
++                produceScript(o.getStrategyClass());
++                script.append("(");
++
++                final Iterator<Map.Entry<Object,Object>> itty = ConfigurationConverter.getMap(
++                        o.getConfiguration()).entrySet().iterator();
++                while (itty.hasNext()) {
++                    final Map.Entry<Object,Object> entry = itty.next();
++                    script.append(entry.getKey().toString());
++                    script.append(": ");
++                    convertToScript(entry.getValue());
++                    if (itty.hasNext()) script.append(", ");
+                 }
+ 
 -                // only need to remove this last bit if entries were added
 -                if (!((Map<?, ?>) object).isEmpty())
 -                    map.deleteCharAt(map.length() - 1);
 -
 -                return map.append("]").toString();
 -            } else if (object instanceof Long)
 -                return object + "L";
 -            else if (object instanceof Double)
 -                return object + "d";
 -            else if (object instanceof Float)
 -                return object + "f";
 -            else if (object instanceof Integer)
 -                return "(int) " + object;
 -            else if (object instanceof Class)
 -                return convertClassToString((Class<?>) object);
 -            else if (object instanceof Timestamp)
 -                return "new Timestamp(" + ((Timestamp) object).getTime() + ")";
 -            else if (object instanceof Date)
 -                return "new Date(" + ((Date) object).getTime() + ")";
 -            else if (object instanceof UUID)
 -                return "UUID.fromString('" + object.toString() + "')";
 -            else if (object instanceof P)
 -                return convertPToString((P) object, new StringBuilder()).toString();
 -            else if (object instanceof SackFunctions.Barrier)
 -                return "SackFunctions.Barrier." + object.toString();
 -            else if (object instanceof VertexProperty.Cardinality)
 -                return "VertexProperty.Cardinality." + object.toString();
 -            else if (object instanceof TraversalOptionParent.Pick)
 -                return "TraversalOptionParent.Pick." + object.toString();
 -            else if (object instanceof Enum)
 -                return ((Enum) object).getDeclaringClass().getSimpleName() + "." + object.toString();
 -            else if (object instanceof Vertex) {
 -                final Vertex vertex = (Vertex) object;
 -                return "new ReferenceVertex(" +
 -                        convertToString(vertex.id()) + "," +
 -                        convertToString(vertex.label()) + ")";
 -            } else if (object instanceof Edge) {
 -                    final Edge edge = (Edge) object;
 -                    return "new ReferenceEdge(" +
 -                            convertToString(edge.id()) + "," +
 -                            convertToString(edge.label()) + "," +
 -                            "new ReferenceVertex(" + convertToString(edge.inVertex().id()) + "," +
 -                            convertToString(edge.inVertex().label()) + ")," +
 -                            "new ReferenceVertex(" + convertToString(edge.outVertex().id()) + "," +
 -                            convertToString(edge.outVertex().label()) + "))";
 -            } else if (object instanceof VertexProperty) {
 -                    final VertexProperty<?> vertexProperty = (VertexProperty<?>) object;
 -                    return "new ReferenceVertexProperty(" +
 -                            convertToString(vertexProperty.id()) + "," +
 -                            convertToString(vertexProperty.label()) + "," +
 -                            convertToString(vertexProperty.value()) + ")";
 -            } else if (object instanceof Lambda) {
 -                final String lambdaString = ((Lambda) object).getLambdaScript().trim();
 -                return lambdaString.startsWith("{") ? lambdaString : "{" + lambdaString + "}";
 -            } else if (object instanceof TraversalStrategyProxy) {
 -                final TraversalStrategyProxy proxy = (TraversalStrategyProxy) object;
 -                final String className = convertClassToString(proxy.getStrategyClass());
 -                if (proxy.getConfiguration().isEmpty())
 -                    return className;
 -                else
 -                    return String.format("new %s(%s)", className, convertMapToArguments(ConfigurationConverter.getMap(proxy.getConfiguration())));
 -            } else if (object instanceof TraversalStrategy) {
 -                return convertToString(new TraversalStrategyProxy(((TraversalStrategy) object)));
 -            } else
 -                return null == object ? "null" : object.toString();
++                return script.append(")");
 +            }
          }
  
 -        protected String internalTranslate(final String start, final Bytecode bytecode) {
 -            final StringBuilder traversalScript = new StringBuilder(start);
 -            for (final Bytecode.Instruction instruction : bytecode.getInstructions()) {
 +        @Override
 +        protected Script produceScript(final String traversalSource, final Bytecode o) {
 +            script.append(traversalSource);
 +            for (final Bytecode.Instruction instruction : o.getInstructions()) {
                  final String methodName = instruction.getOperator();
 -                if (0 == instruction.getArguments().length)
 -                    traversalScript.append(".").append(methodName).append("()");
 -                else {
 -                    traversalScript.append(".");
 -                    String temp = methodName + "(";
 +                if (0 == instruction.getArguments().length) {
 +                    script.append(".").append(methodName).append("()");
 +                } else {
 +                    script.append(".").append(methodName).append("(");
  
                      // have to special case withSack() for Groovy because UnaryOperator and BinaryOperator signatures
                      // make it impossible for the interpreter to figure out which function to call. specifically we need
@@@ -321,42 -238,58 +339,48 @@@
                          final String castSecondArgTo = secondArg.getLambdaArguments() == 1 ? UnaryOperator.class.getName() :
                                  BinaryOperator.class.getName();
                          if (!castFirstArgTo.isEmpty())
 -                            temp = temp + String.format("(%s) ", castFirstArgTo);
 -                        temp = temp + String.format("%s, (%s) %s,",
 -                                convertToString(instruction.getArguments()[0]), castSecondArgTo,
 -                                convertToString(instruction.getArguments()[1]));
 +                            script.append(String.format("(%s) ", castFirstArgTo));
 +                        convertToScript(instruction.getArguments()[0]);
 +                        script.append(", (").append(castSecondArgTo).append(") ");
 +                        convertToScript(instruction.getArguments()[1]);
 +                        script.append(",");
                      } else {
                          for (final Object object : instruction.getArguments()) {
 -                            temp = temp + convertToString(object) + ",";
 +                            convertToScript(object);
 +                            script.append(",");
                          }
                      }
 -                    traversalScript.append(temp.substring(0, temp.length() - 1)).append(")");
 +                    script.setCharAtEnd(')');
                  }
              }
 -            return traversalScript.toString();
 +            return script;
          }
  
 -        protected StringBuilder convertPToString(final P p, final StringBuilder current) {
 -            if (p instanceof TextP) return convertTextPToString((TextP) p, current);
 -            if (p instanceof ConnectiveP) {
 +        @Override
 +        protected Script produceScript(final P<?> p) {
 +            if (p instanceof TextP) {
 +                script.append("TextP.").append(p.getBiPredicate().toString()).append("(");
 +                convertToScript(p.getValue());
 +            } else 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(");
 +                    produceScript(list.get(i));
 +                    if (i < list.size() - 1) {
 +                        script.append(p instanceof OrP ? ".or(" : ".and(");
 +                    }
                  }
 -                current.append(")");
 -            } else
 -                current.append("P.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
 -            return current;
 -        }
 -
 -        protected StringBuilder convertTextPToString(final TextP p, final StringBuilder current) {
 -            current.append("TextP.").append(p.getBiPredicate().toString()).append("(").append(convertToString(p.getValue())).append(")");
 -            return current;
 -        }
 -
 -        /**
 -         * Gets the string representation of a class with the default implementation simply checking to see if the
 -         * {@code Class} is in {@link CoreImports} or not. If it is present that means it can be referenced using the
 -         * simple name otherwise it uses the canonical name.
 -         * <p/>
 -         * Those building custom {@link ScriptTranslator} instances might override this if they have other classes
 -         * that are not in {@link CoreImports} by default.
 -         */
 -        protected String convertClassToString(final Class<?> clazz) {
 -            return CoreImports.getClassImports().contains(clazz) ? clazz.getSimpleName() : clazz.getCanonicalName();
 +            } else {
 +                script.append("P.").append(p.getBiPredicate().toString()).append("(");
 +                convertToScript(p.getValue());
 +            }
 +            script.append(")");
 +            return script;
          }
+ 
+         private String convertMapToArguments(final Map<Object,Object> map) {
+             return map.entrySet().stream().map(entry ->
 -                String.format("%s: %s", entry.getKey().toString(), convertToString(entry.getValue()))).
++                String.format("%s: %s", entry.getKey().toString(), convertToScript(entry.getValue()))).
+                     collect(Collectors.joining(", "));
+         }
      }
  }
 -
diff --cc gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/GroovyTranslatorTest.java
index 2f05994,8455293..ac282f8
--- 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
@@@ -63,28 -63,28 +63,28 @@@ public class GroovyTranslatorTest 
  
      @Test
      public void shouldTranslateStrategies() throws Exception {
-         assertEquals("g.withStrategies(org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy.instance(),org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy.create(new org.apache.commons.configuration2.MapConfiguration([(\"checkAdjacentVertices\"):(false),(\"vertices\"):(__.hasLabel(\"person\"))]))).V().has(\"name\")",
+         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()).getScript());
 -                        V().has("name")));
++                        V().has("name")).getScript());
      }
  
      @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()).getScript();
 -        final String scriptConstantUnary = translator.translate(tConstantUnary);
++        final String scriptConstantUnary = translator.translate(tConstantUnary).getScript();
          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()).getScript();
 -        final String scriptSupplierUnary = translator.translate(tSupplierUnary);
++        final String scriptSupplierUnary = translator.translate(tSupplierUnary).getScript();
          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()).getScript();
 -        final String scriptConstantBinary = translator.translate(tConstantBinary);
++        final String scriptConstantBinary = translator.translate(tConstantBinary).getScript();
          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()).getScript();
 -        final String scriptSupplierBinary = translator.translate(tSupplierBinary);
++        final String scriptSupplierBinary = translator.translate(tSupplierBinary).getScript();
          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 +117,14 @@@
          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()).getScript();
 -        }}));
++        }})).getScript();
          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()).getScript();
 -        final String script = translator.translate(g.inject(Collections.emptyMap()).map(identity));
++        final String script = translator.translate(g.inject(Collections.emptyMap()).map(identity)).getScript();
          assertEquals("g.inject([]).map({it.get()})", script);
      }
  
@@@ -181,12 -181,12 +181,12 @@@
  
          // without type translation we get uglinesss
          final String scriptBad = translator.
-                 translate(g.inject(notSillyEnough).asAdmin().getBytecode()).getScript();
 -                translate(g.inject(notSillyEnough));
++                translate(g.inject(notSillyEnough)).getScript();
          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));
 +        final String scriptGood = GroovyTranslator.of("g", new SillyClassTranslator(false)).
-                 translate(g.inject(notSillyEnough).asAdmin().getBytecode()).getScript();
++                translate(g.inject(notSillyEnough)).getScript();
          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 +202,7 @@@
                  .property("name", "Foo\u0020Bar")
                  .property("age", 25)
                  .property("special", "`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?")
-                 .asAdmin().getBytecode()).getScript();
 -                );
++                ).getScript();
  
          assertEquals("g.addV(\"customer\")" +
                          ".property(\"customer_id\",501L)" +
@@@ -217,19 -217,19 +217,19 @@@
          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()).getScript();
-         assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(" +
 -        final String script1 = translator.translate(g.inject(vertex1));
++        final String script1 = translator.translate(g.inject(vertex1)).getScript();
+         assertEquals("g.inject(new ReferenceVertex(" +
                          "\"customer:10:foo bar \\$100#90\"," +
-                         "\"customer\", Collections.emptyMap()))",
+                         "\"customer\"))",
                  script1);
  
          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()).getScript();
-         assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(" +
 -        final String script2 = translator.translate(g.inject(vertex2));
++        final String script2 = translator.translate(g.inject(vertex2)).getScript();
+         assertEquals("g.inject(new ReferenceVertex(" +
                          "\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\"," +
-                         "\"user\", Collections.emptyMap()))",
+                         "\"user\"))",
                  script2);
  
          final Object id3 = "knows:30:foo\u0020bar\u0020\u0024100:\\u0020\\u0024500#70";
@@@ -237,26 -237,26 +237,26 @@@
                  .setOutV((DetachedVertex) vertex1)
                  .setInV((DetachedVertex) vertex2)
                  .create();
-         final String script3 = translator.translate(g.inject(edge).asAdmin().getBytecode()).getScript();
-         assertEquals("g.inject(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge(" +
 -        final String script3 = translator.translate(g.inject(edge));
++        final String script3 = translator.translate(g.inject(edge)).getScript();
+         assertEquals("g.inject(new ReferenceEdge(" +
                          "\"knows:30:foo bar \\$100:\\\\u0020\\\\u0024500#70\"," +
-                         "\"knows\",Collections.emptyMap()," +
-                         "\"customer:10:foo bar \\$100#90\",\"customer\"," +
-                         "\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\",\"user\"))",
+                         "\"knows\"," +
+                         "new ReferenceVertex(\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\",\"user\")," +
+                         "new ReferenceVertex(\"customer:10:foo bar \\$100#90\",\"customer\")))",
                  script3);
  
          final String script4 = translator.translate(
                  g.addE("knows").from(vertex1).to(vertex2).property("when", "2018/09/21")
-                         .asAdmin().getBytecode()).getScript();
 -                        );
++                        ).getScript();
          assertEquals("g.addE(\"knows\")" +
-                         ".from(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(\"customer:10:foo bar \\$100#90\",\"customer\", Collections.emptyMap()))" +
-                         ".to(new org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex(\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\",\"user\", Collections.emptyMap()))" +
+                         ".from(new ReferenceVertex(\"customer:10:foo bar \\$100#90\",\"customer\"))" +
+                         ".to(new ReferenceVertex(\"user:20:foo\\\\u0020bar\\\\u005c\\\\u0022mr\\\\u005c\\\\u0022\\\\u00241000#50\",\"user\"))" +
                          ".property(\"when\",\"2018/09/21\")",
                  script4);
      }
  
      private void assertTranslation(final String expectedTranslation, final Object... objs) {
-         final String script = translator.translate(g.inject(objs).asAdmin().getBytecode()).getScript();
 -        final String script = translator.translate(g.inject(objs));
++        final String script = translator.translate(g.inject(objs)).getScript();
          assertEquals(String.format("g.inject(%s)", expectedTranslation), script);
      }
  
diff --cc gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/ParameterizedGroovyTranslatorTest.java
index cd65a17,0000000..f38ddeb
mode 100644,000000..100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/ParameterizedGroovyTranslatorTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/translator/ParameterizedGroovyTranslatorTest.java
@@@ -1,366 -1,0 +1,366 @@@
 +/*
 + *  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.process.traversal.translator;
 +
 +import org.apache.tinkerpop.gremlin.jsr223.TranslatorCustomizer;
 +import org.apache.tinkerpop.gremlin.process.traversal.P;
 +import org.apache.tinkerpop.gremlin.process.traversal.Script;
 +import org.apache.tinkerpop.gremlin.process.traversal.Translator;
 +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.strategy.decoration.SubgraphStrategy;
 +import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
 +import org.apache.tinkerpop.gremlin.structure.Edge;
 +import org.apache.tinkerpop.gremlin.structure.T;
 +import org.apache.tinkerpop.gremlin.structure.Vertex;
 +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
 +import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
 +import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 +import org.apache.tinkerpop.gremlin.util.function.Lambda;
 +import org.junit.Test;
 +
 +import javax.script.Bindings;
 +import javax.script.SimpleBindings;
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.Collections;
 +import java.util.HashSet;
 +import java.util.LinkedHashMap;
 +import java.util.function.Function;
 +
 +import static org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource.traversal;
 +import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
 +import static org.junit.Assert.assertEquals;
 +
 +/**
 + *  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 static final GraphTraversalSource g = traversal().withEmbedded(EmptyGraph.instance());
 +    private static final Translator.ScriptTranslator translator = GroovyTranslator.of("g", true);
 +
 +    @Test
 +    public void shouldHandleStrategies() throws Exception {
-         assertEquals("g.withStrategies(org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy.instance(),org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy.create(new org.apache.commons.configuration2.MapConfiguration([(_args_0):(_args_1),(_args_2):(__.hasLabel(_args_3))]))).V().has(_args_4)",
++        assertEquals("g.withStrategies(ReadOnlyStrategy,new SubgraphStrategy(checkAdjacentVertices: _args_0, vertices: __.hasLabel(_args_1))).V().has(_args_2)",
 +                translator.translate(g.withStrategies(ReadOnlyStrategy.instance(),
 +                        SubgraphStrategy.build().checkAdjacentVertices(false).vertices(hasLabel("person")).create()).
 +                        V().has("name").asAdmin().getBytecode()).getScript());
 +    }
 +
 +    @Test
 +    public void shouldSupportStringSupplierLambdas() {
 +        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 Script script = translator.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.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 Script script = translator.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());
 +    }
 +
 +    @Test
 +    public void shouldHandleSet() {
 +        final Script script = translator.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());
 +    }
 +
 +    @Test
 +    public void shouldHandleMaps() {
 +        final Script script = translator.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());
 +    }
 +
 +    @Test
 +    public void shouldHandleEmptyMaps() {
 +        final Function identity = new Lambda.OneArgLambda("it.get()", "gremlin-groovy");
 +        final Script script = translator.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());
 +    }
 +
 +    @Test
 +    public void shouldIncludeCustomTypeTranslationForSomethingSilly() throws Exception {
 +        final ParameterizedSillyClass notSillyEnough = ParameterizedSillyClass.from("not silly enough", 100);
 +
 +        // without type translation we get uglinesss
 +        final Script parameterizedScriptBad = translator.translate(g.inject(notSillyEnough).asAdmin().getBytecode());
 +        final 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.process.traversal.translator.ParameterizedGroovyTranslatorTest.ParameterizedSillyClass.from(_args_0,_args_1))",
 +                parameterizedScriptGood.getScript());
 +    }
 +
 +    @Test
 +    public void shouldHaveValidToString() {
 +        assertEquals("translator[h:gremlin-groovy]", GroovyTranslator.of("h", true).toString());
 +    }
 +
 +    @Test
 +    public void shouldEscapeStrings() {
 +        final Script script = translator.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());
 +    }
 +
 +    @Test
 +    public void shouldHandleVertexAndEdge() {
 +        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 = translator.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());
++        assertEquals("g.inject(new ReferenceVertex(_args_0,_args_1))", script1.getScript());
 +        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 = translator.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());
++        assertEquals("g.inject(new ReferenceVertex(_args_0,_args_1))", script2.getScript());
 +        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 = translator.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());
++        assertEquals(id2, bindings.get("_args_2"));
++        assertEquals("user", bindings.get("_args_3"));
++        assertEquals(id1, bindings.get("_args_4"));
++        assertEquals("customer", bindings.get("_args_5"));
++        assertEquals("g.inject(new ReferenceEdge(_args_0,_args_1,new ReferenceVertex(_args_2,_args_3),new ReferenceVertex(_args_4,_args_5)))", script3.getScript());
 +        bindings.clear();
 +
 +        final Script script4 = translator.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());
++        assertEquals("g.addE(_args_0).from(new ReferenceVertex(_args_1,_args_2)).to(new ReferenceVertex(_args_3,_args_4)).property(_args_5,_args_6)", script4.getScript());
 +        bindings.clear();
 +
 +        final Script script5 = translator.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());
 +    }
 +
 +    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);
 +        }
 +    }
 +}
 +
diff --cc gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy
index b1cd97f,d04a2c4..8a91695
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StepLoader.groovy
@@@ -63,5 -64,24 +64,24 @@@ class StepLoader 
              final Closure closure, final Closure splitOperator, final Closure mergeOperator ->
                  return ((TraversalSource) delegate).withSack(closure as Supplier, splitOperator as UnaryOperator, mergeOperator as BinaryOperator);
          }
+ 
+         /**
+          * Allows for a mix of arguments which may be either {@code TraversalStrategy} object or a
+          * {@code Class<TraversalStrategy>}. If the latter, then the class must be able to be instantiated by the
+          * common convention of {@code instance()}.
+          */
+         TraversalSource.metaClass.withStrategies = { Object... traversalStrategyClassOrInstances ->
+             def instances = traversalStrategyClassOrInstances.collect {
+                 if (it instanceof TraversalStrategy) {
+                     return it
+                 } else if (it instanceof Class<?>) {
+                     def inst = it.metaClass.respondsTo(it, "instance") ? it."instance"() : null
+                     if (null == inst) throw new IllegalArgumentException("${it.name} missing a static 'instance()' method")
+                     return inst
+                 }
 -            }
++            } as TraversalStrategy[]
+ 
 -            return ((TraversalSource) delegate).withStrategies(*instances)
++            return ((TraversalSource) delegate).withStrategies(instances)
+         }
      }
  }
diff --cc gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy
index 0000000,b9651fd..15059af
mode 000000,100644..100644
--- a/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy
+++ b/gremlin-groovy/src/main/groovy/org/apache/tinkerpop/gremlin/groovy/loaders/StrategyLoader.groovy
@@@ -1,0 -1,90 +1,92 @@@
+ /*
+  * 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.loaders
+ 
 -import org.apache.commons.configuration.MapConfiguration
++import org.apache.commons.configuration2.MapConfiguration
+ import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ElementIdStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.HaltedTraverserStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.OptionsStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy
++import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.MatchAlgorithmStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.EdgeLabelVerificationStrategy
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReservedKeysVerificationStrategy
+ 
+ /**
+  * @author Stephen Mallette (http://stephen.genoprime.com)
+  */
+ class StrategyLoader {
+ 
+     static void load() {
+         // EventStrategy/SackStrategy are pretty much the oddballs here along with a few pure "internal" strategies
+         // which don't have create(Configuration). We don't support either EventStrategy or SackStrategy in non-JVM
+         // variants because of their style of usage (JVM specific class structures and lambdas respectively). this
+         // perhaps points to a shortcoming somewhere in the APIs, though i'm not sure EventStrategy would ever work
+         // properly off the JVM and SackStrategy doesn't need to since it's technically like OptionsStrategy which is
+         // constructed via bytecode translation where the lambdas are readily supported.
+ 
+         // decoration
+         // # ConnectiveStrategy is singleton
+         ElementIdStrategy.metaClass.constructor << { Map conf -> ElementIdStrategy.create(new MapConfiguration(conf)) }
+         //EventStrategy.metaClass.constructor << { Map conf -> EventStrategy.create(new MapConfiguration(conf)) }
+         HaltedTraverserStrategy.metaClass.constructor << { Map conf -> HaltedTraverserStrategy.create(new MapConfiguration(conf)) }
+         OptionsStrategy.metaClass.constructor << { Map conf -> OptionsStrategy.create(new MapConfiguration(conf)) }
+         PartitionStrategy.metaClass.constructor << { Map conf -> PartitionStrategy.create(new MapConfiguration(conf)) }
+         // # RequirementsStrategy is internal
+         // SackStrategy.metaClass.constructor << { Map conf -> SackStrategy.create(new MapConfiguration(conf)) }
++        SeedStrategy.metaClass.constructor << { Map conf -> SeedStrategy.create(new MapConfiguration(conf)) }
+         // # SideEffectStrategy is internal
+         SubgraphStrategy.metaClass.constructor << { Map conf -> SubgraphStrategy.create(new MapConfiguration(conf)) }
+         VertexProgramStrategy.metaClass.constructor << { Map conf -> VertexProgramStrategy.create(new MapConfiguration(conf)) }
+ 
+         // finalization
+         MatchAlgorithmStrategy.metaClass.constructor << { Map conf -> MatchAlgorithmStrategy.create(new MapConfiguration(conf)) }
+         // # ProfileStrategy is singleton/internal
+         // # ReferenceElementStrategy is singleton/internal
+         // # ComputerFinalizationStrategy is singleton/internal
+ 
+         // optimization
+         // # AdjacentToIncidentStrategy is singleton/internal
+         // # CountStrategy is singleton/internal
+         // # EarlyLimitStrategy is singleton/internal
+         // # FilterRankingStrategy is singleton/internal
+         // # IdentityRemovalStrategy is singleton/internal
+         // # IncidentToAdjacentStrategy is singleton/internal
+         // # InlineFilterStrategy is singleton/internal
+         // # LazyBarrierStrategy is singleton/internal
+         // # MatchPredicateStrategy is singleton/internal
+         // # OrderLimitStrategy is singleton/internal
+         // # PathProcessorStrategy is singleton/internal
+         // # PathRetractionStrategy is singleton/internal
+         // # RepeatUnrollStrategy is singleton/internal
+         // # GraphFilterStrategy is singleton/internal
+         // # MessagePassingReductionStrategy is singleton/internal
+ 
+         // verification
+         // # ComputerVerificationStrategy is singleton/internal
+         EdgeLabelVerificationStrategy.metaClass.constructor << { Map conf -> EdgeLabelVerificationStrategy.create(new MapConfiguration(conf)) }
+         // # LambdaRestrictionStrategy is singleton
+         // # ReadOnlyStrategy is singleton
+         ReservedKeysVerificationStrategy.metaClass.constructor << { Map conf -> ReservedKeysVerificationStrategy.create(new MapConfiguration(conf)) }
+         // # StandardVerificationStrategy is singleton/internal
+     }
+ 
+ }
diff --cc gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
index 994c79d,efb6812..a1ec2a6
--- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
+++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java
@@@ -23,17 -23,14 +23,20 @@@ import groovy.lang.MissingMethodExcepti
  import groovy.lang.MissingPropertyException;
  import org.apache.commons.lang3.exception.ExceptionUtils;
  import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 +import org.apache.tinkerpop.gremlin.groovy.jsr223.ast.RepeatASTTransformationCustomizer;
 +import org.apache.tinkerpop.gremlin.groovy.jsr223.ast.VarAsBindingASTTransformation;
 +import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer;
 +import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
  import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
  import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SubgraphStrategy;
+ import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
 -import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
 +import org.apache.tinkerpop.gremlin.process.traversal.translator.PythonTranslator;
 +import org.apache.tinkerpop.gremlin.structure.Vertex;
  import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
  import org.apache.tinkerpop.gremlin.util.function.Lambda;
 +import org.codehaus.groovy.control.customizers.CompilationCustomizer;
  import org.javatuples.Pair;
  import org.junit.Test;
  
@@@ -425,57 -423,30 +429,84 @@@ public class GremlinGroovyScriptEngineT
          assertEquals("{ it.get() }", l.getLambdaScript());
      }
  
+     @Test
+     public void shouldAllowGroovySyntaxForStrategies() throws Exception {
+         final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine();
+         final GraphTraversalSource g = EmptyGraph.instance().traversal();
+ 
+         final Bindings b = new SimpleBindings();
+         b.put("g", g);
+ 
+         Traversal t = (Traversal) engine.eval("g.withStrategies(ReadOnlyStrategy).V()", b);
+         Optional<ReadOnlyStrategy> ro = t.asAdmin().getStrategies().getStrategy(ReadOnlyStrategy.class);
+         assertThat(ro.isPresent(), is(true));
+         assertEquals(ReadOnlyStrategy.instance(), ro.get());
+ 
+         t = (Traversal) engine.eval("g.withStrategies(new SubgraphStrategy(vertices: __.hasLabel(\"person\"))).V()", b);
+         Optional<SubgraphStrategy> ss = t.asAdmin().getStrategies().getStrategy(SubgraphStrategy.class);
+         assertThat(ss.isPresent(), is(true));
+         assertEquals(HasStep.class, ss.get().getVertexCriterion().asAdmin().getStartStep().getClass());
+ 
+         t = (Traversal) engine.eval("g.withStrategies(ReadOnlyStrategy, new SubgraphStrategy(vertices: __.hasLabel(\"person\"))).V()", b);
+         ro = t.asAdmin().getStrategies().getStrategy(ReadOnlyStrategy.class);
+         assertThat(ro.isPresent(), is(true));
+         assertEquals(ReadOnlyStrategy.instance(), ro.get());
+         ss = t.asAdmin().getStrategies().getStrategy(SubgraphStrategy.class);
+         assertThat(ss.isPresent(), is(true));
+         assertEquals(HasStep.class, ss.get().getVertexCriterion().asAdmin().getStartStep().getClass());
+     }
++
 +    /**
 +     * Test for TINKERPOP-2394 Unable to use __ class of a custom DSL when passing a script even if this class is imported
 +     */
 +	@Test
 +	public void customizerShouldOverrideCoreImports() throws Exception {
 +		DefaultImportCustomizer customizer = DefaultImportCustomizer.build()
 +				.addClassImports(org.apache.tinkerpop.gremlin.groovy.jsr223.dsl.credential.__.class)
 +				.create();
 +		final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(customizer);
 +		engine.eval("__.users();[]");
 +	}
 +
 +    @Test
 +    public void shouldProduceBindingsForVars() throws Exception {
 +        final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(new GroovyCustomizer() {
 +            @Override
 +            public CompilationCustomizer create() {
 +                return new RepeatASTTransformationCustomizer(new VarAsBindingASTTransformation());
 +            }
 +        });
 +
 +        final GraphTraversalSource g = traversal().withEmbedded(EmptyGraph.instance());
 +        final Bindings bindings = new SimpleBindings();
 +        bindings.put("g", g);
 +        engine.eval("g.V(b).out()", bindings);
 +        final Traversal.Admin<Vertex, Vertex> t = (Traversal.Admin<Vertex, Vertex>)
 +                engine.eval("g.V(v1Id).has(\"person\",\"age\",29).has('person','active',x).in(\"knows\")." +
 +                        System.lineSeparator() +
 +                        "choose(__.out().count()).option(two, __.values(\"name\")).option(three, __.values(\"age\"))." +
 +                        System.lineSeparator() +
 +                        "filter(outE().count().is(y))."  +
 +                        System.lineSeparator() +
 +                        "map(l)." +
 +                        System.lineSeparator() +
 +                        "order().by('name',o)", bindings);
 +        final Bytecode bytecode = t.getBytecode();
 +        engine.eval("g.V(b).out()", bindings);
 +
 +        final PythonTranslator translator = PythonTranslator.of("g");
 +        final String gremlinAsPython = translator.translate(bytecode).getScript();
 +
 +        final Map<String,Object> bytecodeBindings = bytecode.getBindings();
 +        assertEquals(7, bytecodeBindings.size());
 +        assertThat(bytecodeBindings.containsKey("x"), is(true));
 +        assertThat(bytecodeBindings.containsKey("y"), is(true));
 +        assertThat(bytecodeBindings.containsKey("v1Id"), is(true));
 +        assertThat(bytecodeBindings.containsKey("l"), is(true));
 +        assertThat(bytecodeBindings.containsKey("o"), is(true));
 +        assertThat(bytecodeBindings.containsKey("two"), is(true));
 +        assertThat(bytecodeBindings.containsKey("three"), is(true));
 +
 +        assertEquals("g.V(v1Id).has('person','age',29).has('person','active',x).in_('knows').choose(__.out().count()).option(two,__.name).option(three,__.age).filter(__.outE().count().is_(y)).map(l).order().by('name',o)", gremlinAsPython);
 +    }
  }