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

kenhuuu pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 0e743cbc82e3cb9eeb7050ec11e17e701b2263dd
Author: Guian Gumpac <[email protected]>
AuthorDate: Mon Aug 31 16:30:15 2026 -0700

    Fixed P.typeOf()
    
    Assisted-by: Claude Opus 5
---
 .../structure/io/binary/types/PSerializer.java     |  7 +-
 .../io/graphson/TraversalSerializersV2.java        |  4 +
 .../io/graphson/TraversalSerializersV3.java        |  4 +
 .../gremlin/util/ser/AbstractRoundTripTest.java    | 12 +++
 .../util/ser/binary/types/PSerializerTest.java     | 85 ++++++++++++++++++++++
 5 files changed, 111 insertions(+), 1 deletion(-)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java
index 0d123288a4..a1edf6cbdb 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java
@@ -172,7 +172,12 @@ public class PSerializer<T extends P> extends 
SimpleTypeSerializer<T> {
         context.writeValue(length, buffer, false);
 
         for (Object o : argsAsList) {
-            context.write(o, buffer);
+            // typeOf's argument travels as the class's simple name, so the 
read resolves it against
+            // CompareType.GlobalTypeCache.
+            if ("typeOf".equals(predicateName) && o instanceof Class)
+                context.write(((Class<?>) o).getSimpleName(), buffer);
+            else
+                context.write(o, buffer);
         }
     }
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2.java
index 7035ec8105..9daf43f80b 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV2.java
@@ -165,6 +165,10 @@ final class TraversalSerializersV2 {
                         jsonGenerator.writeObject(object);
                     }
                     jsonGenerator.writeEndArray();
+                } else if ("typeOf".equals(p.getPredicateName()) && 
p.getValue() instanceof Class) {
+                    // as in binary/types/PSerializer, typeOf's Class argument 
travels as the simple name so the read
+                    // resolves it against CompareType.GlobalTypeCache.
+                    jsonGenerator.writeObjectField(GraphSONTokens.VALUE, 
((Class<?>) p.getValue()).getSimpleName());
                 } else
                     jsonGenerator.writeObjectField(GraphSONTokens.VALUE, 
p.getValue());
             }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3.java
index ec98331826..2191e2654e 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/TraversalSerializersV3.java
@@ -165,6 +165,10 @@ final class TraversalSerializersV3 {
                 jsonGenerator.writeEndArray();
             } else if (p instanceof NotP) {
                 jsonGenerator.writeObjectField(GraphSONTokens.VALUE, 
p.negate());
+            } else if ("typeOf".equals(p.getPredicateName()) && p.getValue() 
instanceof Class) {
+                // as in binary/types/PSerializer, typeOf's Class argument 
travels as the simple name so the read
+                // resolves it against CompareType.GlobalTypeCache.
+                jsonGenerator.writeObjectField(GraphSONTokens.VALUE, 
((Class<?>) p.getValue()).getSimpleName());
             } else
                 jsonGenerator.writeObjectField(GraphSONTokens.VALUE, 
p.getValue());
 
diff --git 
a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
index 259dacf0ff..98280351db 100644
--- 
a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
+++ 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.computer.Computer;
 import 
org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.decoration.VertexProgramStrategy;
 import 
org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.GType;
 import org.apache.tinkerpop.gremlin.process.traversal.Operator;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
@@ -92,6 +93,7 @@ import java.util.function.Consumer;
 import static 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.hasLabel;
 import static 
org.apache.tinkerpop.gremlin.util.MockitoHamcrestMatcherAdapter.reflectionEquals;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 
 @RunWith(Parameterized.class)
