You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2016/05/31 12:49:42 UTC

[35/49] incubator-tinkerpop git commit: Allow calls to addCustom on GryoMapper to override.

Allow calls to addCustom on GryoMapper to override.

By allowing override, users get complete control over the gryo serialization process and open up more options for Gremlin Server to offer other optional serialization views over gryo.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/d7684757
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/d7684757
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/d7684757

Branch: refs/heads/TINKERPOP-1298
Commit: d7684757734732f39970265a425b921a48d8f0fb
Parents: 985170e
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri May 20 08:33:59 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri May 27 10:59:46 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../upgrade/release-3.2.x-incubating.asciidoc   |  7 +++
 .../gremlin/structure/io/gryo/GryoMapper.java   | 44 +++++++++++---
 .../structure/io/gryo/GryoMapperTest.java       | 63 +++++++++++++++-----
 4 files changed, 92 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d7684757/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ca519b0..5aacd7b 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/incubator-tinkerpop/master/docs/
 TinkerPop 3.2.1 (NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* `GryoMapper` allows overrides of existing serializers on calls to `addCustom` on the builder.
 * Fixed a `NullPointerException` bug around nested `group()`-steps in OLAP.
 * Fixed a severe bug around halted traversers in a multi-job OLAP traversal chain.
 * Ensure a separation of `GraphComputer` and `VertexProgram` configurations in `SparkGraphComputer` and `GiraphGraphComputer`.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d7684757/docs/src/upgrade/release-3.2.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
index 66e5f8c..dec022f 100644
--- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
@@ -40,6 +40,13 @@ for Gremlin Console.
 
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-1297[TINKERPOP-1297]
 
+GryoMapper Construction
+^^^^^^^^^^^^^^^^^^^^^^^
+
+It is now possible to override existing serializers with calls to `addCustom` on the `GryoMapper` builder. This option
+allows complete control over the serializers used by Gryo. Of course, this also makes it possible to produce completely
+non-compliant Gryo files. This feature should be used with caution.
+
 TraversalVertexProgram
 ^^^^^^^^^^^^^^^^^^^^^^
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d7684757/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
index d510706..9cae845 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapper.java
@@ -68,6 +68,7 @@ import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertex;
 import org.apache.tinkerpop.gremlin.structure.util.reference.ReferenceVertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.star.StarGraph;
 import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphGryoSerializer;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.apache.tinkerpop.shaded.kryo.ClassResolver;
 import org.apache.tinkerpop.shaded.kryo.Kryo;
 import org.apache.tinkerpop.shaded.kryo.KryoSerializable;
@@ -104,12 +105,14 @@ import java.util.Date;
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.TimeZone;
 import java.util.TreeMap;
@@ -396,29 +399,43 @@ public final class GryoMapper implements Mapper<Kryo> {
         }
 
         /**
-         * Register custom classes to serializes with gryo using default serialization.
+         * Register custom classes to serializes with gryo using default serialization. Note that calling this method
+         * for a class that is already registered will override that registration.
          */
         public Builder addCustom(final Class... custom) {
-            if (custom != null && custom.length > 0)
-                serializationList.addAll(Arrays.asList(custom).stream()
-                        .map(c -> Triplet.<Class, Function<Kryo, Serializer>, Integer>with(c, null, currentSerializationId.getAndIncrement()))
-                        .collect(Collectors.<Triplet<Class, Function<Kryo, Serializer>, Integer>>toList()));
+            if (custom != null && custom.length > 0) {
+                for (Class clazz : custom) {
+                    addCustom(clazz, (Function<Kryo, Serializer>) null);
+                }
+            }
             return this;
         }
 
         /**
-         * Register custom class to serialize with a custom serialization class.
+         * Register custom class to serialize with a custom serialization class. Note that calling this method for
+         * a class that is already registered will override that registration.
          */
         public Builder addCustom(final Class clazz, final Serializer serializer) {
-            serializationList.add(Triplet.with(clazz, kryo -> serializer, currentSerializationId.getAndIncrement()));
+            if (null == serializer)
+                addCustom(clazz);
+            else
+                addCustom(clazz, kryo -> serializer);
             return this;
         }
 
         /**
-         * Register a custom class to serialize with a custom serializer as returned from a {@link Function}.
+         * Register a custom class to serialize with a custom serializer as returned from a {@link Function}. Note
+         * that calling this method for a class that is already registered will override that registration.
          */
         public Builder addCustom(final Class clazz, final Function<Kryo, Serializer> serializer) {
-            serializationList.add(Triplet.with(clazz, serializer, currentSerializationId.getAndIncrement()));
+            final Optional<Triplet<Class, Function<Kryo, Serializer>, Integer>> found = findSerializer(clazz);
+            if (found.isPresent()) {
+                final Triplet<Class, Function<Kryo, Serializer>, Integer> t = found.get();
+                serializationList.remove(t);
+                serializationList.add(t.setAt1(serializer));
+            } else
+                serializationList.add(Triplet.with(clazz, serializer, currentSerializationId.getAndIncrement()));
+
             return this;
         }
 
@@ -473,5 +490,14 @@ public final class GryoMapper implements Mapper<Kryo> {
 
             return new GryoMapper(this);
         }
+
+        private Optional<Triplet<Class, Function<Kryo, Serializer>, Integer>> findSerializer(final Class clazz) {
+            final Iterator<Triplet<Class, Function<Kryo, Serializer>, Integer>> itty = IteratorUtils.filter(
+                    serializationList, t -> t.getValue0().equals(clazz)).iterator();
+            if (itty.hasNext())
+                return Optional.of(itty.next());
+            else
+                return Optional.empty();
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/d7684757/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
index 861c6f6..29ddc57 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
@@ -29,6 +29,7 @@ import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
 import org.apache.tinkerpop.shaded.kryo.ClassResolver;
 import org.apache.tinkerpop.shaded.kryo.Kryo;
 import org.apache.tinkerpop.shaded.kryo.Registration;
+import org.apache.tinkerpop.shaded.kryo.Serializer;
 import org.apache.tinkerpop.shaded.kryo.io.Input;
 import org.apache.tinkerpop.shaded.kryo.io.Output;
 import org.junit.Test;
@@ -57,9 +58,12 @@ import java.util.Map;
 import java.util.function.Supplier;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.fail;
 
 /**
  * @author Stephen Mallette (http://stephen.genoprime.com)
@@ -220,85 +224,100 @@ public class GryoMapperTest {
     }
 
     @Test
-    public void shouldHandleDuration()throws Exception  {
+    public void shouldOverrideExistingSerializer() throws Exception {
+        final GryoMapper mapper = GryoMapper.build()
+                .addCustom(Duration.class, new OverrideDurationSerializer()).create();
+
+        try (final OutputStream stream = new ByteArrayOutputStream()) {
+            final Output out = new Output(stream);
+            mapper.createMapper().writeObject(out, Duration.ZERO);
+            fail("The OverrideDurationSerializer throws exceptions so this should not have worked");
+        } catch (Exception ex) {
+            assertThat(ex, instanceOf(UnsupportedOperationException.class));
+            assertEquals("I don't do anything", ex.getMessage());
+        }
+    }
+
+    @Test
+    public void shouldHandleDuration() throws Exception  {
         final Duration o = Duration.ZERO;
         assertEquals(o, serializeDeserialize(o, Duration.class));
     }
 
     @Test
-    public void shouldHandleInstant()throws Exception  {
+    public void shouldHandleInstant() throws Exception  {
         final Instant o = Instant.ofEpochMilli(System.currentTimeMillis());
         assertEquals(o, serializeDeserialize(o, Instant.class));
     }
 
     @Test
-    public void shouldHandleLocalDate()throws Exception  {
+    public void shouldHandleLocalDate() throws Exception  {
         final LocalDate o = LocalDate.now();
         assertEquals(o, serializeDeserialize(o, LocalDate.class));
     }
 
     @Test
-    public void shouldHandleLocalDateTime()throws Exception  {
+    public void shouldHandleLocalDateTime() throws Exception  {
         final LocalDateTime o = LocalDateTime.now();
         assertEquals(o, serializeDeserialize(o, LocalDateTime.class));
     }
 
     @Test
-    public void shouldHandleLocalTime()throws Exception  {
+    public void shouldHandleLocalTime() throws Exception  {
         final LocalTime o = LocalTime.now();
         assertEquals(o, serializeDeserialize(o, LocalTime.class));
     }
 
     @Test
-    public void shouldHandleMonthDay()throws Exception  {
+    public void shouldHandleMonthDay() throws Exception  {
         final MonthDay o = MonthDay.now();
         assertEquals(o, serializeDeserialize(o, MonthDay.class));
     }
 
     @Test
-    public void shouldHandleOffsetDateTime()throws Exception  {
+    public void shouldHandleOffsetDateTime() throws Exception  {
         final OffsetDateTime o = OffsetDateTime.now();
         assertEquals(o, serializeDeserialize(o, OffsetDateTime.class));
     }
 
     @Test
-    public void shouldHandleOffsetTime()throws Exception  {
+    public void shouldHandleOffsetTime() throws Exception  {
         final OffsetTime o = OffsetTime.now();
         assertEquals(o, serializeDeserialize(o, OffsetTime.class));
     }
 
     @Test
-    public void shouldHandlePeriod()throws Exception  {
+    public void shouldHandlePeriod() throws Exception  {
         final Period o = Period.ofDays(3);
         assertEquals(o, serializeDeserialize(o, Period.class));
     }
 
     @Test
-    public void shouldHandleYear()throws Exception  {
+    public void shouldHandleYear() throws Exception  {
         final Year o = Year.now();
         assertEquals(o, serializeDeserialize(o, Year.class));
     }
 
     @Test
-    public void shouldHandleYearMonth()throws Exception  {
+    public void shouldHandleYearMonth() throws Exception  {
         final YearMonth o = YearMonth.now();
         assertEquals(o, serializeDeserialize(o, YearMonth.class));
     }
 
     @Test
-    public void shouldHandleZonedDateTime()throws Exception  {
+    public void shouldHandleZonedDateTime() throws Exception  {
         final ZonedDateTime o = ZonedDateTime.now();
         assertEquals(o, serializeDeserialize(o, ZonedDateTime.class));
     }
 
     @Test
-    public void shouldHandleZonedOffset()throws Exception  {
+    public void shouldHandleZonedOffset() throws Exception  {
         final ZoneOffset o  = ZonedDateTime.now().getOffset();
         assertEquals(o, serializeDeserialize(o, ZoneOffset.class));
     }
 
     @Test
-    public void shouldHandleTraversalExplanation()throws Exception  {
+    public void shouldHandleTraversalExplanation() throws Exception  {
         final TraversalExplanation te = __().out().outV().outE().explain();
         assertEquals(te.toString(), serializeDeserialize(te, TraversalExplanation.class).toString());
     }
@@ -349,4 +368,20 @@ public class GryoMapperTest {
             }
         }
     }
+
+    final static class OverrideDurationSerializer extends Serializer<Duration>
+    {
+        @Override
+        public void write(final Kryo kryo, final Output output, final Duration duration)
+        {
+            throw new UnsupportedOperationException("I don't do anything");
+        }
+
+        @Override
+        public Duration read(final Kryo kryo, final Input input, final Class<Duration> durationClass)
+        {
+            throw new UnsupportedOperationException("I don't do anything");
+        }
+    }
+
 }