////
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.
////

[[appendix]]
= Appendix

== TinkerPop 2.x

This section contains a few notes that reference differences between TinkerPop 2.x and 3.x.

One of the major differences between TinkerPop 2.x and TinkerPop 3.x is that in TinkerPop 3.x, the Java convention of
using setters and getters was abandoned in favor of a syntax that is more aligned with the syntax of Gremlin-Groovy in
TinkerPop2. Given that Gremlin-Java8 and Gremlin-Groovy are nearly identical due to the inclusion of Java 8 lambdas, a
big effort was made to ensure that both languages were as similar as possible.

In addition, TinkerPop2 and below made a sharp distinction between the various TinkerPop projects: Blueprints, Pipes,
Gremlin, Frames, Furnace, and Rexster. With TinkerPop 3.x, all of these projects have been merged and are generally
known as Gremlin. *Blueprints* -> Gremlin Structure API : *Pipes* -> `GraphTraversal` : *Frames* -> `Traversal` :
*Furnace* -> `GraphComputer` and `VertexProgram` : *Rexster* -> GremlinServer.

[[graphml-format]]
=== GraphML Format

GraphML was a supported format in TinkerPop 2.x, but there were several issues that made it inconsistent with the
specification that were corrected for 3.x. As a result, attempting to read a GraphML file generated by 2.x with the
3.x `GraphMLReader` will result in error. To help with this problem, an XSLT file is provided as a resource in
`gremlin-core` which will transform 2.x GraphML to 3.x GraphML. It can be used as follows:

[source,java]
----
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;

InputStream stylesheet = Thread.currentThread().getContextClassLoader().getResourceAsStream("tp2-to-tp3-graphml.xslt");
File datafile = new File('/tmp/tp2-graphml.xml');
File outfile = new File('/tmp/tp3-graphml.xml');

TransformerFactory tFactory = TransformerFactory.newInstance();
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = tFactory.newTransformer(stylesource);

StreamSource source = new StreamSource(datafile);
StreamResult result = new StreamResult(new FileWriter(outfile));
transformer.transform(source, result);
----

=== TinkerPop2 Data Migration

image:data-migration.png[width=300,float=right] For those using TinkerPop 2.x, migrating to TinkerPop 3.x will mean a
number of programming changes, but may also require a migration of the data depending on the graph implementation.  For
example, trying to open `TinkerGraph` data from TinkerPop 2.x with TinkerPop 3.x code will not work, however opening a
TinkerPop2 `Neo4jGraph` with a TinkerPop 3.x `Neo4jGraph` should work provided there aren't Neo4j version compatibility
mismatches preventing the read.

If such a situation arises that a particular TinkerPop 2.x `Graph` can not be read by TinkerPop 3.x, a "legacy" data
migration approach exists.  The migration involves writing the TinkerPop2 `Graph` to GraphSON, then reading it to
TinkerPop 3.x with the `LegacyGraphSONReader` (a limited implementation of the `GraphReader` interface).

The following represents an example migration of the "classic" toy graph.  In this example, the "classic" graph is
saved to GraphSON using TinkerPop 2.x.

[source,groovy]
----
gremlin> Gremlin.version()
==>2.5.z
gremlin> graph = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> GraphSONWriter.outputGraph(graph,'/tmp/tp2.json',GraphSONMode.EXTENDED)
==>null
----

The above console session uses the `gremlin-groovy` distribution from TinkerPop2.  It is important to generate the
`tp2.json` file using the `EXTENDED` mode as it will include data types when necessary which will help limit
"lossiness" on the TinkerPop 3.x side when imported.  Once `tp2.json` is created, it can then be imported to a
TinkerPop 3.x `Graph`.

[source,groovy]
----
gremlin> Gremlin.version()
==>x.y.z
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> r = LegacyGraphSONReader.build().create()
==>org.apache.tinkerpop.gremlin.structure.io.graphson.LegacyGraphSONReader@64337702
gremlin> r.readGraph(new FileInputStream('/tmp/tp2.json'), graph)
==>null
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.E()
==>e[11][4-created->3]
==>e[12][6-created->3]
==>e[7][1-knows->2]
==>e[8][1-knows->4]
==>e[9][1-created->3]
==>e[10][4-created->5]
----