This is an automated email from the ASF dual-hosted git repository. Cole-Greer pushed a commit to branch PDT in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit 2e711729bdbcc843139fdc5c3fb585f6f9dcc6dc Author: Cole Greer <[email protected]> AuthorDate: Wed Jun 10 21:22:22 2026 -0700 Address PDT PR review: SPI auto-wiring, API renames, test relocation - Auto-wire an SPI-discovered ProviderDefinedTypeRegistry by default on the Java driver path so registered adapters hydrate/dehydrate with zero config: the default GraphBinaryMessageSerializerV4 and DriverRemoteConnection now use ProviderDefinedTypeRegistry.create(). setPdtRegistry and explicit serializer registries remain as overrides. - Rename the registry factory build() -> create() across Java, Python, and .NET (Go's NewPDTRegistry and JS's constructor are already idiomatic). The old name misleadingly implied the Builder pattern. - Rename the PDT field map terminology properties -> fields across all GLVs (getFields/Fields, toFields/fromFields) to match the @ProviderDefined annotation and the GraphSON wire format, and disambiguate from Element properties. Wire formats and binary layouts are unchanged. - Document that equals()/hashCode() intentionally exclude the transient hydrated field. - Move the PDT GraphBinary serializer tests from gremlin-core to gremlin-util and delete the bespoke HeapBuffer, reusing the netty-backed buffer pattern. - Update provider and reference docs for the renames. Assisted-by: Kiro:claude-opus-4.8 --- docs/src/dev/provider/index.asciidoc | 18 +- docs/src/reference/gremlin-variants.asciidoc | 34 +-- .../gremlin/process/traversal/GremlinLang.java | 4 +- .../types/ProviderDefinedTypeSerializer.java | 12 +- .../io/graphson/PdtGraphSONSerializersV4.java | 2 +- .../structure/io/pdt/ProviderDefinedType.java | 31 +-- .../io/pdt/ProviderDefinedTypeAdapter.java | 6 +- .../io/pdt/ProviderDefinedTypeRegistry.java | 16 +- .../grammar/GeneralLiteralVisitorTest.java | 6 +- .../gremlin/process/traversal/GremlinLangTest.java | 4 +- .../gremlin/structure/io/binary/HeapBuffer.java | 230 --------------------- .../io/graphson/PdtGraphSONSerializersV4Test.java | 30 +-- .../io/pdt/ProviderDefinedTypeRegistryTest.java | 24 +-- .../structure/io/pdt/ProviderDefinedTypeTest.java | 46 ++--- .../Gremlin.Net/Process/Traversal/GremlinLang.cs | 8 +- .../GraphBinary4/Types/CompositePDTSerializer.cs | 10 +- .../Structure/IProviderDefinedTypeAdapter.cs | 8 +- .../Structure/ProviderDefinedAttribute.cs | 2 +- .../Gremlin.Net/Structure/ProviderDefinedType.cs | 20 +- .../Structure/ProviderDefinedTypeRegistry.cs | 18 +- .../Driver/DriverRemoteConnectionTests.cs | 12 +- .../Driver/GremlinClientTests.cs | 26 +-- .../Process/Traversal/GremlinLangTests.cs | 6 +- .../IO/GraphBinary4/ProviderDefinedTypeTests.cs | 6 +- .../Structure/ProviderDefinedTypeRegistryTests.cs | 30 +-- .../driver/remote/DriverRemoteConnection.java | 5 +- gremlin-go/driver/client_test.go | 24 +-- gremlin-go/driver/graphBinaryDeserializer.go | 4 +- gremlin-go/driver/graphBinarySerializer_test.go | 28 +-- gremlin-go/driver/gremlinlang.go | 8 +- gremlin-go/driver/gremlinlang_test.go | 14 +- gremlin-go/driver/pdtRegistry.go | 22 +- gremlin-go/driver/pdtRegistry_test.go | 12 +- gremlin-go/driver/providerDefinedType.go | 14 +- gremlin-go/driver/providerDefinedType_test.go | 4 +- gremlin-go/driver/traversal_test.go | 6 +- .../python/gremlin_python/process/traversal.py | 2 +- .../main/python/gremlin_python/structure/graph.py | 26 +-- .../gremlin_python/structure/io/graphbinaryV4.py | 8 +- .../tests/unit/structure/io/test_graphbinaryV4.py | 12 +- .../structure/io/test_provider_defined_type.py | 6 +- .../gremlin/server/GremlinDriverIntegrateTest.java | 12 +- .../GremlinServerSerializationIntegrateTest.java | 22 +- .../util/ser/GraphBinaryMessageSerializerV4.java | 13 +- .../binary/GraphBinaryPdtSpiAutoWiringTest.java | 134 ++++++++++++ .../util/ser}/binary/GraphBinaryWriterPdtTest.java | 18 +- .../gremlin/util/ser/binary/TestPointAdapter.java | 63 ++++++ .../types/ProviderDefinedTypeSerializerTest.java | 23 ++- ...lin.structure.io.pdt.ProviderDefinedTypeAdapter | 1 + 49 files changed, 537 insertions(+), 553 deletions(-) diff --git a/docs/src/dev/provider/index.asciidoc b/docs/src/dev/provider/index.asciidoc index 511e6a67cd..59c1b32ca1 100644 --- a/docs/src/dev/provider/index.asciidoc +++ b/docs/src/dev/provider/index.asciidoc @@ -1426,13 +1426,13 @@ public class ColorAdapter implements ProviderDefinedTypeAdapter<java.awt.Color> public Class<java.awt.Color> targetClass() { return java.awt.Color.class; } @Override - public Map<String, Object> toProperties(java.awt.Color color) { + public Map<String, Object> toFields(java.awt.Color color) { return Map.of("r", color.getRed(), "g", color.getGreen(), "b", color.getBlue(), "a", color.getAlpha()); } @Override - public java.awt.Color fromProperties(Map<String, Object> fields) { + public java.awt.Color fromFields(Map<String, Object> fields) { return new java.awt.Color((int) fields.get("r"), (int) fields.get("g"), (int) fields.get("b"), (int) fields.get("a")); } @@ -1461,12 +1461,12 @@ annotation to derive the type name and field mapping automatically: [source,java] ---- -ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.build(); +ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.create(); registry.register(Point.class, Address.class, Person.class); ---- Adapter types (for classes you don't own) are discovered automatically via `ServiceLoader` when using -`ProviderDefinedTypeRegistry.build()`. Register them by adding a file at: +`ProviderDefinedTypeRegistry.create()`. Register them by adding a file at: ---- META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter @@ -1485,9 +1485,9 @@ definition time (import time), so any annotated type round-trips without any add ===== .NET -`[ProviderDefined]`-annotated types are discovered automatically. Calling `ProviderDefinedTypeRegistry.Build()` +`[ProviderDefined]`-annotated types are discovered automatically. Calling `ProviderDefinedTypeRegistry.Create()` scans all loaded assemblies for `[ProviderDefined]`-annotated types and registers them for hydration. No extra -configuration is needed — providers simply annotate their types and users call `Build()` to create the registry. +configuration is needed — providers simply annotate their types and users call `Create()` to create the registry. ===== JavaScript @@ -1524,7 +1524,7 @@ the registry is populated: // In the provider's client library public class MyGraphTypeRegistry { public static ProviderDefinedTypeRegistry build() { - ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.build(); // discovers ServiceLoader adapters + ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.create(); // discovers ServiceLoader adapters registry.register(Point.class, Address.class, Person.class); // registers annotated types return registry; } @@ -1549,7 +1549,7 @@ each language driver. ==== JPMS Considerations Annotation-based PDT hydration uses reflection internally — specifically `Constructor.setAccessible(true)` and -`Field.set()` on the provider's annotated class (see `AnnotatedTypeAdapter.fromProperties` in +`Field.set()` on the provider's annotated class (see `AnnotatedTypeAdapter.fromFields` in `ProviderDefinedTypeRegistry`). Under the Java Platform Module System (JPMS), this means the provider's module must `opens` its PDT package to `org.apache.tinkerpop.gremlin.core` (or to `ALL-UNNAMED` for classpath usage), otherwise the JVM will throw `InaccessibleObjectException` at hydration time. @@ -1569,7 +1569,7 @@ Alternatively, providers that cannot modify their module descriptor can pass JVM ---- NOTE: This only applies to annotation-based hydration. Providers using `ProviderDefinedTypeAdapter` with explicit -`fromProperties` logic do not require reflective access and are unaffected by JPMS restrictions. +`fromFields` logic do not require reflective access and are unaffected by JPMS restrictions. [[gremlin-plugins]] == Gremlin Plugins diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc index 2583e93ebf..38c252a5b2 100644 --- a/docs/src/reference/gremlin-variants.asciidoc +++ b/docs/src/reference/gremlin-variants.asciidoc @@ -627,8 +627,8 @@ Consult your graph provider's documentation for the list of PDTs they support. ---- results, err := g.V().Has("location").Values("location").ToList() pdt := results[0].GetInterface().(*gremlingo.ProviderDefinedType) -fmt.Println(pdt.Name) // "x:Point" -fmt.Println(pdt.Properties) // map[x:1.0 y:2.0] +fmt.Println(pdt.Name) // "x:Point" +fmt.Println(pdt.Fields) // map[x:1.0 y:2.0] ---- Working with raw `*ProviderDefinedType` values is always available. Using a `PDTRegistry` is an optional @@ -1560,7 +1560,7 @@ Receiving a raw PDT: ---- ProviderDefinedType pdt = (ProviderDefinedType) g.V().has("location").values("location").next(); String typeName = pdt.getName(); // "x:Point" -Map<String, Object> props = pdt.getProperties(); // {x: 1.0, y: 2.0} +Map<String, Object> fields = pdt.getFields(); // {x: 1.0, y: 2.0} ---- Working with raw `ProviderDefinedType` objects is always available. The following two approaches are optional @@ -1571,8 +1571,8 @@ Using a `ProviderDefinedTypeRegistry` for hydration and dehydration: public class PointAdapter implements ProviderDefinedTypeAdapter<Point> { @Override public String typeName() { return "x:Point"; } @Override public Class<Point> targetClass() { return Point.class; } - @Override public Map<String, Object> toProperties(Point p) { return Map.of("x", p.getX(), "y", p.getY()); } - @Override public Point fromProperties(Map<String, Object> m) { return new Point((double) m.get("x"), (double) m.get("y")); } + @Override public Map<String, Object> toFields(Point p) { return Map.of("x", p.getX(), "y", p.getY()); } + @Override public Point fromFields(Map<String, Object> m) { return new Point((double) m.get("x"), (double) m.get("y")); } } ---- @@ -2224,8 +2224,8 @@ Receiving a raw PDT: ---- const results = await g.V().has('location').values('location').toList(); const pdt = results[0]; -console.log(pdt.name); // "x:Point" -console.log(pdt.properties); // { x: 1.0, y: 2.0 } +console.log(pdt.name); // "x:Point" +console.log(pdt.fields); // { x: 1.0, y: 2.0 } ---- Working with raw `ProviderDefinedType` objects is always available. Using a `ProviderDefinedTypeRegistry` is an @@ -2707,8 +2707,8 @@ Receiving a raw PDT: [source,csharp] ---- var pdt = (ProviderDefinedType) g.V().Has("location").Values<object>("location").Next(); -Console.WriteLine(pdt.Name); // "x:Point" -Console.WriteLine(pdt.Properties); // { x: 1.0, y: 2.0 } +Console.WriteLine(pdt.Name); // "x:Point" +Console.WriteLine(pdt.Fields); // { x: 1.0, y: 2.0 } ---- Working with raw `ProviderDefinedType` objects is always available. The following two approaches are optional @@ -2722,10 +2722,10 @@ public class PointAdapter : IProviderDefinedTypeAdapter<Point> { public string TypeName => "x:Point"; - public Point FromProperties(IReadOnlyDictionary<string, object?> properties) => - new Point((double)properties["x"], (double)properties["y"]); + public Point FromFields(IReadOnlyDictionary<string, object?> fields) => + new Point((double)fields["x"], (double)fields["y"]); - public IReadOnlyDictionary<string, object?> ToProperties(Point value) => + public IReadOnlyDictionary<string, object?> ToFields(Point value) => new Dictionary<string, object?> { ["x"] = value.X, ["y"] = value.Y }; } @@ -2735,7 +2735,7 @@ registry.Register(new PointAdapter()); using var client = new GremlinClient(new GremlinServer("localhost", 8182), pdtRegistry: registry); ---- -The `ProviderDefinedTypeRegistry.Build()` method scans loaded assemblies for `IProviderDefinedTypeAdapter<T>` +The `ProviderDefinedTypeRegistry.Create()` method scans loaded assemblies for `IProviderDefinedTypeAdapter<T>` implementations and registers them automatically. For simpler cases where you own the type, annotate it directly to avoid writing an adapter: @@ -3345,8 +3345,8 @@ Receiving a raw PDT: [source,python] ---- pdt = g.V().has('location').values('location').next() -print(pdt.name) # "x:Point" -print(pdt.properties) # {'x': 1.0, 'y': 2.0} +print(pdt.name) # "x:Point" +print(pdt.fields) # {'x': 1.0, 'y': 2.0} ---- Working with raw `ProviderDefinedType` objects is always available. The following two approaches are optional @@ -3360,7 +3360,7 @@ from gremlin_python.structure.graph import ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry() registry.register('x:Point', - deserialize_fn=lambda props: Point(props['x'], props['y']), + deserialize_fn=lambda fields: Point(fields['x'], fields['y']), serialize_fn=lambda p: {'x': p.x, 'y': p.y}, target_class=Point) @@ -3368,7 +3368,7 @@ g = traversal().with_(DriverRemoteConnection('http://localhost:8182/gremlin', 'g pdt_registry=registry)) ---- -The `ProviderDefinedTypeRegistry.build()` class method discovers adapters via `entry_points` in `pyproject.toml` +The `ProviderDefinedTypeRegistry.create()` class method discovers adapters via `entry_points` in `pyproject.toml` under the `tinkerpop.pdt` group. For simpler cases where you own the type, the `@provider_defined` decorator enables automatic round-trip conversion 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 3e651be971..1edc6217d7 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 @@ -191,7 +191,7 @@ public class GremlinLang implements Cloneable, Serializable { if (arg instanceof ProviderDefinedType) { final ProviderDefinedType pdt = (ProviderDefinedType) arg; - return "PDT(" + argAsString(pdt.getName()) + "," + asString((Map<?, ?>) pdt.getProperties()) + ")"; + return "PDT(" + argAsString(pdt.getName()) + "," + asString((Map<?, ?>) pdt.getFields()) + ")"; } if (arg instanceof Enum) { @@ -273,7 +273,7 @@ public class GremlinLang implements Cloneable, Serializable { final Optional<ProviderDefinedTypeAdapter<?>> adapter = pdtRegistry.getAdapterByClass(arg.getClass()); if (adapter.isPresent()) { @SuppressWarnings("unchecked") - final Map<String, Object> props = ((ProviderDefinedTypeAdapter) adapter.get()).toProperties(arg); + final Map<String, Object> props = ((ProviderDefinedTypeAdapter) adapter.get()).toFields(arg); return argAsString(new ProviderDefinedType(adapter.get().typeName(), props)); } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java index d45b4cf2a9..a833d2d46a 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializer.java @@ -38,19 +38,19 @@ public class ProviderDefinedTypeSerializer extends SimpleTypeSerializer<Provider final String name = context.read(buffer); if (name == null || name.isEmpty()) throw new IOException("ProviderDefinedType name cannot be null or empty"); - final Map<?, ?> properties = context.read(buffer); - for (final Object key : properties.keySet()) { + final Map<?, ?> fields = context.read(buffer); + for (final Object key : fields.keySet()) { if (!(key instanceof String)) - throw new IOException("ProviderDefinedType properties map must have String keys, found: " + key.getClass().getName()); + throw new IOException("ProviderDefinedType fields map must have String keys, found: " + key.getClass().getName()); } @SuppressWarnings("unchecked") - final Map<String, Object> typedProperties = (Map<String, Object>) (Map<?, ?>) properties; - return new ProviderDefinedType(name, typedProperties); + final Map<String, Object> typedFields = (Map<String, Object>) (Map<?, ?>) fields; + return new ProviderDefinedType(name, typedFields); } @Override protected void writeValue(final ProviderDefinedType value, final Buffer buffer, final GraphBinaryWriter context) throws IOException { context.write(value.getName(), buffer); - context.write(value.getProperties(), buffer); + context.write(value.getFields(), buffer); } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java index fb4cd848a3..de116f54aa 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4.java @@ -53,7 +53,7 @@ final class PdtGraphSONSerializersV4 { jsonGenerator.writeStringField("type", pdt.getName()); jsonGenerator.writeFieldName("fields"); jsonGenerator.writeStartObject(); - for (final Map.Entry<String, Object> entry : pdt.getProperties().entrySet()) { + for (final Map.Entry<String, Object> entry : pdt.getFields().entrySet()) { jsonGenerator.writeFieldName(entry.getKey()); jsonGenerator.writeObject(entry.getValue()); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java index 3a67209db9..391d06fd94 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedType.java @@ -31,23 +31,23 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; /** - * An immutable representation of a provider-defined type consisting of a name and a map of properties. + * An immutable representation of a provider-defined type consisting of a name and a map of fields. */ public final class ProviderDefinedType { private static final ConcurrentHashMap<Class<?>, FieldCache> FIELD_CACHE = new ConcurrentHashMap<>(); private final String name; - private final Map<String, Object> properties; + private final Map<String, Object> fields; private Object hydrated; - public ProviderDefinedType(final String name, final Map<String, Object> properties) { + public ProviderDefinedType(final String name, final Map<String, Object> fields) { if (name == null || name.isEmpty()) throw new IllegalArgumentException("name cannot be null or empty"); - if (properties == null) - throw new IllegalArgumentException("properties cannot be null"); + if (fields == null) + throw new IllegalArgumentException("fields cannot be null"); this.name = name; - this.properties = Collections.unmodifiableMap(new LinkedHashMap<>(properties)); + this.fields = Collections.unmodifiableMap(new LinkedHashMap<>(fields)); } /** @@ -139,15 +139,15 @@ public final class ProviderDefinedType { return name; } - public Map<String, Object> getProperties() { - return properties; + public Map<String, Object> getFields() { + return fields; } /** * Returns a copy of this PDT with the hydrated object attached. */ public ProviderDefinedType withHydrated(final Object hydrated) { - final ProviderDefinedType copy = new ProviderDefinedType(this.name, this.properties); + final ProviderDefinedType copy = new ProviderDefinedType(this.name, this.fields); copy.hydrated = hydrated; return copy; } @@ -159,21 +159,28 @@ public final class ProviderDefinedType { return hydrated; } + /** + * Equality is based solely on {@code name} and {@code fields} (the serialized wire form). + * The {@code hydrated} field is intentionally excluded — it is a transient, derived view + * cached by the deserializer via {@link #withHydrated(Object)} and is not part of the + * type's logical identity. + */ @Override public boolean equals(final Object o) { if (this == o) return true; if (!(o instanceof ProviderDefinedType)) return false; final ProviderDefinedType that = (ProviderDefinedType) o; - return name.equals(that.name) && properties.equals(that.properties); + return name.equals(that.name) && fields.equals(that.fields); } + /** See {@link #equals(Object)} for rationale on field inclusion. */ @Override public int hashCode() { - return Objects.hash(name, properties); + return Objects.hash(name, fields); } @Override public String toString() { - return "pdt[" + name + "]" + properties; + return "pdt[" + name + "]" + fields; } } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java index 86880a0584..701fba0d49 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeAdapter.java @@ -21,11 +21,11 @@ package org.apache.tinkerpop.gremlin.structure.io.pdt; import java.util.Map; /** - * Adapter for converting between a typed object and a {@link ProviderDefinedType} property map. + * Adapter for converting between a typed object and a {@link ProviderDefinedType} field map. */ public interface ProviderDefinedTypeAdapter<T> { String typeName(); Class<T> targetClass(); - Map<String, Object> toProperties(T obj); - T fromProperties(Map<String, Object> properties); + Map<String, Object> toFields(T obj); + T fromFields(Map<String, Object> fields); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java index 10d63bc92f..015b2ffee0 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistry.java @@ -49,7 +49,7 @@ public final class ProviderDefinedTypeRegistry { * Creates a registry populated via {@link ServiceLoader} discovery. */ @SuppressWarnings("rawtypes") - public static ProviderDefinedTypeRegistry build() { + public static ProviderDefinedTypeRegistry create() { final ProviderDefinedTypeRegistry registry = new ProviderDefinedTypeRegistry(); for (final ProviderDefinedTypeAdapter adapter : ServiceLoader.load(ProviderDefinedTypeAdapter.class)) { registry.register(adapter); @@ -101,14 +101,14 @@ public final class ProviderDefinedTypeRegistry { if (adapter == null) return pdt; - // recursively hydrate nested PDTs in the properties map + // recursively hydrate nested PDTs in the fields map final Map<String, Object> hydrated = new LinkedHashMap<>(); - for (final Map.Entry<String, Object> entry : pdt.getProperties().entrySet()) { + for (final Map.Entry<String, Object> entry : pdt.getFields().entrySet()) { hydrated.put(entry.getKey(), hydrateValue(entry.getValue())); } try { - return adapter.fromProperties(hydrated); + return adapter.fromFields(hydrated); } catch (final Exception e) { logger.warn("Failed to hydrate ProviderDefinedType '{}', returning raw PDT: {}", pdt.getName(), e.getMessage()); @@ -176,18 +176,18 @@ public final class ProviderDefinedTypeRegistry { @Override public Class<T> targetClass() { return targetClass; } @Override - public Map<String, Object> toProperties(final T obj) { - return ProviderDefinedType.from(obj).getProperties(); + public Map<String, Object> toFields(final T obj) { + return ProviderDefinedType.from(obj).getFields(); } @Override - public T fromProperties(final Map<String, Object> properties) { + public T fromFields(final Map<String, Object> fieldMap) { try { final java.lang.reflect.Constructor<T> ctor = targetClass.getDeclaredConstructor(); ctor.setAccessible(true); final T obj = ctor.newInstance(); for (final Field field : fields) { - final Object value = properties.get(field.getName()); + final Object value = fieldMap.get(field.getName()); if (value != null) field.set(obj, coerce(value, field.getType())); } 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 953565679b..67bf4ffef0 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 @@ -1061,8 +1061,8 @@ public class GeneralLiteralVisitorTest { assertThat(result, instanceOf(ProviderDefinedType.class)); final ProviderDefinedType pdt = (ProviderDefinedType) result; assertEquals("MyType", pdt.getName()); - assertEquals(1, pdt.getProperties().get("x")); - assertEquals("hello", pdt.getProperties().get("y")); + assertEquals(1, pdt.getFields().get("x")); + assertEquals("hello", pdt.getFields().get("y")); } @Test @@ -1074,7 +1074,7 @@ public class GeneralLiteralVisitorTest { assertThat(result, instanceOf(ProviderDefinedType.class)); final ProviderDefinedType pdt = (ProviderDefinedType) result; assertEquals("Empty", pdt.getName()); - assertTrue(pdt.getProperties().isEmpty()); + assertTrue(pdt.getFields().isEmpty()); } @Test 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 24988ed084..1164a5610d 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 @@ -473,10 +473,10 @@ public class GremlinLangTest { registry.register(new ProviderDefinedTypeAdapter<DualType>() { @Override public String typeName() { return "AdapterName"; } @Override public Class<DualType> targetClass() { return DualType.class; } - @Override public Map<String, Object> toProperties(final DualType obj) { + @Override public Map<String, Object> toFields(final DualType obj) { return Collections.singletonMap("v", obj.value); } - @Override public DualType fromProperties(final Map<String, Object> properties) { + @Override public DualType fromFields(final Map<String, Object> properties) { return new DualType((int) properties.get("v")); } }); diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/HeapBuffer.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/HeapBuffer.java deleted file mode 100644 index e7f090cd1b..0000000000 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/HeapBuffer.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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; - -import org.apache.tinkerpop.gremlin.structure.io.Buffer; - -import java.io.IOException; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; - -/** - * A simple heap-based {@link Buffer} implementation for unit testing in gremlin-core. - */ -public class HeapBuffer implements Buffer { - private byte[] data; - private int readerIndex; - private int writerIndex; - private int markedWriterIndex; - - public HeapBuffer(final int initialCapacity) { - this.data = new byte[initialCapacity]; - } - - public static HeapBuffer allocate(final int capacity) { - return new HeapBuffer(capacity); - } - - private void ensureCapacity(final int needed) { - if (writerIndex + needed > data.length) { - data = Arrays.copyOf(data, Math.max(data.length * 2, writerIndex + needed)); - } - } - - @Override public int readableBytes() { return writerIndex - readerIndex; } - @Override public int readerIndex() { return readerIndex; } - @Override public Buffer readerIndex(final int readerIndex) { this.readerIndex = readerIndex; return this; } - @Override public int writerIndex() { return writerIndex; } - @Override public Buffer writerIndex(final int writerIndex) { this.writerIndex = writerIndex; return this; } - @Override public Buffer markWriterIndex() { this.markedWriterIndex = writerIndex; return this; } - @Override public Buffer resetWriterIndex() { this.writerIndex = markedWriterIndex; return this; } - @Override public int capacity() { return data.length; } - @Override public boolean isDirect() { return false; } - - @Override - public boolean readBoolean() { return readByte() != 0; } - - @Override - public byte readByte() { return data[readerIndex++]; } - - @Override - public short readShort() { - short v = (short) ((data[readerIndex] & 0xFF) << 8 | (data[readerIndex + 1] & 0xFF)); - readerIndex += 2; - return v; - } - - @Override - public int readInt() { - int v = (data[readerIndex] & 0xFF) << 24 | (data[readerIndex + 1] & 0xFF) << 16 | - (data[readerIndex + 2] & 0xFF) << 8 | (data[readerIndex + 3] & 0xFF); - readerIndex += 4; - return v; - } - - @Override - public long readLong() { - long v = ((long)(data[readerIndex] & 0xFF) << 56) | ((long)(data[readerIndex+1] & 0xFF) << 48) | - ((long)(data[readerIndex+2] & 0xFF) << 40) | ((long)(data[readerIndex+3] & 0xFF) << 32) | - ((long)(data[readerIndex+4] & 0xFF) << 24) | ((long)(data[readerIndex+5] & 0xFF) << 16) | - ((long)(data[readerIndex+6] & 0xFF) << 8) | ((long)(data[readerIndex+7] & 0xFF)); - readerIndex += 8; - return v; - } - - @Override - public float readFloat() { return Float.intBitsToFloat(readInt()); } - - @Override - public double readDouble() { return Double.longBitsToDouble(readLong()); } - - @Override - public Buffer readBytes(final byte[] destination) { - System.arraycopy(data, readerIndex, destination, 0, destination.length); - readerIndex += destination.length; - return this; - } - - @Override - public Buffer readBytes(final byte[] destination, final int dstIndex, final int length) { - System.arraycopy(data, readerIndex, destination, dstIndex, length); - readerIndex += length; - return this; - } - - @Override - public Buffer readBytes(final ByteBuffer dst) { - int len = dst.remaining(); - dst.put(data, readerIndex, len); - readerIndex += len; - return this; - } - - @Override - public Buffer readBytes(final OutputStream out, final int length) throws IOException { - out.write(data, readerIndex, length); - readerIndex += length; - return this; - } - - @Override - public Buffer writeBoolean(final boolean value) { return writeByte(value ? 1 : 0); } - - @Override - public Buffer writeByte(final int value) { - ensureCapacity(1); - data[writerIndex++] = (byte) value; - return this; - } - - @Override - public Buffer writeShort(final int value) { - ensureCapacity(2); - data[writerIndex++] = (byte) (value >>> 8); - data[writerIndex++] = (byte) value; - return this; - } - - @Override - public Buffer writeInt(final int value) { - ensureCapacity(4); - data[writerIndex++] = (byte) (value >>> 24); - data[writerIndex++] = (byte) (value >>> 16); - data[writerIndex++] = (byte) (value >>> 8); - data[writerIndex++] = (byte) value; - return this; - } - - @Override - public Buffer writeLong(final long value) { - ensureCapacity(8); - data[writerIndex++] = (byte) (value >>> 56); - data[writerIndex++] = (byte) (value >>> 48); - data[writerIndex++] = (byte) (value >>> 40); - data[writerIndex++] = (byte) (value >>> 32); - data[writerIndex++] = (byte) (value >>> 24); - data[writerIndex++] = (byte) (value >>> 16); - data[writerIndex++] = (byte) (value >>> 8); - data[writerIndex++] = (byte) value; - return this; - } - - @Override - public Buffer writeFloat(final float value) { return writeInt(Float.floatToIntBits(value)); } - - @Override - public Buffer writeDouble(final double value) { return writeLong(Double.doubleToLongBits(value)); } - - @Override - public Buffer writeBytes(final byte[] src) { - ensureCapacity(src.length); - System.arraycopy(src, 0, data, writerIndex, src.length); - writerIndex += src.length; - return this; - } - - @Override - public Buffer writeBytes(final ByteBuffer src) { - int len = src.remaining(); - ensureCapacity(len); - src.get(data, writerIndex, len); - writerIndex += len; - return this; - } - - @Override - public Buffer writeBytes(final byte[] src, final int srcIndex, final int length) { - ensureCapacity(length); - System.arraycopy(src, srcIndex, data, writerIndex, length); - writerIndex += length; - return this; - } - - @Override public boolean release() { return true; } - @Override public Buffer retain() { return this; } - @Override public int referenceCount() { return 1; } - @Override public int nioBufferCount() { return 1; } - - @Override - public ByteBuffer[] nioBuffers() { - return new ByteBuffer[] { nioBuffer() }; - } - - @Override - public ByteBuffer[] nioBuffers(final int index, final int length) { - return new ByteBuffer[] { nioBuffer(index, length) }; - } - - @Override - public ByteBuffer nioBuffer() { - return ByteBuffer.wrap(data, readerIndex, readableBytes()).slice(); - } - - @Override - public ByteBuffer nioBuffer(final int index, final int length) { - return ByteBuffer.wrap(data, index, length).slice(); - } - - @Override - public Buffer getBytes(final int index, final byte[] dst) { - System.arraycopy(data, index, dst, 0, dst.length); - return this; - } -} diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java index 67786dbcd8..1b54c39b39 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/PdtGraphSONSerializersV4Test.java @@ -80,9 +80,9 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { final ProviderDefinedType pdt = mapper.readValue(json, ProviderDefinedType.class); assertEquals("Point", pdt.getName()); - assertEquals(2, pdt.getProperties().size()); - assertEquals(1, pdt.getProperties().get("x")); - assertEquals(2, pdt.getProperties().get("y")); + assertEquals(2, pdt.getFields().size()); + assertEquals(1, pdt.getFields().get("x")); + assertEquals(2, pdt.getFields().get("y")); } @Test @@ -95,7 +95,7 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { final ProviderDefinedType result = serializeDeserialize(mapper, original, ProviderDefinedType.class); assertEquals(original.getName(), result.getName()); - assertEquals(original.getProperties(), result.getProperties()); + assertEquals(original.getFields(), result.getFields()); } @Test @@ -122,11 +122,11 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { // round-trip nested final ProviderDefinedType result = serializeDeserialize(mapper, outer, ProviderDefinedType.class); assertEquals("NamedPoint", result.getName()); - assertTrue(result.getProperties().get("location") instanceof ProviderDefinedType); - final ProviderDefinedType nestedResult = (ProviderDefinedType) result.getProperties().get("location"); + assertTrue(result.getFields().get("location") instanceof ProviderDefinedType); + final ProviderDefinedType nestedResult = (ProviderDefinedType) result.getFields().get("location"); assertEquals("Point", nestedResult.getName()); - assertEquals(10, nestedResult.getProperties().get("x")); - assertEquals(20, nestedResult.getProperties().get("y")); + assertEquals(10, nestedResult.getFields().get("x")); + assertEquals(20, nestedResult.getFields().get("y")); } @Test @@ -139,9 +139,9 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { final ProviderDefinedType result = serializeDeserialize(mapper, pdt, ProviderDefinedType.class); assertEquals("NullableType", result.getName()); - assertEquals("test", result.getProperties().get("name")); - assertNull(result.getProperties().get("value")); - assertTrue(result.getProperties().containsKey("value")); + assertEquals("test", result.getFields().get("name")); + assertNull(result.getFields().get("value")); + assertTrue(result.getFields().containsKey("value")); } // --- Hydration tests --- @@ -155,13 +155,13 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { static class PointAdapter implements ProviderDefinedTypeAdapter<Point> { @Override public String typeName() { return "Point"; } @Override public Class<Point> targetClass() { return Point.class; } - @Override public Map<String, Object> toProperties(Point obj) { + @Override public Map<String, Object> toFields(Point obj) { final Map<String, Object> m = new HashMap<>(); m.put("x", obj.x); m.put("y", obj.y); return m; } - @Override public Point fromProperties(Map<String, Object> properties) { + @Override public Point fromFields(Map<String, Object> properties) { return new Point((int) properties.get("x"), (int) properties.get("y")); } } @@ -202,7 +202,7 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { assertNull(result.getHydrated()); assertEquals("Point", result.getName()); - assertEquals(1, result.getProperties().get("x")); + assertEquals(1, result.getFields().get("x")); } @Test @@ -225,6 +225,6 @@ public class PdtGraphSONSerializersV4Test extends AbstractGraphSONTest { assertNull(result.getHydrated()); assertEquals("Unknown", result.getName()); - assertEquals(1, result.getProperties().get("a")); + assertEquals(1, result.getFields().get("a")); } } diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java index 13f9a05b59..acc2b01174 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeRegistryTest.java @@ -43,13 +43,13 @@ public class ProviderDefinedTypeRegistryTest { static class PointAdapter implements ProviderDefinedTypeAdapter<Point> { @Override public String typeName() { return "Point"; } @Override public Class<Point> targetClass() { return Point.class; } - @Override public Map<String, Object> toProperties(Point obj) { + @Override public Map<String, Object> toFields(Point obj) { final Map<String, Object> m = new HashMap<>(); m.put("x", obj.x); m.put("y", obj.y); return m; } - @Override public Point fromProperties(Map<String, Object> properties) { + @Override public Point fromFields(Map<String, Object> properties) { return new Point((int) properties.get("x"), (int) properties.get("y")); } } @@ -64,13 +64,13 @@ public class ProviderDefinedTypeRegistryTest { static class LineAdapter implements ProviderDefinedTypeAdapter<Line> { @Override public String typeName() { return "Line"; } @Override public Class<Line> targetClass() { return Line.class; } - @Override public Map<String, Object> toProperties(Line obj) { + @Override public Map<String, Object> toFields(Line obj) { final Map<String, Object> m = new HashMap<>(); m.put("start", obj.start); m.put("end", obj.end); return m; } - @Override public Line fromProperties(Map<String, Object> properties) { + @Override public Line fromFields(Map<String, Object> properties) { return new Line((Point) properties.get("start"), (Point) properties.get("end")); } } @@ -79,8 +79,8 @@ public class ProviderDefinedTypeRegistryTest { static class FailingAdapter implements ProviderDefinedTypeAdapter<Point> { @Override public String typeName() { return "Failing"; } @Override public Class<Point> targetClass() { return Point.class; } - @Override public Map<String, Object> toProperties(Point obj) { return new HashMap<>(); } - @Override public Point fromProperties(Map<String, Object> properties) { + @Override public Map<String, Object> toFields(Point obj) { return new HashMap<>(); } + @Override public Point fromFields(Map<String, Object> properties) { throw new RuntimeException("intentional failure"); } } @@ -162,7 +162,7 @@ public class ProviderDefinedTypeRegistryTest { final ProviderDefinedType linePdt = new ProviderDefinedType("Line", lineProps); // Line adapter will receive ProviderDefinedType values for start/end since Point is not registered. - // The LineAdapter.fromProperties casts to Point which will throw ClassCastException, + // The LineAdapter.fromFields casts to Point which will throw ClassCastException, // so hydrate should fall back to returning the raw PDT. final Object result = registry.hydrate(linePdt); assertSame(linePdt, result); @@ -202,13 +202,13 @@ public class ProviderDefinedTypeRegistryTest { static class PolygonAdapter implements ProviderDefinedTypeAdapter<Polygon> { @Override public String typeName() { return "Polygon"; } @Override public Class<Polygon> targetClass() { return Polygon.class; } - @Override public Map<String, Object> toProperties(Polygon obj) { + @Override public Map<String, Object> toFields(Polygon obj) { final Map<String, Object> m = new HashMap<>(); m.put("vertices", obj.vertices); return m; } @SuppressWarnings("unchecked") - @Override public Polygon fromProperties(Map<String, Object> properties) { + @Override public Polygon fromFields(Map<String, Object> properties) { return new Polygon((List<Point>) properties.get("vertices")); } } @@ -249,9 +249,9 @@ public class ProviderDefinedTypeRegistryTest { registry.register(new ProviderDefinedTypeAdapter<Map>() { @Override public String typeName() { return "PointMap"; } @Override public Class<Map> targetClass() { return Map.class; } - @Override public Map<String, Object> toProperties(Map obj) { return new HashMap<>(); } + @Override public Map<String, Object> toFields(Map obj) { return new HashMap<>(); } @SuppressWarnings("unchecked") - @Override public Map fromProperties(Map<String, Object> properties) { + @Override public Map fromFields(Map<String, Object> properties) { return (Map<String, Object>) properties.get("points"); } }); @@ -283,7 +283,7 @@ public class ProviderDefinedTypeRegistryTest { public void shouldBuildViaServiceLoader() { // ServiceLoader.load will find adapters on the classpath. With no META-INF/services file // in test scope, this should produce an empty registry that still functions. - final ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.build(); + final ProviderDefinedTypeRegistry registry = ProviderDefinedTypeRegistry.create(); final Map<String, Object> props = new HashMap<>(); props.put("x", 1); diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java index 2c153700c8..d39d152951 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java +++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/pdt/ProviderDefinedTypeTest.java @@ -99,7 +99,7 @@ public class ProviderDefinedTypeTest { props.put("y", 2); final ProviderDefinedType pdt = new ProviderDefinedType("Point", props); assertEquals("Point", pdt.getName()); - assertEquals(props, pdt.getProperties()); + assertEquals(props, pdt.getFields()); } @Test @@ -108,7 +108,7 @@ public class ProviderDefinedTypeTest { props.put("x", 1); final ProviderDefinedType pdt = new ProviderDefinedType("Point", props); props.put("y", 2); - assertEquals(1, pdt.getProperties().size()); + assertEquals(1, pdt.getFields().size()); } @Test @@ -116,15 +116,15 @@ public class ProviderDefinedTypeTest { final Map<String, Object> props = new HashMap<>(); props.put("x", 1); final ProviderDefinedType pdt = new ProviderDefinedType("Point", props); - assertThrows(UnsupportedOperationException.class, () -> pdt.getProperties().put("y", 2)); + assertThrows(UnsupportedOperationException.class, () -> pdt.getFields().put("y", 2)); } @Test public void shouldCreateFromAnnotatedObject() { final ProviderDefinedType pdt = ProviderDefinedType.from(new Point()); assertEquals("Point", pdt.getName()); - assertEquals(1, pdt.getProperties().get("x")); - assertEquals(2, pdt.getProperties().get("y")); + assertEquals(1, pdt.getFields().get("x")); + assertEquals(2, pdt.getFields().get("y")); } @Test @@ -136,16 +136,16 @@ public class ProviderDefinedTypeTest { @Test public void shouldFilterWithIncludedFields() { final ProviderDefinedType pdt = ProviderDefinedType.from(new IncludedFieldsPoint()); - assertEquals(1, pdt.getProperties().size()); - assertEquals(10, pdt.getProperties().get("x")); + assertEquals(1, pdt.getFields().size()); + assertEquals(10, pdt.getFields().get("x")); } @Test public void shouldFilterWithExcludedFields() { final ProviderDefinedType pdt = ProviderDefinedType.from(new ExcludedFieldsPoint()); - assertEquals(2, pdt.getProperties().size()); - assertEquals(10, pdt.getProperties().get("x")); - assertEquals(20, pdt.getProperties().get("y")); + assertEquals(2, pdt.getFields().size()); + assertEquals(10, pdt.getFields().get("x")); + assertEquals(20, pdt.getFields().get("y")); } @Test @@ -189,9 +189,9 @@ public class ProviderDefinedTypeTest { @Test public void shouldPreserveNullFieldValues() { final ProviderDefinedType pdt = ProviderDefinedType.from(new NullFieldPoint()); - assertEquals(2, pdt.getProperties().size()); - assertEquals(null, pdt.getProperties().get("label")); - assertEquals(5, pdt.getProperties().get("x")); + assertEquals(2, pdt.getFields().size()); + assertEquals(null, pdt.getFields().get("label")); + assertEquals(5, pdt.getFields().get("x")); } @Test @@ -203,25 +203,25 @@ public class ProviderDefinedTypeTest { public void shouldIncludeInheritedFields() { final ProviderDefinedType pdt = ProviderDefinedType.from(new InheritedPoint()); assertEquals("GeoPoint", pdt.getName()); - assertEquals(3, pdt.getProperties().size()); - assertEquals("origin", pdt.getProperties().get("label")); - assertEquals(1, pdt.getProperties().get("x")); - assertEquals(2, pdt.getProperties().get("y")); + assertEquals(3, pdt.getFields().size()); + assertEquals("origin", pdt.getFields().get("label")); + assertEquals(1, pdt.getFields().get("x")); + assertEquals(2, pdt.getFields().get("y")); } @Test public void shouldExcludeInheritedFields() { final ProviderDefinedType pdt = ProviderDefinedType.from(new InheritedExcluded()); - assertEquals(2, pdt.getProperties().size()); - assertEquals("test", pdt.getProperties().get("label")); - assertEquals(1, pdt.getProperties().get("x")); + assertEquals(2, pdt.getFields().size()); + assertEquals("test", pdt.getFields().get("label")); + assertEquals(1, pdt.getFields().get("x")); } @Test public void shouldIncludeOnlySpecifiedFieldsAcrossHierarchy() { final ProviderDefinedType pdt = ProviderDefinedType.from(new InheritedIncluded()); - assertEquals(2, pdt.getProperties().size()); - assertEquals("included", pdt.getProperties().get("label")); - assertEquals(1, pdt.getProperties().get("x")); + assertEquals(2, pdt.getFields().size()); + assertEquals("included", pdt.getFields().get("label")); + assertEquals(1, pdt.getFields().get("x")); } } diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs index bb48d96bc6..b6d1d24267 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GremlinLang.cs @@ -340,14 +340,14 @@ namespace Gremlin.Net.Process.Traversal if (arg is ProviderDefinedType pdt) { var sb2 = new StringBuilder("["); - var count = pdt.Properties.Count; + var count = pdt.Fields.Count; if (count == 0) { sb2.Append(':'); } else { - foreach (var kvp in pdt.Properties) + foreach (var kvp in pdt.Fields) { sb2.Append(ArgAsString(kvp.Key)).Append(':').Append(ArgAsString(kvp.Value)); if (--count > 0) sb2.Append(','); @@ -382,8 +382,8 @@ namespace Gremlin.Net.Process.Traversal var adapterInfo = PdtRegistry.GetAdapterByType(arg.GetType()); if (adapterInfo != null) { - var (adapterTypeName, toProperties) = adapterInfo.Value; - var props = toProperties(arg); + var (adapterTypeName, toFields) = adapterInfo.Value; + var props = toFields(arg); return ArgAsString(new ProviderDefinedType(adapterTypeName, new Dictionary<string, object?>(props))); } diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs index 49c4bdff66..10e2a082fa 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IO/GraphBinary4/Types/CompositePDTSerializer.cs @@ -47,8 +47,8 @@ namespace Gremlin.Net.Structure.IO.GraphBinary4.Types { // Write name as fully-qualified string await writer.WriteAsync(value.Name, stream, cancellationToken).ConfigureAwait(false); - // Write properties as fully-qualified map - await writer.WriteAsync((IDictionary<string, object?>)new Dictionary<string, object?>(value.Properties), + // Write fields as fully-qualified map + await writer.WriteAsync((IDictionary<string, object?>)new Dictionary<string, object?>(value.Fields), stream, cancellationToken).ConfigureAwait(false); } @@ -63,16 +63,16 @@ namespace Gremlin.Net.Structure.IO.GraphBinary4.Types var map = await reader.ReadAsync(stream, cancellationToken).ConfigureAwait(false) as IDictionary<object, object?>; - var properties = new Dictionary<string, object?>(); + var fields = new Dictionary<string, object?>(); if (map != null) { foreach (var kv in map) { - properties[(string)kv.Key] = kv.Value; + fields[(string)kv.Key] = kv.Value; } } - return new ProviderDefinedType(name!, properties); + return new ProviderDefinedType(name!, fields); } } } diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs index cd7af23e3c..89dce66cfc 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Structure/IProviderDefinedTypeAdapter.cs @@ -37,13 +37,13 @@ namespace Gremlin.Net.Structure string TypeName { get; } /// <summary> - /// Creates a typed instance from the PDT properties. + /// Creates a typed instance from the PDT fields. /// </summary> - T FromProperties(IReadOnlyDictionary<string, object?> properties); + T FromFields(IReadOnlyDictionary<string, object?> fields); /// <summary> - /// Converts a typed instance back to PDT properties. + /// Converts a typed instance back to PDT fields. /// </summary> - IReadOnlyDictionary<string, object?> ToProperties(T obj); + IReadOnlyDictionary<string, object?> ToFields(T obj); } } diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs index c7d25667e5..f9a418e01a 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedAttribute.cs @@ -67,7 +67,7 @@ namespace Gremlin.Net.Structure if (!RegisteredTypes.TryGetValue(pdt.Name, out var type)) return pdt; var obj = Activator.CreateInstance(type)!; - foreach (var (key, value) in pdt.Properties) + foreach (var (key, value) in pdt.Fields) { var prop = type.GetProperty(key, BindingFlags.Public | BindingFlags.Instance); if (prop != null && prop.CanWrite && value != null) diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs index ac6c9d60f9..69c005c188 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedType.cs @@ -28,7 +28,7 @@ using System.Linq; namespace Gremlin.Net.Structure { /// <summary> - /// Represents a provider-defined type (PDT) with a name and a set of properties. + /// Represents a provider-defined type (PDT) with a name and a set of fields. /// </summary> public class ProviderDefinedType { @@ -36,12 +36,12 @@ namespace Gremlin.Net.Structure /// Initializes a new instance of the <see cref="ProviderDefinedType"/> class. /// </summary> /// <param name="name">The fully-qualified name of the provider-defined type.</param> - /// <param name="properties">The properties of the provider-defined type.</param> - public ProviderDefinedType(string name, IReadOnlyDictionary<string, object?> properties) + /// <param name="fields">The fields of the provider-defined type.</param> + public ProviderDefinedType(string name, IReadOnlyDictionary<string, object?> fields) { Name = name ?? throw new ArgumentNullException(nameof(name)); if (string.IsNullOrEmpty(name)) throw new ArgumentException("name cannot be empty", nameof(name)); - Properties = properties ?? new Dictionary<string, object?>(); + Fields = fields ?? new Dictionary<string, object?>(); } /// <summary> @@ -50,21 +50,21 @@ namespace Gremlin.Net.Structure public string Name { get; } /// <summary> - /// Gets the properties of this provider-defined type. + /// Gets the fields of this provider-defined type. /// </summary> - public IReadOnlyDictionary<string, object?> Properties { get; } + public IReadOnlyDictionary<string, object?> Fields { get; } /// <inheritdoc /> public override string ToString() => - $"pdt[{Name}]{{{string.Join(", ", Properties.Select(kv => $"{kv.Key}={kv.Value}"))}}}"; + $"pdt[{Name}]{{{string.Join(", ", Fields.Select(kv => $"{kv.Key}={kv.Value}"))}}}"; /// <inheritdoc /> public override bool Equals(object? obj) => obj is ProviderDefinedType other && Name == other.Name && - Properties.Count == other.Properties.Count && - Properties.All(kv => other.Properties.TryGetValue(kv.Key, out var v) && Equals(kv.Value, v)); + Fields.Count == other.Fields.Count && + Fields.All(kv => other.Fields.TryGetValue(kv.Key, out var v) && Equals(kv.Value, v)); /// <inheritdoc /> - public override int GetHashCode() => HashCode.Combine(Name, Properties.Count); + public override int GetHashCode() => HashCode.Combine(Name, Fields.Count); } } diff --git a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs index b33269c98c..530c7979bf 100644 --- a/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs +++ b/gremlin-dotnet/src/Gremlin.Net/Structure/ProviderDefinedTypeRegistry.cs @@ -54,7 +54,7 @@ namespace Gremlin.Net.Structure /// <item>Types annotated with <see cref="ProviderDefinedAttribute"/> (annotation-based round-trip)</item> /// </list> /// </summary> - public static ProviderDefinedTypeRegistry Build() + public static ProviderDefinedTypeRegistry Create() { var registry = new ProviderDefinedTypeRegistry(); @@ -103,13 +103,13 @@ namespace Gremlin.Net.Structure } /// <summary> - /// Returns the type name and ToProperties method for the given CLR type, or null if not registered. + /// Returns the type name and ToFields method for the given CLR type, or null if not registered. /// </summary> internal (string typeName, Func<object, IReadOnlyDictionary<string, object?>>)? GetAdapterByType(Type type) { if (!_adaptersByType.TryGetValue(type, out var entry)) return null; - var method = entry.adapter.GetType().GetMethod("ToProperties"); + var method = entry.adapter.GetType().GetMethod("ToFields"); if (method == null) return null; return (entry.typeName, obj => (IReadOnlyDictionary<string, object?>)method.Invoke(entry.adapter, new[] { obj })!); } @@ -124,15 +124,15 @@ namespace Gremlin.Net.Structure return pdt; try { - var hydratedProps = new Dictionary<string, object?>(); - foreach (var (key, value) in pdt.Properties) + var hydratedFields = new Dictionary<string, object?>(); + foreach (var (key, value) in pdt.Fields) { - hydratedProps[key] = value is ProviderDefinedType nested ? Hydrate(nested) : value; + hydratedFields[key] = value is ProviderDefinedType nested ? Hydrate(nested) : value; } - var readOnlyProps = new ReadOnlyDictionary<string, object?>(hydratedProps); - var method = adapterObj.GetType().GetMethod("FromProperties"); - return method!.Invoke(adapterObj, new object[] { readOnlyProps })!; + var readOnlyFields = new ReadOnlyDictionary<string, object?>(hydratedFields); + var method = adapterObj.GetType().GetMethod("FromFields"); + return method!.Invoke(adapterObj, new object[] { readOnlyFields })!; } catch (Exception) { diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs index 1f6ce57e01..3aaedb218e 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/DriverRemoteConnectionTests.cs @@ -113,8 +113,8 @@ public class DriverRemoteConnectionTests Assert.Single(results); var result = Assert.IsType<ProviderDefinedType>(results[0]); Assert.Equal("TestPoint", result.Name); - Assert.Equal(1, result.Properties["x"]); - Assert.Equal(2, result.Properties["y"]); + Assert.Equal(1, result.Fields["x"]); + Assert.Equal(2, result.Fields["y"]); } [Fact] @@ -168,16 +168,16 @@ public class DriverRemoteConnectionTests { public string TypeName => "TestPoint"; - public TestPointClass FromProperties(IReadOnlyDictionary<string, object?> properties) + public TestPointClass FromFields(IReadOnlyDictionary<string, object?> fields) { return new TestPointClass { - X = Convert.ToInt32(properties["x"]), - Y = Convert.ToInt32(properties["y"]) + X = Convert.ToInt32(fields["x"]), + Y = Convert.ToInt32(fields["y"]) }; } - public IReadOnlyDictionary<string, object?> ToProperties(TestPointClass obj) + public IReadOnlyDictionary<string, object?> ToFields(TestPointClass obj) { return new ReadOnlyDictionary<string, object?>( new Dictionary<string, object?> { { "x", obj.X }, { "y", obj.Y } }); diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs index fab9af53e4..a5fdac7c8e 100644 --- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Driver/GremlinClientTests.cs @@ -219,9 +219,9 @@ namespace Gremlin.Net.IntegrationTest.Driver Assert.Single(results); var pdt = Assert.IsType<ProviderDefinedType>(results[0]); Assert.Equal("Point", pdt.Name); - Assert.Equal(2, pdt.Properties.Count); - Assert.Equal(1, pdt.Properties["x"]); - Assert.Equal(2, pdt.Properties["y"]); + Assert.Equal(2, pdt.Fields.Count); + Assert.Equal(1, pdt.Fields["x"]); + Assert.Equal(2, pdt.Fields["y"]); } [Fact] @@ -238,14 +238,14 @@ namespace Gremlin.Net.IntegrationTest.Driver Assert.Single(results); var pdt = Assert.IsType<ProviderDefinedType>(results[0]); Assert.Equal("Person", pdt.Name); - Assert.Equal("Alice", pdt.Properties["name"]); - Assert.Equal(30, pdt.Properties["age"]); + Assert.Equal("Alice", pdt.Fields["name"]); + Assert.Equal(30, pdt.Fields["age"]); - var address = Assert.IsType<ProviderDefinedType>(pdt.Properties["address"]); + var address = Assert.IsType<ProviderDefinedType>(pdt.Fields["address"]); Assert.Equal("Address", address.Name); - Assert.Equal("123 Main St", address.Properties["street"]); - Assert.Equal("Springfield", address.Properties["city"]); - Assert.Equal("12345", address.Properties["zip"]); + Assert.Equal("123 Main St", address.Fields["street"]); + Assert.Equal("Springfield", address.Fields["city"]); + Assert.Equal("12345", address.Fields["zip"]); } [Fact] @@ -264,13 +264,13 @@ namespace Gremlin.Net.IntegrationTest.Driver var p1 = Assert.IsType<ProviderDefinedType>(list[0]); Assert.Equal("Point", p1.Name); - Assert.Equal(1, p1.Properties["x"]); - Assert.Equal(2, p1.Properties["y"]); + Assert.Equal(1, p1.Fields["x"]); + Assert.Equal(2, p1.Fields["y"]); var p2 = Assert.IsType<ProviderDefinedType>(list[1]); Assert.Equal("Point", p2.Name); - Assert.Equal(3, p2.Properties["x"]); - Assert.Equal(4, p2.Properties["y"]); + Assert.Equal(3, p2.Fields["x"]); + Assert.Equal(4, p2.Fields["y"]); } } } diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs index a0c15d1ef5..e6dc565d72 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Process/Traversal/GremlinLangTests.cs @@ -1203,10 +1203,10 @@ namespace Gremlin.Net.UnitTest.Process.Traversal { public string TypeName => "adapter.Point"; - public AnnotatedPointWithAdapter FromProperties(IReadOnlyDictionary<string, object?> properties) => - new() { X = (int)properties["a"]!, Y = (int)properties["b"]! }; + public AnnotatedPointWithAdapter FromFields(IReadOnlyDictionary<string, object?> fields) => + new() { X = (int)fields["a"]!, Y = (int)fields["b"]! }; - public IReadOnlyDictionary<string, object?> ToProperties(AnnotatedPointWithAdapter obj) => + public IReadOnlyDictionary<string, object?> ToFields(AnnotatedPointWithAdapter obj) => new Dictionary<string, object?> { { "a", obj.X }, { "b", obj.Y } }; } } diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs index 36a6318b52..c8b3b008f8 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/IO/GraphBinary4/ProviderDefinedTypeTests.cs @@ -49,7 +49,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4 Assert.NotNull(actual); Assert.Equal(expected.Name, actual!.Name); - Assert.Equal(expected.Properties, actual.Properties); + Assert.Equal(expected.Fields, actual.Fields); } [Fact] @@ -64,7 +64,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4 Assert.NotNull(actual); Assert.Equal(expected.Name, actual!.Name); - Assert.Empty(actual.Properties); + Assert.Empty(actual.Fields); } [Fact] @@ -80,7 +80,7 @@ namespace Gremlin.Net.UnitTest.Structure.IO.GraphBinary4 Assert.NotNull(actual); Assert.Equal(expected.Name, actual!.Name); - Assert.Null(actual.Properties["key"]); + Assert.Null(actual.Fields["key"]); } [Fact] diff --git a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs index a9aefc6ee2..512b3f31d5 100644 --- a/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs +++ b/gremlin-dotnet/test/Gremlin.Net.UnitTest/Structure/ProviderDefinedTypeRegistryTests.cs @@ -103,17 +103,17 @@ namespace Gremlin.Net.UnitTest.Structure } [Fact] - public void BuildShouldReturnRegistryWithoutCrashing() + public void CreateShouldReturnRegistryWithoutCrashing() { - var registry = ProviderDefinedTypeRegistry.Build(); + var registry = ProviderDefinedTypeRegistry.Create(); Assert.NotNull(registry); } [Fact] - public void BuildShouldDiscoverAdapterFromAssembly() + public void CreateShouldDiscoverAdapterFromAssembly() { - var registry = ProviderDefinedTypeRegistry.Build(); + var registry = ProviderDefinedTypeRegistry.Create(); var pdt = new ProviderDefinedType("test:Discoverable", new Dictionary<string, object?> { ["value"] = "hello" }); @@ -144,10 +144,10 @@ namespace Gremlin.Net.UnitTest.Structure { public string TypeName => "geo:Point"; - public Point FromProperties(IReadOnlyDictionary<string, object?> properties) => - new() { X = (double)properties["x"]!, Y = (double)properties["y"]! }; + public Point FromFields(IReadOnlyDictionary<string, object?> fields) => + new() { X = (double)fields["x"]!, Y = (double)fields["y"]! }; - public IReadOnlyDictionary<string, object?> ToProperties(Point obj) => + public IReadOnlyDictionary<string, object?> ToFields(Point obj) => new Dictionary<string, object?> { ["x"] = obj.X, ["y"] = obj.Y }; } @@ -155,10 +155,10 @@ namespace Gremlin.Net.UnitTest.Structure { public string TypeName => "geo:Line"; - public Line FromProperties(IReadOnlyDictionary<string, object?> properties) => - new() { Start = (Point)properties["start"]!, End = (Point)properties["end"]! }; + public Line FromFields(IReadOnlyDictionary<string, object?> fields) => + new() { Start = (Point)fields["start"]!, End = (Point)fields["end"]! }; - public IReadOnlyDictionary<string, object?> ToProperties(Line obj) => + public IReadOnlyDictionary<string, object?> ToFields(Line obj) => new Dictionary<string, object?> { ["start"] = obj.Start, ["end"] = obj.End }; } @@ -166,10 +166,10 @@ namespace Gremlin.Net.UnitTest.Structure { public string TypeName => "bad:Type"; - public object FromProperties(IReadOnlyDictionary<string, object?> properties) => + public object FromFields(IReadOnlyDictionary<string, object?> fields) => throw new InvalidOperationException("intentional failure"); - public IReadOnlyDictionary<string, object?> ToProperties(object obj) => + public IReadOnlyDictionary<string, object?> ToFields(object obj) => throw new InvalidOperationException("intentional failure"); } @@ -187,10 +187,10 @@ namespace Gremlin.Net.UnitTest.Structure { public string TypeName => "test:Discoverable"; - public DiscoverableType FromProperties(IReadOnlyDictionary<string, object?> properties) => - new() { Value = (string)properties["value"]! }; + public DiscoverableType FromFields(IReadOnlyDictionary<string, object?> fields) => + new() { Value = (string)fields["value"]! }; - public IReadOnlyDictionary<string, object?> ToProperties(DiscoverableType obj) => + public IReadOnlyDictionary<string, object?> ToFields(DiscoverableType obj) => new Dictionary<string, object?> { ["value"] = obj.Value }; } } diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java index 3643aa9415..6c2fea1e71 100644 --- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java +++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnection.java @@ -55,7 +55,10 @@ public class DriverRemoteConnection implements RemoteConnection { private transient Optional<Configuration> conf = Optional.empty(); private final boolean attachElements; - private ProviderDefinedTypeRegistry pdtRegistry; + + // Default to SPI-discovered adapters so PDT dehydration works with zero configuration. + // This performs a lightweight ServiceLoader scan; the serializer path does its own independent scan. + private ProviderDefinedTypeRegistry pdtRegistry = ProviderDefinedTypeRegistry.create(); public DriverRemoteConnection(final Configuration conf) { final boolean hasClusterConf = IteratorUtils.anyMatch(conf.getKeys(), k -> k.startsWith("clusterConfiguration")); diff --git a/gremlin-go/driver/client_test.go b/gremlin-go/driver/client_test.go index c234a99918..ffffcad5cb 100644 --- a/gremlin-go/driver/client_test.go +++ b/gremlin-go/driver/client_test.go @@ -318,8 +318,8 @@ func TestProviderDefinedTypeIntegration(t *testing.T) { pdt, ok := result.Data.(*ProviderDefinedType) require.True(t, ok, "expected *ProviderDefinedType, got %T", result.Data) assert.Equal(t, "Point", pdt.Name) - assert.Equal(t, int32(1), pdt.Properties["x"]) - assert.Equal(t, int32(2), pdt.Properties["y"]) + assert.Equal(t, int32(1), pdt.Fields["x"]) + assert.Equal(t, int32(2), pdt.Fields["y"]) }) t.Run("nested PDT (Person with Address)", func(t *testing.T) { @@ -343,15 +343,15 @@ func TestProviderDefinedTypeIntegration(t *testing.T) { pdt, ok := result.Data.(*ProviderDefinedType) require.True(t, ok, "expected *ProviderDefinedType, got %T", result.Data) assert.Equal(t, "Person", pdt.Name) - assert.Equal(t, "Alice", pdt.Properties["name"]) - assert.Equal(t, int32(30), pdt.Properties["age"]) + assert.Equal(t, "Alice", pdt.Fields["name"]) + assert.Equal(t, int32(30), pdt.Fields["age"]) - address, ok := pdt.Properties["address"].(*ProviderDefinedType) + address, ok := pdt.Fields["address"].(*ProviderDefinedType) require.True(t, ok, "expected nested *ProviderDefinedType for address") assert.Equal(t, "Address", address.Name) - assert.Equal(t, "123 Main St", address.Properties["street"]) - assert.Equal(t, "Springfield", address.Properties["city"]) - assert.Equal(t, "12345", address.Properties["zip"]) + assert.Equal(t, "123 Main St", address.Fields["street"]) + assert.Equal(t, "Springfield", address.Fields["city"]) + assert.Equal(t, "12345", address.Fields["zip"]) }) t.Run("PDT in collection", func(t *testing.T) { @@ -378,13 +378,13 @@ func TestProviderDefinedTypeIntegration(t *testing.T) { p1, ok := list[0].(*ProviderDefinedType) require.True(t, ok) assert.Equal(t, "Point", p1.Name) - assert.Equal(t, int32(1), p1.Properties["x"]) - assert.Equal(t, int32(2), p1.Properties["y"]) + assert.Equal(t, int32(1), p1.Fields["x"]) + assert.Equal(t, int32(2), p1.Fields["y"]) p2, ok := list[1].(*ProviderDefinedType) require.True(t, ok) assert.Equal(t, "Point", p2.Name) - assert.Equal(t, int32(3), p2.Properties["x"]) - assert.Equal(t, int32(4), p2.Properties["y"]) + assert.Equal(t, int32(3), p2.Fields["x"]) + assert.Equal(t, int32(4), p2.Fields["y"]) }) } \ No newline at end of file diff --git a/gremlin-go/driver/graphBinaryDeserializer.go b/gremlin-go/driver/graphBinaryDeserializer.go index 8b20080cb0..dda90cfa52 100644 --- a/gremlin-go/driver/graphBinaryDeserializer.go +++ b/gremlin-go/driver/graphBinaryDeserializer.go @@ -639,14 +639,14 @@ func (d *GraphBinaryDeserializer) readCompositePDT() (interface{}, error) { if propsObj != nil { raw, ok := propsObj.(map[interface{}]interface{}) if !ok { - return nil, fmt.Errorf("ProviderDefinedType properties must be a map") + return nil, fmt.Errorf("ProviderDefinedType fields must be a map") } props = make(map[string]interface{}, len(raw)) for k, v := range raw { props[fmt.Sprint(k)] = v } } - pdt := &ProviderDefinedType{Name: name, Properties: props} + pdt := &ProviderDefinedType{Name: name, Fields: props} if d.pdtRegistry != nil { hydrated := d.pdtRegistry.Hydrate(pdt) if hydrated != pdt { diff --git a/gremlin-go/driver/graphBinarySerializer_test.go b/gremlin-go/driver/graphBinarySerializer_test.go index ea43a45e6d..e6f8cda81b 100644 --- a/gremlin-go/driver/graphBinarySerializer_test.go +++ b/gremlin-go/driver/graphBinarySerializer_test.go @@ -541,8 +541,8 @@ func TestProviderDefinedTypeSerialization(t *testing.T) { t.Run("round-trip simple PDT", func(t *testing.T) { source := &ProviderDefinedType{ - Name: "com.example.MyType", - Properties: map[string]interface{}{"key": "value", "num": int32(42)}, + Name: "com.example.MyType", + Fields: map[string]interface{}{"key": "value", "num": int32(42)}, } var buf bytes.Buffer err := serializer.write(source, &buf) @@ -554,18 +554,18 @@ func TestProviderDefinedTypeSerialization(t *testing.T) { pdt, ok := result.(*ProviderDefinedType) assert.True(t, ok) assert.Equal(t, source.Name, pdt.Name) - assert.Equal(t, source.Properties["key"], pdt.Properties["key"]) - assert.Equal(t, source.Properties["num"], pdt.Properties["num"]) + assert.Equal(t, source.Fields["key"], pdt.Fields["key"]) + assert.Equal(t, source.Fields["num"], pdt.Fields["num"]) }) t.Run("round-trip nested PDT", func(t *testing.T) { inner := &ProviderDefinedType{ - Name: "com.example.Inner", - Properties: map[string]interface{}{"x": int32(1)}, + Name: "com.example.Inner", + Fields: map[string]interface{}{"x": int32(1)}, } outer := &ProviderDefinedType{ - Name: "com.example.Outer", - Properties: map[string]interface{}{"child": inner}, + Name: "com.example.Outer", + Fields: map[string]interface{}{"child": inner}, } var buf bytes.Buffer err := serializer.write(outer, &buf) @@ -577,10 +577,10 @@ func TestProviderDefinedTypeSerialization(t *testing.T) { pdt, ok := result.(*ProviderDefinedType) assert.True(t, ok) assert.Equal(t, "com.example.Outer", pdt.Name) - child, ok := pdt.Properties["child"].(*ProviderDefinedType) + child, ok := pdt.Fields["child"].(*ProviderDefinedType) assert.True(t, ok) assert.Equal(t, "com.example.Inner", child.Name) - assert.Equal(t, int32(1), child.Properties["x"]) + assert.Equal(t, int32(1), child.Fields["x"]) }) t.Run("empty name produces error", func(t *testing.T) { @@ -603,8 +603,8 @@ func TestProviderDefinedTypeSerialization(t *testing.T) { }, nil) source := &ProviderDefinedType{ - Name: "com.example.MyType", - Properties: map[string]interface{}{"key": "value"}, + Name: "com.example.MyType", + Fields: map[string]interface{}{"key": "value"}, } var buf bytes.Buffer err := serializer.write(source, &buf) @@ -621,8 +621,8 @@ func TestProviderDefinedTypeSerialization(t *testing.T) { t.Run("no hydration without registry", func(t *testing.T) { source := &ProviderDefinedType{ - Name: "com.example.MyType", - Properties: map[string]interface{}{"key": "value"}, + Name: "com.example.MyType", + Fields: map[string]interface{}{"key": "value"}, } var buf bytes.Buffer err := serializer.write(source, &buf) diff --git a/gremlin-go/driver/gremlinlang.go b/gremlin-go/driver/gremlinlang.go index dac9e64aa8..c6c36ad128 100644 --- a/gremlin-go/driver/gremlinlang.go +++ b/gremlin-go/driver/gremlinlang.go @@ -206,7 +206,7 @@ func (gl *GremlinLang) argAsString(arg interface{}) (string, error) { name := reflect.ValueOf(v).Type().Name() return fmt.Sprintf("%s.%s", strings.ToUpper(name), v), nil case *ProviderDefinedType: - props := v.Properties + props := v.Fields if props == nil { props = map[string]interface{}{} } @@ -304,10 +304,10 @@ func (gl *GremlinLang) argAsString(arg interface{}) (string, error) { // default behavior for a given Go type. if gl.pdtRegistry != nil { adapter := gl.pdtRegistry.GetAdapterByType(reflect.TypeOf(arg)) - if adapter != nil && adapter.ToProperties != nil { - props, err := adapter.ToProperties(arg) + if adapter != nil && adapter.ToFields != nil { + props, err := adapter.ToFields(arg) if err == nil { - pdt := &ProviderDefinedType{Name: adapter.TypeName, Properties: props} + pdt := &ProviderDefinedType{Name: adapter.TypeName, Fields: props} return gl.argAsString(pdt) } } diff --git a/gremlin-go/driver/gremlinlang_test.go b/gremlin-go/driver/gremlinlang_test.go index 9ab9b218f0..7794770115 100644 --- a/gremlin-go/driver/gremlinlang_test.go +++ b/gremlin-go/driver/gremlinlang_test.go @@ -863,7 +863,7 @@ func Test_ConvertParametersToString(t *testing.T) { func Test_PDT_GremlinLang(t *testing.T) { t.Run("basic PDT", func(t *testing.T) { g := NewGraphTraversalSource(nil, nil) - pdt := &ProviderDefinedType{Name: "MyType", Properties: map[string]interface{}{"x": int32(1), "y": "hello"}} + pdt := &ProviderDefinedType{Name: "MyType", Fields: map[string]interface{}{"x": int32(1), "y": "hello"}} gremlin := g.Inject(pdt).GremlinLang.GetGremlin() expected := `g.inject(PDT("MyType",["x":1,"y":"hello"]))` if gremlin != expected { @@ -873,7 +873,7 @@ func Test_PDT_GremlinLang(t *testing.T) { t.Run("empty PDT", func(t *testing.T) { g := NewGraphTraversalSource(nil, nil) - pdt := &ProviderDefinedType{Name: "Empty", Properties: map[string]interface{}{}} + pdt := &ProviderDefinedType{Name: "Empty", Fields: map[string]interface{}{}} gremlin := g.Inject(pdt).GremlinLang.GetGremlin() expected := `g.inject(PDT("Empty",[:]))` if gremlin != expected { @@ -883,7 +883,7 @@ func Test_PDT_GremlinLang(t *testing.T) { t.Run("PDT with special characters in name", func(t *testing.T) { g := NewGraphTraversalSource(nil, nil) - pdt := &ProviderDefinedType{Name: `say"hello"`, Properties: map[string]interface{}{"v": int32(1)}} + pdt := &ProviderDefinedType{Name: `say"hello"`, Fields: map[string]interface{}{"v": int32(1)}} gremlin := g.Inject(pdt).GremlinLang.GetGremlin() expected := `g.inject(PDT("say\"hello\"",["v":1]))` if gremlin != expected { @@ -893,7 +893,7 @@ func Test_PDT_GremlinLang(t *testing.T) { t.Run("PDT with backslash in name", func(t *testing.T) { g := NewGraphTraversalSource(nil, nil) - pdt := &ProviderDefinedType{Name: `back\slash`, Properties: map[string]interface{}{"v": int32(1)}} + pdt := &ProviderDefinedType{Name: `back\slash`, Fields: map[string]interface{}{"v": int32(1)}} gremlin := g.Inject(pdt).GremlinLang.GetGremlin() expected := `g.inject(PDT("back\\slash",["v":1]))` if gremlin != expected { @@ -903,8 +903,8 @@ func Test_PDT_GremlinLang(t *testing.T) { t.Run("nested PDT", func(t *testing.T) { g := NewGraphTraversalSource(nil, nil) - inner := &ProviderDefinedType{Name: "Inner", Properties: map[string]interface{}{"v": int32(1)}} - outer := &ProviderDefinedType{Name: "Outer", Properties: map[string]interface{}{"inner": inner}} + inner := &ProviderDefinedType{Name: "Inner", Fields: map[string]interface{}{"v": int32(1)}} + outer := &ProviderDefinedType{Name: "Outer", Fields: map[string]interface{}{"inner": inner}} gremlin := g.Inject(outer).GremlinLang.GetGremlin() expected := `g.inject(PDT("Outer",["inner":PDT("Inner",["v":1])]))` if gremlin != expected { @@ -914,7 +914,7 @@ func Test_PDT_GremlinLang(t *testing.T) { t.Run("PDT map keys sorted", func(t *testing.T) { g := NewGraphTraversalSource(nil, nil) - pdt := &ProviderDefinedType{Name: "T", Properties: map[string]interface{}{"z": int32(3), "a": int32(1), "m": int32(2)}} + pdt := &ProviderDefinedType{Name: "T", Fields: map[string]interface{}{"z": int32(3), "a": int32(1), "m": int32(2)}} gremlin := g.Inject(pdt).GremlinLang.GetGremlin() expected := `g.inject(PDT("T",["a":1,"m":2,"z":3]))` if gremlin != expected { diff --git a/gremlin-go/driver/pdtRegistry.go b/gremlin-go/driver/pdtRegistry.go index 1d14feec6c..8dd81bcb47 100644 --- a/gremlin-go/driver/pdtRegistry.go +++ b/gremlin-go/driver/pdtRegistry.go @@ -23,9 +23,9 @@ import "reflect" // PDTAdapter defines how to hydrate/dehydrate a provider-defined type. type PDTAdapter struct { - TypeName string - FromProperties func(map[string]interface{}) (interface{}, error) - ToProperties func(interface{}) (map[string]interface{}, error) + TypeName string + FromFields func(map[string]interface{}) (interface{}, error) + ToFields func(interface{}) (map[string]interface{}, error) } // PDTRegistry maps type names to their hydration adapters. @@ -41,13 +41,13 @@ func NewPDTRegistry() *PDTRegistry { // RegisterFuncs registers hydration/dehydration functions for a type name. func (r *PDTRegistry) RegisterFuncs(typeName string, fromProps func(map[string]interface{}) (interface{}, error), toProps func(interface{}) (map[string]interface{}, error)) { - adapter := &PDTAdapter{TypeName: typeName, FromProperties: fromProps, ToProperties: toProps} + adapter := &PDTAdapter{TypeName: typeName, FromFields: fromProps, ToFields: toProps} r.adaptersByName[typeName] = adapter } // RegisterFuncsWithType registers hydration/dehydration functions for a type name and associates a Go type for dehydration lookup. func (r *PDTRegistry) RegisterFuncsWithType(typeName string, targetType reflect.Type, fromProps func(map[string]interface{}) (interface{}, error), toProps func(interface{}) (map[string]interface{}, error)) { - adapter := &PDTAdapter{TypeName: typeName, FromProperties: fromProps, ToProperties: toProps} + adapter := &PDTAdapter{TypeName: typeName, FromFields: fromProps, ToFields: toProps} r.adaptersByName[typeName] = adapter r.adaptersByType[targetType] = adapter } @@ -56,7 +56,7 @@ func (r *PDTRegistry) RegisterFuncsWithType(typeName string, targetType reflect. func (r *PDTRegistry) RegisterType(typeName string, targetType reflect.Type) { r.adaptersByName[typeName] = &PDTAdapter{ TypeName: typeName, - FromProperties: func(props map[string]interface{}) (interface{}, error) { + FromFields: func(props map[string]interface{}) (interface{}, error) { obj := reflect.New(targetType).Elem() for i := 0; i < targetType.NumField(); i++ { field := targetType.Field(i) @@ -88,15 +88,15 @@ func (r *PDTRegistry) Hydrate(pdt *ProviderDefinedType) interface{} { if !ok { return pdt } - hydratedProps := make(map[string]interface{}, len(pdt.Properties)) - for k, v := range pdt.Properties { + hydratedFields := make(map[string]interface{}, len(pdt.Fields)) + for k, v := range pdt.Fields { if nested, ok := v.(*ProviderDefinedType); ok { - hydratedProps[k] = r.Hydrate(nested) + hydratedFields[k] = r.Hydrate(nested) } else { - hydratedProps[k] = v + hydratedFields[k] = v } } - result, err := adapter.FromProperties(hydratedProps) + result, err := adapter.FromFields(hydratedFields) if err != nil { return pdt } diff --git a/gremlin-go/driver/pdtRegistry_test.go b/gremlin-go/driver/pdtRegistry_test.go index 18a97566d8..cbd4ef1a98 100644 --- a/gremlin-go/driver/pdtRegistry_test.go +++ b/gremlin-go/driver/pdtRegistry_test.go @@ -33,14 +33,14 @@ func TestPDTRegistryRegisterFuncsAndHydrate(t *testing.T) { return [2]int{props["x"].(int), props["y"].(int)}, nil }, nil) - pdt := &ProviderDefinedType{Name: "x:Point", Properties: map[string]interface{}{"x": 1, "y": 2}} + pdt := &ProviderDefinedType{Name: "x:Point", Fields: map[string]interface{}{"x": 1, "y": 2}} result := reg.Hydrate(pdt) assert.Equal(t, [2]int{1, 2}, result) } func TestPDTRegistryNoAdapterReturnsRawPDT(t *testing.T) { reg := NewPDTRegistry() - pdt := &ProviderDefinedType{Name: "x:Unknown", Properties: map[string]interface{}{"a": "b"}} + pdt := &ProviderDefinedType{Name: "x:Unknown", Fields: map[string]interface{}{"a": "b"}} result := reg.Hydrate(pdt) assert.Equal(t, pdt, result) } @@ -51,7 +51,7 @@ func TestPDTRegistryAdapterErrorReturnsRawPDT(t *testing.T) { return nil, errors.New("fail") }, nil) - pdt := &ProviderDefinedType{Name: "x:Bad", Properties: map[string]interface{}{}} + pdt := &ProviderDefinedType{Name: "x:Bad", Fields: map[string]interface{}{}} result := reg.Hydrate(pdt) assert.Equal(t, pdt, result) } @@ -65,8 +65,8 @@ func TestPDTRegistryNestedHydration(t *testing.T) { return "outer:" + props["child"].(string), nil }, nil) - inner := &ProviderDefinedType{Name: "x:Inner", Properties: map[string]interface{}{"val": "hi"}} - outer := &ProviderDefinedType{Name: "x:Outer", Properties: map[string]interface{}{"child": inner}} + inner := &ProviderDefinedType{Name: "x:Inner", Fields: map[string]interface{}{"val": "hi"}} + outer := &ProviderDefinedType{Name: "x:Outer", Fields: map[string]interface{}{"child": inner}} result := reg.Hydrate(outer) assert.Equal(t, "outer:hi!", result) } @@ -81,7 +81,7 @@ func TestPDTRegistryRegisterType(t *testing.T) { reg := NewPDTRegistry() reg.RegisterType("x:Point", reflect.TypeOf(testPoint{})) - pdt := &ProviderDefinedType{Name: "x:Point", Properties: map[string]interface{}{"x": 3, "y": 4, "L": "label"}} + pdt := &ProviderDefinedType{Name: "x:Point", Fields: map[string]interface{}{"x": 3, "y": 4, "L": "label"}} result := reg.Hydrate(pdt) assert.Equal(t, testPoint{X: 3, Y: 4, L: "label"}, result) } diff --git a/gremlin-go/driver/providerDefinedType.go b/gremlin-go/driver/providerDefinedType.go index c2d969f67e..2a5a359892 100644 --- a/gremlin-go/driver/providerDefinedType.go +++ b/gremlin-go/driver/providerDefinedType.go @@ -26,25 +26,25 @@ import ( // ProviderDefinedType represents a provider-defined type (PDT) in GraphBinary serialization. type ProviderDefinedType struct { - Name string - Properties map[string]interface{} + Name string + Fields map[string]interface{} } func (p *ProviderDefinedType) String() string { - return fmt.Sprintf("pdt[%s]%v", p.Name, p.Properties) + return fmt.Sprintf("pdt[%s]%v", p.Name, p.Fields) } -// pdtWriter serializes a ProviderDefinedType as a fully-qualified string (name) followed by a fully-qualified map (properties). +// pdtWriter serializes a ProviderDefinedType as a fully-qualified string (name) followed by a fully-qualified map (fields). func pdtWriter(value interface{}, w io.Writer, typeSerializer *graphBinaryTypeSerializer) error { pdt := value.(*ProviderDefinedType) if err := typeSerializer.write(pdt.Name, w); err != nil { return err } - if pdt.Properties == nil { + if pdt.Fields == nil { return typeSerializer.write(map[interface{}]interface{}{}, w) } - m := make(map[interface{}]interface{}, len(pdt.Properties)) - for k, v := range pdt.Properties { + m := make(map[interface{}]interface{}, len(pdt.Fields)) + for k, v := range pdt.Fields { m[k] = v } return typeSerializer.write(m, w) diff --git a/gremlin-go/driver/providerDefinedType_test.go b/gremlin-go/driver/providerDefinedType_test.go index 91963456d8..8d0f394e24 100644 --- a/gremlin-go/driver/providerDefinedType_test.go +++ b/gremlin-go/driver/providerDefinedType_test.go @@ -28,8 +28,8 @@ import ( func TestProviderDefinedType(t *testing.T) { t.Run("String method", func(t *testing.T) { pdt := &ProviderDefinedType{ - Name: "com.example.Test", - Properties: map[string]interface{}{"a": int32(1)}, + Name: "com.example.Test", + Fields: map[string]interface{}{"a": int32(1)}, } assert.Contains(t, pdt.String(), "pdt[com.example.Test]") }) diff --git a/gremlin-go/driver/traversal_test.go b/gremlin-go/driver/traversal_test.go index bc842f1008..f26c241855 100644 --- a/gremlin-go/driver/traversal_test.go +++ b/gremlin-go/driver/traversal_test.go @@ -872,7 +872,7 @@ func TestProviderDefinedTypeTraversalAPIIntegration(t *testing.T) { defer remote.Close() g := Traversal_().With(remote) - pdt := &ProviderDefinedType{Name: "TestPoint", Properties: map[string]interface{}{"x": int32(1), "y": int32(2)}} + pdt := &ProviderDefinedType{Name: "TestPoint", Fields: map[string]interface{}{"x": int32(1), "y": int32(2)}} results, err := g.Inject(pdt).ToList() require.NoError(t, err) @@ -881,8 +881,8 @@ func TestProviderDefinedTypeTraversalAPIIntegration(t *testing.T) { result, ok := results[0].GetInterface().(*ProviderDefinedType) require.True(t, ok, "expected *ProviderDefinedType, got %T", results[0].GetInterface()) assert.Equal(t, "TestPoint", result.Name) - assert.Equal(t, int32(1), result.Properties["x"]) - assert.Equal(t, int32(2), result.Properties["y"]) + assert.Equal(t, int32(1), result.Fields["x"]) + assert.Equal(t, int32(2), result.Fields["y"]) }) t.Run("registry-based round-trip via typed struct", func(t *testing.T) { diff --git a/gremlin-python/src/main/python/gremlin_python/process/traversal.py b/gremlin-python/src/main/python/gremlin_python/process/traversal.py index 6b8bcbfea3..b4e4a788ed 100644 --- a/gremlin-python/src/main/python/gremlin_python/process/traversal.py +++ b/gremlin-python/src/main/python/gremlin_python/process/traversal.py @@ -907,7 +907,7 @@ class GremlinLang(object): return tmp if isinstance(arg, ProviderDefinedType): - return f'PDT({self._arg_as_string(arg.name)},{self._process_dict(arg.properties)})' + return f'PDT({self._arg_as_string(arg.name)},{self._process_dict(arg.fields)})' if isinstance(arg, Vertex): return f'{self._arg_as_string(arg.id)}' diff --git a/gremlin-python/src/main/python/gremlin_python/structure/graph.py b/gremlin-python/src/main/python/gremlin_python/structure/graph.py index 6160af3c10..5105013811 100644 --- a/gremlin-python/src/main/python/gremlin_python/structure/graph.py +++ b/gremlin-python/src/main/python/gremlin_python/structure/graph.py @@ -144,33 +144,33 @@ class Path(object): class ProviderDefinedType(object): - def __init__(self, name, properties): + def __init__(self, name, fields): if not name: raise ValueError("name cannot be null or empty") self._name = name - self._properties = dict(properties) if properties else {} - if any(not isinstance(k, str) for k in self._properties): - raise TypeError("ProviderDefinedType property keys must be strings") + self._fields = dict(fields) if fields else {} + if any(not isinstance(k, str) for k in self._fields): + raise TypeError("ProviderDefinedType field keys must be strings") @property def name(self): return self._name @property - def properties(self): - return self._properties + def fields(self): + return self._fields def __eq__(self, other): - return isinstance(other, ProviderDefinedType) and self._name == other._name and self._properties == other._properties + return isinstance(other, ProviderDefinedType) and self._name == other._name and self._fields == other._fields def __hash__(self): try: - return hash((self._name, frozenset(self._properties.items()))) + return hash((self._name, frozenset(self._fields.items()))) except TypeError: return hash(self._name) def __repr__(self): - return f"pdt[{self._name}]{self._properties}" + return f"pdt[{self._name}]{self._fields}" class ProviderDefinedTypeRegistry(object): @@ -191,7 +191,7 @@ class ProviderDefinedTypeRegistry(object): } @classmethod - def build(cls): + def create(cls): """Create a registry populated by entry_points discovery. Providers register adapters via pyproject.toml: @@ -228,9 +228,9 @@ class ProviderDefinedTypeRegistry(object): if adapter is None: return pdt try: - hydrated_props = {k: self.hydrate(v) if isinstance(v, ProviderDefinedType) else v - for k, v in pdt.properties.items()} - return adapter['deserialize'](hydrated_props) + hydrated_fields = {k: self.hydrate(v) if isinstance(v, ProviderDefinedType) else v + for k, v in pdt.fields.items()} + return adapter['deserialize'](hydrated_fields) except Exception as e: import logging logging.getLogger(__name__).warning(f"PDT hydration failed for '{pdt.name}': {e}") diff --git a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py index cc5d9518fd..fa1ca12cb5 100644 --- a/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py +++ b/gremlin-python/src/main/python/gremlin_python/structure/io/graphbinaryV4.py @@ -181,7 +181,7 @@ class GraphBinaryReader(object): """Hydrate a ProviderDefinedType using a @provider_defined decorated class.""" cls = _pdt_decorated_types[pdt.name] props = {} - for k, v in pdt.properties.items(): + for k, v in pdt.fields.items(): if isinstance(v, ProviderDefinedType) and v.name in _pdt_decorated_types: props[k] = self._hydrate_decorated(v) elif self.pdt_registry is not None and isinstance(v, ProviderDefinedType): @@ -958,7 +958,7 @@ class ProviderDefinedTypeIO(_GraphBinaryTypeIO): def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True): cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend) StringIO.dictify(obj.name, writer, to_extend) - MapIO.dictify(obj.properties, writer, to_extend) + MapIO.dictify(obj.fields, writer, to_extend) return to_extend @classmethod @@ -968,5 +968,5 @@ class ProviderDefinedTypeIO(_GraphBinaryTypeIO): @classmethod def _read_pdt(cls, b, r): name = r.read_object(b) - properties = r.read_object(b) - return ProviderDefinedType(name, properties) \ No newline at end of file + fields = r.read_object(b) + return ProviderDefinedType(name, fields) \ No newline at end of file diff --git a/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py b/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py index 21b9cf7173..f7c8c7aa51 100644 --- a/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py +++ b/gremlin-python/src/main/python/tests/unit/structure/io/test_graphbinaryV4.py @@ -322,19 +322,19 @@ class TestGraphBinaryV4(object): result = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(pdt)) assert isinstance(result, ProviderDefinedType) assert result.name == 'Point' - assert result.properties == {'x': 1, 'y': 2} + assert result.fields == {'x': 1, 'y': 2} def test_provider_defined_type_nested(self): inner = ProviderDefinedType('Address', {'street': 'Main'}) outer = ProviderDefinedType('Person', {'name': 'Alice', 'address': inner}) result = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(outer)) assert result.name == 'Person' - assert result.properties['name'] == 'Alice' - assert isinstance(result.properties['address'], ProviderDefinedType) - assert result.properties['address'].name == 'Address' + assert result.fields['name'] == 'Alice' + assert isinstance(result.fields['address'], ProviderDefinedType) + assert result.fields['address'].name == 'Address' def test_provider_defined_type_null_field(self): pdt = ProviderDefinedType('NullableType', {'value': None, 'name': 'test'}) result = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(pdt)) - assert result.properties['value'] is None - assert result.properties['name'] == 'test' + assert result.fields['value'] is None + assert result.fields['name'] == 'test' diff --git a/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py b/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py index 32deaa9840..b97b9905d8 100644 --- a/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py +++ b/gremlin-python/src/main/python/tests/unit/structure/io/test_provider_defined_type.py @@ -105,7 +105,7 @@ class TestProviderDefinedTypeRegistry(object): class TestProviderDefinedTypeRegistryBuild(object): def test_build_returns_registry_with_no_entry_points(self): - registry = ProviderDefinedTypeRegistry.build() + registry = ProviderDefinedTypeRegistry.create() assert isinstance(registry, ProviderDefinedTypeRegistry) def test_build_loads_entry_point(self): @@ -122,7 +122,7 @@ class TestProviderDefinedTypeRegistryBuild(object): else: mock_entry_points.return_value = {'tinkerpop.pdt': [mock_ep]} - registry = ProviderDefinedTypeRegistry.build() + registry = ProviderDefinedTypeRegistry.create() assert "com.mock.Type" in registry._adapters_by_name def test_build_handles_failing_entry_point(self): @@ -139,7 +139,7 @@ class TestProviderDefinedTypeRegistryBuild(object): else: mock_entry_points.return_value = {'tinkerpop.pdt': [mock_ep]} - registry = ProviderDefinedTypeRegistry.build() + registry = ProviderDefinedTypeRegistry.create() assert isinstance(registry, ProviderDefinedTypeRegistry) assert len(registry._adapters_by_name) == 0 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 03fafbd3f1..3f7f61dd30 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 @@ -1287,8 +1287,8 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration assertTrue(result instanceof ProviderDefinedType); final ProviderDefinedType r = (ProviderDefinedType) result; assertEquals("TestPoint", r.getName()); - assertEquals(1, r.getProperties().get("x")); - assertEquals(2, r.getProperties().get("y")); + assertEquals(1, r.getFields().get("x")); + assertEquals(2, r.getFields().get("y")); } finally { cluster.close(); } @@ -1386,8 +1386,8 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration value instanceof ProviderDefinedType); final ProviderDefinedType pdt = (ProviderDefinedType) value; assertEquals("Point", pdt.getName()); - assertEquals(3, pdt.getProperties().get("x")); - assertEquals(4, pdt.getProperties().get("y")); + assertEquals(3, pdt.getFields().get("x")); + assertEquals(4, pdt.getFields().get("y")); } finally { // cleanup client.submit("g.V().hasLabel('location').drop().iterate()", groovyRequestOptions).all().get(); @@ -1407,13 +1407,13 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration // so the adapter's type name matches the server type name "Point". @Override public String typeName() { return "Point"; } @Override public Class<TestPoint> targetClass() { return TestPoint.class; } - @Override public Map<String, Object> toProperties(final TestPoint obj) { + @Override public Map<String, Object> toFields(final TestPoint obj) { final Map<String, Object> m = new HashMap<>(); m.put("x", obj.x); m.put("y", obj.y); return m; } - @Override public TestPoint fromProperties(final Map<String, Object> props) { + @Override public TestPoint fromFields(final Map<String, Object> props) { return new TestPoint(((Number) props.get("x")).intValue(), ((Number) props.get("y")).intValue()); } } diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java index 28a81731e3..746184fab4 100644 --- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java +++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSerializationIntegrateTest.java @@ -278,8 +278,8 @@ public class GremlinServerSerializationIntegrateTest extends AbstractGremlinServ assertEquals(1, results.size()); final ProviderDefinedType pdt = (ProviderDefinedType) results.get(0).getObject(); assertEquals("Point", pdt.getName()); - assertEquals(1, pdt.getProperties().get("x")); - assertEquals(2, pdt.getProperties().get("y")); + assertEquals(1, pdt.getFields().get("x")); + assertEquals(2, pdt.getFields().get("y")); } @Test @@ -291,13 +291,13 @@ public class GremlinServerSerializationIntegrateTest extends AbstractGremlinServ assertEquals(1, results.size()); final ProviderDefinedType person = (ProviderDefinedType) results.get(0).getObject(); assertEquals("Person", person.getName()); - assertEquals("Alice", person.getProperties().get("name")); - assertEquals(30, person.getProperties().get("age")); + assertEquals("Alice", person.getFields().get("name")); + assertEquals(30, person.getFields().get("age")); - final ProviderDefinedType address = (ProviderDefinedType) person.getProperties().get("address"); + final ProviderDefinedType address = (ProviderDefinedType) person.getFields().get("address"); assertEquals("Address", address.getName()); - assertEquals("123 Main St", address.getProperties().get("street")); - assertEquals("Springfield", address.getProperties().get("city")); + assertEquals("123 Main St", address.getFields().get("street")); + assertEquals("Springfield", address.getFields().get("city")); } @Test @@ -311,13 +311,13 @@ public class GremlinServerSerializationIntegrateTest extends AbstractGremlinServ final ProviderDefinedType p1 = (ProviderDefinedType) list.get(0); assertEquals("Point", p1.getName()); - assertEquals(1, p1.getProperties().get("x")); - assertEquals(2, p1.getProperties().get("y")); + assertEquals(1, p1.getFields().get("x")); + assertEquals(2, p1.getFields().get("y")); final ProviderDefinedType p2 = (ProviderDefinedType) list.get(1); assertEquals("Point", p2.getName()); - assertEquals(3, p2.getProperties().get("x")); - assertEquals(4, p2.getProperties().get("y")); + assertEquals(3, p2.getFields().get("x")); + assertEquals(4, p2.getFields().get("y")); } @Test diff --git a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java index 795712ff76..9204118184 100644 --- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java +++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/ser/GraphBinaryMessageSerializerV4.java @@ -55,18 +55,15 @@ public class GraphBinaryMessageSerializerV4 extends AbstractMessageSerializer<Gr private static final String MIME_TYPE = SerTokens.MIME_GRAPHBINARY_V4; /** - * Creates a new instance of the message serializer using the default type serializers. + * Creates a new instance of the message serializer using the default type serializers and + * an SPI-discovered {@link ProviderDefinedTypeRegistry} for automatic PDT hydration. */ public GraphBinaryMessageSerializerV4() { - this(TypeSerializerRegistry.INSTANCE); + this(TypeSerializerRegistry.INSTANCE, ProviderDefinedTypeRegistry.create()); } public GraphBinaryMessageSerializerV4(final TypeSerializerRegistry registry) { - reader = new GraphBinaryReader(registry); - writer = new GraphBinaryWriter(registry); - mapper = new GraphBinaryMapper(writer, reader); - - requestSerializer = new RequestMessageSerializer(); + this(registry, ProviderDefinedTypeRegistry.create()); } public GraphBinaryMessageSerializerV4(final TypeSerializerRegistry registry, final ProviderDefinedTypeRegistry pdtRegistry) { @@ -104,7 +101,7 @@ public class GraphBinaryMessageSerializerV4 extends AbstractMessageSerializer<Gr } final TypeSerializerRegistry registry = builder.create(); - reader = new GraphBinaryReader(registry); + reader = new GraphBinaryReader(registry, ProviderDefinedTypeRegistry.create()); writer = new GraphBinaryWriter(registry); requestSerializer = new RequestMessageSerializer(); diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryPdtSpiAutoWiringTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryPdtSpiAutoWiringTest.java new file mode 100644 index 0000000000..b356b82776 --- /dev/null +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryPdtSpiAutoWiringTest.java @@ -0,0 +1,134 @@ +/* + * 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; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; +import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; +import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeRegistry; +import org.apache.tinkerpop.gremlin.util.message.ResponseMessage; +import org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV4; +import org.apache.tinkerpop.gremlin.util.ser.SerializationException; +import org.junit.Test; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Validates that the default {@link GraphBinaryMessageSerializerV4} auto-wires SPI-discovered + * {@link org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter} implementations + * for hydration without any user configuration. + */ +public class GraphBinaryPdtSpiAutoWiringTest { + + private final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + + @Test + public void shouldAutoHydrateSpiDiscoveredAdapterWithDefaultSerializer() throws SerializationException { + // The default no-arg constructor should pick up TestPointAdapter via SPI + final GraphBinaryMessageSerializerV4 serializer = new GraphBinaryMessageSerializerV4(); + + // Build a response containing a raw ProviderDefinedType matching the test adapter's typeName + final Map<String, Object> fields = new LinkedHashMap<>(); + fields.put("x", 10); + fields.put("y", 20); + final ProviderDefinedType pdt = new ProviderDefinedType("test.Point", fields); + + final ResponseMessage response = ResponseMessage.build() + .result(Collections.singletonList(pdt)) + .create(); + + // Serialize and deserialize — the reader should hydrate the PDT into TestPoint + final ByteBuf buffer = serializer.writeHeader(response, allocator); + try { + final ResponseMessage deserialized = serializer.readChunk(buffer, true); + assertNotNull(deserialized.getResult().getData()); + assertEquals(1, deserialized.getResult().getData().size()); + + final Object result = deserialized.getResult().getData().get(0); + assertTrue("Expected hydrated TestPoint but got: " + result.getClass().getName(), + result instanceof TestPointAdapter.TestPoint); + + final TestPointAdapter.TestPoint point = (TestPointAdapter.TestPoint) result; + assertEquals(10, point.x); + assertEquals(20, point.y); + } finally { + buffer.release(); + } + } + + @Test + public void shouldAutoHydrateSpiDiscoveredAdapterAfterConfigure() throws SerializationException { + // Verify configure() also includes the SPI registry + final GraphBinaryMessageSerializerV4 serializer = new GraphBinaryMessageSerializerV4(); + serializer.configure(Collections.emptyMap(), Collections.emptyMap()); + + final Map<String, Object> fields = new LinkedHashMap<>(); + fields.put("x", 5); + fields.put("y", 15); + final ProviderDefinedType pdt = new ProviderDefinedType("test.Point", fields); + + final ResponseMessage response = ResponseMessage.build() + .result(Collections.singletonList(pdt)) + .create(); + + final ByteBuf buffer = serializer.writeHeader(response, allocator); + try { + final ResponseMessage deserialized = serializer.readChunk(buffer, true); + final Object result = deserialized.getResult().getData().get(0); + assertTrue("Expected hydrated TestPoint after configure()", result instanceof TestPointAdapter.TestPoint); + } finally { + buffer.release(); + } + } + + @Test + public void shouldUseExplicitPdtRegistryOverSpiDefault() throws SerializationException { + // An empty registry should NOT hydrate since it has no adapters registered + final ProviderDefinedTypeRegistry emptyRegistry = ProviderDefinedTypeRegistry.empty(); + final GraphBinaryMessageSerializerV4 serializer = new GraphBinaryMessageSerializerV4( + TypeSerializerRegistry.INSTANCE, emptyRegistry); + + final Map<String, Object> fields = new LinkedHashMap<>(); + fields.put("x", 1); + fields.put("y", 2); + final ProviderDefinedType pdt = new ProviderDefinedType("test.Point", fields); + + final ResponseMessage response = ResponseMessage.build() + .result(Collections.singletonList(pdt)) + .create(); + + final ByteBuf buffer = serializer.writeHeader(response, allocator); + try { + final ResponseMessage deserialized = serializer.readChunk(buffer, true); + final Object result = deserialized.getResult().getData().get(0); + // With empty registry, should remain as raw ProviderDefinedType (no hydration) + assertTrue("Expected raw ProviderDefinedType with explicit empty registry but got: " + result.getClass().getName(), + result instanceof ProviderDefinedType); + } finally { + buffer.release(); + } + } +} diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriterPdtTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryWriterPdtTest.java similarity index 77% rename from gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriterPdtTest.java rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryWriterPdtTest.java index 863e2559da..2a3fa78d4f 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriterPdtTest.java +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/GraphBinaryWriterPdtTest.java @@ -16,11 +16,15 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.tinkerpop.gremlin.structure.io.binary; +package org.apache.tinkerpop.gremlin.util.ser.binary; +import io.netty.buffer.ByteBufAllocator; 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.structure.io.pdt.ProviderDefined; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; +import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory; import org.junit.Test; import java.io.IOException; @@ -35,6 +39,8 @@ public class GraphBinaryWriterPdtTest { private static final GraphBinaryReader reader = new GraphBinaryReader(); private static final GraphBinaryWriter writer = new GraphBinaryWriter(); + private static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + private static final NettyBufferFactory bufferFactory = new NettyBufferFactory(); @ProviderDefined static class TestPoint { @@ -53,19 +59,19 @@ public class GraphBinaryWriterPdtTest { @Test public void shouldAutoConvertAnnotatedObjectToPdt() throws IOException { - final Buffer buffer = HeapBuffer.allocate(1024); + final Buffer buffer = bufferFactory.create(allocator.buffer()); writer.write(new TestPoint(1, 2), buffer); buffer.readerIndex(0); final ProviderDefinedType result = reader.read(buffer); assertEquals("TestPoint", result.getName()); - assertEquals(1, result.getProperties().get("x")); - assertEquals(2, result.getProperties().get("y")); + assertEquals(1, result.getFields().get("x")); + assertEquals(2, result.getFields().get("y")); } @Test public void shouldThrowActionableMessageForUnannotatedType() { - final Buffer buffer = HeapBuffer.allocate(1024); + final Buffer buffer = bufferFactory.create(allocator.buffer()); final IOException ex = assertThrows(IOException.class, () -> writer.write(new UnannotatedType(), buffer)); assertTrue(ex.getMessage().contains("@ProviderDefined")); assertTrue(ex.getMessage().contains("UnannotatedType")); @@ -78,7 +84,7 @@ public class GraphBinaryWriterPdtTest { props.put("y", 2); final ProviderDefinedType pdt = new ProviderDefinedType("TestPoint", props); - final Buffer buffer = HeapBuffer.allocate(1024); + final Buffer buffer = bufferFactory.create(allocator.buffer()); writer.write(pdt, buffer); buffer.readerIndex(0); diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TestPointAdapter.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TestPointAdapter.java new file mode 100644 index 0000000000..6a352f274c --- /dev/null +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/TestPointAdapter.java @@ -0,0 +1,63 @@ +/* + * 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; + +import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Test-only adapter registered via META-INF/services for SPI auto-wiring validation. + */ +public class TestPointAdapter implements ProviderDefinedTypeAdapter<TestPointAdapter.TestPoint> { + + public static class TestPoint { + public final int x; + public final int y; + + public TestPoint(final int x, final int y) { + this.x = x; + this.y = y; + } + } + + @Override + public String typeName() { + return "test.Point"; + } + + @Override + public Class<TestPoint> targetClass() { + return TestPoint.class; + } + + @Override + public Map<String, Object> toFields(final TestPoint obj) { + final Map<String, Object> fields = new LinkedHashMap<>(); + fields.put("x", obj.x); + fields.put("y", obj.y); + return fields; + } + + @Override + public TestPoint fromFields(final Map<String, Object> fields) { + return new TestPoint(((Number) fields.get("x")).intValue(), ((Number) fields.get("y")).intValue()); + } +} diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializerTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/ProviderDefinedTypeSerializerTest.java similarity index 89% rename from gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializerTest.java rename to gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/ProviderDefinedTypeSerializerTest.java index 76f373609d..822a835f3b 100644 --- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ProviderDefinedTypeSerializerTest.java +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/binary/types/ProviderDefinedTypeSerializerTest.java @@ -16,15 +16,17 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.tinkerpop.gremlin.structure.io.binary.types; +package org.apache.tinkerpop.gremlin.util.ser.binary.types; +import io.netty.buffer.ByteBufAllocator; 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.structure.io.binary.HeapBuffer; +import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedType; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter; import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeRegistry; +import org.apache.tinkerpop.gremlin.util.ser.NettyBufferFactory; import org.junit.Test; import java.io.IOException; @@ -42,9 +44,11 @@ public class ProviderDefinedTypeSerializerTest { private static final GraphBinaryReader reader = new GraphBinaryReader(); private static final GraphBinaryWriter writer = new GraphBinaryWriter(); + private static final ByteBufAllocator allocator = ByteBufAllocator.DEFAULT; + private static final NettyBufferFactory bufferFactory = new NettyBufferFactory(); private Buffer writeAndRead(final Object value) throws IOException { - final Buffer buffer = HeapBuffer.allocate(1024); + final Buffer buffer = bufferFactory.create(allocator.buffer()); writer.write(value, buffer); buffer.readerIndex(0); return buffer; @@ -120,8 +124,7 @@ public class ProviderDefinedTypeSerializerTest { @Test(expected = IOException.class) public void shouldThrowOnEmptyNameDuringRead() throws IOException { - // Manually write a PDT with empty name to trigger the validation - final Buffer buffer = HeapBuffer.allocate(256); + final Buffer buffer = bufferFactory.create(allocator.buffer()); // Write type code for COMPOSITE_PDT buffer.writeByte(0xF0); // Write value_flag = 0 (not null) @@ -141,7 +144,7 @@ public class ProviderDefinedTypeSerializerTest { @Test(expected = IOException.class) public void shouldThrowOnNonStringKeyInPropertiesMap() throws IOException { - final Buffer buffer = HeapBuffer.allocate(256); + final Buffer buffer = bufferFactory.create(allocator.buffer()); // Write type code for COMPOSITE_PDT (0xF0), value_flag 0 buffer.writeByte(0xF0); buffer.writeByte(0x00); @@ -170,7 +173,7 @@ public class ProviderDefinedTypeSerializerTest { @Test public void shouldHandleNullPdt() throws IOException { - final Buffer buffer = HeapBuffer.allocate(64); + final Buffer buffer = bufferFactory.create(allocator.buffer()); writer.write(null, buffer); buffer.readerIndex(0); final Object result = reader.read(buffer); @@ -188,18 +191,18 @@ public class ProviderDefinedTypeSerializerTest { public Class<Map<String, Object>> targetClass() { return (Class) Map.class; } @Override - public Map<String, Object> fromProperties(final Map<String, Object> properties) { + public Map<String, Object> fromFields(final Map<String, Object> properties) { final Map<String, Object> result = new LinkedHashMap<>(properties); result.put("hydrated", true); return result; } @Override - public Map<String, Object> toProperties(final Map<String, Object> value) { return value; } + public Map<String, Object> toFields(final Map<String, Object> value) { return value; } }); final GraphBinaryReader hydratingReader = new GraphBinaryReader( - org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry.INSTANCE, pdtRegistry); + TypeSerializerRegistry.INSTANCE, pdtRegistry); final Map<String, Object> props = new LinkedHashMap<>(); props.put("x", 1); diff --git a/gremlin-util/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter b/gremlin-util/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter new file mode 100644 index 0000000000..408bc7aa62 --- /dev/null +++ b/gremlin-util/src/test/resources/META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter @@ -0,0 +1 @@ +org.apache.tinkerpop.gremlin.util.ser.binary.TestPointAdapter
