This is an automated email from the ASF dual-hosted git repository. Cole-Greer pushed a commit to branch simplePDT in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit a23714f3c8e302bc9afa7cfd85aae417a6ec5413 Author: Cole Greer <[email protected]> AuthorDate: Wed Jun 24 13:47:53 2026 -0700 Add PrimitivePDT grammar literal overload, translators, and GremlinLang support Adds the gremlin-lang text form for PrimitivePDT as an overload of the existing PDT(...) literal: PDT("name", "value"). - Gremlin.g4: pdtLiteral gains a second unlabeled alternative (K_PDT LPAREN stringLiteral COMMA stringLiteral RPAREN). Unambiguous with the composite map form ('[' vs quote on the 2nd arg). Reuses K_PDT. - GenericLiteralVisitor.visitPdtLiteral branches on genericMapLiteral != null; the primitive form builds PrimitiveProviderDefinedType(name, value). - GremlinLang.argAsString emits PDT(<name>,<value>) for PrimitiveProviderDefinedType and auto-dehydrates classes with a registered PrimitivePDTAdapter. - All translator visitors (Java, Groovy, Python, Javascript, Go, DotNet, Anonymized) emit the language-native primitive construction; the base TranslateVisitor passthrough covers both forms. Composite branches updated from stringLiteral() to stringLiteral(0) for the new list accessor. GLV runtime libraries are handled in later beads. Tests: GeneralLiteralVisitorTest (parse primitive + composite still works), GremlinLangTest (round-trip + auto-dehydration), GremlinTranslatorTest (per-language primitive emission). tinkerpop-2gy.5 Assisted-by: Kiro:claude-opus-4.8 --- .../language/grammar/GenericLiteralVisitor.java | 22 ++++++++++------ .../translator/AnonymizedTranslatorVisitor.java | 7 +++++- .../translator/DotNetTranslateVisitor.java | 18 ++++++++++---- .../language/translator/GoTranslateVisitor.java | 18 ++++++++++---- .../translator/GroovyTranslateVisitor.java | 18 ++++++++++---- .../language/translator/JavaTranslateVisitor.java | 18 ++++++++++---- .../translator/JavascriptTranslateVisitor.java | 18 ++++++++++---- .../translator/PythonTranslateVisitor.java | 18 ++++++++++---- .../gremlin/process/traversal/GremlinLang.java | 13 ++++++++++ .../grammar/GeneralLiteralVisitorTest.java | 25 +++++++++++++++++++ .../language/translator/GremlinTranslatorTest.java | 9 +++++++ .../gremlin/process/traversal/GremlinLangTest.java | 29 ++++++++++++++++++++++ gremlin-language/src/main/antlr4/Gremlin.g4 | 1 + 13 files changed, 175 insertions(+), 39 deletions(-) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java index 83fc03daf4..2317556f14 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java @@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitiveProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; import org.apache.tinkerpop.gremlin.util.DatetimeHelper; @@ -584,15 +585,20 @@ public class GenericLiteralVisitor extends DefaultGremlinBaseVisitor<Object> { */ @Override public Object visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - final String name = (String) visitStringLiteral(ctx.stringLiteral()); - final Map<String, Object> fields = new LinkedHashMap<>(); - final Map<?, ?> rawMap = (Map<?, ?>) visitGenericMapLiteral(ctx.genericMapLiteral()); - for (final Map.Entry<?, ?> entry : rawMap.entrySet()) { - if (!(entry.getKey() instanceof String)) - throw new IllegalArgumentException("PDT fields map must have String keys, found: " + entry.getKey().getClass().getName()); - fields.put((String) entry.getKey(), entry.getValue()); + final String name = (String) visitStringLiteral(ctx.stringLiteral(0)); + if (ctx.genericMapLiteral() != null) { + final Map<String, Object> fields = new LinkedHashMap<>(); + final Map<?, ?> rawMap = (Map<?, ?>) visitGenericMapLiteral(ctx.genericMapLiteral()); + for (final Map.Entry<?, ?> entry : rawMap.entrySet()) { + if (!(entry.getKey() instanceof String)) + throw new IllegalArgumentException("PDT fields map must have String keys, found: " + entry.getKey().getClass().getName()); + fields.put((String) entry.getKey(), entry.getValue()); + } + return new ProviderDefinedType(name, fields); + } else { + final String value = (String) visitStringLiteral(ctx.stringLiteral(1)); + return new PrimitiveProviderDefinedType(name, value); } - return new ProviderDefinedType(name, fields); } /** diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/AnonymizedTranslatorVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/AnonymizedTranslatorVisitor.java index 40f869dac3..4e0fc5efa3 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/AnonymizedTranslatorVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/AnonymizedTranslatorVisitor.java @@ -20,6 +20,7 @@ package org.apache.tinkerpop.gremlin.language.translator; import org.antlr.v4.runtime.ParserRuleContext; import org.apache.tinkerpop.gremlin.language.grammar.GremlinParser; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitiveProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; import java.math.BigDecimal; @@ -208,6 +209,10 @@ public class AnonymizedTranslatorVisitor extends TranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - return anonymize(ctx, ProviderDefinedType.class); + if (ctx.genericMapLiteral() != null) { + return anonymize(ctx, ProviderDefinedType.class); + } else { + return anonymize(ctx, PrimitiveProviderDefinedType.class); + } } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java index 7c296572cf..f26908340d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java @@ -1209,11 +1209,19 @@ public class DotNetTranslateVisitor extends AbstractTranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - sb.append("new ProviderDefinedType("); - sb.append(ctx.stringLiteral().getText()); - sb.append(", "); - visitGenericMapLiteral(ctx.genericMapLiteral()); - sb.append(")"); + if (ctx.genericMapLiteral() != null) { + sb.append("new ProviderDefinedType("); + sb.append(ctx.stringLiteral(0).getText()); + sb.append(", "); + visitGenericMapLiteral(ctx.genericMapLiteral()); + sb.append(")"); + } else { + sb.append("new PrimitiveProviderDefinedType("); + sb.append(ctx.stringLiteral(0).getText()); + sb.append(", "); + sb.append(ctx.stringLiteral(1).getText()); + sb.append(")"); + } return null; } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java index f4094e541e..5f43d2d031 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java @@ -378,11 +378,19 @@ public class GoTranslateVisitor extends AbstractTranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - sb.append("&gremlingo.ProviderDefinedType{Name: "); - visitStringLiteral(ctx.stringLiteral()); - sb.append(", Fields: "); - visitGenericMapLiteral(ctx.genericMapLiteral()); - sb.append("}"); + if (ctx.genericMapLiteral() != null) { + sb.append("&gremlingo.ProviderDefinedType{Name: "); + visitStringLiteral(ctx.stringLiteral(0)); + sb.append(", Fields: "); + visitGenericMapLiteral(ctx.genericMapLiteral()); + sb.append("}"); + } else { + sb.append("&gremlingo.PrimitiveProviderDefinedType{Name: "); + visitStringLiteral(ctx.stringLiteral(0)); + sb.append(", Value: "); + visitStringLiteral(ctx.stringLiteral(1)); + sb.append("}"); + } return null; } 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 index 2fd655a506..eee45b2289 100644 --- 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 @@ -154,11 +154,19 @@ public class GroovyTranslateVisitor extends TranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - sb.append("new ProviderDefinedType("); - sb.append(ctx.stringLiteral().getText()); - sb.append(", "); - visitGenericMapLiteral(ctx.genericMapLiteral()); - sb.append(")"); + if (ctx.genericMapLiteral() != null) { + sb.append("new ProviderDefinedType("); + sb.append(ctx.stringLiteral(0).getText()); + sb.append(", "); + visitGenericMapLiteral(ctx.genericMapLiteral()); + sb.append(")"); + } else { + sb.append("new PrimitiveProviderDefinedType("); + sb.append(ctx.stringLiteral(0).getText()); + sb.append(", "); + sb.append(ctx.stringLiteral(1).getText()); + sb.append(")"); + } 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 6f28494526..bcd0066d06 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 @@ -272,11 +272,19 @@ public class JavaTranslateVisitor extends AbstractTranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - sb.append("new ProviderDefinedType("); - sb.append(ctx.stringLiteral().getText()); - sb.append(", "); - visitGenericMapLiteral(ctx.genericMapLiteral()); - sb.append(")"); + if (ctx.genericMapLiteral() != null) { + sb.append("new ProviderDefinedType("); + sb.append(ctx.stringLiteral(0).getText()); + sb.append(", "); + visitGenericMapLiteral(ctx.genericMapLiteral()); + sb.append(")"); + } else { + sb.append("new PrimitiveProviderDefinedType("); + sb.append(ctx.stringLiteral(0).getText()); + sb.append(", "); + sb.append(ctx.stringLiteral(1).getText()); + sb.append(")"); + } return null; } 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 cf6284d275..3987c3b6c4 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 @@ -242,11 +242,19 @@ public class JavascriptTranslateVisitor extends AbstractTranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - sb.append("new ProviderDefinedType("); - visitStringLiteral(ctx.stringLiteral()); - sb.append(", "); - visitGenericMapLiteral(ctx.genericMapLiteral()); - sb.append(")"); + if (ctx.genericMapLiteral() != null) { + sb.append("new ProviderDefinedType("); + visitStringLiteral(ctx.stringLiteral(0)); + sb.append(", "); + visitGenericMapLiteral(ctx.genericMapLiteral()); + sb.append(")"); + } else { + sb.append("new PrimitiveProviderDefinedType("); + visitStringLiteral(ctx.stringLiteral(0)); + sb.append(", "); + visitStringLiteral(ctx.stringLiteral(1)); + sb.append(")"); + } return null; } 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 694d6b4238..f7362519b5 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 @@ -319,11 +319,19 @@ public class PythonTranslateVisitor extends AbstractTranslateVisitor { @Override public Void visitPdtLiteral(final GremlinParser.PdtLiteralContext ctx) { - sb.append("ProviderDefinedType("); - visitStringLiteral(ctx.stringLiteral()); - sb.append(", "); - visitGenericMapLiteral(ctx.genericMapLiteral()); - sb.append(")"); + if (ctx.genericMapLiteral() != null) { + sb.append("ProviderDefinedType("); + visitStringLiteral(ctx.stringLiteral(0)); + sb.append(", "); + visitGenericMapLiteral(ctx.genericMapLiteral()); + sb.append(")"); + } else { + sb.append("PrimitiveProviderDefinedType("); + visitStringLiteral(ctx.stringLiteral(0)); + sb.append(", "); + visitStringLiteral(ctx.stringLiteral(1)); + sb.append(")"); + } return null; } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java index c1bc3461aa..3470de1981 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLang.java @@ -31,6 +31,8 @@ import org.apache.tinkerpop.gremlin.structure.Column; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefined; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitivePDTAdapter; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitiveProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.CompositePDTAdapter; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter; @@ -190,6 +192,11 @@ public class GremlinLang implements Cloneable, Serializable { return String.format("Binary(\"%s\")", Base64.getEncoder().encodeToString((byte[]) arg)); } + if (arg instanceof PrimitiveProviderDefinedType) { + final PrimitiveProviderDefinedType pdt = (PrimitiveProviderDefinedType) arg; + return "PDT(" + argAsString(pdt.getName()) + "," + argAsString(pdt.getValue()) + ")"; + } + if (arg instanceof ProviderDefinedType) { final ProviderDefinedType pdt = (ProviderDefinedType) arg; return "PDT(" + argAsString(pdt.getName()) + "," + asString((Map<?, ?>) pdt.getFields()) + ")"; @@ -271,6 +278,12 @@ public class GremlinLang implements Cloneable, Serializable { // Intentional precedence: a registered adapter takes priority over @ProviderDefined annotation // so that providers/users can override annotation-derived behavior with an explicit adapter. if (pdtRegistry != null) { + final Optional<PrimitivePDTAdapter<?>> primitiveAdapter = pdtRegistry.getPrimitiveAdapterByClass(arg.getClass()); + if (primitiveAdapter.isPresent()) { + @SuppressWarnings("unchecked") + final String value = ((PrimitivePDTAdapter) primitiveAdapter.get()).toValue(arg); + return argAsString(new PrimitiveProviderDefinedType(primitiveAdapter.get().typeName(), value)); + } final Optional<ProviderDefinedTypeAdapter<?>> adapter = pdtRegistry.getAdapterByClass(arg.getClass()); if (adapter.isPresent()) { @SuppressWarnings("unchecked") diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java index 3adc7b63bb..2bfb0b5908 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java @@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.GType; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.T; import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitiveProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; import org.hamcrest.Matchers; import org.junit.Assert; @@ -1089,5 +1090,29 @@ public class GeneralLiteralVisitorTest { assertTrue(e.getMessage().contains("PDT fields map must have String keys, found: java.lang.Integer")); } } + + @Test + public void shouldParsePrimitivePdtLiteral() { + final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString("PDT(\"Uint32\",\"42\")")); + final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer)); + final GremlinParser.PdtLiteralContext ctx = parser.pdtLiteral(); + final Object result = new GenericLiteralVisitor(new GremlinAntlrToJava()).visitPdtLiteral(ctx); + assertThat(result, instanceOf(PrimitiveProviderDefinedType.class)); + final PrimitiveProviderDefinedType pdt = (PrimitiveProviderDefinedType) result; + assertEquals("Uint32", pdt.getName()); + assertEquals("42", pdt.getValue()); + } + + @Test + public void shouldParsePrimitivePdtLiteralWithEmptyValue() { + final GremlinLexer lexer = new GremlinLexer(CharStreams.fromString("PDT(\"Empty\",\"\")")); + final GremlinParser parser = new GremlinParser(new CommonTokenStream(lexer)); + final GremlinParser.PdtLiteralContext ctx = parser.pdtLiteral(); + final Object result = new GenericLiteralVisitor(new GremlinAntlrToJava()).visitPdtLiteral(ctx); + assertThat(result, instanceOf(PrimitiveProviderDefinedType.class)); + final PrimitiveProviderDefinedType pdt = (PrimitiveProviderDefinedType) result; + assertEquals("Empty", pdt.getName()); + assertEquals("", pdt.getValue()); + } } } 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 43c785a845..f7f28ea589 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 @@ -1489,6 +1489,15 @@ public class GremlinTranslatorTest { "g.inject(new ProviderDefinedType(\"Point\", new LinkedHashMap<Object, Object>() {{ put(\"x\", 1); put(\"y\", 2); }}))", "g.inject(new ProviderDefinedType(\"Point\", new Map([[\"x\", 1], [\"y\", 2]])))", "g.inject(ProviderDefinedType('Point', { 'x': 1, 'y': 2 }))"}, + {"g.inject(PDT(\"Uint32\",\"42\"))", + null, + "g.inject(primitiveproviderdefinedtype0)", + "g.Inject<object>(new PrimitiveProviderDefinedType(\"Uint32\", \"42\"))", + "g.Inject(&gremlingo.PrimitiveProviderDefinedType{Name: \"Uint32\", Value: \"42\"})", + "g.inject(new PrimitiveProviderDefinedType(\"Uint32\", \"42\"))", + "g.inject(new PrimitiveProviderDefinedType(\"Uint32\", \"42\"))", + "g.inject(new PrimitiveProviderDefinedType(\"Uint32\", \"42\"))", + "g.inject(PrimitiveProviderDefinedType('Uint32', '42'))"}, }); } diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java index ad506a5cc9..d76be1464b 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/GremlinLangTest.java @@ -29,6 +29,8 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex; import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefined; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitivePDTAdapter; +import org.apache.tinkerpop.gremlin.structure.io.pdt.PrimitiveProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.CompositePDTAdapter; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeRegistry; @@ -157,6 +159,11 @@ public class GremlinLangTest { // Nested PDT {g.inject(new ProviderDefinedType("Outer", asMap("inner", new ProviderDefinedType("Inner", asMap("v", 1))))), "g.inject(PDT(\"Outer\",[\"inner\":PDT(\"Inner\",[\"v\":1])]))"}, + // Primitive PDT + {g.inject(new PrimitiveProviderDefinedType("Uint32", "42")), + "g.inject(PDT(\"Uint32\",\"42\"))"}, + {g.inject(new PrimitiveProviderDefinedType("Empty", "")), + "g.inject(PDT(\"Empty\",\"\"))"}, }); } @@ -525,6 +532,28 @@ public class GremlinLangTest { assertEquals("g.inject(PDT(\"Container\",[\"location\":PDT(\"Point\",[\"x\":3,\"y\":7])]))", gremlin); } + + private static class Uint32 { + final long value; + Uint32(final long value) { this.value = value; } + } + + @Test + public void shouldDehydratePrimitiveRegisteredType() { + final ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.empty(); + registry.register(new PrimitivePDTAdapter<Uint32>() { + @Override public String typeName() { return "Uint32"; } + @Override public Class<Uint32> targetClass() { return Uint32.class; } + @Override public String toValue(final Uint32 obj) { return String.valueOf(obj.value); } + @Override public Uint32 fromValue(final String value) { return new Uint32(Long.parseLong(value)); } + }); + + final GraphTraversalSource g2 = traversal().with(EmptyGraph.instance()); + g2.getGremlinLang().setPdtRegistry(registry); + final String gremlin = g2.inject(new Uint32(99)).asAdmin().getGremlinLang().getGremlin(); + + assertEquals("g.inject(PDT(\"Uint32\",\"99\"))", gremlin); + } } public static class UnsupportedTypeTests { diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 b/gremlin-language/src/main/antlr4/Gremlin.g4 index fbe8d41404..8c112cbf6c 100644 --- a/gremlin-language/src/main/antlr4/Gremlin.g4 +++ b/gremlin-language/src/main/antlr4/Gremlin.g4 @@ -1731,6 +1731,7 @@ binaryLiteral pdtLiteral : K_PDT LPAREN stringLiteral COMMA genericMapLiteral RPAREN + | K_PDT LPAREN stringLiteral COMMA stringLiteral RPAREN ;
