This is an automated email from the ASF dual-hosted git repository. xiazcy pushed a commit to branch graphbinary-ordered-map in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
commit bfcdae21aa0d1096c26b028053a17f9bf5e03dde Author: Yang Xia <[email protected]> AuthorDate: Mon Sep 16 20:29:41 2024 -0700 refactored graphbinary serializers in java and python to process `value_flag` byte and added ordered flag 0x02 to map serializers --- CHANGELOG.asciidoc | 2 + .../structure/io/binary/GraphBinaryWriter.java | 10 +++ .../io/binary/types/BigDecimalSerializer.java | 2 +- .../io/binary/types/BigIntegerSerializer.java | 2 +- .../io/binary/types/BulkSetSerializer.java | 2 +- .../io/binary/types/ByteBufferSerializer.java | 2 +- .../structure/io/binary/types/CharSerializer.java | 2 +- .../io/binary/types/CollectionSerializer.java | 2 +- .../io/binary/types/DateTimeSerializer.java | 2 +- .../io/binary/types/DurationSerializer.java | 2 +- .../structure/io/binary/types/EdgeSerializer.java | 2 +- .../structure/io/binary/types/EnumSerializer.java | 12 +--- .../structure/io/binary/types/GraphSerializer.java | 2 +- .../structure/io/binary/types/ListSerializer.java | 4 +- .../io/binary/types/MapEntrySerializer.java | 2 +- .../structure/io/binary/types/MapSerializer.java | 6 +- .../structure/io/binary/types/PSerializer.java | 3 +- .../structure/io/binary/types/PathSerializer.java | 2 +- .../io/binary/types/PropertySerializer.java | 2 +- .../structure/io/binary/types/SetSerializer.java | 4 +- .../io/binary/types/SimpleTypeSerializer.java | 22 +++++-- .../io/binary/types/SingleTypeSerializer.java | 3 +- .../io/binary/types/StringSerializer.java | 2 +- .../types/TraversalExplanationSerializer.java | 2 +- .../io/binary/types/TraverserSerializer.java | 2 +- .../structure/io/binary/types/TreeSerializer.java | 2 +- .../structure/io/binary/types/UUIDSerializer.java | 2 +- .../io/binary/types/VertexPropertySerializer.java | 2 +- .../io/binary/types/VertexSerializer.java | 2 +- .../gremlin_python/structure/io/graphbinaryV4.py | 74 +++++++++++++--------- .../tests/structure/io/test_graphbinaryV4.py | 8 +++ .../gremlin/util/ser/AbstractRoundTripTest.java | 8 ++- 32 files changed, 116 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc index e561a2154e..30642b1746 100644 --- a/CHANGELOG.asciidoc +++ b/CHANGELOG.asciidoc @@ -65,6 +65,8 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima * Remove serializers for datatype removed from GraphBinaryV4 IO spec. * Add `DateTime` serializer for Java and Python according to GraphBinaryV4 IO spec. * Replaced `Date` with `OffsetDateTime` in Java core. +* Refactored GraphBinary serializers in Java and Python to read and write the `value_flag` byte set by different serializers for special handling. +* Add ordered `value_flag` `0x02` to Map serializers in Java and Python drivers. * The `maxContentLength` setting for Gremlin Driver has been renamed to `maxResponseContentLength` and now blocks incoming responses that are too large based on total response size. * The `maxContentLength` setting for Gremlin Server has been renamed to `maxRequestContentLength`. diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriter.java index 80b1df0b1b..53a2a55868 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriter.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/GraphBinaryWriter.java @@ -45,6 +45,7 @@ public class GraphBinaryWriter { private final TypeSerializerRegistry registry; private final static byte VALUE_FLAG_NULL = 1; private final static byte VALUE_FLAG_NONE = 0; + private final static byte VALUE_FLAG_ORDERED = 2; public final static byte VERSION_BYTE = (byte)0x81; private final static byte[] unspecifiedNullBytes = new byte[] { DataType.UNSPECIFIED_NULL.getCodeByte(), 0x01}; private final static byte[] customTypeCodeBytes = new byte[] { DataType.CUSTOM.getCodeByte() }; @@ -135,4 +136,13 @@ public class GraphBinaryWriter { public void writeValueFlagNone(Buffer buffer) { buffer.writeByte(VALUE_FLAG_NONE); } + + /** + * Writes a single byte with value 2, representing an ordered value_flag. + */ + public void writeValueFlagOrdered(Buffer buffer) { + buffer.writeByte(VALUE_FLAG_ORDERED); + } + + } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigDecimalSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigDecimalSerializer.java index ad8add1865..c02cdb520e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigDecimalSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigDecimalSerializer.java @@ -36,7 +36,7 @@ public class BigDecimalSerializer extends SimpleTypeSerializer<BigDecimal> { } @Override - protected BigDecimal readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected BigDecimal readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final int scale = context.readValue(buffer, Integer.class, false); final BigInteger unscaled = context.readValue(buffer, BigInteger.class, false); return new BigDecimal(unscaled, scale); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigIntegerSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigIntegerSerializer.java index ab877c7d1b..a680c1ec4c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigIntegerSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BigIntegerSerializer.java @@ -36,7 +36,7 @@ public class BigIntegerSerializer extends SimpleTypeSerializer<BigInteger> { } @Override - protected BigInteger readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected BigInteger readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final byte[] bigIntBytes = new byte[buffer.readInt()]; buffer.readBytes(bigIntBytes); return new BigInteger(bigIntBytes); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BulkSetSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BulkSetSerializer.java index 7811f73366..9ebb495566 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BulkSetSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/BulkSetSerializer.java @@ -36,7 +36,7 @@ public class BulkSetSerializer extends SimpleTypeSerializer<BulkSet> { } @Override - protected BulkSet readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected BulkSet readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final int length = buffer.readInt(); final BulkSet result = new BulkSet(); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ByteBufferSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ByteBufferSerializer.java index 4e613ce158..01eebfd820 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ByteBufferSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ByteBufferSerializer.java @@ -36,7 +36,7 @@ public class ByteBufferSerializer extends SimpleTypeSerializer<ByteBuffer> { } @Override - protected ByteBuffer readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected ByteBuffer readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final ByteBuffer bb = ByteBuffer.allocate(buffer.readInt()); buffer.readBytes(bb); bb.rewind(); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CharSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CharSerializer.java index 89110b72b1..5f68e59e77 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CharSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CharSerializer.java @@ -32,7 +32,7 @@ public class CharSerializer extends SimpleTypeSerializer<Character> { } @Override - protected Character readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Character readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final int firstByte = buffer.readByte() & 0xff; int byteLength = 1; // A byte with the first byte ON (10000000) signals that more bytes are needed to represent the UTF-8 char diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CollectionSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CollectionSerializer.java index b5020bd965..3f493d533c 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CollectionSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/CollectionSerializer.java @@ -33,7 +33,7 @@ class CollectionSerializer extends SimpleTypeSerializer<Collection> { } @Override - protected Collection readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Collection readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final int length = buffer.readInt(); final ArrayList result = new ArrayList(length); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DateTimeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DateTimeSerializer.java index 416ceb8aa1..e4ce833426 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DateTimeSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DateTimeSerializer.java @@ -39,7 +39,7 @@ public class DateTimeSerializer extends SimpleTypeSerializer<OffsetDateTime> { } @Override - protected OffsetDateTime readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected OffsetDateTime readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final LocalDate localDate = LocalDate.of(buffer.readInt(), buffer.readByte(), buffer.readByte()); final LocalTime localTime = LocalTime.ofNanoOfDay(buffer.readLong()); final LocalDateTime ldt = LocalDateTime.of(localDate, localTime); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DurationSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DurationSerializer.java index 9c0b52630f..66b6561dc4 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DurationSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/DurationSerializer.java @@ -35,7 +35,7 @@ public class DurationSerializer extends SimpleTypeSerializer<Duration> { } @Override - protected Duration readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Duration readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { return Duration.ofSeconds(buffer.readLong(), buffer.readInt()); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java index 6c52b815e5..3dffc4c983 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EdgeSerializer.java @@ -40,7 +40,7 @@ public class EdgeSerializer extends SimpleTypeSerializer<Edge> { } @Override - protected Edge readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Edge readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final Object id = context.read(buffer); final String label = context.readValue(buffer, String.class, false); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java index 394477dd4b..cea0de3372 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/EnumSerializer.java @@ -18,21 +18,11 @@ */ package org.apache.tinkerpop.gremlin.structure.io.binary.types; -import org.apache.tinkerpop.gremlin.process.traversal.DT; -import org.apache.tinkerpop.gremlin.process.traversal.Merge; -import org.apache.tinkerpop.gremlin.process.traversal.Operator; -import org.apache.tinkerpop.gremlin.process.traversal.Order; -import org.apache.tinkerpop.gremlin.process.traversal.Pick; -import org.apache.tinkerpop.gremlin.process.traversal.Pop; -import org.apache.tinkerpop.gremlin.process.traversal.SackFunctions; -import org.apache.tinkerpop.gremlin.process.traversal.Scope; import org.apache.tinkerpop.gremlin.structure.io.binary.DataType; import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; -import org.apache.tinkerpop.gremlin.structure.Column; import org.apache.tinkerpop.gremlin.structure.Direction; import org.apache.tinkerpop.gremlin.structure.T; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; import org.apache.tinkerpop.gremlin.structure.io.Buffer; import java.io.IOException; @@ -56,7 +46,7 @@ public class EnumSerializer<E extends Enum> extends SimpleTypeSerializer<E> { } @Override - protected E readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected E readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { return readFunc.apply(context.read(buffer)); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java index f107b8afac..41511884e8 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/GraphSerializer.java @@ -51,7 +51,7 @@ public class GraphSerializer extends SimpleTypeSerializer<Graph> { } @Override - protected Graph readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Graph readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { if (null == openMethod) throw new IOException("TinkerGraph is an optional dependency to gremlin-driver - if deserializing Graph instances it must be explicitly added as a dependency"); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ListSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ListSerializer.java index 74ac14bd31..7ee26bb460 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ListSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/ListSerializer.java @@ -34,9 +34,9 @@ public class ListSerializer extends SimpleTypeSerializer<List> { } @Override - protected List readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected List readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { // The collection is a List<> - return (List) collectionSerializer.readValue(buffer, context); + return (List) collectionSerializer.readValue(buffer, context, valueFlag); } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapEntrySerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapEntrySerializer.java index e8a28d6328..3912c4748a 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapEntrySerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapEntrySerializer.java @@ -32,7 +32,7 @@ public class MapEntrySerializer extends SimpleTypeSerializer<Map.Entry> implemen } @Override - protected Map.Entry readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Map.Entry readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { throw new IOException("A map entry should not be read individually"); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapSerializer.java index c2b95d0b53..230c8f2483 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/MapSerializer.java @@ -24,6 +24,7 @@ import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; import org.apache.tinkerpop.gremlin.structure.io.Buffer; import java.io.IOException; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -34,10 +35,11 @@ public class MapSerializer extends SimpleTypeSerializer<Map> { } @Override - protected Map readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Map readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final int length = buffer.readInt(); - final Map<Object,Object> result = new LinkedHashMap<>(length); + // original read value outputs LinkedHashMap, do we want to keep all result as LinkedHashMap anyway? + final Map<Object,Object> result = (valueFlag & 2) == 2 ? new LinkedHashMap<>(length) : new HashMap<>(length); for (int i = 0; i < length; i++) { result.put(context.read(buffer), context.read(buffer)); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java index 5190457a3f..ef0c7d5f6e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PSerializer.java @@ -22,7 +22,6 @@ import org.apache.tinkerpop.gremlin.structure.io.binary.DataType; import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; import org.apache.tinkerpop.gremlin.process.traversal.P; -import org.apache.tinkerpop.gremlin.process.traversal.util.AndP; import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP; import org.apache.tinkerpop.gremlin.structure.io.Buffer; @@ -53,7 +52,7 @@ public class PSerializer<T extends P> extends SimpleTypeSerializer<T> { } @Override - protected T readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected T readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final String predicateName = context.readValue(buffer, String.class, false); final int length = context.readValue(buffer, Integer.class, false); final Object[] args = new Object[length]; diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PathSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PathSerializer.java index b59436c8e0..1d5b3fc829 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PathSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PathSerializer.java @@ -40,7 +40,7 @@ public class PathSerializer extends SimpleTypeSerializer<Path> { } @Override - protected Path readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Path readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final MutablePath path = (MutablePath) MutablePath.make(); final List<Set<String>> labels = context.read(buffer); final List<Object> objects = context.read(buffer); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PropertySerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PropertySerializer.java index cfa22ef1cd..1626967141 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PropertySerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/PropertySerializer.java @@ -37,7 +37,7 @@ public class PropertySerializer extends SimpleTypeSerializer<Property> { } @Override - protected Property readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Property readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final Property p = new ReferenceProperty<>(context.readValue(buffer, String.class, false), context.read(buffer)); // discard the parent element as it's not serialized for references right now diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SetSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SetSerializer.java index 9a7a7392e0..abe88c0daa 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SetSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SetSerializer.java @@ -35,8 +35,8 @@ public class SetSerializer extends SimpleTypeSerializer<Set>{ } @Override - protected Set readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { - return new HashSet<>(collectionSerializer.readValue(buffer, context)); + protected Set readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { + return new HashSet<>(collectionSerializer.readValue(buffer, context, valueFlag)); } @Override diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SimpleTypeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SimpleTypeSerializer.java index 8c7918f973..745638b9f8 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SimpleTypeSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SimpleTypeSerializer.java @@ -25,6 +25,7 @@ import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializer; import org.apache.tinkerpop.gremlin.structure.io.Buffer; import java.io.IOException; +import java.util.LinkedHashMap; /** * Base class for serialization of types that don't contain type specific information only {type_code}, {value_flag} @@ -49,24 +50,27 @@ public abstract class SimpleTypeSerializer<T> implements TypeSerializer<T> { @Override public T readValue(final Buffer buffer, final GraphBinaryReader context, final boolean nullable) throws IOException { + byte valueFlag =(byte)0x00; if (nullable) { - final byte valueFlag = buffer.readByte(); + valueFlag = buffer.readByte(); if ((valueFlag & 1) == 1) { return null; } } - return readValue(buffer, context); + return readValue(buffer, context, valueFlag); } /** * Reads a non-nullable value according to the type format. - * @param buffer A buffer which reader index has been set to the beginning of the {value}. - * @param context The binary reader. - * @return + * + * @param buffer A buffer which reader index has been set to the beginning of the {value}. + * @param context The binary reader. + * @param valueFlag The {value_flag} set by different serializers for special handling, e.g. 0x02 as ordering for Maps. * @throws IOException + * @since 4.0.0 */ - protected abstract T readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException; + protected abstract T readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException; @Override public void write(final T value, final Buffer buffer, final GraphBinaryWriter context) throws IOException { @@ -85,7 +89,11 @@ public abstract class SimpleTypeSerializer<T> implements TypeSerializer<T> { } if (nullable) { - context.writeValueFlagNone(buffer); + if (value instanceof LinkedHashMap) { + context.writeValueFlagOrdered(buffer); + } else { + context.writeValueFlagNone(buffer); + } } writeValue(value, buffer, context); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SingleTypeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SingleTypeSerializer.java index 3b4390e87e..7d234929bf 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SingleTypeSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/SingleTypeSerializer.java @@ -24,7 +24,6 @@ import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; import org.apache.tinkerpop.gremlin.structure.io.Buffer; import org.apache.tinkerpop.gremlin.structure.io.binary.Marker; -import java.time.Year; import java.util.function.BiConsumer; import java.util.function.Function; @@ -63,7 +62,7 @@ public class SingleTypeSerializer<T> extends SimpleTypeSerializer<T> { } @Override - public T readValue(final Buffer buffer, final GraphBinaryReader context) { + public T readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) { return readFunc.apply(buffer); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/StringSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/StringSerializer.java index c90c5e1991..e2487ae99e 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/StringSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/StringSerializer.java @@ -31,7 +31,7 @@ public class StringSerializer extends SimpleTypeSerializer<String> { } @Override - protected String readValue(final Buffer buffer, final GraphBinaryReader context) { + protected String readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) { // Use Netty 4.0 API (avoid ByteBuf#readCharSequence() method) to maximize compatibility final byte[] bytes = new byte[buffer.readInt()]; buffer.readBytes(bytes); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalExplanationSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalExplanationSerializer.java index 5c8d8bd095..24bde4dd98 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalExplanationSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraversalExplanationSerializer.java @@ -45,7 +45,7 @@ public class TraversalExplanationSerializer extends SimpleTypeSerializer<Travers } @Override - protected TraversalExplanation readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected TraversalExplanation readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { throw new IOException("A TraversalExplanation should not be read individually"); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraverserSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraverserSerializer.java index 6361fb01e8..59d9cbd1f7 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraverserSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TraverserSerializer.java @@ -37,7 +37,7 @@ public class TraverserSerializer extends SimpleTypeSerializer<Traverser> { } @Override - protected Traverser readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Traverser readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final long bulk = context.readValue(buffer, Long.class, false); final Object v = context.read(buffer); return new DefaultRemoteTraverser<>(v, bulk); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TreeSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TreeSerializer.java index 66bbf8ed4c..aa5ecc197d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TreeSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/TreeSerializer.java @@ -32,7 +32,7 @@ public class TreeSerializer extends SimpleTypeSerializer<Tree> { } @Override - protected Tree readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Tree readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final int length = buffer.readInt(); final Tree result = new Tree(); diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/UUIDSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/UUIDSerializer.java index dc458d4837..2d615679fd 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/UUIDSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/UUIDSerializer.java @@ -31,7 +31,7 @@ public class UUIDSerializer extends SimpleTypeSerializer<UUID> { } @Override - protected UUID readValue(final Buffer buffer, final GraphBinaryReader context) { + protected UUID readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) { return new UUID(buffer.readLong(), buffer.readLong()); } diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java index dd3afbec05..90c8dc6c28 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexPropertySerializer.java @@ -41,7 +41,7 @@ public class VertexPropertySerializer extends SimpleTypeSerializer<VertexPropert } @Override - protected VertexProperty readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected VertexProperty readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final DetachedVertexProperty.Builder builder = DetachedVertexProperty.build() .setId(context.read(buffer)) .setLabel(context.readValue(buffer, String.class, false)) diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java index f25055e9a2..56b88d6b5d 100644 --- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java +++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/binary/types/VertexSerializer.java @@ -39,7 +39,7 @@ public class VertexSerializer extends SimpleTypeSerializer<Vertex> { } @Override - protected Vertex readValue(final Buffer buffer, final GraphBinaryReader context) throws IOException { + protected Vertex readValue(final Buffer buffer, final GraphBinaryReader context, byte valueFlag) throws IOException { final Object id = context.read(buffer); final String label = context.readValue(buffer, String.class, false); final List<DetachedVertexProperty> properties = context.read(buffer); 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 3cf8f53a3e..4818121743 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 @@ -171,7 +171,7 @@ class _GraphBinaryTypeIO(object, metaclass=GraphBinaryTypeType): graphbinary_type = None @classmethod - def prefix_bytes(cls, graphbin_type, as_value=False, nullable=True, to_extend=None): + def prefix_bytes(cls, graphbin_type, as_value=False, nullable=True, to_extend=None, ordered=False): if to_extend is None: to_extend = bytearray() @@ -179,7 +179,10 @@ class _GraphBinaryTypeIO(object, metaclass=GraphBinaryTypeType): to_extend += uint8_pack(graphbin_type.value) if nullable: - to_extend += int8_pack(0) + if ordered: + to_extend += int8_pack(2) + else: + to_extend += int8_pack(0) return to_extend @@ -189,7 +192,14 @@ class _GraphBinaryTypeIO(object, metaclass=GraphBinaryTypeType): @classmethod def is_null(cls, buff, reader, else_opt, nullable=True): - return None if nullable and buff.read(1)[0] == 0x01 else else_opt(buff, reader) + flag = 0x00 + if nullable: + flag = buff.read(1)[0] + if flag == 0x01: + return None + else: + return else_opt(buff, reader, flag) + return else_opt(buff, reader, flag) def dictify(self, obj, writer, to_extend, as_value=False, nullable=True): raise NotImplementedError() @@ -216,7 +226,7 @@ class LongIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: int64_unpack(buff.read(8)), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: int64_unpack(buff.read(8)), nullable) class IntIO(LongIO): @@ -228,7 +238,7 @@ class IntIO(LongIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: cls.read_int(b), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: cls.read_int(b), nullable) class ShortIO(LongIO): @@ -240,7 +250,7 @@ class ShortIO(LongIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: int16_unpack(buff.read(2)), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: int16_unpack(buff.read(2)), nullable) class BigIntIO(_GraphBinaryTypeIO): @@ -275,7 +285,7 @@ class BigIntIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=False): - return cls.is_null(buff, reader, lambda b, r: cls.read_bigint(b), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: cls.read_bigint(b), nullable) def _long_bits_to_double(bits): @@ -314,7 +324,7 @@ class FloatIO(LongIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: float_unpack(b.read(4)), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: float_unpack(b.read(4)), nullable) class DoubleIO(FloatIO): @@ -329,7 +339,7 @@ class DoubleIO(FloatIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: double_unpack(b.read(8)), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: double_unpack(b.read(8)), nullable) class BigDecimalIO(_GraphBinaryTypeIO): @@ -351,7 +361,7 @@ class BigDecimalIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=False): - return cls.is_null(buff, reader, lambda b, r: cls._read(b), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: cls._read(b), nullable) class DateTimeIO(_GraphBinaryTypeIO): @@ -383,7 +393,7 @@ class DateTimeIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_dt, nullable) @classmethod - def _read_dt(cls, b, r): + def _read_dt(cls, b, r, flag): year = r.to_object(b, DataType.int, False) month = r.to_object(b, DataType.byte, False) day = r.to_object(b, DataType.byte, False) @@ -408,7 +418,7 @@ class CharIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_char, nullable) @classmethod - def _read_char(cls, b, r): + def _read_char(cls, b, r, flag): max_bytes = 4 x = b.read(1) while max_bytes > 0: @@ -434,7 +444,7 @@ class StringIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: b.read(cls.read_int(b)).decode("utf-8"), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: b.read(cls.read_int(b)).decode("utf-8"), nullable) class ListIO(_GraphBinaryTypeIO): @@ -456,7 +466,7 @@ class ListIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_list, nullable) @classmethod - def _read_list(cls, b, r): + def _read_list(cls, b, r, flag): size = cls.read_int(b) the_list = [] while size > 0: @@ -483,7 +493,7 @@ class MapIO(_GraphBinaryTypeIO): @classmethod def dictify(cls, obj, writer, to_extend, as_value=False, nullable=True): - cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend) + cls.prefix_bytes(cls.graphbinary_type, as_value, nullable, to_extend, ordered=isinstance(obj, OrderedDict)) to_extend.extend(int32_pack(len(obj))) for k, v in obj.items(): @@ -497,9 +507,11 @@ class MapIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_map, nullable) @classmethod - def _read_map(cls, b, r): + def _read_map(cls, b, r, flag): size = cls.read_int(b) - the_dict = {} + # python dict preserves insertion order as of 3.7, but does not assert order for equality, do we want to use + # the actual OrderedDict or keep as dict regardless of {flag_value}? + the_dict = OrderedDict() if flag == 0x02 else {} while size > 0: k = HashableDict.of(r.read_object(b)) v = r.read_object(b) @@ -522,7 +534,7 @@ class UuidIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: uuid.UUID(bytes=b.read(16)), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: uuid.UUID(bytes=b.read(16)), nullable) class EdgeIO(_GraphBinaryTypeIO): @@ -550,7 +562,7 @@ class EdgeIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_edge, nullable) @classmethod - def _read_edge(cls, b, r): + def _read_edge(cls, b, r, flag): edgeid = r.read_object(b) edgelbl = r.to_object(b, DataType.string, False) inv = Vertex(r.read_object(b), r.to_object(b, DataType.string, False)) @@ -575,7 +587,7 @@ class PathIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): - return cls.is_null(buff, reader, lambda b, r: Path(r.read_object(b), r.read_object(b)), nullable) + return cls.is_null(buff, reader, lambda b, r, flag: Path(r.read_object(b), r.read_object(b)), nullable) class PropertyIO(_GraphBinaryTypeIO): @@ -596,7 +608,7 @@ class PropertyIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_property, nullable) @classmethod - def _read_property(cls, b, r): + def _read_property(cls, b, r, flag): p = Property(r.to_object(b, DataType.string, False), r.read_object(b), None) b.read(2) return p @@ -634,7 +646,7 @@ class VertexIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_vertex, nullable) @classmethod - def _read_vertex(cls, b, r): + def _read_vertex(cls, b, r, flag): vertex = Vertex(r.read_object(b), r.to_object(b, DataType.string, False), r.read_object(b)) return vertex @@ -659,7 +671,7 @@ class VertexPropertyIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_vertexproperty, nullable) @classmethod - def _read_vertexproperty(cls, b, r): + def _read_vertexproperty(cls, b, r, flag): vp = VertexProperty(r.read_object(b), r.to_object(b, DataType.string, False), r.read_object(b), None) b.read(2) vp.properties = r.read_object(b) @@ -679,7 +691,7 @@ class _EnumIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_enumval, nullable) @classmethod - def _read_enumval(cls, b, r): + def _read_enumval(cls, b, r, flag): enum_name = r.to_object(b) return cls.python_type[SymbolUtil.to_snake_case(enum_name)] @@ -689,7 +701,7 @@ class DirectionIO(_EnumIO): python_type = Direction @classmethod - def _read_enumval(cls, b, r): + def _read_enumval(cls, b, r, flag): # Direction needs to retain all CAPS. note that to_/from_ are really just aliases of IN/OUT # so they don't need to be accounted for in serialization enum_name = r.to_object(b) @@ -714,7 +726,7 @@ class ByteIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): return cls.is_null(buff, reader, - lambda b, r: int.__new__(SingleByte, int8_unpack(b.read(1))), + lambda b, r, flag: int.__new__(SingleByte, int8_unpack(b.read(1))), nullable) @@ -734,7 +746,7 @@ class ByteBufferIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_bytebuffer, nullable) @classmethod - def _read_bytebuffer(cls, b, r): + def _read_bytebuffer(cls, b, r, flag): size = cls.read_int(b) return ByteBufferType(b.read(size)) @@ -752,7 +764,7 @@ class BooleanIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): return cls.is_null(buff, reader, - lambda b, r: True if int8_unpack(b.read(1)) == 0x01 else False, + lambda b, r, flag: True if int8_unpack(b.read(1)) == 0x01 else False, nullable) @@ -766,7 +778,7 @@ class BulkSetDeserializer(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_bulkset, nullable) @classmethod - def _read_bulkset(cls, b, r): + def _read_bulkset(cls, b, r, flag): size = cls.read_int(b) the_list = [] while size > 0: @@ -795,7 +807,7 @@ class DurationIO(_GraphBinaryTypeIO): return cls.is_null(buff, reader, cls._read_duration, nullable) @classmethod - def _read_duration(cls, b, r): + def _read_duration(cls, b, r, flag): seconds = r.to_object(b, DataType.long, False) nanos = r.to_object(b, DataType.int, False) return timedelta(seconds=seconds, microseconds=nanos / 1000) @@ -814,5 +826,5 @@ class MarkerIO(_GraphBinaryTypeIO): @classmethod def objectify(cls, buff, reader, nullable=True): return cls.is_null(buff, reader, - lambda b, r: Marker.of(int8_unpack(b.read(1))), + lambda b, r, flag: Marker.of(int8_unpack(b.read(1))), nullable) \ No newline at end of file diff --git a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV4.py b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV4.py index 486773fa0d..ae878f3638 100644 --- a/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV4.py +++ b/gremlin-python/src/main/python/tests/structure/io/test_graphbinaryV4.py @@ -19,6 +19,7 @@ under the License. import uuid import math +from collections import OrderedDict from datetime import datetime, timedelta, timezone from gremlin_python.statics import long, bigint, BigDecimal, SingleByte, SingleChar, ByteBufferType @@ -149,6 +150,13 @@ class TestGraphBinaryV4(object): output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x)) assert x == output + def test_ordered_dict(self): + x = OrderedDict() + x['a'] = 1 + x['b'] = 2 + output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x)) + assert x == output + def test_uuid(self): x = uuid.UUID("41d2e28a-20a4-4ab0-b379-d810dede3786") output = self.graphbinary_reader.read_object(self.graphbinary_writer.write_object(x)) diff --git a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java index c1bcc66529..d361784f07 100644 --- a/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java +++ b/gremlin-util/src/test/java/org/apache/tinkerpop/gremlin/util/ser/AbstractRoundTripTest.java @@ -81,6 +81,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -107,6 +108,10 @@ public abstract class AbstractRoundTripTest { final Map<String, Map<String, Integer>> nestedMap = new HashMap<>(); nestedMap.put("first", map); + final Map<String, Integer> orderedMap = new LinkedHashMap<>(); + map.put("one", 1); + map.put("two", 2); + final List<Object> list = new ArrayList<>(); list.add("string 1"); list.add("string 1"); @@ -214,7 +219,8 @@ public abstract class AbstractRoundTripTest { new Object[] {"ListSingle", list, null}, new Object[] {"ListNested", nestedList, null}, new Object[] {"Map", map, null}, - new Object[] {"Map", nestedMap, null}, + new Object[] {"MapNested", nestedMap, null}, + new Object[] {"OrderedMap", orderedMap, null}, new Object[] {"Set", set, null}, new Object[] {"SetNested", nestedSet, null}); }
