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

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

commit 6d834a221718913ab089c4a13fae69def0881c08
Author: Stephen Mallette <[email protected]>
AuthorDate: Wed Jan 3 08:32:02 2024 -0500

    groovy
---
 .../translator/GroovyTranslateVisitor.java         | 116 +++++++++++++++++++
 .../language/translator/JavaTranslateVisitor.java  |   2 +
 .../translator/JavascriptTranslateVisitor.java     |  10 ++
 .../translator/PythonTranslateVisitor.java         |   1 +
 .../language/translator/TranslateVisitor.java      |   5 +-
 .../gremlin/language/translator/Translator.java    |   5 +
 .../language/translator/GremlinTranslatorTest.java | 128 +++++++++++++++++++--
 .../tinkerpop/gremlin/features/StepDefinition.java |   9 +-
 8 files changed, 262 insertions(+), 14 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java
new file mode 100644
index 0000000000..44e7d2d56f
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GroovyTranslateVisitor.java
@@ -0,0 +1,116 @@
+/*
+ * 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.language.translator;
+
+import org.apache.tinkerpop.gremlin.language.grammar.GremlinParser;
+
+/**
+ * Converts a Gremlin traversal string into a Groovy source code 
representation of that traversal with an aim at
+ * sacrificing some formatting for the ability to compile correctly. The 
translations may require use of TinkerPop's
+ * sugar syntax and therefore requires use of the {@code GremlinLoader} in the 
gremlin-groovy module unless you are
+ * specifically certain that your translations will not result in the use of 
that syntax. If in doubt, prefer the
+ * {@link JavaTranslateVisitor} instead.
+ * <ul>
+ *     <li>Normalize numeric suffixes to lower case</li>
+ *     <li>If floats are not suffixed they will translate as BigDecimal</li>
+ *     <li>Makes anonymous traversals explicit with double underscore</li>
+ *     <li>Makes enums explicit with their proper name</li>
+ * </ul>
+ */
+public class GroovyTranslateVisitor extends TranslateVisitor {
+    public GroovyTranslateVisitor() {
+        this("g");
+    }
+
+    public GroovyTranslateVisitor(final String graphTraversalSourceName) {
+        super(graphTraversalSourceName);
+    }
+
+    @Override
+    public Void visitStructureVertex(final 
GremlinParser.StructureVertexContext ctx) {
+        sb.append("new DetachedVertex(");
+        visit(ctx.getChild(3)); // id
+        sb.append(", ");
+        visit(ctx.getChild(5)); // label
+        sb.append(")");
+        return null;
+    }
+
+    @Override
+    public Void visitIntegerLiteral(final GremlinParser.IntegerLiteralContext 
ctx) {
+        final String integerLiteral = ctx.getText().toLowerCase();
+
+        // check suffix
+        final int lastCharIndex = integerLiteral.length() - 1;
+        final char lastCharacter = integerLiteral.charAt(lastCharIndex);
+        switch (lastCharacter) {
+            case 'b':
+                // parse B/b as byte
+                sb.append("new Byte(");
+                sb.append(integerLiteral, 0, lastCharIndex);
+                sb.append(")");
+                break;
+            case 's':
+                // parse S/s as short
+                sb.append("new Short(");
+                sb.append(integerLiteral, 0, lastCharIndex);
+                sb.append(")");
+                break;
+            case 'i':
+            case 'l':
+                // parse I/i and L/l as Integer and Long respectively
+                sb.append(integerLiteral, 0, 
lastCharIndex).append(lastCharacter);
+                break;
+            case 'n':
+                // parse N/n as BigInteger which for groovy is "g" shorthand
+                sb.append(integerLiteral, 0, lastCharIndex).append("g");
+                break;
+            default:
+                // everything else just goes as specified
+                sb.append(integerLiteral);
+                break;
+        }
+        return null;
+    }
+
+    @Override
+    public Void visitFloatLiteral(final GremlinParser.FloatLiteralContext ctx) 
{
+        final String floatLiteral = ctx.getText().toLowerCase();
+
+        // check suffix
+        final int lastCharIndex = floatLiteral.length() - 1;
+        final char lastCharacter = floatLiteral.charAt(lastCharIndex);
+        switch (lastCharacter) {
+            case 'f':
+            case 'd':
+                // parse F/f as Float and D/d suffix as Double
+                sb.append(floatLiteral, 0, 
lastCharIndex).append(lastCharacter);
+                break;
+            case 'm':
+                // parse N/n as BigDecimal which for groovy is "g" shorthand
+                sb.append(floatLiteral, 0, lastCharIndex).append("g");
+                break;
+            default:
+                // everything else just goes as specified
+                sb.append(floatLiteral);
+                break;
+        }
+        return null;
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java
index f176e85943..9f0d43065e 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java
@@ -31,6 +31,8 @@ import java.util.List;
  * sacrificing some formatting for the ability to compile correctly.
  * <ul>
  *     <li>Range syntax has no direct support</li>
+ *     <li>Normalizes whitespace</li>
+ *     <li>Normalize numeric suffixes to lower case</li>
  *     <li>If floats are not suffixed they will translate as BigDecimal</li>
  *     <li>Makes anonymous traversals explicit with double underscore</li>
  *     <li>Makes enums explicit with their proper name</li>
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavascriptTranslateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavascriptTranslateVisitor.java
index f6d03478a0..b0f0852dd2 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavascriptTranslateVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavascriptTranslateVisitor.java
@@ -30,6 +30,16 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+/**
+ * Converts a Gremlin traversal string into a Javascript source code 
representation of that traversal with an aim at
+ * sacrificing some formatting for the ability to compile correctly.
+ * <ul>
+ *     <li>Range syntax has no direct support</li>
+ *     <li>Normalizes whitespace</li>
+ *     <li>Makes anonymous traversals explicit with double underscore</li>
+ *     <li>Makes enums explicit with their proper name</li>
+ * </ul>
+ */
 public class JavascriptTranslateVisitor extends AbstractTranslateVisitor {
     public JavascriptTranslateVisitor() {
         this("g");
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
index 76a40010c6..4a99dade0c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/PythonTranslateVisitor.java
@@ -35,6 +35,7 @@ import java.util.Map;
  * sacrificing some formatting for the ability to compile correctly.
  * <ul>
  *     <li>Range syntax has no direct support</li>
+ *     <li>Normalizes whitespace</li>
  *     <li>If floats are not suffixed they will translate as BigDecimal</li>
  *     <li>Makes anonymous traversals explicit with double underscore</li>
  *     <li>Makes enums explicit with their proper name</li>
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
index 924011c734..94a4bb7632 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/TranslateVisitor.java
@@ -44,6 +44,7 @@ import java.util.Set;
  * A Gremlin to Gremlin translator. Makes no changes to input except:
  * <ul>
  *     <li>Normalizes whitespace</li>
+ *     <li>Normalize numeric suffixes to lower case</li>
  *     <li>Makes anonymous traversals explicit with double underscore</li>
  *     <li>Makes enums explicit with their proper name</li>
  * </ul>
@@ -2269,13 +2270,13 @@ public class TranslateVisitor extends 
AbstractParseTreeVisitor<Void> implements
 
     @Override
     public Void visitIntegerLiteral(final GremlinParser.IntegerLiteralContext 
ctx) {
-        sb.append(ctx.getText());
+        sb.append(ctx.getText().toLowerCase());
         return null;
     }
 
     @Override
     public Void visitFloatLiteral(final GremlinParser.FloatLiteralContext ctx) 
{
-        sb.append(ctx.getText());
+        sb.append(ctx.getText().toLowerCase());
         return null;
     }
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/Translator.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/Translator.java
index 169105c2bf..9a1788b9f5 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/Translator.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/Translator.java
@@ -35,6 +35,11 @@ public enum Translator {
      */
     ANONYMIZED("Anonymized", AnonymizedTranslatorVisitor::new),
 
+    /**
+     * Translates to gremlin-groovy.
+     */
+    GROOVY("Groovy", GroovyTranslateVisitor::new),
+
     /**
      * Translates to gremlin-java.
      */
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
index ce95ec4c9d..a9f954d414 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/translator/GremlinTranslatorTest.java
@@ -80,6 +80,7 @@ public class GremlinTranslatorTest {
         private final String query;
         private final String expectedForLang;
         private final String expectedForAnonymized;
+        private final String expectedForGroovy;
         private final String expectedForJava;
         private final String expectedForJavascript;
         private final String expectedForPython;
@@ -90,6 +91,7 @@ public class GremlinTranslatorTest {
          * <ol>
          *     <li>Language</li>
          *     <li>Anonymized</li>
+         *     <li>Groovy</li>
          *     <li>Java</li>
          *     <li>Javascript</li>
          *     <li>Python</li>
@@ -104,256 +106,306 @@ public class GremlinTranslatorTest {
                             null,
                             null,
                             null,
+                            null,
                             null},
                     {"g.with(\"x\")",
                             null,
                             "g.with(string0)",
                             null,
+                            null,
                             "g.with_(\"x\")",
                             "g.with_('x')"},
                     {"g.with(\"x\n\\\"yz\")",
                             null,
                             "g.with(string0)",
                             null,
+                            null,
                             "g.with_(\"x\n\\\"yz\")",
                             "g.with_('x\n\\\"yz')"},
                     {"g.with('x', 'xyz')",
                             null,
                             "g.with(string0, string1)",
+                            null,
                             "g.with(\"x\", \"xyz\")",
                             "g.with_(\"x\", \"xyz\")",
                             "g.with_('x', 'xyz')"},
                     {"g.with('x','xyz')",
                             "g.with('x', 'xyz')",
                             "g.with(string0, string1)",
+                            "g.with('x', 'xyz')",
                             "g.with(\"x\", \"xyz\")",
                             "g.with_(\"x\", \"xyz\")",
                             "g.with_('x', 'xyz')"},
                     {"g.with('x', '')",
                             null,
                             "g.with(string0, string1)",
+                            null,
                             "g.with(\"x\", \"\")",
                             "g.with_(\"x\", \"\")",
                             "g.with_('x', '')"},
+                    {"g.with('x', '     ')",
+                            null,
+                            "g.with(string0, string1)",
+                            null,
+                            "g.with(\"x\", \"     \")",
+                            "g.with_(\"x\", \"     \")",
+                            "g.with_('x', '     ')"},
                     {"g.with('x', 'x')",
                             null,
                             "g.with(string0, string0)",
+                            null,
                             "g.with(\"x\", \"x\")",
                             "g.with_(\"x\", \"x\")",
                             "g.with_('x', 'x')"},
                     {"g.with('x', null)",
                             null,
                             "g.with(string0, object0)",
+                            null,
                             "g.with(\"x\", null)",
                             "g.with_(\"x\", null)",
                             "g.with_('x', None)"},
                     {"g.with('x', NaN)",
                             null,
                             "g.with(string0, number0)",
+                            null,
                             "g.with(\"x\", Double.NaN)",
                             "g.with_(\"x\", Number.NaN)",
                             "g.with_('x', float('nan'))"},
                     {"g.with('x', Infinity)",
                             null,
                             "g.with(string0, number0)",
+                            null,
                             "g.with(\"x\", Double.POSITIVE_INFINITY)",
                             "g.with_(\"x\", Number.POSITIVE_INFINITY)",
                             "g.with_('x', float('inf'))"},
                     {"g.with('x', -Infinity)",
                             null,
                             "g.with(string0, number0)",
+                            null,
                             "g.with(\"x\", Double.NEGATIVE_INFINITY)",
                             "g.with_(\"x\", Number.NEGATIVE_INFINITY)",
                             "g.with_('x', float('-inf'))"},
                     {"g.with('x', 1.0)",
                             null,
                             "g.with(string0, number0)",
+                            null,
                             "g.with(\"x\", 1.0)",
                             "g.with_(\"x\", 1.0)",
                             "g.with_('x', 1.0)",},
                     {"g.with('x', 1.0D)",
-                            null,
+                            "g.with('x', 1.0d)",
                             "g.with(string0, double0)",
+                            "g.with('x', 1.0d)",
                             "g.with(\"x\", 1.0d)",
                             "g.with_(\"x\", 1.0)",
                             "g.with_('x', 1.0)"},
                     {"g.with('x', 1.0d)",
                             null,
                             "g.with(string0, double0)",
+                            null,
                             "g.with(\"x\", 1.0d)",
                             "g.with_(\"x\", 1.0)",
                             "g.with_('x', 1.0)"},
                     {"g.with('x', -1.0d)",
                             null,
                             "g.with(string0, double0)",
+                            null,
                             "g.with(\"x\", -1.0d)",
                             "g.with_(\"x\", -1.0)",
                             "g.with_('x', -1.0)"},
                     {"g.with('x', 1.0F)",
-                            null,
+                            "g.with('x', 1.0f)",
                             "g.with(string0, float0)",
+                            "g.with('x', 1.0f)",
                             "g.with(\"x\", 1.0f)",
                             "g.with_(\"x\", 1.0)",
                             "g.with_('x', 1.0)"},
                     {"g.with('x', 1.0f)",
                             null,
                             "g.with(string0, float0)",
+                            null,
                             "g.with(\"x\", 1.0f)",
                             "g.with_(\"x\", 1.0)",
                             "g.with_('x', 1.0)"},
                     {"g.with('x', -1.0F)",
-                            null,
+                            "g.with('x', -1.0f)",
                             "g.with(string0, float0)",
+                            "g.with('x', -1.0f)",
                             "g.with(\"x\", -1.0f)",
                             "g.with_(\"x\", -1.0)",
                             "g.with_('x', -1.0)"},
                     {"g.with('x', 1.0m)",
                             null,
                             "g.with(string0, bigdecimal0)",
+                            "g.with('x', 1.0g)",
                             "g.with(\"x\", new BigDecimal(\"1.0\"))",
                             "g.with_(\"x\", 1.0)",
                             "g.with_('x', 1.0)"},
                     {"g.with('x', -1.0m)",
                             null,
                             "g.with(string0, bigdecimal0)",
+                            "g.with('x', -1.0g)",
                             "g.with(\"x\", new BigDecimal(\"-1.0\"))",
                             "g.with_(\"x\", -1.0)",
                             "g.with_('x', -1.0)"},
                     {"g.with('x', -1.0M)",
-                            null,
+                            "g.with('x', -1.0m)",
                             "g.with(string0, bigdecimal0)",
+                            "g.with('x', -1.0g)",
                             "g.with(\"x\", new BigDecimal(\"-1.0\"))",
                             "g.with_(\"x\", -1.0)",
                             "g.with_('x', -1.0)"},
                     {"g.with('x', 1b)",
                             null,
                             "g.with(string0, byte0)",
+                            "g.with('x', new Byte(1))",
                             "g.with(\"x\", new Byte(1))",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', 1B)",
-                            null,
+                            "g.with('x', 1b)",
                             "g.with(string0, byte0)",
+                            "g.with('x', new Byte(1))",
                             "g.with(\"x\", new Byte(1))",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', -1b)",
                             null,
                             "g.with(string0, byte0)",
+                            "g.with('x', new Byte(-1))",
                             "g.with(\"x\", new Byte(-1))",
                             "g.with_(\"x\", -1)",
                             "g.with_('x', -1)"},
                     {"g.with('x', 1s)",
                             null,
                             "g.with(string0, short0)",
+                            "g.with('x', new Short(1))",
                             "g.with(\"x\", new Short(1))",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', -1s)",
                             null,
                             "g.with(string0, short0)",
+                            "g.with('x', new Short(-1))",
                             "g.with(\"x\", new Short(-1))",
                             "g.with_(\"x\", -1)",
                             "g.with_('x', -1)"},
                     {"g.with('x', 1S)",
-                            null,
+                            "g.with('x', 1s)",
                             "g.with(string0, short0)",
+                            "g.with('x', new Short(1))",
                             "g.with(\"x\", new Short(1))",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', 1i)",
                             null,
                             "g.with(string0, integer0)",
+                            null,
                             "g.with(\"x\", 1)",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', 1I)",
-                            null,
+                            "g.with('x', 1i)",
                             "g.with(string0, integer0)",
+                            "g.with('x', 1i)",
                             "g.with(\"x\", 1)",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', -1i)",
                             null,
                             "g.with(string0, integer0)",
+                            null,
                             "g.with(\"x\", -1)",
                             "g.with_(\"x\", -1)",
                             "g.with_('x', -1)"},
                     {"g.with('x', 1l)",
                             null,
                             "g.with(string0, long0)",
+                            null,
                             "g.with(\"x\", 1l)",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', long(1))"},
                     {"g.with('x', 1L)",
-                            null,
+                            "g.with('x', 1l)",
                             "g.with(string0, long0)",
+                            "g.with('x', 1l)",
                             "g.with(\"x\", 1l)",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', long(1))"},
                     {"g.with('x', -1l)",
                             null,
                             "g.with(string0, long0)",
+                            null,
                             "g.with(\"x\", -1l)",
                             "g.with_(\"x\", -1)",
                             "g.with_('x', long(-1))"},
                     {"g.with('x', 1n)",
                             null,
                             "g.with(string0, biginteger0)",
+                            "g.with('x', 1g)",
                             "g.with(\"x\", new BigInteger(\"1\"))",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', 1N)",
-                            null,
+                            "g.with('x', 1n)",
                             "g.with(string0, biginteger0)",
+                            "g.with('x', 1g)",
                             "g.with(\"x\", new BigInteger(\"1\"))",
                             "g.with_(\"x\", 1)",
                             "g.with_('x', 1)"},
                     {"g.with('x', -1n)",
                             null,
                             "g.with(string0, biginteger0)",
+                            "g.with('x', -1g)",
                             "g.with(\"x\", new BigInteger(\"-1\"))",
                             "g.with_(\"x\", -1)",
                             "g.with_('x', -1)"},
                     {"g.with('x', datetime('2023-08-02T00:00:00Z'))",
                             null,
                             "g.with(string0, date0)",
+                            null,
                             "g.with(\"x\", new Date(1690934400000))",
                             "g.with_(\"x\", new Date(1690934400000))",
                             "g.with_('x', 
datetime.datetime.utcfromtimestamp(1690934400000 / 1000.0))"},
                     {"g.with('x', [x: 1])",
                             "g.with('x', [x:1])",
                             "g.with(string0, map0)",
+                            "g.with('x', [x:1])",
                             "g.with(\"x\", new LinkedHashMap<Object, Object>() 
{{ put(\"x\", 1); }})",
                             "g.with_(\"x\", new Map([[\"x\", 1]]))",
                             "g.with_('x', { 'x': 1 })"},
                     {"g.with('x', [x:1, new:2])",
                             null,
                             "g.with(string0, map0)",
+                            null,
                             "g.with(\"x\", new LinkedHashMap<Object, Object>() 
{{ put(\"x\", 1); put(\"new\", 2); }})",
                             "g.with_(\"x\", new Map([[\"x\", 1], [\"new\", 
2]]))",
                             "g.with_('x', { 'x': 1, 'new': 2 })"},
                     {"g.with('x', [\"x\":1])",
                             null,
                             "g.with(string0, map0)",
+                            null,
                             "g.with(\"x\", new LinkedHashMap<Object, Object>() 
{{ put(\"x\", 1); }})",
                             "g.with_(\"x\", new Map([[\"x\", 1]]))",
                             "g.with_('x', { 'x': 1 })"},
                     {"g.with('x', [1:'x'])",
                             null,
                             "g.with(string0, map0)",
+                            null,
                             "g.with(\"x\", new LinkedHashMap<Object, Object>() 
{{ put(1, \"x\"); }})",
                             "g.with_(\"x\", new Map([[1, \"x\"]]))",
                             "g.with_('x', { 1: 'x' })"},
                     {"g.with('x', [1, 'x'])",
                             null,
                             "g.with(string0, list0)",
+                            null,
                             "g.with(\"x\", new ArrayList<Object>() {{ add(1); 
add(\"x\"); }})",
                             "g.with_(\"x\", [1, \"x\"])",
                             "g.with_('x', [1, 'x'])"},
                     {"g.with('x', 0..5)",
                             null,
                             "g.with(string0, number0..number1)",
+                            "g.with('x', 0..5)",
                             "Java does not support range literals",
                             "Javascript does not support range literals",
                             "Python does not support range literals"},
@@ -362,26 +414,31 @@ public class GremlinTranslatorTest {
                             "g.withBulk(boolean0)",
                             null,
                             null,
+                            null,
                             "g.with_bulk(False)"},
                     {"g.withBulk(true)",
                             null,
                             "g.withBulk(boolean0)",
                             null,
                             null,
+                            null,
                             "g.with_bulk(True)"},
                     {"g.withBulk( true )",
                             "g.withBulk(true)",
                             "g.withBulk(boolean0)",
                             "g.withBulk(true)",
                             "g.withBulk(true)",
+                            "g.withBulk(true)",
                             "g.with_bulk(True)"},
                     {"g.withBulk(x)",
                             null,
                             null,
                             null,
                             null,
+                            null,
                             "g.with_bulk(x)"},
                     {"g.withStrategies(ReadOnlyStrategy)",
+                            null,
                             null,
                             null,
                             "g.withStrategies(ReadOnlyStrategy.instance())",
@@ -390,18 +447,21 @@ public class GremlinTranslatorTest {
                     {"g.withStrategies(new SeedStrategy(seed:10000))",
                             null,
                             "g.withStrategies(new SeedStrategy(seed:number0))",
+                            null,
                             
"g.withStrategies(SeedStrategy.build().seed(10000).create())",
                             "g.withStrategies(new SeedStrategy({seed: 
10000}))",
                             "g.with_strategies(SeedStrategy(seed=10000))"},
                     {"g.withStrategies(new 
PartitionStrategy(includeMetaProperties: true, partitionKey:'x'))",
                             "g.withStrategies(new 
PartitionStrategy(includeMetaProperties:true, partitionKey:'x'))",
                             "g.withStrategies(new 
PartitionStrategy(includeMetaProperties:boolean0, partitionKey:string0))",
+                            "g.withStrategies(new 
PartitionStrategy(includeMetaProperties:true, partitionKey:'x'))",
                             
"g.withStrategies(PartitionStrategy.build().includeMetaProperties(true).partitionKey(\"x\").create())",
                             "g.withStrategies(new 
PartitionStrategy({includeMetaProperties: true, partitionKey: \"x\"}))",
                             
"g.with_strategies(PartitionStrategy(include_meta_properties=True, 
partition_key='x'))"},
                     {"g.withStrategies(new 
SubgraphStrategy(vertices:__.has('name', 'vadas'), edges: has('weight', 
gt(0.5))))",
                             "g.withStrategies(new 
SubgraphStrategy(vertices:__.has('name', 'vadas'), edges:__.has('weight', 
P.gt(0.5))))",
                             "g.withStrategies(new 
SubgraphStrategy(vertices:__.has(string0, string1), edges:__.has(string2, 
P.gt(number0))))",
+                            "g.withStrategies(new 
SubgraphStrategy(vertices:__.has('name', 'vadas'), edges:__.has('weight', 
P.gt(0.5))))",
                             
"g.withStrategies(SubgraphStrategy.build().vertices(__.has(\"name\", 
\"vadas\")).edges(__.has(\"weight\", P.gt(0.5))).create())",
                             "g.withStrategies(new SubgraphStrategy({vertices: 
__.has(\"name\", \"vadas\"), edges: __.has(\"weight\", P.gt(0.5))}))",
                             
"g.with_strategies(SubgraphStrategy(vertices=__.has('name', 'vadas'), 
edges=__.has('weight', P.gt(0.5))))"},
@@ -411,12 +471,14 @@ public class GremlinTranslatorTest {
                             "                                                  
       __.has(\"weight\", 1.0).hasLabel(\"created\")))).E()",
                             "g.withStrategies(new 
SubgraphStrategy(checkAdjacentVertices:false, vertices:__.has(\"name\", 
P.within(\"josh\", \"lop\", \"ripple\")), edges:__.or(__.has(\"weight\", 
0.4).hasLabel(\"created\"), __.has(\"weight\", 
1.0).hasLabel(\"created\")))).E()",
                             "g.withStrategies(new 
SubgraphStrategy(checkAdjacentVertices:boolean0, vertices:__.has(string0, 
P.within(string1, string2, string3)), edges:__.or(__.has(string4, 
number0).hasLabel(string5), __.has(string4, number1).hasLabel(string5)))).E()",
+                            "g.withStrategies(new 
SubgraphStrategy(checkAdjacentVertices:false, vertices:__.has(\"name\", 
P.within(\"josh\", \"lop\", \"ripple\")), edges:__.or(__.has(\"weight\", 
0.4).hasLabel(\"created\"), __.has(\"weight\", 
1.0).hasLabel(\"created\")))).E()",
                             
"g.withStrategies(SubgraphStrategy.build().checkAdjacentVertices(false).vertices(__.has(\"name\",
 P.within(\"josh\", \"lop\", \"ripple\"))).edges(__.or(__.has(\"weight\", 
0.4).hasLabel(\"created\"), __.has(\"weight\", 
1.0).hasLabel(\"created\"))).create()).E()",
                             "g.withStrategies(new 
SubgraphStrategy({checkAdjacentVertices: false, vertices: __.has(\"name\", 
P.within(\"josh\", \"lop\", \"ripple\")), edges: __.or(__.has(\"weight\", 
0.4).hasLabel(\"created\"), __.has(\"weight\", 
1.0).hasLabel(\"created\"))})).E()",
                             
"g.with_strategies(SubgraphStrategy(check_adjacent_vertices=False, 
vertices=__.has('name', P.within('josh', 'lop', 'ripple')), 
edges=__.or_(__.has('weight', 0.4).has_label('created'), __.has('weight', 
1.0).has_label('created')))).E()"},
                     {"g.inject(0..5)",
                             null,
                             "g.inject(number0..number1)",
+                            "g.inject(0..5)",
                             "Java does not support range literals",
                             "Javascript does not support range literals",
                             "Python does not support range literals"},
@@ -425,28 +487,33 @@ public class GremlinTranslatorTest {
                             "g.inject(number0).asDate()",
                             null,
                             null,
+                            null,
                             "g.inject(long(1694017707000)).as_date()"},
                     {"g.V().hasLabel(null)",
                             null,
                             "g.V().hasLabel(string0)",
                             null,
                             null,
+                            null,
                             "g.V().has_label(None)",},
                     {"g.V().hasLabel('person')",
                             null,
                             "g.V().hasLabel(string0)",
+                            "g.V().hasLabel('person')",
                             "g.V().hasLabel(\"person\")",
                             "g.V().hasLabel(\"person\")",
                             "g.V().has_label('person')"},
                     {"g.V().hasLabel('person', 'software', 'class')",
                             null,
                             "g.V().hasLabel(string0, string1, string2)",
+                            "g.V().hasLabel('person', 'software', 'class')",
                             "g.V().hasLabel(\"person\", \"software\", 
\"class\")",
                             "g.V().hasLabel(\"person\", \"software\", 
\"class\")",
                             "g.V().has_label('person', 'software', 'class')"},
                     {"g.V().hasLabel(null, 'software', 'class')",
                             null,
                             "g.V().hasLabel(string0, string1, string2)",
+                            "g.V().hasLabel(null, 'software', 'class')",
                             "g.V().hasLabel(null, \"software\", \"class\")",
                             "g.V().hasLabel(null, \"software\", \"class\")",
                             "g.V().has_label(None, 'software', 'class')"},
@@ -455,106 +522,124 @@ public class GremlinTranslatorTest {
                             null,
                             null,
                             null,
+                            null,
                             null},
                     {"g.V().map(out().count())",
                             "g.V().map(__.out().count())",
                             "g.V().map(__.out().count())",
                             "g.V().map(__.out().count())",
                             "g.V().map(__.out().count())",
+                            "g.V().map(__.out().count())",
                             "g.V().map(__.out().count())"},
                     {"g.V().fold().count(Scope.local)",
                             null,
                             null,
                             null,
                             null,
+                            null,
                             null},
                     {"g.V().fold().count(Scope.local)",
                             null,
                             null,
                             null,
                             null,
+                            null,
                             null},
                     {"g.V().has(T.id, 1)",
                             null,
                             "g.V().has(T.id, number0)",
                             null,
                             null,
+                            null,
                             "g.V().has(T.id_, 1)"},
                     {"g.V().has(id, 1)",
                             "g.V().has(T.id, 1)",
                             "g.V().has(T.id, number0)",
                             "g.V().has(T.id, 1)",
                             "g.V().has(T.id, 1)",
+                            "g.V().has(T.id, 1)",
                             "g.V().has(T.id_, 1)"},
                     {"g.V().has(\"name\", P.within(\"josh\",\"stephen\"))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
                             "g.V().has(string0, P.within(string1, string2))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
+                            "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
                             "g.V().has('name', P.within('josh', 'stephen'))"},
                     {"g.V().has(\"name\", P.eq(\"josh\"))",
                             null,
                             "g.V().has(string0, P.eq(string1))",
                             null,
                             null,
+                            null,
                             "g.V().has('name', P.eq('josh'))"},
                     {"g.V().has(\"name\", P.eq(\"josh\").negate())",
                             null,
                             "g.V().has(string0, P.eq(string1).negate())",
                             null,
                             null,
+                            null,
                             "g.V().has('name', P.eq('josh').negate())"},
                     {"g.V().has(\"name\", P.within())",
                             null,
                             "g.V().has(string0, P.within())",
                             null,
                             null,
+                            null,
                             "g.V().has('name', P.within())"},
                     {"g.V().has(\"name\", 
P.within(\"josh\",\"stephen\").or(eq(\"vadas\")))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\").or(P.eq(\"vadas\")))",
                             "g.V().has(string0, P.within(string1, 
string2).or(P.eq(string3)))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\").or(P.eq(\"vadas\")))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\").or(P.eq(\"vadas\")))",
+                            "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\").or(P.eq(\"vadas\")))",
                             "g.V().has('name', P.within('josh', 
'stephen').or_(P.eq('vadas')))"},
                     {"g.V().has(\"name\", within(\"josh\", \"stephen\"))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
                             "g.V().has(string0, P.within(string1, string2))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
                             "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
+                            "g.V().has(\"name\", P.within(\"josh\", 
\"stephen\"))",
                             "g.V().has('name', P.within('josh', 'stephen'))"},
                     {"g.V().has(\"name\", TextP.containing(\"j\").negate())",
                             null,
                             "g.V().has(string0, 
TextP.containing(string1).negate())",
                             null,
                             null,
+                            null,
                             "g.V().has('name', 
TextP.containing('j').negate())"},
                     {"g.V().hasLabel(\"person\").has(\"age\", 
P.not(P.lte(10).and(P.not(P.between(11, 
20)))).and(P.lt(29).or(P.eq(35)))).values(\"name\")",
                             null,
                             "g.V().hasLabel(string0).has(string1, 
P.not(P.lte(number0).and(P.not(P.between(number1, 
number2)))).and(P.lt(number3).or(P.eq(number4)))).values(string2)",
                             null,
                             null,
+                            null,
                             "g.V().has_label('person').has('age', 
P.not_(P.lte(10).and_(P.not_(P.between(11, 
20)))).and_(P.lt(29).or_(P.eq(35)))).values('name')"},
                     {"g.V().has(\"name\", containing(\"j\"))",
                             "g.V().has(\"name\", TextP.containing(\"j\"))",
                             "g.V().has(string0, TextP.containing(string1))",
                             "g.V().has(\"name\", TextP.containing(\"j\"))",
                             "g.V().has(\"name\", TextP.containing(\"j\"))",
+                            "g.V().has(\"name\", TextP.containing(\"j\"))",
                             "g.V().has('name', TextP.containing('j'))"},
                     {"g.V().property(set, \"name\", \"stephen\")",
                             "g.V().property(Cardinality.set, \"name\", 
\"stephen\")",
                             "g.V().property(Cardinality.set, string0, 
string1)",
                             "g.V().property(Cardinality.set, \"name\", 
\"stephen\")",
                             "g.V().property(Cardinality.set, \"name\", 
\"stephen\")",
+                            "g.V().property(Cardinality.set, \"name\", 
\"stephen\")",
                             "g.V().property(Cardinality.set_, 'name', 
'stephen')"},
                     {"g.V().property(Cardinality.set, \"name\", \"stephen\")",
                             null,
                             "g.V().property(Cardinality.set, string0, 
string1)",
                             null,
                             null,
+                            null,
                             "g.V().property(Cardinality.set_, 'name', 
'stephen')"},
                     {"g.V().has('name', 
'foo').property([\"name\":Cardinality.set(\"bar\"), \"age\":43])",
                             null,
                             "g.V().has(string0, string1).property(map0)",
+                            null,
                             "g.V().has(\"name\", \"foo\").property(new 
LinkedHashMap<Object, Object>() {{ put(\"name\", Cardinality.set(\"bar\")); 
put(\"age\", 43); }})",
                             "g.V().has(\"name\", \"foo\").property(new 
Map([[\"name\", CardinalityValue.set(\"bar\")], [\"age\", 43]]))",
                             "g.V().has('name', 'foo').property({ 'name': 
CardinalityValue.set_('bar'), 'age': 43 })"},
@@ -562,6 +647,7 @@ public class GremlinTranslatorTest {
                             null,
                             "g.V(new Vertex(number0, string0)).limit(number0)",
                             "g.V(new DetachedVertex(1, \"person\")).limit(1)",
+                            "g.V(new DetachedVertex(1, \"person\")).limit(1)",
                             "g.V(new Vertex(1, \"person\")).limit(1)",
                             "g.V(Vertex(1, 'person')).limit(1)",},
                     
{"g.V().both().properties().dedup().hasKey(\"age\").value()",
@@ -569,11 +655,13 @@ public class GremlinTranslatorTest {
                             
"g.V().both().properties().dedup().hasKey(string0).value()",
                             null,
                             null,
+                            null,
                             
"g.V().both().properties().dedup().has_key('age').value()",},
                     
{"g.V().connectedComponent().with(ConnectedComponent.propertyName, 
\"component\")",
                             
"g.V().connectedComponent().with(ConnectedComponent.propertyName, 
\"component\")",
                             
"g.V().connectedComponent().with(ConnectedComponent.propertyName, string0)",
                             
"g.V().connectedComponent().with(ConnectedComponent.propertyName, 
\"component\")",
+                            
"g.V().connectedComponent().with(ConnectedComponent.propertyName, 
\"component\")",
                             
"g.V().connectedComponent().with_(ConnectedComponent.propertyName, 
\"component\")",
                             
"g.V().connected_component().with_(ConnectedComponent.property_name, 
'component')"},
                     {"g.withSideEffect(\"c\", xx2).withSideEffect(\"m\", 
xx3).mergeE(xx1).option(Merge.onCreate, __.select(\"c\")).option(Merge.onMatch, 
__.select(\"m\"))",
@@ -581,23 +669,27 @@ public class GremlinTranslatorTest {
                             "g.withSideEffect(string0, 
xx2).withSideEffect(string1, xx3).mergeE(map0).option(Merge.onCreate, 
__.select(string0)).option(Merge.onMatch, __.select(string1))",
                             null,
                             null,
+                            null,
                             "g.with_side_effect('c', 
xx2).with_side_effect('m', xx3).merge_e(xx1).option(Merge.on_create, 
__.select('c')).option(Merge.on_match, __.select('m'))"},
                     {"g.V(1, 2, 3)",
                             null,
                             "g.V(number0, number1, number2)",
                             null,
                             null,
+                            null,
                             null},
                     {"g.V().limit(1)",
                             null,
                             "g.V().limit(number0)",
                             null,
                             null,
+                            null,
                             null},
                     {"g.V().limit(1L)",
-                            null,
+                            "g.V().limit(1l)",
                             "g.V().limit(long0)",
                             "g.V().limit(1l)",
+                            "g.V().limit(1l)",
                             "g.V().limit(1)",
                             "g.V().limit(long(1))"},
                     {"g.V().limit(x)",
@@ -605,36 +697,42 @@ public class GremlinTranslatorTest {
                             null,
                             null,
                             null,
+                            null,
                             null},
                     {"g.V().toList()",
                             null,
                             null,
                             null,
                             null,
+                            null,
                             "g.V().to_list()"},
                     {"g.V().iterate()",
                             null,
                             null,
                             null,
                             null,
+                            null,
                             null},
                     {"g.tx().commit()",
                             null,
                             null,
                             null,
                             null,
+                            null,
                             null},
             });
         }
 
         public TranslationTest(final String query, final String 
expectedForLang,
                                final String expectedForAnonymized,
+                               final String expectedForGroovy,
                                final String expectedForJava,
                                final String expectedForJavascript,
                                final String expectedForPython) {
             this.query = query;
             this.expectedForLang = expectedForLang != null ? expectedForLang : 
query;
             this.expectedForAnonymized = expectedForAnonymized != null ? 
expectedForAnonymized : query;
+            this.expectedForGroovy = expectedForGroovy != null ? 
expectedForGroovy : query;
             this.expectedForJava = expectedForJava != null ? expectedForJava : 
query;
             this.expectedForJavascript = expectedForJavascript != null ? 
expectedForJavascript : query;
             this.expectedForPython = expectedForPython != null ? 
expectedForPython : query;
@@ -652,6 +750,16 @@ public class GremlinTranslatorTest {
             assertEquals(expectedForAnonymized, translatedQuery);
         }
 
+        @Test
+        public void shouldTranslateForGroovy() {
+            try {
+                final String translatedQuery = 
GremlinTranslator.translate(query, "g", Translator.GROOVY).getTranslated();
+                assertEquals(expectedForGroovy, translatedQuery);
+            } catch (TranslatorException e) {
+                assertThat(e.getMessage(), startsWith(expectedForGroovy));
+            }
+        }
+
         @Test
         public void shouldTranslateForJava() {
             try {
diff --git 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
index ba28d95a0b..f43d350992 100644
--- 
a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
+++ 
b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/features/StepDefinition.java
@@ -32,6 +32,8 @@ import org.antlr.v4.runtime.CommonTokenStream;
 import org.apache.tinkerpop.gremlin.language.grammar.GremlinAntlrToJava;
 import org.apache.tinkerpop.gremlin.language.grammar.GremlinLexer;
 import org.apache.tinkerpop.gremlin.language.grammar.GremlinParser;
+import org.apache.tinkerpop.gremlin.language.translator.GremlinTranslator;
+import org.apache.tinkerpop.gremlin.language.translator.Translator;
 import org.apache.tinkerpop.gremlin.process.traversal.Merge;
 import org.apache.tinkerpop.gremlin.process.traversal.Path;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
@@ -69,7 +71,6 @@ import static org.junit.Assert.fail;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -444,7 +445,11 @@ public final class StepDefinition {
     }
 
     private Traversal parseGremlin(final String script) {
-        final GremlinLexer lexer = new 
GremlinLexer(CharStreams.fromString(script));
+        // tests the normalizer by running the script from the feature file 
first
+        final String normalizedGremlin = GremlinTranslator.translate(script, 
Translator.LANGUAGE).getTranslated();
+
+        // parse the Gremlin to a Traversal
+        final GremlinLexer lexer = new 
GremlinLexer(CharStreams.fromString(normalizedGremlin));
         final GremlinParser parser = new GremlinParser(new 
CommonTokenStream(lexer));
         final GremlinParser.QueryContext ctx = parser.query();
         return (Traversal) new GremlinAntlrToJava(g).visitQuery(ctx);

Reply via email to