@@ -159,6 +161,13 @@ public abstract class AbstractRoundTripTest {
         final DefaultTraversalMetrics traversalMetrics = new 
DefaultTraversalMetrics(666, nestedMetrics);
         final DefaultTraversalMetrics emptyTraversalMetrics = new 
DefaultTraversalMetrics(444, Collections.emptyList());
 
+        // the three P.typeOf rows assert by evaluating the decoded predicate, 
since the Class form arrives as String
+        final Consumer<P> typeOfBoolean = p -> {
+            assertThat(p.test(Boolean.FALSE), is(true));
+            assertThat(p.test(Boolean.TRUE), is(true));
+            assertThat(p.test("false"), is(false));
+        };
+
         return Arrays.asList(
                 new Object[] {"String", "ABC", null},
                 new Object[] {"Char", '£', null},
@@ -232,6 +241,9 @@ public abstract class AbstractRoundTripTest {
                 new Object[] {"Pnot", P.not(P.lte(1)), null},
                 new Object[] {"Pwithout", P.without(1,2,3,4,null), null},
                 new Object[] {"Pinside", P.inside(0.0d, 0.6d), null},
+                new Object[] {"PtypeOfGType", P.typeOf(GType.BOOLEAN), 
typeOfBoolean},
+                new Object[] {"PtypeOfString", P.typeOf("Boolean"), 
typeOfBoolean},
+                new Object[] {"PtypeOfClass", P.typeOf(Boolean.class), 
typeOfBoolean},
                 new Object[] {"TextPstartingWith", TextP.startingWith("mark"), 
null},
                 new Object[] {"TextPregex", TextP.regex("^meh"), null},
                 new Object[] {"TextPnotRegex", TextP.notRegex("^meh"), null},
diff --git 
a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/PSerializerTest.java
 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/PSerializerTest.java
new file mode 100644
index 0000000000..110af5c218
--- /dev/null
+++ 
b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/PSerializerTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.util.ser.binary.types;
+
+import io.netty.buffer.ByteBufAllocator;
+import org.apache.tinkerpop.gremlin.process.traversal.CompareType;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.structure.io.Buffer;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader;
+import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter;
+import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * GraphBinary encoding details for {@code P.typeOf(Class)}. Format-agnostic 
round trips of all three
+ * {@code P.typeOf} overloads are rows in {@code AbstractRoundTripTest}, which 
drives GraphBinary and GraphSON.
+ */
+public class PSerializerTest {
+
+    private static final NettyBufferFactory bufferFactory = new 
NettyBufferFactory();
+
+    private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT;
+
+    /**
+     * The {@code Class} form decodes to {@code String}, so deliberately not 
{@code equals} to what was written.
+     */
+    @Test
+    public void shouldWriteTypeOfClassAsSimpleName() throws Exception {
+        assertEquals(P.typeOf("Boolean"), roundTrip(P.typeOf(Boolean.class)));
+    }
+
+    /**
+     * The refusal comes from {@code GlobalTypeCache} on evaluation, not from 
{@code ClassRegistry} on read.
+     */
+    @Test
+    public void shouldFailOnUnregisteredClassWithGlobalTypeCacheMessage() 
throws Exception {
+        final P<Object> read = roundTrip(P.typeOf(UnregisteredType.class));
+
+        try {
+            read.test("anything");
+            fail("A class that GlobalTypeCache does not hold must not 
evaluate");
+        } catch (IllegalArgumentException ex) {
+            assertThat(ex.getMessage(), containsString("is not a registered 
type"));
+            assertThat(ex.getMessage(), 
containsString(UnregisteredType.class.getSimpleName()));
+            assertThat(ex.getMessage(), not(containsString("Class not 
recognized")));
+        }
+    }
+
+    private P<Object> roundTrip(final P<Object> p) throws IOException {
+        final Buffer buffer = bufferFactory.create(allocator.buffer());
+        new GraphBinaryWriter().write(p, buffer);
+
+        return (P<Object>) new GraphBinaryReader().read(buffer);
+    }
+
+    /**
+     * A class {@link CompareType.GlobalTypeCache} does not hold. Never 
register it.
+     */
+    private static final class UnregisteredType {
+    }
+}

Reply via email to