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

xiazcy pushed a commit to branch type-enum-poc
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit c9935f465cdcd78296124eb6f75f55d36578c563
Author: xiazcy <[email protected]>
AuthorDate: Fri Sep 5 09:30:48 2025 -0700

    Add mechanism for extending data type enums
---
 .../grammar/DefaultGremlinBaseVisitor.java         |  15 +++
 .../language/grammar/GenericLiteralVisitor.java    |   5 +
 .../language/grammar/GremlinAntlrToJava.java       |   7 ++
 .../grammar/TraversalGremlinTypesVisitor.java      |  55 ++++++++
 .../language/grammar/TraversalMethodVisitor.java   |   9 ++
 .../grammar/TraversalPredicateVisitor.java         |  10 +-
 .../translator/PythonTranslateVisitor.java         |   2 +-
 .../tinkerpop/gremlin/process/traversal/P.java     |   9 ++
 .../tinkerpop/gremlin/process/traversal/Type.java  |  64 ++++++++++
 .../traversal/dsl/graph/GraphTraversal.java        |  21 ++--
 .../process/traversal/step/map/AsNumberStep.java   |  26 +++-
 .../traversal/translator/PythonTranslator.java     |   2 +-
 .../apache/tinkerpop/gremlin/structure/CType.java  | 140 +++++++++++++++++++++
 .../tinkerpop/gremlin/structure/CustomType.java    |  42 +++++++
 .../apache/tinkerpop/gremlin/structure/GType.java  |  71 +++++++++++
 .../gremlin/structure/GremlinDataType.java         | 113 +++++++++++++++++
 .../apache/tinkerpop/gremlin/structure/NType.java  |  59 +++++++++
 .../apache/tinkerpop/gremlin/structure/Point.java  |  56 +++++++++
 .../gremlin/structure/io/binary/DataType.java      |   1 +
 .../io/binary/TypeSerializerRegistry.java          |  10 +-
 .../structure/io/binary/types/EnumSerializer.java  |   2 +
 .../io/binary/types/GremlinDataTypeSerializer.java |  96 ++++++++++++++
 .../tinkerpop/gremlin/util/NumberHelper.java       |  10 ++
 .../language/translator/GremlinTranslatorTest.java |   4 +-
 .../tinkerpop/gremlin/process/traversal/PTest.java |   7 ++
 .../traversal/step/map/AsNumberStepTest.java       |   3 +
 gremlin-language/src/main/antlr4/Gremlin.g4        |  17 +++
 .../gremlin/server/GremlinDriverIntegrateTest.java |  30 ++++-
 28 files changed, 857 insertions(+), 29 deletions(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index d988430a26..a3b8f841aa 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -1082,6 +1082,9 @@ public class DefaultGremlinBaseVisitor<T> extends 
AbstractParseTreeVisitor<T> im
        /**
         * {@inheritDoc}
         */
+       @Override public T 
visitTraversalMethod_asNumber_traversalGremlinTypes(final 
GremlinParser.TraversalMethod_asNumber_traversalGremlinTypesContext ctx) { 
notImplemented(ctx); return null; }/**
+        * {@inheritDoc}
+        */
        @Override public T visitTraversalScope(final 
GremlinParser.TraversalScopeContext ctx) { notImplemented(ctx); return null; }
        /**
         * {@inheritDoc}
@@ -1123,6 +1126,10 @@ public class DefaultGremlinBaseVisitor<T> extends 
AbstractParseTreeVisitor<T> im
         * {@inheritDoc}
         */
        @Override public T visitTraversalN(GremlinParser.TraversalNContext ctx) 
{ notImplemented(ctx); return null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalGremlinTypes(final 
GremlinParser.TraversalGremlinTypesContext ctx) { notImplemented(ctx); return 
null; }
        /**
         * {@inheritDoc}
         */
@@ -1155,6 +1162,14 @@ public class DefaultGremlinBaseVisitor<T> extends 
AbstractParseTreeVisitor<T> im
         * {@inheritDoc}
         */
        @Override public T visitTraversalPredicate_neq(final 
GremlinParser.TraversalPredicate_neqContext ctx) { notImplemented(ctx); return 
null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalPredicate_typeOf(final 
GremlinParser.TraversalPredicate_typeOfContext ctx) { notImplemented(ctx); 
return null; }
+//     /**
+//      * {@inheritDoc}
+//      */
+//     @Override public T visitTraversalPredicate_nof(final 
GremlinParser.TraversalPredicate_nofContext ctx) { notImplemented(ctx); return 
null; }
        /**
         * {@inheritDoc}
         */
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 eb0b9dc343..d9a909bfd6 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
@@ -606,6 +606,11 @@ public class GenericLiteralVisitor extends 
DefaultGremlinBaseVisitor<Object> {
         return TraversalEnumParser.parseTraversalNFromContext(ctx);
     }
 
+    @Override
+    public Object visitTraversalGremlinTypes(final 
GremlinParser.TraversalGremlinTypesContext ctx) {
+        return antlr.traversalGremlinTypesVisitor.visitGremlinDataType(ctx);
+    }
+
     @Override
     public Object visitTraversalStrategy(final 
GremlinParser.TraversalStrategyContext ctx) {
         return antlr.traversalStrategyVisitor.visitTraversalStrategy(ctx);
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
index ab6dbccb0a..f7f270e3ae 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GremlinAntlrToJava.java
@@ -29,6 +29,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 
@@ -94,6 +95,11 @@ public class GremlinAntlrToJava extends 
DefaultGremlinBaseVisitor<Object> {
      */
     final TraversalStrategyVisitor traversalStrategyVisitor;
 
+    /**
+     * Parses {@link GremlinDataType} instances.
+     */
+    final TraversalGremlinTypesVisitor traversalGremlinTypesVisitor;
+
     /**
      * Parses {@link P} instances.
      */
@@ -191,6 +197,7 @@ public class GremlinAntlrToJava extends 
DefaultGremlinBaseVisitor<Object> {
         this.txVisitor = new TraversalSourceTxVisitor(g, this);
         this.traversalPredicateVisitor = new TraversalPredicateVisitor(this);
         this.traversalStrategyVisitor = new TraversalStrategyVisitor(this);
+        this.traversalGremlinTypesVisitor = new 
TraversalGremlinTypesVisitor(this);
         this.genericVisitor = new GenericLiteralVisitor(this);
         this.argumentVisitor = new ArgumentVisitor(variableResolver, this);
     }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalGremlinTypesVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalGremlinTypesVisitor.java
new file mode 100644
index 0000000000..5489028715
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalGremlinTypesVisitor.java
@@ -0,0 +1,55 @@
+/*
+ * 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.grammar;
+
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+
+import java.util.Optional;
+
+public class TraversalGremlinTypesVisitor {
+    protected final GremlinAntlrToJava antlr;
+
+    public TraversalGremlinTypesVisitor(final GremlinAntlrToJava antlrToJava) {
+        this.antlr = antlrToJava;
+    }
+
+    public GremlinDataType visitGremlinDataType(final 
GremlinParser.TraversalGremlinTypesContext ctx) {
+        return tryToConstructGremlinDataType(ctx.getText());
+    }
+
+    /**
+     * Try to instantiate by checking registered {@link GremlinDataType} 
implementations that are
+     * registered globally. Only strategies that are registered globally can 
be constructed in this way.
+     */
+    private static GremlinDataType tryToConstructGremlinDataType(final String 
typeName) {
+        System.out.println(typeName);
+
+        // try to grab the class from registered sources
+        final Optional<GremlinDataType> opt = 
GremlinDataType.GlobalTypeCache.getRegisteredType(typeName);
+
+        System.out.println(opt);
+
+        if (opt.isEmpty())
+            throw new IllegalStateException("GremlinDataType not recognized - 
" + typeName);
+
+        return opt.get();
+
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 058dea096a..1e2546ec86 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -2128,6 +2128,15 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
                 
TraversalEnumParser.parseTraversalNFromContext(ctx.traversalN()));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal 
visitTraversalMethod_asNumber_traversalGremlinTypes(final 
GremlinParser.TraversalMethod_asNumber_traversalGremlinTypesContext ctx) {
+        return graphTraversal.asNumber(
+                
antlr.traversalGremlinTypesVisitor.visitGremlinDataType(ctx.traversalGremlinTypes()));
+    }
+
     public GraphTraversal[] getNestedTraversalList(final 
GremlinParser.NestedTraversalListContext ctx) {
         return ctx.nestedTraversalExpr().nestedTraversal()
                 .stream()
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
index ca481c8638..849c68be22 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalPredicateVisitor.java
@@ -23,8 +23,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.TextP;
 
 import java.util.Collection;
-import java.util.List;
-import java.util.Set;
 
 public class TraversalPredicateVisitor extends DefaultGremlinBaseVisitor<P> {
 
@@ -79,6 +77,14 @@ public class TraversalPredicateVisitor extends 
DefaultGremlinBaseVisitor<P> {
         return P.neq(getSingleGenericLiteralArgument(ctx));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public P visitTraversalPredicate_typeOf(final 
GremlinParser.TraversalPredicate_typeOfContext ctx) {
+        return P.typeOf(getSingleGenericLiteralArgument(ctx));
+    }
+
     /**
      * {@inheritDoc}
      */
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 971e61805b..b38b9255bd 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
@@ -111,7 +111,7 @@ public class PythonTranslateVisitor extends 
AbstractTranslateVisitor {
     public Void visitClassType(final GremlinParser.ClassTypeContext ctx) {
         final Optional<? extends Class<? extends TraversalStrategy>> strategy 
= TraversalStrategies.GlobalCache.getRegisteredStrategyClass(ctx.getText());
         final String fqcn = strategy.map(Class::getName).orElse(ctx.getText());
-        sb.append("GremlinType('").append(fqcn).append("')");
+        sb.append("GremlinDataType('").append(fqcn).append("')");
         return null;
     }
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
index 917a13891d..718473da76 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/P.java
@@ -145,6 +145,15 @@ public class P<V> implements Predicate<V>, Serializable, 
Cloneable {
         return new P(Compare.neq, value);
     }
 
+    /**
+     * Determines if values are of a type.
+     *
+     * @since 3.8.0-incubating
+     */
+    public static <V> P<V> typeOf(final V value) {
+        return new P(Type.typeOf, value);
+    }
+
     /**
      * Determines if a value is less than another.
      *
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Type.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Type.java
new file mode 100644
index 0000000000..f1080f0bc1
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Type.java
@@ -0,0 +1,64 @@
+/*
+ * 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;
+
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+
+import java.util.Optional;
+
+/**
+ * {@code Type} is a {@code BiPredicate} that determines whether the first 
argument is a type of the second argument.
+ *
+ */
+public enum Type implements PBiPredicate<Object, Object> {
+
+    /**
+     * Evaluates if the first object is equal to the second per Gremlin 
Comparison semantics.
+     *
+     * @since 3.8.0
+     */
+    typeOf {
+        @Override
+        public boolean test(final Object first, final Object second) {
+            Class<?> secondClass;
+            if (second instanceof GremlinDataType) {
+                secondClass = ((GremlinDataType) second).getType();
+            } else if (second instanceof String) {
+                try {
+                    // for java class names
+                    secondClass = Class.forName((String) second);
+                } catch (ClassNotFoundException e) {
+                    // for string name of type token we can use the cache
+                    final Optional<GremlinDataType> opt = 
GremlinDataType.GlobalTypeCache.getRegisteredType((String) second);
+                    if (opt.isEmpty())
+                        return false;
+                    else
+                        secondClass = opt.get().getType();
+                }
+            } else if (second instanceof Class) {
+                secondClass = (Class<?>) second;
+            } else {
+                return false;
+            }
+
+            return (secondClass).isAssignableFrom(first.getClass());
+        }
+
+    },
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 2d70e4e155..e479b4be63 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -195,16 +195,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Element;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.PropertyType;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.*;
 import org.apache.tinkerpop.gremlin.util.function.ConstantSupplier;
 
 import java.time.OffsetDateTime;
@@ -1954,6 +1945,16 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         return this.asAdmin().addStep(new AsNumberStep<>(this.asAdmin(), 
numberToken));
     }
 
+    public default GraphTraversal<S, Number> asNumber(final GremlinDataType 
numberToken) {
+        this.asAdmin().getBytecode().addStep(Symbols.asNumber, numberToken);
+        return this.asAdmin().addStep(new AsNumberStep<>(this.asAdmin(), 
numberToken));
+    }
+
+    public default GraphTraversal<S, Number> asNumber(final Class numberToken) 
{
+        this.asAdmin().getBytecode().addStep(Symbols.asNumber, numberToken);
+        return this.asAdmin().addStep(new AsNumberStep<>(this.asAdmin(), 
numberToken));
+    }
+
     /**
      * Calculates the difference between the list traverser and list argument.
      *
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
index 29ea0007e7..92bacc904d 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
@@ -23,6 +23,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.N;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import 
org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.NumberHelper;
 
@@ -35,6 +37,8 @@ import java.util.Set;
 public class AsNumberStep<S> extends ScalarMapStep<S, Number> {
 
     private N numberToken;
+    private GremlinDataType gDT;
+    private Class<?> clazz;
 
     public AsNumberStep(final Traversal.Admin traversal) {
         super(traversal);
@@ -46,16 +50,30 @@ public class AsNumberStep<S> extends ScalarMapStep<S, 
Number> {
         this.numberToken = numberToken;
     }
 
+    public AsNumberStep(final Traversal.Admin traversal, final GremlinDataType 
numberToken) {
+        super(traversal);
+        this.gDT = numberToken;
+    }
+
+    public AsNumberStep(final Traversal.Admin traversal, final Class<?> 
numberToken) {
+        super(traversal);
+        this.gDT = GType.valueOf(numberToken.getSimpleName().toUpperCase());
+    }
+
     @Override
     protected Number map(final Traverser.Admin<S> traverser) {
         final Object object = traverser.get();
         if (object instanceof String) {
             String numberText = (String) object;
             Number number = parseNumber(numberText);
-            return numberToken == null ? number : castNumber(number, 
numberToken);
+            return numberToken == null ? (gDT == null ? number : 
castNumber(number, gDT))
+                    : castNumber(number, numberToken);
+//            return numberToken == null ? number : castNumber(number, 
numberToken);
         } else if (object instanceof Number) {
             Number number = (Number) object;
-            return numberToken == null ? number : castNumber(number, 
numberToken);
+            return numberToken == null ? (gDT == null ? number : 
castNumber(number, gDT))
+                    : castNumber(number, numberToken);
+//            return numberToken == null ? number : castNumber(number, 
numberToken);
         }
         throw new IllegalArgumentException(String.format("Can't parse type %s 
as number.", object == null ? "null" : object.getClass().getSimpleName()));
     }
@@ -100,4 +118,8 @@ public class AsNumberStep<S> extends ScalarMapStep<S, 
Number> {
         return NumberHelper.castTo(number, numberToken);
     }
 
+    private static Number castNumber(final Number number, final 
GremlinDataType numberToken) {
+        return NumberHelper.castTo(number, numberToken);
+    }
+
 }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
index 907ef242b3..ae342b5771 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/translator/PythonTranslator.java
@@ -260,7 +260,7 @@ public final class PythonTranslator implements 
Translator.ScriptTranslator {
 
         @Override
         protected Script produceScript(final Class<?> o) {
-            return script.append("GremlinType('" + o.getCanonicalName() + 
"')");
+            return script.append("GremlinDataType('" + o.getCanonicalName() + 
"')");
         }
 
         @Override
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CType.java 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CType.java
new file mode 100644
index 0000000000..e18e4a9036
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CType.java
@@ -0,0 +1,140 @@
+/*
+ * 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.structure;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+public enum CType implements GremlinDataType{
+    ;
+
+    // Registry for custom type mappings
+    private static final ConcurrentMap<String, CustomTypeInfo> CUSTOM_REGISTRY 
= new ConcurrentHashMap<>();
+
+    // Instance fields for the enum
+    private final Class<?> javaType;
+
+    CType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+
+    @Override
+    public String getName() {
+        return "";
+    }
+
+    @Override
+    public Class<?> getType() {
+        return null;
+    }
+
+    @Override
+    public GremlinDataType fromName(String name) {
+        return null;
+    }
+
+
+    /**
+     * Register a custom TypeToken enum class
+     */
+    public static <E extends Enum<E> & GremlinDataType> void register(
+            String customTypeName,
+            Class<E> enumClass,
+            Function<String, E> factory) {
+
+        CUSTOM_REGISTRY.put(customTypeName, new CustomTypeInfo(enumClass, 
factory));
+    }
+
+    /**
+     * Register using reflection (convenience method)
+     */
+    public static <E extends Enum<E> & GremlinDataType> void register(
+            String customTypeName,
+            Class<E> enumClass) {
+
+        register(customTypeName, enumClass, name -> Enum.valueOf(enumClass, 
name));
+    }
+
+    /**
+     * Create a TypeToken instance from a custom type registration
+     */
+    public static Optional<GremlinDataType> createCustomInstance(String 
customTypeName, String enumValueName) {
+        CustomTypeInfo info = CUSTOM_REGISTRY.get(customTypeName);
+        if (info == null) {
+            return Optional.empty();
+        }
+
+        try {
+            return Optional.of(info.factory.apply(enumValueName));
+        } catch (Exception e) {
+            return Optional.empty();
+        }
+    }
+
+    /**
+     * Get the custom type name for a TypeToken instance
+     */
+    public static Optional<String> getCustomTypeName(GremlinDataType token) {
+        Class<?> tokenClass = token.getClass();
+        return CUSTOM_REGISTRY.entrySet().stream()
+                .filter(entry -> entry.getValue().enumClass.equals(tokenClass))
+                .map(Map.Entry::getKey)
+                .findFirst();
+    }
+
+    /**
+     * Check if a custom type is registered
+     */
+    public static boolean isCustomTypeRegistered(String customTypeName) {
+        return CUSTOM_REGISTRY.containsKey(customTypeName);
+    }
+
+    /**
+     * Get all registered custom type names
+     */
+    public static Set<String> getRegisteredCustomTypes() {
+        return Collections.unmodifiableSet(CUSTOM_REGISTRY.keySet());
+    }
+
+    /**
+     * Check if a TypeToken instance is a custom type
+     */
+    public static boolean isCustomType(GremlinDataType token) {
+        return getCustomTypeName(token).isPresent();
+    }
+
+    // Internal class to hold registration info
+    private static class CustomTypeInfo {
+        final Class<? extends Enum<? extends GremlinDataType>> enumClass;
+        final Function<String, ? extends GremlinDataType> factory;
+
+        CustomTypeInfo(Class<? extends Enum<? extends GremlinDataType>> 
enumClass,
+                       Function<String, ? extends GremlinDataType> factory) {
+            this.enumClass = enumClass;
+            this.factory = factory;
+        }
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CustomType.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CustomType.java
new file mode 100644
index 0000000000..a47a2fd990
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/CustomType.java
@@ -0,0 +1,42 @@
+/*
+ * 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.structure;
+
+/**
+ * Custom types
+ */
+public enum CustomType implements GremlinDataType {
+    POINT(Point.class);
+
+    private final Class<?> javaType;
+
+    CustomType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String getName() { return this.name(); }
+
+    @Override
+    public Class<?> getType() { return javaType; }
+
+    @Override
+    public GremlinDataType fromName(String name) { return 
CustomType.valueOf(name.toUpperCase()); }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GType.java 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GType.java
new file mode 100644
index 0000000000..1a92fadfe0
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GType.java
@@ -0,0 +1,71 @@
+/*
+ * 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.structure;
+
+import org.apache.tinkerpop.gremlin.util.NumberHelper;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.time.OffsetDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Gremlin types
+ */
+public enum GType implements GremlinDataType {
+    BIG_DECIMAL(BigDecimal.class),
+    BIG_INTEGER(BigInteger.class),
+    BOOLEAN(Boolean.class),
+    BYTE(Byte.class),
+    CHARACTER(Character.class),
+    DATETIME(OffsetDateTime.class),
+    DOUBLE(Double.class),
+    FLOAT(Float.class),
+    INT(int.class),
+    INTEGER(Integer.class),
+    LIST(List.class),
+    LONG(Long.class),
+    MAP(Map.class),
+    NUMBER(Number.class),
+    SET(Set.class),
+    SHORT(Short.class),
+    STRING(String.class),
+    UNKNOWN(null),
+    UUID(UUID.class),
+    VERTEX(Vertex.class),;
+
+    private final Class<?> javaType;
+
+    GType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String getName() { return this.name(); }
+
+    @Override
+    public Class<?> getType() { return javaType; }
+
+    @Override
+    public GremlinDataType fromName(String name) { return 
GType.valueOf(name.toUpperCase()); }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GremlinDataType.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GremlinDataType.java
new file mode 100644
index 0000000000..bef28c679e
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/GremlinDataType.java
@@ -0,0 +1,113 @@
+/*
+ * 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.structure;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+public interface GremlinDataType {
+
+    String getName();
+    Class<?> getType();
+    GremlinDataType fromName(String name);
+
+    // Optional: provide default categorization methods
+    default boolean isPrimitive() {
+        return getType().isPrimitive();
+    }
+
+    default boolean isNumeric() {
+        Class<?> type = getType();
+        return type == int.class || type == Integer.class ||
+                type == long.class || type == Long.class ||
+                type == double.class || type == Double.class ||
+                type == float.class || type == Float.class ||
+                type == BigDecimal.class || type == BigInteger.class;
+    }
+
+    final class GlobalTypeCache {
+
+        private GlobalTypeCache() {
+            throw new IllegalStateException("Utility class");
+        }
+
+        /**
+         * A register of the simple names for all strategies.
+         */
+        private static final Map<String, GremlinDataType> GLOBAL_TYPE_REGISTRY 
= new ConcurrentHashMap<>() {};
+
+        static {
+            for (GremlinDataType value : GType.values()) {
+                GLOBAL_TYPE_REGISTRY.put("GType." + value.getName(), value);
+            }
+        }
+
+        /**
+         * Registers all constants of a GremlinDataType class by its name 
(formatted as {GremlinDataType}.{TYPE}), so
+         * it is available to the grammar when parsing Gremlin.
+         */
+        public static void registerDataType(final Class<? extends Enum<? 
extends GremlinDataType>> enumClass) {
+            for (Enum<? extends GremlinDataType> constant : 
enumClass.getEnumConstants()) {
+                GLOBAL_TYPE_REGISTRY.put(enumClass.getSimpleName() + "." + 
constant.name(), (GremlinDataType) constant);
+            }
+        }
+
+        /**
+         * Unregisters a single GremlinDataType Enum constant by its name 
(formatted as {GremlinDataType}.{TYPE}).
+         * If the GremlinDataType is not in the registry then the grammar 
cannot reference it
+         */
+        public static void registerDataType(final String name, final 
GremlinDataType gdt) {
+            GLOBAL_TYPE_REGISTRY.put(name, gdt);
+        }
+
+        /**
+         * Unregisters all constants of a GremlinDataType class. If the 
GremlinDataType is not in the registry then the
+         * grammar cannot reference it
+         */
+        public static void unregisterDataType(final Class<? extends Enum<? 
extends GremlinDataType>> enumClass) {
+            for (Enum<? extends GremlinDataType> constant : 
enumClass.getEnumConstants()) {
+                GLOBAL_TYPE_REGISTRY.remove(enumClass.getSimpleName() + "." + 
constant.name());
+            }
+        }
+
+        /**
+         * Unregisters a single GremlinDataType by its name (formatted as 
{GremlinDataType}.{TYPE}). If the GremlinDataType
+         * is not in the registry then the grammar cannot reference it
+         */
+        public static void unregisterDataType(final String name) {
+            GLOBAL_TYPE_REGISTRY.remove(name);
+        }
+
+        /**
+         * Looks up a Gremlin DataType by its simple name.
+         */
+        public static Optional<GremlinDataType> getRegisteredType(final String 
typeName) {
+            System.out.println(GLOBAL_TYPE_REGISTRY);
+            if (GLOBAL_TYPE_REGISTRY.containsKey(typeName))
+                return Optional.of(GLOBAL_TYPE_REGISTRY.get(typeName));
+
+            return Optional.empty();
+        }
+
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/NType.java 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/NType.java
new file mode 100644
index 0000000000..71219b7f26
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/NType.java
@@ -0,0 +1,59 @@
+/*
+ * 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.structure;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Number types
+ */
+public enum NType implements GremlinDataType {
+    BYTE(Byte.class),
+    SHORT(Short.class),
+    INT(int.class),
+    INTEGER(Integer.class),
+    LONG(Long.class),
+    FLOAT(Float.class),
+    DOUBLE(Double.class),
+    BIG_INTEGER(BigInteger.class),
+    BIG_DECIMAL(BigDecimal.class),;
+
+    private final Class<?> javaType;
+
+    NType(Class<?> javaType) {
+        this.javaType = javaType;
+    }
+
+    @Override
+    public String getName() { return this.name(); }
+
+    @Override
+    public Class<?> getType() { return javaType; }
+
+    @Override
+    public GremlinDataType fromName(String name) { return 
NType.valueOf(name.toUpperCase()); }
+
+    static {
+        // register types
+//        for (GremlinDataType value : NType.values()) {
+//            GremlinDataType.GlobalTypeCache.registerDataType("NType." + 
value.getName(), value);
+//        }
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Point.java 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Point.java
new file mode 100644
index 0000000000..25d27e25f8
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/Point.java
@@ -0,0 +1,56 @@
+/*
+ * 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.structure;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+
+public class Point {
+    private Integer x;
+    private Integer y;
+
+    // constructors
+    public Point(final Integer x, final Integer y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    // getters and setters
+    public Integer getX() {
+        return x;
+    }
+
+    public Integer getY() {
+        return y;
+    }
+
+    public void setX(final Integer x) {
+        this.x = x;
+    }
+
+    public void setY(final Integer y) {
+        this.y = y;
+    }
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
index c0738a3496..112ca4f52e 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/DataType.java
@@ -73,6 +73,7 @@ public enum DataType {
     MERGE(0x2E),
     DT(0x2F),
     N(0x30),
+    GREMLINDATATYPE(0X31),
 
     CHAR(0X80),
     DURATION(0X81),
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
index 62597d16d9..c535332d64 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/TypeSerializerRegistry.java
@@ -40,14 +40,7 @@ import 
org.apache.tinkerpop.gremlin.process.traversal.util.Metrics;
 import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
 import 
org.apache.tinkerpop.gremlin.process.traversal.util.TraversalExplanation;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMetrics;
-import org.apache.tinkerpop.gremlin.structure.Column;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.T;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+import org.apache.tinkerpop.gremlin.structure.*;
 import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
 import org.apache.tinkerpop.gremlin.structure.io.binary.types.*;
 import org.apache.tinkerpop.gremlin.util.function.Lambda;
@@ -123,6 +116,7 @@ public class TypeSerializerRegistry {
             new RegistryEntry<>(DT.class, EnumSerializer.DTSerializer),
             new RegistryEntry<>(Merge.class, EnumSerializer.MergeSerializer),
             new RegistryEntry<>(N.class, new NSerializer()),
+            new RegistryEntry<>(GremlinDataType.class, new 
GremlinDataTypeSerializer()),
             new RegistryEntry<>(Operator.class, 
EnumSerializer.OperatorSerializer),
             new RegistryEntry<>(Order.class, EnumSerializer.OrderSerializer),
             new RegistryEntry<>(Pick.class, EnumSerializer.PickSerializer),
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
index 7ee0dd0406..fccf268607 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java
@@ -58,6 +58,8 @@ public class EnumSerializer<E extends Enum> extends 
SimpleTypeSerializer<E> {
     public static final EnumSerializer<Pop> PopSerializer = new 
EnumSerializer<>(DataType.POP, Pop::valueOf);
     public static final EnumSerializer<Scope> ScopeSerializer = new 
EnumSerializer<>(DataType.SCOPE, Scope::valueOf);
     public static final EnumSerializer<T> TSerializer = new 
EnumSerializer<>(DataType.T, T::valueOf);
+//    public static final EnumSerializer<GType> GTypeSerializer = new 
EnumSerializer<>(DataType.GTYPE, GType::valueOf);
+//    public static final EnumSerializer<NType> NTypeSerializer = new 
EnumSerializer<>(DataType.NTYPE, NType::valueOf);
 
     private final Function<String, E> readFunc;
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GremlinDataTypeSerializer.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GremlinDataTypeSerializer.java
new file mode 100644
index 0000000000..c3c645e9ca
--- /dev/null
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GremlinDataTypeSerializer.java
@@ -0,0 +1,96 @@
+/*
+ * 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.structure.io.binary.types;
+
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+import org.apache.tinkerpop.gremlin.structure.io.Buffer;
+import org.apache.tinkerpop.gremlin.structure.io.binary.DataType;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GremlinDataTypeSerializer extends 
SimpleTypeSerializer<GremlinDataType> {
+    // Registry of all known TypeToken implementations
+    private static final Map<String, TypeTokenFactory> TYPE_FACTORIES = new 
HashMap<>();
+
+    static {
+        // Register your enum types here
+        registerTypeFactory("GType", GType::valueOf);
+        // Add more as needed
+    }
+
+    public GremlinDataTypeSerializer() {
+        super(DataType.GREMLINDATATYPE);
+    }
+
+    /**
+     * Register a factory for creating TypeToken instances from strings
+     */
+    public static void registerTypeFactory(String typeName, TypeTokenFactory 
factory) {
+        TYPE_FACTORIES.put(typeName, factory);
+    }
+
+    @Override
+    protected GremlinDataType readValue(final Buffer buffer, final 
GraphBinaryReader context) throws IOException {
+        // Read the enum class name
+        final String enumClassName = context.read(buffer);
+        // Read the enum value name
+        final String enumValueName = context.read(buffer);
+
+        System.out.println("Reading " + enumClassName + " with value " + 
enumValueName);
+
+        TypeTokenFactory factory = TYPE_FACTORIES.get(enumClassName);
+        if (factory == null) {
+            throw new IOException("Unknown TypeToken enum class: " + 
enumClassName);
+        }
+
+        try {
+            return factory.create(enumValueName);
+        } catch (Exception e) {
+            throw new IOException("Failed to create TypeToken for " + 
enumClassName + "." + enumValueName, e);
+        }
+    }
+
+    @Override
+    protected void writeValue(final GremlinDataType value, final Buffer 
buffer, final GraphBinaryWriter context) throws IOException {
+        // Write the enum class name (simple name)
+        String enumClassName = value.getClass().getSimpleName();
+        context.write(enumClassName, buffer);
+
+        System.out.println("Writing " + enumClassName + " to " + buffer);
+
+        // Write the enum value name
+        if (value instanceof Enum) {
+            context.write(((Enum<?>) value).name(), buffer);
+        } else {
+            // Fallback for non-enum implementations
+            context.write(value.getType(), buffer);
+        }
+    }
+
+    @FunctionalInterface
+    public interface TypeTokenFactory {
+        GremlinDataType create(String name) throws Exception;
+    }
+
+}
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
index 41beeaa392..017bd55625 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/NumberHelper.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.util;
 
 import org.apache.tinkerpop.gremlin.process.traversal.N;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -712,6 +713,15 @@ public final class NumberHelper {
         return performConversion(a, clazz);
     }
 
+    public static Number castTo(final Number a, final GremlinDataType 
numberToken) {
+        Class<? extends Number> clazz = (Class<? extends Number>) 
numberToken.getType();
+        return performConversion(a, clazz);
+    }
+
+    public static Number castTo(final Number a, final Class<? extends Number> 
clazz) {
+        return performConversion(a, clazz);
+    }
+
     /**
      * Core conversion logic.
      * Throws ArithmeticException when conversion would overflow.
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 0a6f6b3a4a..b381719d45 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
@@ -702,7 +702,7 @@ public class GremlinTranslatorTest {
                             null,
                             "g.withoutStrategies(ReadOnlyStrategy.class)",
                             "g.withoutStrategies(ReadOnlyStrategy)",  // 
javascript needs TINKERPOP-3055
-                            
"g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy')])"},
+                            
"g.without_strategies(*[GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy')])"},
                     
{"g.withStrategies(ReservedKeysVerificationStrategy(throwException: true, keys: 
[\"age\"])).addV(\"person\").property(\"age\", 29).property(\"name\", 
\"marko\")",
                             
"g.withStrategies(ReservedKeysVerificationStrategy(throwException:true, 
keys:[\"age\"])).addV(\"person\").property(\"age\", 29).property(\"name\", 
\"marko\")",
                             
"g.withStrategies(ReservedKeysVerificationStrategy(throwException:boolean0, 
keys:list0)).addV(string0).property(string1, number0).property(string2, 
string3)",
@@ -721,7 +721,7 @@ public class GremlinTranslatorTest {
                             null,
                             "g.withoutStrategies(ReadOnlyStrategy.class, 
PathRetractionStrategy.class, FilterRankingStrategy.class)",
                             "g.withoutStrategies(ReadOnlyStrategy, 
PathRetractionStrategy, FilterRankingStrategy)",  // javascript - needs 
TINKERPOP-3055
-                            
"g.without_strategies(*[GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy'),
 
GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy'),
 
GremlinType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy')])"},
+                            
"g.without_strategies(*[GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy'),
 
GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy'),
 
GremlinDataType('org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy')])"},
                     {"g.inject(0..5)",
                             null,
                             "g.inject(number0..number1)",
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
index 15855e0108..bda483b7d9 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
@@ -21,6 +21,9 @@ package org.apache.tinkerpop.gremlin.process.traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
 import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
+import org.apache.tinkerpop.gremlin.structure.CustomType;
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.Point;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -55,6 +58,10 @@ public class PTest {
         @Parameterized.Parameters(name = "{0}.test({1}) = {2}")
         public static Iterable<Object[]> data() {
             return new ArrayList<>(Arrays.asList(new Object[][]{
+                    {P.typeOf(Number.class), 1, true},
+                    {P.typeOf(GType.NUMBER), 1, true},
+                    {P.typeOf(CustomType.POINT), new Point(1, 2), true},
+                    {P.typeOf(Number.class.getCanonicalName()), 1, true},
                     {P.eq(0), 0, true},
                     {P.eq(0), -0, true},
                     {P.eq(0), +0, true},
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
index ec98bd0285..224a587d02 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
@@ -22,6 +22,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.N;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
+import org.apache.tinkerpop.gremlin.structure.GType;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
 import org.junit.Test;
 
 import java.math.BigDecimal;
@@ -49,6 +51,7 @@ public class AsNumberStepTest extends StepTest {
         assertEquals(1L, __.__(1L).asNumber().next());
         assertEquals(3.14f, __.__(3.14).asNumber(N.float_).next());
         assertEquals(3.14, __.__(3.14f).asNumber(N.double_).next());
+        assertEquals(3.14, __.__(3.14f).asNumber(GType.DOUBLE).next());
         assertEquals(1, __.__("1").asNumber(N.int_).next());
         assertEquals(1, __.__("1").asNumber().next());
         assertEquals((byte) 1, __.__("1").asNumber(N.byte_).next());
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 
b/gremlin-language/src/main/antlr4/Gremlin.g4
index a3544cfe71..0b6ee396d4 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -362,6 +362,7 @@ traversalMethod_asDate
  traversalMethod_asNumber
      : K_ASNUMBER LPAREN RPAREN #traversalMethod_asNumber_Empty
      | K_ASNUMBER LPAREN traversalN RPAREN #traversalMethod_asNumber_traversalN
+     | K_ASNUMBER LPAREN traversalGremlinTypes RPAREN 
#traversalMethod_asNumber_traversalGremlinTypes
      ;
 
 traversalMethod_asString
@@ -961,6 +962,11 @@ traversalMethod_write
     ARGUMENT AND TERMINAL RULES
 **********************************************/
 
+traversalGremlinTypes
+    : nakedKey
+    | nakedKey DOT nakedKey
+    ;
+
 traversalStrategy
     : K_NEW? classType (LPAREN (configuration (COMMA configuration)*)? RPAREN)?
     ;
@@ -1095,6 +1101,7 @@ traversalPredicate
     | traversalPredicate_inside
     | traversalPredicate_outside
     | traversalPredicate_between
+    | traversalPredicate_typeOf
     | traversalPredicate_within
     | traversalPredicate_without
     | traversalPredicate_not
@@ -1150,6 +1157,10 @@ traversalPredicate_neq
     : (K_P DOT K_NEQ | K_NEQ) LPAREN genericArgument RPAREN
     ;
 
+traversalPredicate_typeOf
+    : (K_P DOT K_TYPEOF | K_TYPEOF) LPAREN genericArgument RPAREN
+    ;
+
 traversalPredicate_lt
     : (K_P DOT K_LT | K_LT) LPAREN genericArgument RPAREN
     ;
@@ -1579,6 +1590,7 @@ genericLiteral
     | traversalPick
     | traversalDT
     | traversalN
+    | traversalGremlinTypes
     | genericSetLiteral
     | genericCollectionLiteral
     | genericRangeLiteral
@@ -1677,6 +1689,10 @@ variable
     : Identifier
     ;
 
+//gremlinType
+//    : Identifier
+//    ;
+
 // every Gremlin keyword must be listed here or else these words will not be 
able to be used as
 // Map/Configuration keys as naked identifiers like [all: 123]. without having 
that definition
 // here that sort of Map definition will get a syntax error.
@@ -2109,6 +2125,7 @@ K_NEQ: 'neq';
 K_NEW: 'new';
 K_NORMSACK: 'normSack';
 K_NULL: 'null';
+K_TYPEOF: 'typeOf';
 K_ONCREATE: 'onCreate';
 K_ONMATCH: 'onMatch';
 K_OPERATOR: 'Operator';
diff --git 
a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
 
b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index 1ba8c43b39..a2f5a793f9 100644
--- 
a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ 
b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@ -22,11 +22,16 @@ import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
 import nl.altindag.log.LogCaptor;
 import org.apache.tinkerpop.gremlin.driver.Channelizer;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
+import org.apache.tinkerpop.gremlin.structure.CustomType;
+import org.apache.tinkerpop.gremlin.structure.GType;
 import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.structure.io.Mapper;
+import org.apache.tinkerpop.gremlin.structure.GremlinDataType;
+import org.apache.tinkerpop.gremlin.structure.NType;
+import org.apache.tinkerpop.gremlin.structure.Point;
+import 
org.apache.tinkerpop.gremlin.structure.io.binary.types.GremlinDataTypeSerializer;
 import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper;
-import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV2;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerIoRegistryV3;
 import org.apache.tinkerpop.gremlin.util.ExceptionHelper;
 import org.apache.tinkerpop.gremlin.TestHelper;
@@ -44,7 +49,6 @@ import 
org.apache.tinkerpop.gremlin.util.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.util.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
 import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1;
-import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV2;
 import org.apache.tinkerpop.gremlin.util.ser.GraphSONMessageSerializerV3;
 import org.apache.tinkerpop.gremlin.util.ser.Serializers;
 import org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin;
@@ -1978,4 +1982,24 @@ public class GremlinDriverIntegrateTest extends 
AbstractGremlinServerIntegration
             cluster.close();
         }
     }
+
+    @Test
+    public void test() throws Exception {
+        final Cluster cluster = 
TestClientFactory.build().serializer(Serializers.GRAPHBINARY_V1).create();
+        try {
+            final Client client = cluster.connect().alias("g");
+            final GraphTraversalSource g = 
traversal().with(DriverRemoteConnection.using(client));
+            GremlinDataType.GlobalTypeCache.registerDataType(NType.class);
+            GremlinDataTypeSerializer.registerTypeFactory("NType", 
NType::valueOf);
+            GremlinDataType.GlobalTypeCache.registerDataType(CustomType.class);
+            GremlinDataTypeSerializer.registerTypeFactory("CustomType", 
CustomType::valueOf);
+            System.out.println(g.inject("1").asNumber(NType.DOUBLE).next());
+            
System.out.println(client.submit("g.inject('1').asNumber(NType.DOUBLE)", 
RequestOptions.build().language("gremlin-lang").create()).all().get());
+            
System.out.println(g.inject(1.0,2,3,"hello",false).is(P.typeOf(GType.NUMBER)).fold().next());
+            
System.out.println(client.submit("g.inject(1.0,'hello').is(P.typeOf(GType.DOUBLE)).fold()",
 RequestOptions.build().language("gremlin-lang").create()).all().get());
+            cluster.close();
+        } finally {
+            cluster.close();
+        }
+    }
 }

Reply via email to