spmallette commented on code in PR #3433:
URL: https://github.com/apache/tinkerpop/pull/3433#discussion_r3305784602


##########
docs/src/dev/provider/pdt.asciidoc:
##########
@@ -0,0 +1,295 @@
+////
+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.
+////
+
+[[provider-defined-types]]
+== Provider Defined Types (PDT)
+
+Provider Defined Types allow graph providers to expose custom types that 
drivers can serialize and deserialize without
+manual configuration on the client side. A provider annotates a class (or 
registers an adapter for a class it doesn't
+own), and the type flows through the wire protocol automatically. Clients 
receive PDT values as structured objects they
+can use directly or hydrate into language-native types.
+
+[[pdt-for-graph-providers]]
+=== For Graph Providers
+
+==== Basic Usage
+
+Annotate a class with `@ProviderDefined` from the 
`org.apache.tinkerpop.gremlin.structure.io.pdt` package:
+
+[source,java]
+----
+import org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefined;
+
+@ProviderDefined(name = "x:Point")
+public class Point {
+    private final double x;
+    private final double y;
+
+    public Point(double x, double y) {
+        this.x = x;
+        this.y = y;
+    }
+
+    public double getX() { return x; }
+    public double getY() { return y; }
+}
+----
+
+The `name` attribute is a unique identifier for the type, typically namespaced 
(e.g. `"x:Point"`). By default, all
+fields are included. Use `includedFields` or `excludedFields` to control which 
fields are serialized:
+
+[source,java]
+----
+@ProviderDefined(name = "x:Point", includedFields = {"x", "y"})
+public class Point { ... }
+
+// or exclude specific fields
+@ProviderDefined(name = "x:Person", excludedFields = {"internalId"})
+public class Person { ... }
+----
+
+==== Nested Types
+
+PDT supports nested custom types. Each nested type must also be annotated:
+
+[source,java]
+----
+@ProviderDefined(name = "x:Address")
+public class Address {
+    private final String street;
+    private final String city;
+
+    public Address(String street, String city) {
+        this.street = street;
+        this.city = city;
+    }
+
+    public String getStreet() { return street; }
+    public String getCity() { return city; }
+}
+
+@ProviderDefined(name = "x:Person")
+public class Person {
+    private final String name;
+    private final Address address;
+
+    public Person(String name, Address address) {
+        this.name = name;
+        this.address = address;
+    }
+
+    public String getName() { return name; }
+    public Address getAddress() { return address; }
+}
+----
+
+When serialized, the `address` field is itself encoded as a PDT value.
+
+==== Adapter for Types You Don't Own
+
+For classes you cannot annotate (e.g. `java.awt.Color`), implement 
`ProviderDefinedTypeAdapter<T>`:
+
+[source,java]
+----
+import 
org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter;
+
+public class ColorAdapter implements 
ProviderDefinedTypeAdapter<java.awt.Color> {
+
+    @Override
+    public String typeName() {
+        return "x:Color";
+    }
+
+    @Override
+    public Class<java.awt.Color> targetClass() {
+        return java.awt.Color.class;
+    }
+
+    @Override
+    public Map<String, Object> toProperties(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) {
+        return new java.awt.Color((int) fields.get("r"), (int) fields.get("g"),
+                                  (int) fields.get("b"), (int) 
fields.get("a"));
+    }
+}
+----
+
+==== ServiceLoader Registration
+
+Register adapters for auto-discovery by adding a file at:
+
+----
+META-INF/services/org.apache.tinkerpop.gremlin.structure.io.pdt.ProviderDefinedTypeAdapter
+----
+
+with the fully qualified class name of each adapter:
+
+----
+com.example.graph.ColorAdapter
+----
+
+Annotated classes (`@ProviderDefined`) are discovered automatically via 
classpath scanning and do not require
+ServiceLoader registration.
+
+[[pdt-for-driver-users]]
+=== For Driver Users
+
+==== Receiving PDT Values
+
+PDT values arrive on the client as `ProviderDefinedType` objects containing a 
`name` (String) and a `properties` map.
+No configuration is needed to receive them — any driver that supports the 
TinkerPop 4 wire format will deserialize
+PDTs automatically.
+
+[source,java]
+----
+// Java - values arrive as ProviderDefinedType by default
+ProviderDefinedType pdt = (ProviderDefinedType) vertex.value("location");
+String typeName = pdt.getName();           // "x:Point"
+Map<String, Object> props = pdt.getProperties(); // {x: 1.0, y: 2.0}
+----
+
+==== Optional Hydration
+
+To convert `ProviderDefinedType` into language-native objects, register 
adapters with a
+`ProviderDefinedTypeRegistry`. This is optional — basic consumption works 
without it.
+
+===== Java
+
+Implement `ProviderDefinedTypeAdapter<T>` and register via ServiceLoader (same 
mechanism as the provider side). The
+driver discovers adapters on the classpath and hydrates automatically.
+
+===== Python (planned)
+
+[source,python]
+----
+from gremlin_python.structure.io.pdt import provider_defined
+
+@provider_defined(name="x:Point")
+class Point:
+    def __init__(self, x: float, y: float):
+        self.x = x
+        self.y = y
+----
+
+Registration via `entry_points` in `setup.cfg` or `pyproject.toml`. This 
feature is designed but not yet implemented.
+
+===== .NET (planned)
+
+[source,csharp]
+----
+public class PointAdapter : IProviderDefinedTypeAdapter<Point>
+{
+    public string Name => "x:Point";
+
+    public Point FromFields(IDictionary<string, object> fields) =>
+        new Point((double)fields["x"], (double)fields["y"]);
+
+    public IDictionary<string, object> ToFields(Point value) =>
+        new Dictionary<string, object> { ["x"] = value.X, ["y"] = value.Y };
+}
+----
+
+Discovered via assembly scanning. This feature is designed but not yet 
implemented.
+
+===== JavaScript
+
+[source,javascript]
+----
+const { registry } = require('gremlin');
+
+registry.register('x:Point', {
+    serialize: (point) => ({ x: point.x, y: point.y }),
+    deserialize: (fields) => new Point(fields.x, fields.y)
+});
+----
+
+===== Go
+
+[source,go]
+----
+type Point struct {
+    X float64 `pdt:"x"`
+    Y float64 `pdt:"y"`
+}
+
+func init() {
+    pdt.RegisterFuncs("x:Point",
+        func(p Point) map[string]any { return map[string]any{"x": p.X, "y": 
p.Y} },
+        func(m map[string]any) Point { return Point{X: m["x"].(float64), Y: 
m["y"].(float64)} },
+    )
+}
+----
+
+[[pdt-wire-format-graphbinary]]
+=== Wire Format (GraphBinary V4)

Review Comment:
   isn't this just GraphBinary documentation? link to that instead of placing 
it here?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to