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

jorgebg pushed a commit to branch TINKERPOP-2149
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit e98a01f1193383c2c51a4dd951e505d681db6106
Author: Jorge Bay Gondra <jorgebaygon...@gmail.com>
AuthorDate: Mon Feb 4 16:59:02 2019 +0100

    TINKERPOP-2149 Add fallback resolver to TypeSerializerRegistry
---
 .../driver/ser/binary/TypeSerializerRegistry.java  | 44 ++++++++++++++++------
 .../ser/binary/TypeSerializerRegistryTest.java     | 38 +++++++++++++++++++
 .../ser/binary/types/sample/SamplePerson.java      |  2 +-
 3 files changed, 72 insertions(+), 12 deletions(-)

diff --git 
a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java
 
b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java
index 89022b8..ee9f08d 100644
--- 
a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java
+++ 
b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistry.java
@@ -82,6 +82,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
 
 public class TypeSerializerRegistry {
 
@@ -164,6 +165,7 @@ public class TypeSerializerRegistry {
 
     public static class Builder {
         private final List<RegistryEntry> list = new LinkedList<>();
+        private Function<Class<?>, TypeSerializer<?>> fallbackResolver;
 
         /**
          * Adds a serializer for a built-in type.
@@ -214,10 +216,18 @@ public class TypeSerializerRegistry {
         }
 
         /**
+         * Provides a way to resolve the type serializer to use when there 
isn't any direct match.
+         */
+        public Builder withFallbackResolver(Function<Class<?>, 
TypeSerializer<?>> fallbackResolver) {
+            this.fallbackResolver = fallbackResolver;
+            return this;
+        }
+
+        /**
          * Creates a new {@link TypeSerializerRegistry} instance based on the 
serializers added.
          */
         public TypeSerializerRegistry create() {
-            return new TypeSerializerRegistry(list);
+            return new TypeSerializerRegistry(list, fallbackResolver);
         }
     }
 
@@ -256,6 +266,7 @@ public class TypeSerializerRegistry {
     private final Map<Class<?>, TypeSerializer<?>> serializersByInterface = 
new LinkedHashMap<>();
     private final Map<DataType, TypeSerializer<?>> serializersByDataType = new 
HashMap<>();
     private final Map<String, CustomTypeSerializer> 
serializersByCustomTypeName = new HashMap<>();
+    private Function<Class<?>, TypeSerializer<?>> fallbackResolver;
 
     /**
      * Stores serializers by class, where the class resolution involved a 
lookup or special conditions.
@@ -263,7 +274,8 @@ public class TypeSerializerRegistry {
      */
     private final ConcurrentHashMap<Class<?>, TypeSerializer<?>> 
serializersByImplementation = new ConcurrentHashMap<>();
 
-    private TypeSerializerRegistry(final Collection<RegistryEntry> entries) {
+    private TypeSerializerRegistry(final Collection<RegistryEntry> entries,
+                                   final Function<Class<?>, TypeSerializer<?>> 
fallbackResolver) {
         final Set<Class> providedTypes = new HashSet<>(entries.size());
 
         // Include user-provided entries first
@@ -274,6 +286,8 @@ public class TypeSerializerRegistry {
 
         // Followed by the defaults
         Arrays.stream(defaultEntries).filter(e -> 
!providedTypes.contains(e.type)).forEach(this::put);
+
+        this.fallbackResolver = fallbackResolver;
     }
 
     private void put(final RegistryEntry entry) {
@@ -316,15 +330,16 @@ public class TypeSerializerRegistry {
             serializer = serializersByImplementation.get(type);
         }
 
-        if (null == serializer && Enum.class.isAssignableFrom(type)) {
+        if (serializer != null) {
+            return (TypeSerializer) serializer;
+        }
+
+        // Use different lookup techniques and cache the lookup result when 
successful
+
+        if (Enum.class.isAssignableFrom(type)) {
             // maybe it's a enum - enums with bodies are weird in java, they 
are subclasses of themselves, so
             // Columns.values will be of type Column$2.
             serializer = serializers.get(type.getSuperclass());
-
-            // In case it matched, store the match
-            if (serializer != null) {
-                serializersByImplementation.put(type, serializer);
-            }
         }
 
         if (null == serializer) {
@@ -332,14 +347,21 @@ public class TypeSerializerRegistry {
             for (Map.Entry<Class<?>, TypeSerializer<?>> entry : 
serializersByInterface.entrySet()) {
                 if (entry.getKey().isAssignableFrom(type)) {
                     serializer = entry.getValue();
-                    // Store the type-to-interface match, to avoid looking it 
up in the future
-                    serializersByImplementation.put(type, serializer);
                     break;
                 }
             }
         }
 
-        return validateInstance(serializer, type.getTypeName());
+        if (null == serializer && fallbackResolver != null) {
+            serializer = fallbackResolver.apply(type);
+        }
+
+        validateInstance(serializer, type.getTypeName());
+
+        // Store the lookup match to avoid looking it up in the future
+        serializersByImplementation.put(type, serializer);
+
+        return (TypeSerializer<DT>) serializer;
     }
 
     public <DT> TypeSerializer<DT> getSerializer(final DataType dataType) 
throws SerializationException {
diff --git 
a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java
 
b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java
index 40524c5..732abc0 100644
--- 
a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java
+++ 
b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/TypeSerializerRegistryTest.java
@@ -21,12 +21,15 @@ package org.apache.tinkerpop.gremlin.driver.ser.binary;
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.ByteBufAllocator;
 import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import 
org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample.SamplePerson;
+import 
org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample.SamplePersonSerializer;
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.junit.Test;
 
 import java.util.UUID;
 
+import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertSame;
 
 public class TypeSerializerRegistryTest {
@@ -75,6 +78,41 @@ public class TypeSerializerRegistryTest {
         assertSame(expectedForProperty, 
registry.getSerializer(DataType.PROPERTY));
     }
 
+    @Test
+    public void shouldUseFallbackResolverWhenThereIsNoMatch() {
+        final int[] called = {0};
+        final TypeSerializerRegistry registry = TypeSerializerRegistry.build()
+                .withFallbackResolver(t -> {
+                    called[0]++;
+                    return null;
+                }).create();
+
+        String message = null;
+        try {
+            registry.getSerializer(SamplePerson.class);
+        } catch (SerializationException ex) {
+            message = ex.getMessage();
+        }
+
+        assertEquals("Serializer for type 
org.apache.tinkerpop.gremlin.driver.ser.binary.types.sample.SamplePerson not 
found", message);
+        assertEquals(1, called[0]);
+    }
+
+    @Test
+    public void shouldUseFallbackResolverReturnValue() throws 
SerializationException {
+        TypeSerializer expected = new SamplePersonSerializer();
+        final int[] called = {0};
+        final TypeSerializerRegistry registry = TypeSerializerRegistry.build()
+                .withFallbackResolver(t -> {
+                    called[0]++;
+                    return expected;
+                }).create();
+
+        TypeSerializer<SamplePerson> serializer = 
registry.getSerializer(SamplePerson.class);
+        assertEquals(1, called[0]);
+        assertSame(expected, serializer);
+    }
+
     private static class TestVertexPropertySerializer extends 
TestBaseTypeSerializer<VertexProperty> {
 
         @Override
diff --git 
a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java
 
b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java
index 10d9bcb..fd4d05a 100644
--- 
a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java
+++ 
b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ser/binary/types/sample/SamplePerson.java
@@ -24,7 +24,7 @@ import java.util.Objects;
 /**
  * A sample custom data type containing few properties.
  */
-class SamplePerson {
+public class SamplePerson {
     private final String name;
     private final Date birthDate;
 

Reply via email to