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;