You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2015/03/03 19:10:38 UTC
[6/8] incubator-tinkerpop git commit: Renamed Gremlin Kryo to simply
Gryo.
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
new file mode 100644
index 0000000..164758d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
@@ -0,0 +1,400 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.gryo;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import org.apache.tinkerpop.gremlin.process.T;
+import org.apache.tinkerpop.gremlin.structure.*;
+import org.apache.tinkerpop.gremlin.structure.io.GraphReader;
+import org.apache.tinkerpop.gremlin.structure.util.batch.BatchGraph;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
+
+import java.io.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Function;
+
+/**
+ * The {@link GraphReader} for the Gremlin Structure serialization format based on Kryo. The format is meant to be
+ * non-lossy in terms of Gremlin Structure to Gremlin Structure migrations (assuming both structure implementations
+ * support the same graph features).
+ * <br/>
+ * This implementation is not thread-safe.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class GryoReader implements GraphReader {
+ private final Kryo kryo;
+ private final GryoMapper.HeaderReader headerReader;
+
+ private final long batchSize;
+ private final String vertexIdKey;
+ private final String edgeIdKey;
+
+ private final File tempFile;
+
+ final AtomicLong counter = new AtomicLong(0);
+
+ private GryoReader(final File tempFile, final long batchSize,
+ final String vertexIdKey, final String edgeIdKey,
+ final GryoMapper gryoMapper) {
+ this.kryo = gryoMapper.createMapper();
+ this.headerReader = gryoMapper.getHeaderReader();
+ this.vertexIdKey = vertexIdKey;
+ this.edgeIdKey = edgeIdKey;
+ this.tempFile = tempFile;
+ this.batchSize = batchSize;
+ }
+
+ @Override
+ public Iterator<Vertex> readVertices(final InputStream inputStream, final Direction direction,
+ final Function<DetachedVertex, Vertex> vertexMaker,
+ final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+ final Input input = new Input(inputStream);
+ return new Iterator<Vertex>() {
+ @Override
+ public boolean hasNext() {
+ return !input.eof();
+ }
+
+ @Override
+ public Vertex next() {
+ try {
+ final Vertex v = readVertex(direction, vertexMaker, edgeMaker, input);
+
+ // read the vertex terminator
+ kryo.readClassAndObject(input);
+
+ return v;
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ };
+ }
+
+ @Override
+ public Edge readEdge(final InputStream inputStream, final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+ final Input input = new Input(inputStream);
+ this.headerReader.read(kryo, input);
+ final Object o = kryo.readClassAndObject(input);
+ return edgeMaker.apply((DetachedEdge) o);
+ }
+
+ @Override
+ public Vertex readVertex(final InputStream inputStream, final Function<DetachedVertex, Vertex> vertexMaker) throws IOException {
+ return readVertex(inputStream, null, vertexMaker, null);
+ }
+
+ @Override
+ public Vertex readVertex(final InputStream inputStream, final Direction direction, Function<DetachedVertex, Vertex> vertexMaker, final Function<DetachedEdge, Edge> edgeMaker) throws IOException {
+ final Input input = new Input(inputStream);
+ return readVertex(direction, vertexMaker, edgeMaker, input);
+ }
+
+ @Override
+ public void readGraph(final InputStream inputStream, final Graph graphToWriteTo) throws IOException {
+ this.counter.set(0);
+ final Input input = new Input(inputStream);
+ this.headerReader.read(kryo, input);
+
+ final BatchGraph graph;
+ try {
+ // will throw an exception if not constructed properly
+ graph = BatchGraph.build(graphToWriteTo)
+ .vertexIdKey(vertexIdKey)
+ .edgeIdKey(edgeIdKey)
+ .bufferSize(batchSize).create();
+ } catch (Exception ex) {
+ throw new IOException("Could not instantiate BatchGraph wrapper", ex);
+ }
+
+ try (final Output output = new Output(new FileOutputStream(tempFile))) {
+ final boolean supportedMemory = input.readBoolean();
+ if (supportedMemory) {
+ // if the graph that serialized the data supported sideEffects then the sideEffects needs to be read
+ // to advance the reader forward. if the graph being read into doesn't support the sideEffects
+ // then we just setting the data to sideEffects.
+ final Map<String, Object> memMap = (Map<String, Object>) kryo.readObject(input, HashMap.class);
+ if (graphToWriteTo.features().graph().variables().supportsVariables()) {
+ final Graph.Variables variables = graphToWriteTo.variables();
+ memMap.forEach(variables::set);
+ }
+ }
+
+ final boolean hasSomeVertices = input.readBoolean();
+ if (hasSomeVertices) {
+ final List<Object> vertexArgs = new ArrayList<>();
+ while (!input.eof()) {
+ final DetachedVertex current = (DetachedVertex) kryo.readClassAndObject(input);
+ appendToArgList(vertexArgs, T.id, current.id());
+ appendToArgList(vertexArgs, T.label, current.label());
+
+ final Vertex v = graph.addVertex(vertexArgs.toArray());
+ vertexArgs.clear();
+ current.iterators().propertyIterator().forEachRemaining(p -> createVertexProperty(graphToWriteTo, v, p, false));
+
+ // the gio file should have been written with a direction specified
+ final boolean hasDirectionSpecified = input.readBoolean();
+ final Direction directionInStream = kryo.readObject(input, Direction.class);
+ final Direction directionOfEdgeBatch = kryo.readObject(input, Direction.class);
+
+ // graph serialization requires that a direction be specified in the stream and that the
+ // direction of the edges be OUT
+ if (!hasDirectionSpecified || directionInStream != Direction.OUT || directionOfEdgeBatch != Direction.OUT)
+ throw new IllegalStateException(String.format("Stream must specify edge direction and that direction must be %s", Direction.OUT));
+
+ // if there are edges then read them to end and write to temp, otherwise read what should be
+ // the vertex terminator
+ if (!input.readBoolean())
+ kryo.readClassAndObject(input);
+ else
+ readToEndOfEdgesAndWriteToTemp(input, output);
+ }
+ }
+ } catch (Exception ex) {
+ throw new IOException(ex);
+ }
+ // done writing to temp
+
+ // start reading in the edges now from the temp file
+ try (final Input edgeInput = new Input(new FileInputStream(tempFile))) {
+ readFromTempEdges(edgeInput, graph);
+ graph.tx().commit();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new IOException(ex);
+ } finally {
+ deleteTempFileSilently();
+ }
+ }
+
+ private static void createVertexProperty(final Graph graphToWriteTo, final Vertex v, final VertexProperty<Object> p, final boolean hidden) {
+ final List<Object> propertyArgs = new ArrayList<>();
+ if (graphToWriteTo.features().vertex().properties().supportsUserSuppliedIds())
+ appendToArgList(propertyArgs, T.id, p.id());
+ p.iterators().propertyIterator().forEachRemaining(it -> appendToArgList(propertyArgs, it.key(), it.value()));
+ v.property(p.key(), p.value(), propertyArgs.toArray());
+ }
+
+ private static void appendToArgList(final List<Object> propertyArgs, final Object key, final Object val) {
+ propertyArgs.add(key);
+ propertyArgs.add(val);
+ }
+
+ private Vertex readVertex(final Direction directionRequested, final Function<DetachedVertex, Vertex> vertexMaker,
+ final Function<DetachedEdge, Edge> edgeMaker, final Input input) throws IOException {
+ if (null != directionRequested && null == edgeMaker)
+ throw new IllegalArgumentException("If a directionRequested is specified then an edgeAdder function should also be specified");
+
+ this.headerReader.read(kryo, input);
+
+ final DetachedVertex detachedVertex = (DetachedVertex) kryo.readClassAndObject(input);
+ final Vertex v = vertexMaker.apply(detachedVertex);
+
+ final boolean streamContainsEdgesInSomeDirection = input.readBoolean();
+ if (!streamContainsEdgesInSomeDirection && directionRequested != null)
+ throw new IllegalStateException(String.format("The direction %s was requested but no attempt was made to serialize edges into this stream", directionRequested));
+
+ // if there are edges in the stream and the direction is not present then the rest of the stream is
+ // simply ignored
+ if (directionRequested != null) {
+ final Direction directionsInStream = kryo.readObject(input, Direction.class);
+ if (directionsInStream != Direction.BOTH && directionsInStream != directionRequested)
+ throw new IllegalStateException(String.format("Stream contains %s edges, but requesting %s", directionsInStream, directionRequested));
+
+ final Direction firstDirection = kryo.readObject(input, Direction.class);
+ if (firstDirection == Direction.OUT && (directionRequested == Direction.BOTH || directionRequested == Direction.OUT))
+ readEdges(input, edgeMaker);
+ else {
+ // requested direction in, but BOTH must be serialized so skip this. the illegalstateexception
+ // prior to this IF should have caught a problem where IN is not supported at all
+ if (firstDirection == Direction.OUT && directionRequested == Direction.IN)
+ skipEdges(input);
+ }
+
+ if (directionRequested == Direction.BOTH || directionRequested == Direction.IN) {
+ // if the first direction was OUT then it was either read or skipped. in that case, the marker
+ // of the stream is currently ready to read the IN direction. otherwise it's in the perfect place
+ // to start reading edges
+ if (firstDirection == Direction.OUT)
+ kryo.readObject(input, Direction.class);
+
+ readEdges(input, edgeMaker);
+ }
+ }
+
+ return v;
+ }
+
+ private void readEdges(final Input input, final Function<DetachedEdge, Edge> edgeMaker) {
+ if (input.readBoolean()) {
+ Object next = kryo.readClassAndObject(input);
+ while (!next.equals(EdgeTerminator.INSTANCE)) {
+ final DetachedEdge detachedEdge = (DetachedEdge) next;
+ edgeMaker.apply(detachedEdge);
+ next = kryo.readClassAndObject(input);
+ }
+ }
+ }
+
+ private void skipEdges(final Input input) {
+ if (input.readBoolean()) {
+ Object next = kryo.readClassAndObject(input);
+ while (!next.equals(EdgeTerminator.INSTANCE)) {
+ // next edge to skip or the terminator
+ next = kryo.readClassAndObject(input);
+ }
+ }
+ }
+
+ /**
+ * Reads through the all the edges for a vertex and writes the edges to a temp file which will be read later.
+ */
+ private void readToEndOfEdgesAndWriteToTemp(final Input input, final Output output) throws IOException {
+ Object next = kryo.readClassAndObject(input);
+ while (!next.equals(EdgeTerminator.INSTANCE)) {
+ kryo.writeClassAndObject(output, next);
+
+ // next edge or terminator
+ next = kryo.readClassAndObject(input);
+ }
+
+ // this should be the vertex terminator
+ kryo.readClassAndObject(input);
+
+ kryo.writeClassAndObject(output, EdgeTerminator.INSTANCE);
+ kryo.writeClassAndObject(output, VertexTerminator.INSTANCE);
+ }
+
+
+ /**
+ * Read the edges from the temp file and load them to the graph.
+ */
+ private void readFromTempEdges(final Input input, final Graph graphToWriteTo) {
+ final List<Object> edgeArgs = new ArrayList<>();
+ while (!input.eof()) {
+ // in this case the outId is the id assigned by the graph
+ Object next = kryo.readClassAndObject(input);
+ while (!next.equals(EdgeTerminator.INSTANCE)) {
+ final DetachedEdge detachedEdge = (DetachedEdge) next;
+ final Vertex vOut = graphToWriteTo.iterators().vertexIterator(detachedEdge.iterators().vertexIterator(Direction.OUT).next().id()).next();
+ final Vertex inV = graphToWriteTo.iterators().vertexIterator(detachedEdge.iterators().vertexIterator(Direction.IN).next().id()).next();
+
+ detachedEdge.iterators().propertyIterator().forEachRemaining(p -> edgeArgs.addAll(Arrays.asList(p.key(), p.value())));
+
+ appendToArgList(edgeArgs, T.id, detachedEdge.id());
+
+ vOut.addEdge(detachedEdge.label(), inV, edgeArgs.toArray());
+
+ edgeArgs.clear();
+ next = kryo.readClassAndObject(input);
+ }
+
+ // vertex terminator
+ kryo.readClassAndObject(input);
+ }
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ private void deleteTempFileSilently() {
+ try {
+ tempFile.delete();
+ } catch (Exception ignored) {
+ }
+ }
+
+ public static Builder build() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private File tempFile;
+ private long batchSize = BatchGraph.DEFAULT_BUFFER_SIZE;
+ private String vertexIdKey = T.id.getAccessor();
+ private String edgeIdKey = T.id.getAccessor();
+
+ /**
+ * Always use the most recent gryo version by default
+ */
+ private GryoMapper gryoMapper = GryoMapper.build().create();
+
+ private Builder() {
+ this.tempFile = new File(UUID.randomUUID() + ".tmp");
+ }
+
+ /**
+ * Set the size between commits when reading into the {@link Graph} instance. This value defaults to
+ * {@link BatchGraph#DEFAULT_BUFFER_SIZE}.
+ */
+ public Builder batchSize(final long batchSize) {
+ this.batchSize = batchSize;
+ return this;
+ }
+
+ /**
+ * Supply a mapper {@link GryoMapper} instance to use as the serializer for the {@code KryoWriter}.
+ */
+ public Builder mapper(final GryoMapper gryoMapper) {
+ this.gryoMapper = gryoMapper;
+ return this;
+ }
+
+ /**
+ * The name of the key to supply to
+ * {@link org.apache.tinkerpop.gremlin.structure.util.batch.BatchGraph.Builder#vertexIdKey} when reading data into
+ * the {@link Graph}.
+ */
+ public Builder vertexIdKey(final String vertexIdKey) {
+ this.vertexIdKey = vertexIdKey;
+ return this;
+ }
+
+ /**
+ * The name of the key to supply to
+ * {@link org.apache.tinkerpop.gremlin.structure.util.batch.BatchGraph.Builder#edgeIdKey} when reading data into
+ * the {@link Graph}.
+ */
+ public Builder edgeIdKey(final String edgeIdKey) {
+ this.edgeIdKey = edgeIdKey;
+ return this;
+ }
+
+ /**
+ * The reader requires a working directory to write temp files to. If this value is not set, it will write
+ * the temp file to the local directory.
+ */
+ public Builder workingDirectory(final String workingDirectory) {
+ final File f = new File(workingDirectory);
+ if (!f.exists() || !f.isDirectory())
+ throw new IllegalArgumentException(String.format("%s is not a directory or does not exist", workingDirectory));
+
+ tempFile = new File(workingDirectory + File.separator + UUID.randomUUID() + ".tmp");
+ return this;
+ }
+
+ public GryoReader create() {
+ return new GryoReader(tempFile, batchSize, this.vertexIdKey, this.edgeIdKey, this.gryoMapper);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoWriter.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoWriter.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoWriter.java
new file mode 100644
index 0000000..6b31e43
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoWriter.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.gryo;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Output;
+import org.apache.tinkerpop.gremlin.structure.Direction;
+import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.io.GraphWriter;
+import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.UUID;
+
+/**
+ * The {@link GraphWriter} for the Gremlin Structure serialization format based on Kryo. The format is meant to be
+ * non-lossy in terms of Gremlin Structure to Gremlin Structure migrations (assuming both structure implementations
+ * support the same graph features).
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GryoWriter implements GraphWriter {
+ private Kryo kryo;
+ private final GryoMapper.HeaderWriter headerWriter;
+ private static final UUID delimiter = UUID.fromString("2DEE3ABF-9963-4546-A578-C1C48690D7F7");
+ public static final byte[] DELIMITER = new byte[16];
+
+ static {
+ final ByteBuffer bb = ByteBuffer.wrap(DELIMITER);
+ bb.putLong(delimiter.getMostSignificantBits());
+ bb.putLong(delimiter.getLeastSignificantBits());
+ }
+
+ private GryoWriter(final GryoMapper gryoMapper) {
+ this.kryo = gryoMapper.createMapper();
+ this.headerWriter = gryoMapper.getHeaderWriter();
+ }
+
+ @Override
+ public void writeGraph(final OutputStream outputStream, final Graph g) throws IOException {
+ final Output output = new Output(outputStream);
+ this.headerWriter.write(kryo, output);
+
+ final boolean supportsGraphMemory = g.features().graph().variables().supportsVariables();
+ output.writeBoolean(supportsGraphMemory);
+ if (supportsGraphMemory)
+ kryo.writeObject(output, new HashMap(g.variables().asMap()));
+
+ final Iterator<Vertex> vertices = g.iterators().vertexIterator();
+ final boolean hasSomeVertices = vertices.hasNext();
+ output.writeBoolean(hasSomeVertices);
+ while (vertices.hasNext()) {
+ final Vertex v = vertices.next();
+ writeVertexToOutput(output, v, Direction.OUT);
+ }
+
+ output.flush();
+ }
+
+ @Override
+ public void writeVertex(final OutputStream outputStream, final Vertex v, final Direction direction) throws IOException {
+ final Output output = new Output(outputStream);
+ this.headerWriter.write(kryo, output);
+ writeVertexToOutput(output, v, direction);
+ output.flush();
+ }
+
+ @Override
+ public void writeVertex(final OutputStream outputStream, final Vertex v) throws IOException {
+ final Output output = new Output(outputStream);
+ this.headerWriter.write(kryo, output);
+ writeVertexWithNoEdgesToOutput(output, v);
+ output.flush();
+ }
+
+ @Override
+ public void writeEdge(final OutputStream outputStream, final Edge e) throws IOException {
+ final Output output = new Output(outputStream);
+ this.headerWriter.write(kryo, output);
+ kryo.writeClassAndObject(output, DetachedFactory.detach(e, true));
+ output.flush();
+ }
+
+ private void writeEdgeToOutput(final Output output, final Edge e) {
+ this.writeElement(output, e, null);
+ }
+
+ private void writeVertexWithNoEdgesToOutput(final Output output, final Vertex v) {
+ writeElement(output, v, null);
+ }
+
+ private void writeVertexToOutput(final Output output, final Vertex v, final Direction direction) {
+ this.writeElement(output, v, direction);
+ }
+
+ private void writeElement(final Output output, final Element e, final Direction direction) {
+ kryo.writeClassAndObject(output, e);
+
+ if (e instanceof Vertex) {
+ output.writeBoolean(direction != null);
+ if (direction != null) {
+ final Vertex v = (Vertex) e;
+ kryo.writeObject(output, direction);
+ if (direction == Direction.BOTH || direction == Direction.OUT)
+ writeDirectionalEdges(output, Direction.OUT, v.iterators().edgeIterator(Direction.OUT));
+
+ if (direction == Direction.BOTH || direction == Direction.IN)
+ writeDirectionalEdges(output, Direction.IN, v.iterators().edgeIterator(Direction.IN));
+ }
+
+ kryo.writeClassAndObject(output, VertexTerminator.INSTANCE);
+ }
+ }
+
+ private void writeDirectionalEdges(final Output output, final Direction d, final Iterator<Edge> vertexEdges) {
+ final boolean hasEdges = vertexEdges.hasNext();
+ kryo.writeObject(output, d);
+ output.writeBoolean(hasEdges);
+
+ while (vertexEdges.hasNext()) {
+ final Edge edgeToWrite = vertexEdges.next();
+ writeEdgeToOutput(output, edgeToWrite);
+ }
+
+ if (hasEdges)
+ kryo.writeClassAndObject(output, EdgeTerminator.INSTANCE);
+ }
+
+ public static Builder build() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ /**
+ * Always creates the most current version available.
+ */
+ private GryoMapper gryoMapper = GryoMapper.build().create();
+
+ private Builder() {
+ }
+
+ /**
+ * Supply a mapper {@link GryoMapper} instance to use as the serializer for the {@code KryoWriter}.
+ */
+ public Builder mapper(final GryoMapper gryoMapper) {
+ this.gryoMapper = gryoMapper;
+ return this;
+ }
+
+ /**
+ * Create the {@code GryoWriter}.
+ */
+ public GryoWriter create() {
+ return new GryoWriter(this.gryoMapper);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/URISerializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/URISerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/URISerializer.java
new file mode 100644
index 0000000..c0c7b48
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/URISerializer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.gryo;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+import java.net.URI;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class URISerializer extends Serializer<URI> {
+
+ public URISerializer() {
+ setImmutable(true);
+ }
+
+ @Override
+ public void write(final Kryo kryo, final Output output, final URI uri) {
+ output.writeString(uri.toString());
+ }
+
+ @Override
+ public URI read(final Kryo kryo, final Input input, final Class<URI> uriClass) {
+ return URI.create(input.readString());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UUIDSerializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UUIDSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UUIDSerializer.java
new file mode 100644
index 0000000..ffcf199
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/UUIDSerializer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.gryo;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+import java.util.UUID;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class UUIDSerializer extends Serializer<UUID> {
+ public UUIDSerializer() {
+ setImmutable(true);
+ }
+
+ @Override
+ public void write(final Kryo kryo, final Output output, final UUID uuid) {
+ output.writeLong(uuid.getMostSignificantBits());
+ output.writeLong(uuid.getLeastSignificantBits());
+ }
+
+ @Override
+ public UUID read(final Kryo kryo, final Input input, final Class<UUID> uuidClass) {
+ return new UUID(input.readLong(), input.readLong());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexByteArrayInputStream.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexByteArrayInputStream.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexByteArrayInputStream.java
new file mode 100644
index 0000000..3544009
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexByteArrayInputStream.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.gryo;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * An {@link InputStream} implementation that can independently process a Gryo file written with
+ * {@link GryoWriter#writeVertices(java.io.OutputStream, org.apache.tinkerpop.gremlin.process.Traversal)}.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class VertexByteArrayInputStream extends FilterInputStream {
+
+ private static final byte[] vertexTerminatorClass = new byte[]{15, 1, 1, 9};
+ private static final byte[] pattern = ByteBuffer.allocate(vertexTerminatorClass.length + 8).put(vertexTerminatorClass).putLong(4185403236219066774L).array();
+
+ public VertexByteArrayInputStream(final InputStream inputStream) {
+ super(inputStream);
+ }
+
+ /**
+ * Read the bytes of the next {@link org.apache.tinkerpop.gremlin.structure.Vertex} in the stream. The returned
+ * stream can then be passed to {@link GryoReader#readVertex(java.io.InputStream, java.util.function.Function)}.
+ */
+ public ByteArrayOutputStream readVertexBytes() throws IOException {
+ final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ final LinkedList<Byte> buffer = new LinkedList<>();
+
+ int current = read();
+ while (current > -1 && (buffer.size() < 12 || !isMatch(buffer))) {
+ stream.write(current);
+
+ current = read();
+ if (buffer.size() > 11)
+ buffer.removeFirst();
+
+ buffer.addLast((byte) current);
+ }
+
+ return stream;
+ }
+
+ private static boolean isMatch(final List<Byte> input) {
+ for (int i = 0; i < pattern.length; i++) {
+ if (pattern[i] != input.get(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexTerminator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexTerminator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexTerminator.java
new file mode 100644
index 0000000..7f056ae
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/VertexTerminator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.gryo;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * Represents the end of a vertex in a serialization stream.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+class VertexTerminator {
+ public static final VertexTerminator INSTANCE = new VertexTerminator();
+
+ public final byte[] terminal;
+
+ private VertexTerminator() {
+ terminal = ByteBuffer.allocate(8).putLong(4185403236219066774L).array();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final VertexTerminator that = (VertexTerminator) o;
+
+ return terminal == that.terminal;
+
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(terminal);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EdgeTerminator.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EdgeTerminator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EdgeTerminator.java
deleted file mode 100644
index 17ab9f3..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EdgeTerminator.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-package org.apache.tinkerpop.gremlin.structure.io.kryo;
-
-/**
- * Represents the end of an edge list in a serialization stream.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-class EdgeTerminator {
- public static final EdgeTerminator INSTANCE = new EdgeTerminator();
- private final boolean terminal;
-
- private EdgeTerminator() {
- this.terminal = true;
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final EdgeTerminator that = (EdgeTerminator) o;
-
- return terminal == that.terminal;
- }
-
- @Override
- public int hashCode() {
- return (terminal ? 1 : 0);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EntrySerializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EntrySerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EntrySerializer.java
deleted file mode 100644
index befd18c..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/EntrySerializer.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.
- */
-package org.apache.tinkerpop.gremlin.structure.io.kryo;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-
-import java.util.AbstractMap;
-import java.util.Map;
-
-/**
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-class EntrySerializer extends Serializer<Map.Entry> {
- @Override
- public void write(final Kryo kryo, final Output output, final Map.Entry entry) {
- kryo.writeClassAndObject(output, entry.getKey());
- kryo.writeClassAndObject(output, entry.getValue());
- }
-
- @Override
- public Map.Entry read(final Kryo kryo, final Input input, final Class<Map.Entry> entryClass) {
- return new AbstractMap.SimpleEntry(kryo.readClassAndObject(input), kryo.readClassAndObject(input));
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GraphSerializer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GraphSerializer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GraphSerializer.java
deleted file mode 100644
index dc378e5..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GraphSerializer.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.
- */
-package org.apache.tinkerpop.gremlin.structure.io.kryo;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import org.apache.tinkerpop.gremlin.process.Path;
-import org.apache.tinkerpop.gremlin.process.Traverser;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedFactory;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedPath;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
-
-/**
- * Class used to serialize graph-based objects such as vertices, edges, properties, and paths.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
-class GraphSerializer {
- /**
- * Serializes any {@link Edge} implementation encountered to a {@link DetachedEdge}.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
- static class EdgeSerializer extends Serializer<Edge> {
- @Override
- public void write(final Kryo kryo, final Output output, final Edge edge) {
- kryo.writeClassAndObject(output, DetachedFactory.detach(edge, true));
- }
-
- @Override
- public Edge read(final Kryo kryo, final Input input, final Class<Edge> edgeClass) {
- final Object o = kryo.readClassAndObject(input);
- return (Edge) o;
- }
- }
-
- /**
- * Serializes any {@link Vertex} implementation encountered to an {@link DetachedVertex}.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
- static class VertexSerializer extends Serializer<Vertex> {
- public VertexSerializer() {
- }
-
- @Override
- public void write(final Kryo kryo, final Output output, final Vertex vertex) {
- kryo.writeClassAndObject(output, DetachedFactory.detach(vertex, true));
- }
-
- @Override
- public Vertex read(final Kryo kryo, final Input input, final Class<Vertex> vertexClass) {
- return (Vertex) kryo.readClassAndObject(input);
- }
- }
-
- /**
- * Serializes any {@link Property} implementation encountered to an {@link DetachedProperty}.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
- static class PropertySerializer extends Serializer<Property> {
- public PropertySerializer() {
- }
-
- @Override
- public void write(final Kryo kryo, final Output output, final Property property) {
- kryo.writeClassAndObject(output, DetachedFactory.detach(property));
- }
-
- @Override
- public Property read(final Kryo kryo, final Input input, final Class<Property> propertyClass) {
- return (Property) kryo.readClassAndObject(input);
- }
- }
-
- /**
- * Serializes any {@link VertexProperty} implementation encountered to an {@link DetachedVertexProperty}.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
- static class VertexPropertySerializer extends Serializer<VertexProperty> {
- public VertexPropertySerializer() {
- }
-
- @Override
- public void write(final Kryo kryo, final Output output, final VertexProperty vertexProperty) {
- kryo.writeClassAndObject(output, DetachedFactory.detach(vertexProperty, true));
- }
-
- @Override
- public VertexProperty read(final Kryo kryo, final Input input, final Class<VertexProperty> vertexPropertyClass) {
- return (VertexProperty) kryo.readClassAndObject(input);
- }
- }
-
- /**
- * Serializes any {@link Path} implementation encountered to an {@link DetachedPath}.
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
- static class PathSerializer extends Serializer<Path> {
- public PathSerializer() {
- }
-
- @Override
- public void write(final Kryo kryo, final Output output, final Path path) {
- kryo.writeClassAndObject(output, DetachedFactory.detach(path, false));
- }
-
- @Override
- public Path read(final Kryo kryo, final Input input, final Class<Path> pathClass) {
- return (Path) kryo.readClassAndObject(input);
- }
-
- }
-
- /**
- * Serializes any {@link Traverser} implementation encountered via pre-processing with {@link Traverser.Admin#detach()}.
- *
- * @author Marko A. Rodriguez (http://markorodriguez.com)
- */
- /*static class TraverserSerializer extends Serializer<Traverser.Admin> {
- public TraverserSerializer() {
- }
-
- @Override
- public void write(final Kryo kryo, final Output output, final Traverser.Admin traverser) {
- kryo.writeClassAndObject(output, traverser.asAdmin().detach());
- }
-
- @Override
- public Traverser.Admin read(final Kryo kryo, final Input input, final Class<Traverser.Admin> traverser) {
- return (Traverser.Admin) kryo.readClassAndObject(input);
- }
-
- }*/
-}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GremlinClassResolver.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GremlinClassResolver.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GremlinClassResolver.java
deleted file mode 100644
index a7c48b9..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/GremlinClassResolver.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * 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.
- */
-package org.apache.tinkerpop.gremlin.structure.io.kryo;
-
-import com.esotericsoftware.kryo.ClassResolver;
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.KryoException;
-import com.esotericsoftware.kryo.Registration;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.util.IdentityObjectIntMap;
-import com.esotericsoftware.kryo.util.IntMap;
-import com.esotericsoftware.kryo.util.ObjectMap;
-import org.apache.tinkerpop.gremlin.process.Path;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedPath;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
-
-import static com.esotericsoftware.kryo.util.Util.getWrapperClass;
-
-/**
- * This mapper implementation of the {@code ClassResolver} helps ensure that all Vertex and Edge concrete classes
- * get properly serialized and deserialized by stripping them of their concrete class name so that they are treated
- * generically.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-class GremlinClassResolver implements ClassResolver {
- static public final byte NAME = -1;
-
- protected Kryo kryo;
-
- protected final IntMap<Registration> idToRegistration = new IntMap<>();
- protected final ObjectMap<Class, Registration> classToRegistration = new ObjectMap<>();
-
- protected IdentityObjectIntMap<Class> classToNameId;
- protected IntMap<Class> nameIdToClass;
- protected ObjectMap<String, Class> nameToClass;
- protected int nextNameId;
-
- private int memoizedClassId = -1;
- private Registration memoizedClassIdValue;
- private Class memoizedClass;
- private Registration memoizedClassValue;
-
- @Override
- public void setKryo(Kryo kryo) {
- this.kryo = kryo;
- }
-
- @Override
- public Registration register(final Registration registration) {
- if (null == registration) throw new IllegalArgumentException("Registration cannot be null.");
- if (registration.getId() != NAME) idToRegistration.put(registration.getId(), registration);
-
- classToRegistration.put(registration.getType(), registration);
- if (registration.getType().isPrimitive())
- classToRegistration.put(getWrapperClass(registration.getType()), registration);
- return registration;
- }
-
- @Override
- public Registration registerImplicit(final Class type) {
- return register(new Registration(type, kryo.getDefaultSerializer(type), NAME));
- }
-
- @Override
- public Registration getRegistration(final Class clazz) {
- // force all instances of Vertex, Edge, VertexProperty, etc. to their respective interface
- final Class type;
- if (!DetachedVertex.class.isAssignableFrom(clazz) && Vertex.class.isAssignableFrom(clazz))
- type = Vertex.class;
- else if (!DetachedEdge.class.isAssignableFrom(clazz) && Edge.class.isAssignableFrom(clazz))
- type = Edge.class;
- else if (!DetachedVertexProperty.class.isAssignableFrom(clazz) && VertexProperty.class.isAssignableFrom(clazz))
- type = VertexProperty.class;
- else if (!DetachedProperty.class.isAssignableFrom(clazz) && !DetachedVertexProperty.class.isAssignableFrom(clazz) && Property.class.isAssignableFrom(clazz))
- type = Property.class;
- else if (!DetachedPath.class.isAssignableFrom(clazz) && Path.class.isAssignableFrom(clazz))
- type = Path.class;
- else
- type = clazz;
-
- if (type == memoizedClass) return memoizedClassValue;
- final Registration registration = classToRegistration.get(type);
- if (registration != null) {
- memoizedClass = type;
- memoizedClassValue = registration;
- }
-
- return registration;
- }
-
- @Override
- public Registration getRegistration(final int classID) {
- return idToRegistration.get(classID);
- }
-
- @Override
- public Registration writeClass(final Output output, final Class type) {
- if (null == type) {
- output.writeVarInt(Kryo.NULL, true);
- return null;
- }
-
- final Registration registration = kryo.getRegistration(type);
- if (registration.getId() == NAME)
- writeName(output, type);
- else
- output.writeVarInt(registration.getId() + 2, true);
-
- return registration;
- }
-
- protected void writeName(final Output output, final Class type) {
- output.writeVarInt(NAME + 2, true);
- if (classToNameId != null) {
- final int nameId = classToNameId.get(type, -1);
- if (nameId != -1) {
- output.writeVarInt(nameId, true);
- return;
- }
- }
- // Only write the class name the first time encountered in object graph.
- final int nameId = nextNameId++;
- if (classToNameId == null) classToNameId = new IdentityObjectIntMap<>();
- classToNameId.put(type, nameId);
- output.writeVarInt(nameId, true);
- output.writeString(type.getName());
- }
-
- @Override
- public Registration readClass(final Input input) {
- final int classID = input.readVarInt(true);
- switch (classID) {
- case Kryo.NULL:
- return null;
- case NAME + 2: // Offset for NAME and NULL.
- return readName(input);
- }
-
- if (classID == memoizedClassId) return memoizedClassIdValue;
- final Registration registration = idToRegistration.get(classID - 2);
- if (registration == null) throw new KryoException("Encountered unregistered class ID: " + (classID - 2));
- memoizedClassId = classID;
- memoizedClassIdValue = registration;
- return registration;
- }
-
- protected Registration readName(final Input input) {
- final int nameId = input.readVarInt(true);
- if (nameIdToClass == null) nameIdToClass = new IntMap<>();
- Class type = nameIdToClass.get(nameId);
- if (type == null) {
- // Only read the class name the first time encountered in object graph.
- final String className = input.readString();
- type = getTypeByName(className);
- if (type == null) {
- try {
- type = Class.forName(className, false, kryo.getClassLoader());
- } catch (ClassNotFoundException ex) {
- throw new KryoException("Unable to find class: " + className, ex);
- }
- if (nameToClass == null) nameToClass = new ObjectMap<>();
- nameToClass.put(className, type);
- }
- nameIdToClass.put(nameId, type);
- }
- return kryo.getRegistration(type);
- }
-
- protected Class<?> getTypeByName(final String className) {
- return nameToClass != null ? nameToClass.get(className) : null;
- }
-
- @Override
- public void reset() {
- if (!kryo.isRegistrationRequired()) {
- if (classToNameId != null) classToNameId.clear();
- if (nameIdToClass != null) nameIdToClass.clear();
- nextNameId = 0;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/929a2889/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/KryoMapper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/KryoMapper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/KryoMapper.java
deleted file mode 100644
index 5a35d87..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/kryo/KryoMapper.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * 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.
- */
-package org.apache.tinkerpop.gremlin.structure.io.kryo;
-
-import com.esotericsoftware.kryo.Kryo;
-import com.esotericsoftware.kryo.KryoSerializable;
-import com.esotericsoftware.kryo.Serializer;
-import com.esotericsoftware.kryo.io.Input;
-import com.esotericsoftware.kryo.io.Output;
-import com.esotericsoftware.kryo.util.DefaultStreamFactory;
-import com.esotericsoftware.kryo.util.MapReferenceResolver;
-import org.apache.tinkerpop.gremlin.process.Path;
-import org.apache.tinkerpop.gremlin.process.T;
-import org.apache.tinkerpop.gremlin.process.computer.MapReduce;
-import org.apache.tinkerpop.gremlin.process.computer.util.MapMemory;
-import org.apache.tinkerpop.gremlin.process.graph.util.Tree;
-import org.apache.tinkerpop.gremlin.process.traverser.B_O_PA_S_SE_SL_Traverser;
-import org.apache.tinkerpop.gremlin.process.traverser.B_O_P_PA_S_SE_SL_Traverser;
-import org.apache.tinkerpop.gremlin.process.traverser.B_O_Traverser;
-import org.apache.tinkerpop.gremlin.process.traverser.O_Traverser;
-import org.apache.tinkerpop.gremlin.process.util.BulkSet;
-import org.apache.tinkerpop.gremlin.process.util.metric.DependantMutableMetrics;
-import org.apache.tinkerpop.gremlin.process.util.metric.MutableMetrics;
-import org.apache.tinkerpop.gremlin.process.util.metric.StandardTraversalMetrics;
-import org.apache.tinkerpop.gremlin.process.util.TraverserSet;
-import org.apache.tinkerpop.gremlin.structure.Contains;
-import org.apache.tinkerpop.gremlin.structure.Direction;
-import org.apache.tinkerpop.gremlin.structure.Edge;
-import org.apache.tinkerpop.gremlin.structure.Property;
-import org.apache.tinkerpop.gremlin.structure.Vertex;
-import org.apache.tinkerpop.gremlin.structure.VertexProperty;
-import org.apache.tinkerpop.gremlin.structure.io.Mapper;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedEdge;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedPath;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedProperty;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
-import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertexProperty;
-import org.javatuples.Triplet;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.net.URI;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.BiPredicate;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * A {@link Mapper} implementation for Kryo.
- *
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-public final class KryoMapper implements Mapper<Kryo> {
- static final byte[] GIO = "gio".getBytes();
- private final List<Triplet<Class, Function<Kryo, Serializer>, Integer>> serializationList;
- private final HeaderWriter headerWriter;
- private final HeaderReader headerReader;
- private final byte[] versionedHeader;
-
- public static final byte DEFAULT_EXTENDED_VERSION = Byte.MIN_VALUE;
-
- private KryoMapper(final List<Triplet<Class, Function<Kryo, Serializer>, Integer>> serializationList,
- final HeaderWriter headerWriter,
- final HeaderReader headerReader) {
- this.serializationList = serializationList;
- this.headerWriter = headerWriter;
- this.headerReader = headerReader;
-
- final Output out = new Output(32);
- try {
- this.headerWriter.write(createMapper(), out);
- } catch (IOException ioe) {
- throw new RuntimeException(ioe);
- }
- this.versionedHeader = out.toBytes();
- }
-
- @Override
- public Kryo createMapper() {
- final Kryo kryo = new Kryo(new GremlinClassResolver(), new MapReferenceResolver(), new DefaultStreamFactory());
- kryo.addDefaultSerializer(Map.Entry.class, new EntrySerializer());
- kryo.setRegistrationRequired(true);
- serializationList.forEach(p -> {
- final Function<Kryo, Serializer> serializer = p.getValue1();
- if (null == serializer)
- kryo.register(p.getValue0(), kryo.getDefaultSerializer(p.getValue0()), p.getValue2());
- else
- kryo.register(p.getValue0(), serializer.apply(kryo), p.getValue2());
- });
- return kryo;
- }
-
- public HeaderWriter getHeaderWriter() {
- return headerWriter;
- }
-
- public HeaderReader getHeaderReader() {
- return headerReader;
- }
-
- /**
- * Gets the header for a Gremlin Kryo file, which is based on the version of Gremlin Kryo that is constructed
- * via the builder classes.
- */
- public byte[] getVersionedHeader() {
- return versionedHeader;
- }
-
- @FunctionalInterface
- public interface HeaderReader {
- public void read(final Kryo kryo, final Input input) throws IOException;
- }
-
- @FunctionalInterface
- public interface HeaderWriter {
- public void write(final Kryo kryo, final Output output) throws IOException;
- }
-
- /**
- * Use a specific version of Gremlin Kryo.
- */
- public static Builder build(final Version version) {
- return version.getBuilder();
- }
-
- /**
- * Use the most current version of Gremlin Kryo.
- */
- public static Builder build() {
- return Version.V_1_0_0.getBuilder();
- }
-
- public static interface Builder {
- /**
- * Add mapper classes to serializes with kryo using standard serialization.
- */
- public Builder addCustom(final Class... custom);
-
- /**
- * Add mapper class to serializes with mapper serialization.
- */
- public Builder addCustom(final Class clazz, final Serializer serializer);
-
- /**
- * Add mapper class to serializes with mapper serialization as returned from a {@link Function}.
- */
- public Builder addCustom(final Class clazz, final Function<Kryo, Serializer> serializer);
-
- /**
- * If using mapper classes it might be useful to tag the version stamped to the serialization with a mapper
- * value, such that Kryo serialization at 1.0.0 would have a fourth byte for an extended version. The user
- * supplied fourth byte can then be used to ensure the right deserializer is used to read the data. If this
- * value is not supplied then it is written as {@link Byte#MIN_VALUE}. The value supplied here should be greater
- * than or equal to zero.
- */
- public Builder extendedVersion(final byte extendedVersion);
-
- /**
- * By default the {@link #extendedVersion(byte)} is checked against what is read from an input source and if
- * those values are equal the version being read is considered "compliant". To alter this behavior, supply a
- * mapper compliance {@link Predicate} to evaluate the value read from the input source (i.e. first argument)
- * and the value marked in the {@code GremlinKryo} instance {i.e. second argument}. Supplying this function is
- * useful when versions require backward compatibility or other more complex checks. This function is only used
- * if the {@link #extendedVersion(byte)} is set to something other than its default.
- */
- public Builder compliant(final BiPredicate<Byte, Byte> compliant);
-
- public KryoMapper create();
- }
-
- public enum Version {
- V_1_0_0(BuilderV1d0.class);
-
- private final Class<? extends Builder> builder;
-
- private Version(final Class<? extends Builder> builder) {
- this.builder = builder;
- }
-
- Builder getBuilder() {
- try {
- return builder.newInstance();
- } catch (Exception x) {
- throw new RuntimeException("GremlinKryo Builder implementation cannot be instantiated", x);
- }
- }
- }
-
- public static class BuilderV1d0 implements Builder {
-
- /**
- * Map with one entry that is used so that it is possible to get the class of LinkedHashMap.Entry.
- */
- private static final LinkedHashMap m = new LinkedHashMap() {{
- put("junk", "dummy");
- }};
-
- private static final Class LINKED_HASH_MAP_ENTRY_CLASS = m.entrySet().iterator().next().getClass();
-
- /**
- * Note that the following are pre-registered boolean, Boolean, byte, Byte, char, Character, double, Double,
- * int, Integer, float, Float, long, Long, short, Short, String, void.
- */
- private final List<Triplet<Class, Function<Kryo, Serializer>, Integer>> serializationList = new ArrayList<Triplet<Class, Function<Kryo, Serializer>, Integer>>() {{
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(byte[].class, null, 25));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(char[].class, null, 26));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(short[].class, null, 27));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(int[].class, null, 28));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(long[].class, null, 29));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(float[].class, null, 30));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(double[].class, null, 31));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(String[].class, null, 32));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Object[].class, null, 33));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(ArrayList.class, null, 10));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(BigInteger.class, null, 34));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(BigDecimal.class, null, 35));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Calendar.class, null, 39));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Class.class, null, 41));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collection.class, null, 37));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collections.EMPTY_LIST.getClass(), null, 51));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collections.EMPTY_MAP.getClass(), null, 52));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collections.EMPTY_SET.getClass(), null, 53));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collections.singleton(null).getClass(), null, 54));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collections.singletonList(null).getClass(), null, 24));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Collections.singletonMap(null, null).getClass(), null, 23));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Contains.class, null, 49));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Currency.class, null, 40));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Date.class, null, 38));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Direction.class, null, 12));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(DetachedEdge.class, null, 21));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(DetachedVertexProperty.class, null, 20));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(DetachedProperty.class, null, 18));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(DetachedVertex.class, null, 19));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(DetachedPath.class, null, 60));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(EdgeTerminator.class, null, 14));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(EnumSet.class, null, 46));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(HashMap.class, null, 11));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(HashMap.Entry.class, null, 16));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(KryoSerializable.class, null, 36));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(LinkedHashMap.class, null, 47));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(LinkedHashSet.class, null, 71));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(LINKED_HASH_MAP_ENTRY_CLASS, null, 15));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Locale.class, null, 22));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(StringBuffer.class, null, 43));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(StringBuilder.class, null, 44));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(T.class, null, 48));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(TimeZone.class, null, 42));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(TreeMap.class, null, 45));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(TreeSet.class, null, 50));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(UUID.class, kryo -> new UUIDSerializer(), 17));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(URI.class, kryo -> new URISerializer(), 72));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(VertexTerminator.class, null, 13));
-
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Edge.class, kryo -> new GraphSerializer.EdgeSerializer(), 65));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Vertex.class, kryo -> new GraphSerializer.VertexSerializer(), 66));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Property.class, kryo -> new GraphSerializer.PropertySerializer(), 67));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(VertexProperty.class, kryo -> new GraphSerializer.VertexPropertySerializer(), 68));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Path.class, kryo -> new GraphSerializer.PathSerializer(), 59));
- // HACK!
- //add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Traverser.Admin.class, kryo -> new GraphSerializer.TraverserSerializer(), 55));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_O_Traverser.class, null, 75));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(O_Traverser.class, null, 76));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_O_P_PA_S_SE_SL_Traverser.class, null, 77));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(B_O_PA_S_SE_SL_Traverser.class, null, 78));
-
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(TraverserSet.class, null, 58));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(Tree.class, null, 61));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(HashSet.class, null, 62));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(BulkSet.class, null, 64));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MutableMetrics.class, null, 69));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(StandardTraversalMetrics.class, null, 70));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MapMemory.class, null, 73));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(MapReduce.NullObject.class, null, 74));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(AtomicLong.class, null, 79));
- add(Triplet.<Class, Function<Kryo, Serializer>, Integer>with(DependantMutableMetrics.class, null, 80)); // ***LAST ID**
- }};
-
- private static final byte major = 1;
- private static final byte minor = 0;
- private static final byte patchLevel = 0;
-
- private byte extendedVersion = DEFAULT_EXTENDED_VERSION;
- private BiPredicate<Byte, Byte> compliant = (readExt, serExt) -> readExt.equals(serExt);
-
- /**
- * Starts numbering classes for Kryo serialization at 65536 to leave room for future usage by TinkerPop.
- */
- private final AtomicInteger currentSerializationId = new AtomicInteger(65536);
-
- /**
- * {@inheritDoc}
- */
- @Override
- 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()));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Builder addCustom(final Class clazz, final Serializer serializer) {
- serializationList.add(Triplet.with(clazz, kryo -> serializer, currentSerializationId.getAndIncrement()));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Builder addCustom(final Class clazz, final Function<Kryo, Serializer> serializer) {
- serializationList.add(Triplet.with(clazz, serializer, currentSerializationId.getAndIncrement()));
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Builder extendedVersion(final byte extendedVersion) {
- if (extendedVersion > DEFAULT_EXTENDED_VERSION && extendedVersion < 0)
- throw new IllegalArgumentException("The extendedVersion must be greater than zero");
-
- this.extendedVersion = extendedVersion;
- return this;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Builder compliant(final BiPredicate<Byte, Byte> compliant) {
- if (null == compliant)
- throw new IllegalArgumentException("compliant");
-
- this.compliant = compliant;
- return this;
- }
-
- @Override
- public KryoMapper create() {
- return new KryoMapper(serializationList, this::writeHeader, this::readHeader);
- }
-
- private void writeHeader(final Kryo kryo, final Output output) throws IOException {
- // 32 byte header total
- output.writeBytes(GIO);
-
- // some space for later
- output.writeBytes(new byte[25]);
-
- // version x.y.z
- output.writeByte(major);
- output.writeByte(minor);
- output.writeByte(patchLevel);
- output.writeByte(extendedVersion);
- }
-
- private void readHeader(final Kryo kryo, final Input input) throws IOException {
- if (!Arrays.equals(GIO, input.readBytes(3)))
- throw new IOException("Invalid format - first three bytes of header do not match expected value");
-
- // skip the next 25 bytes in v1
- input.readBytes(25);
-
- // final three bytes of header are the version which should be 1.0.0
- final byte[] version = input.readBytes(3);
- final byte extension = input.readByte();
-
- // direct match on version for now
- if (version[0] != major || version[1] != minor || version[2] != patchLevel)
- throw new IOException(String.format(
- "The version [%s.%s.%s] in the stream cannot be understood by this reader",
- version[0], version[1], version[2]));
-
- if (extendedVersion >= 0 && !compliant.test(extension, extendedVersion))
- throw new IOException(String.format(
- "The extension [%s] in the input source is not compliant with this configuration of GremlinKryo - [%s]",
- extension, extendedVersion));
- }
- }
-}