| /* |
| * 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; |
| |
| import org.apache.commons.configuration2.Configuration; |
| import org.apache.tinkerpop.gremlin.AbstractGremlinTest; |
| import org.apache.tinkerpop.gremlin.FeatureRequirement; |
| import org.apache.tinkerpop.gremlin.LoadGraphWith; |
| import org.apache.tinkerpop.gremlin.TestHelper; |
| 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.Graph.Features.EdgePropertyFeatures; |
| import org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures; |
| import org.apache.tinkerpop.gremlin.structure.T; |
| import org.apache.tinkerpop.gremlin.structure.Vertex; |
| import org.apache.tinkerpop.gremlin.structure.VertexProperty; |
| import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLReader; |
| import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLResourceAccess; |
| import org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLWriter; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONResourceAccess; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONTokens; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONVersion; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.LegacyGraphSONReader; |
| import org.apache.tinkerpop.gremlin.structure.io.graphson.TypeInfo; |
| import org.apache.tinkerpop.gremlin.structure.io.util.CustomId; |
| import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; |
| import org.apache.tinkerpop.shaded.jackson.databind.JsonNode; |
| import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper; |
| import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.experimental.runners.Enclosed; |
| import org.junit.runner.RunWith; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import javax.xml.XMLConstants; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.stream.StreamResult; |
| import javax.xml.transform.stream.StreamSource; |
| import javax.xml.validation.Schema; |
| import javax.xml.validation.SchemaFactory; |
| import javax.xml.validation.Validator; |
| import java.io.BufferedReader; |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.OutputStream; |
| import java.io.Reader; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.net.URL; |
| import java.util.List; |
| import java.util.UUID; |
| |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.ElementFeatures.FEATURE_ANY_IDS; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VariableFeatures.FEATURE_VARIABLES; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures.FEATURE_BOOLEAN_VALUES; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures.FEATURE_DOUBLE_VALUES; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures.FEATURE_FLOAT_VALUES; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures.FEATURE_INTEGER_VALUES; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures.FEATURE_LONG_VALUES; |
| import static org.apache.tinkerpop.gremlin.structure.Graph.Features.VertexPropertyFeatures.FEATURE_STRING_VALUES; |
| import static org.apache.tinkerpop.gremlin.structure.io.IoCore.graphson; |
| import static org.hamcrest.core.Is.is; |
| import static org.hamcrest.core.StringContains.containsString; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| import static org.junit.Assume.assumeThat; |
| |
| /** |
| * @author Joshua Shinavier (http://fortytwo.net) |
| * @author Stephen Mallette (http://stephen.genoprime.com) |
| * @author Marko A. Rodriguez (http://markorodriguez.com) |
| */ |
| @RunWith(Enclosed.class) |
| public class IoTest { |
| private static final Logger logger = LoggerFactory.getLogger(IoTest.class); |
| |
| private static final String CLASSIC_GRAPH_WITH_COLOR = "<?xml version=\"1.0\" ?>\n" + |
| "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.1/graphml.xsd\">\n" + |
| " <key id=\"age\" for=\"node\" attr.name=\"age\" attr.type=\"int\"></key>\n" + |
| " <key id=\"colorV\" for=\"node\" attr.name=\"color\" attr.type=\"string\"></key>\n" + |
| " <key id=\"labelV\" for=\"node\" attr.name=\"labelV\" attr.type=\"string\"></key>\n" + |
| " <key id=\"lang\" for=\"node\" attr.name=\"lang\" attr.type=\"string\"></key>\n" + |
| " <key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\"></key>\n" + |
| " <key id=\"colorE\" for=\"edge\" attr.name=\"color\" attr.type=\"string\"></key>\n" + |
| " <key id=\"labelE\" for=\"edge\" attr.name=\"labelE\" attr.type=\"string\"></key>\n" + |
| " <key id=\"weight\" for=\"edge\" attr.name=\"weight\" attr.type=\"float\"></key>\n" + |
| " <graph id=\"G\" edgedefault=\"directed\">\n" + |
| " <node id=\"1\">\n" + |
| " <data key=\"labelV\">vertex</data>\n" + |
| " <data key=\"age\">29</data>\n" + |
| " <data key=\"colorV\">#6495ed</data>\n" + |
| " <data key=\"name\">marko</data>\n" + |
| " </node>\n" + |
| " <node id=\"2\">\n" + |
| " <data key=\"labelV\">vertex</data>\n" + |
| " <data key=\"age\">27</data>\n" + |
| " <data key=\"colorV\">#6495ed</data>\n" + |
| " <data key=\"name\">vadas</data>\n" + |
| " </node>\n" + |
| " <node id=\"3\">\n" + |
| " <data key=\"labelV\">vertex</data>\n" + |
| " <data key=\"lang\">java</data>\n" + |
| " <data key=\"colorV\">#6495ed</data>\n" + |
| " <data key=\"name\">lop</data>\n" + |
| " </node>\n" + |
| " <node id=\"4\">\n" + |
| " <data key=\"labelV\">vertex</data>\n" + |
| " <data key=\"age\">32</data>\n" + |
| " <data key=\"colorV\">#6495ed</data>\n" + |
| " <data key=\"name\">josh</data>\n" + |
| " </node>\n" + |
| " <node id=\"5\">\n" + |
| " <data key=\"labelV\">vertex</data>\n" + |
| " <data key=\"lang\">java</data>\n" + |
| " <data key=\"colorV\">#6495ed</data>\n" + |
| " <data key=\"name\">ripple</data>\n" + |
| " </node>\n" + |
| " <node id=\"6\">\n" + |
| " <data key=\"labelV\">vertex</data>\n" + |
| " <data key=\"age\">35</data>\n" + |
| " <data key=\"colorV\">#6495ed</data>\n" + |
| " <data key=\"name\">peter</data>\n" + |
| " </node>\n" + |
| " <edge id=\"10\" source=\"4\" target=\"5\">\n" + |
| " <data key=\"labelE\">created</data>\n" + |
| " <data key=\"colorE\">#ee0000</data>\n" + |
| " <data key=\"weight\">1.0</data>\n" + |
| " </edge>\n" + |
| " <edge id=\"11\" source=\"4\" target=\"3\">\n" + |
| " <data key=\"labelE\">created</data>\n" + |
| " <data key=\"colorE\">#ee0000</data>\n" + |
| " <data key=\"weight\">0.4</data>\n" + |
| " </edge>\n" + |
| " <edge id=\"12\" source=\"6\" target=\"3\">\n" + |
| " <data key=\"labelE\">created</data>\n" + |
| " <data key=\"colorE\">#ee0000</data>\n" + |
| " <data key=\"weight\">0.2</data>\n" + |
| " </edge>\n" + |
| " <edge id=\"7\" source=\"1\" target=\"2\">\n" + |
| " <data key=\"labelE\">knows</data>\n" + |
| " <data key=\"colorE\">#ee0000</data>\n" + |
| " <data key=\"weight\">0.5</data>\n" + |
| " </edge>\n" + |
| " <edge id=\"8\" source=\"1\" target=\"4\">\n" + |
| " <data key=\"labelE\">knows</data>\n" + |
| " <data key=\"colorE\">#ee0000</data>\n" + |
| " <data key=\"weight\">1.0</data>\n" + |
| " </edge>\n" + |
| " <edge id=\"9\" source=\"1\" target=\"3\">\n" + |
| " <data key=\"labelE\">created</data>\n" + |
| " <data key=\"colorE\">#ee0000</data>\n" + |
| " <data key=\"weight\">0.4</data>\n" + |
| " </edge>\n" + |
| " </graph>\n" + |
| "</graphml>"; |
| |
| public static class GraphMLTest extends AbstractGremlinTest { |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadGraphML() throws IOException { |
| readGraphMLIntoGraph(graph, "tinkerpop-classic.xml"); |
| assertClassicGraph(graph, false, true); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadGraphMLWithNoEdgeLabels() throws IOException { |
| readGraphMLIntoGraph(graph, "tinkerpop-no-edge-labels.xml"); |
| assertNoEdgeGraph(graph, false, true); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadGraphMLUnorderedElements() throws IOException { |
| readGraphMLIntoGraph(graph, "tinkerpop-classic-unordered.xml"); |
| assertClassicGraph(graph, false, true); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_BOOLEAN_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_LONG_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_DOUBLE_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadGraphMLWithAllSupportedDataTypes() throws IOException { |
| final GraphReader reader = GraphMLReader.build().create(); |
| try (final InputStream stream = getResourceAsStream(GraphMLResourceAccess.class, "graph-types.xml")) { |
| reader.readGraph(stream, graph); |
| } |
| |
| final Vertex v = graph.vertices().next(); |
| assertEquals(123.45d, v.value("d"), 0.000001d); |
| assertEquals("some-string", v.<String>value("s")); |
| assertEquals(29, v.<Integer>value("i").intValue()); |
| assertEquals(true, v.<Boolean>value("b")); |
| assertEquals(123.54f, v.value("f"), 0.000001f); |
| assertEquals(10000000l, v.<Long>value("l").longValue()); |
| assertEquals("junk", v.<String>value("n")); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_BOOLEAN_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_LONG_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_DOUBLE_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadGraphMLWithoutStrictOption() throws IOException { |
| final GraphReader reader = GraphMLReader.build().strict(false).create(); |
| try (final InputStream stream = getResourceAsStream(GraphMLResourceAccess.class, "graph-types-bad.xml")) { |
| reader.readGraph(stream, graph); |
| } |
| |
| final Vertex v = graph.vertices().next(); |
| assertFalse(v.values("d").hasNext()); |
| assertEquals("some-string", v.<String>value("s")); |
| assertFalse(v.values("i").hasNext()); |
| assertEquals(false, v.<Boolean>value("b")); |
| assertFalse(v.values("f").hasNext()); |
| assertFalse(v.values("l").hasNext()); |
| assertEquals("junk", v.<String>value("n")); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadGraphMLWithoutEdgeIds() throws IOException { |
| final GraphReader reader = GraphMLReader.build().strict(false).create(); |
| try (final InputStream stream = getResourceAsStream(GraphMLResourceAccess.class, "graph-no-edge-ids.xml")) { |
| reader.readGraph(stream, graph); |
| } |
| assertEquals(1, IteratorUtils.count(graph.edges())); |
| assertEquals(2, IteratorUtils.count(graph.vertices())); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_REMOVE_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_REMOVE_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_STRING_VALUES) |
| public void shouldReadGraphMLWithCommonVertexAndEdgePropertyNames() throws IOException { |
| final GraphReader reader = GraphMLReader.build().create(); |
| try (final InputStream stream = new ByteArrayInputStream(CLASSIC_GRAPH_WITH_COLOR.getBytes("UTF-8"))) { |
| reader.readGraph(stream, graph); |
| } |
| |
| // there is also a "color" property on this dataset that is on both edges and vertices |
| graph.vertices().forEachRemaining(v -> assertEquals("#6495ed", v.value("color"))); |
| graph.edges().forEachRemaining(e -> assertEquals("#ee0000", e.value("color"))); |
| |
| final GraphWriter writer = GraphMLWriter.build().create(); |
| try (final OutputStream out = new ByteArrayOutputStream()) { |
| writer.writeGraph(out, graph); |
| |
| graph.vertices().forEachRemaining(Element::remove); |
| try (final InputStream stream = new ByteArrayInputStream(((ByteArrayOutputStream) out).toByteArray())) { |
| reader.readGraph(stream, graph); |
| } |
| |
| // there is also a "color" property on this dataset that is on both edges and vertices |
| graph.vertices().forEachRemaining(v -> assertEquals("#6495ed", v.value("color"))); |
| graph.edges().forEachRemaining(e -> assertEquals("#ee0000", e.value("color"))); |
| } |
| } |
| |
| @Test(expected = NumberFormatException.class) |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_BOOLEAN_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_LONG_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_DOUBLE_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadGraphMLWithStrictOption() throws IOException { |
| final GraphReader reader = GraphMLReader.build().strict(true).create(); |
| try (final InputStream stream = getResourceAsStream(GraphMLResourceAccess.class, "graph-types-bad.xml")) { |
| reader.readGraph(stream, graph); |
| } |
| } |
| |
| /** |
| * Only need to execute this test with TinkerGraph or other graphs that support user supplied identifiers. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NUMERIC_IDS) |
| @LoadGraphWith(LoadGraphWith.GraphData.CLASSIC) |
| public void shouldWriteNormalizedGraphML() throws Exception { |
| try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { |
| final GraphMLWriter w = GraphMLWriter.build().normalize(true).create(); |
| w.writeGraph(bos, graph); |
| final String expected = streamToString(getResourceAsStream(GraphMLResourceAccess.class, "tinkerpop-classic-normalized.xml")); |
| assertEquals(expected.replace("\n", "").replace("\r", ""), bos.toString().replace("\n", "").replace("\r", "")); |
| } |
| } |
| |
| @Test |
| @LoadGraphWith(LoadGraphWith.GraphData.CREW) |
| public void shouldNotWriteGraphMLFromGraphWithMultiProperties() throws Exception { |
| try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { |
| final GraphMLWriter w = GraphMLWriter.build().create(); |
| w.writeGraph(bos, graph); |
| fail("Should not be able to write multi-properties to GraphML"); |
| } catch (IllegalStateException iae) { |
| assertThat(iae.getMessage(), containsString("multi-properties are not directly supported by GraphML format")); |
| } |
| } |
| |
| /** |
| * Note: this is only a very lightweight test of writer/reader encoding. It is known that there are characters |
| * which, when written by GraphMLWriter, cause parse errors for GraphMLReader. However, this happens uncommonly |
| * enough that is not yet known which characters those are. Only need to execute this test with TinkerGraph |
| * or other graphs that support user supplied identifiers. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_STRING_IDS) |
| public void shouldProperlyEncodeWithGraphML() throws Exception { |
| assumeThat("GraphML web site is down so XSD cannot be retrieved", is(isGraphMLXSDPresent())); |
| |
| final Vertex v = graph.addVertex(T.id, "1"); |
| v.property(VertexProperty.Cardinality.single, "text", "\u00E9"); |
| |
| final GraphMLWriter w = GraphMLWriter.build().create(); |
| |
| final File f = TestHelper.generateTempFile(this.getClass(), "test", ".txt"); |
| try (final OutputStream out = new FileOutputStream(f)) { |
| w.writeGraph(out, graph); |
| } |
| |
| validateXmlAgainstGraphMLXsd(f); |
| |
| // reusing the same config used for creation of "g". |
| final Configuration configuration = graphProvider.newGraphConfiguration("g2", this.getClass(), name.getMethodName(), null); |
| graphProvider.clear(configuration); |
| final Graph g2 = graphProvider.openTestGraph(configuration); |
| final GraphMLReader r = GraphMLReader.build().create(); |
| |
| try (final InputStream in = new FileInputStream(f)) { |
| r.readGraph(in, g2); |
| } |
| |
| final Vertex v2 = g2.vertices("1").next(); |
| assertEquals("\u00E9", v2.property("text").value()); |
| |
| // need to manually close the "g2" instance |
| graphProvider.clear(g2, configuration); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteSelfLoopingEdges() throws Exception { |
| final Graph source = graph; |
| final Vertex v1 = source.addVertex(); |
| final Vertex v2 = source.addVertex(); |
| v1.addEdge("CONTROL", v2); |
| v1.addEdge("SELFLOOP", v1); |
| |
| final Configuration targetConf = graphProvider.newGraphConfiguration("target", this.getClass(), name.getMethodName(), null); |
| final Graph target = graphProvider.openTestGraph(targetConf); |
| try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| source.io(IoCore.graphml()).writer().create().writeGraph(os, source); |
| try (ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray())) { |
| target.io(IoCore.graphml()).reader().create().readGraph(is, target); |
| } |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| |
| assertEquals(IteratorUtils.count(source.vertices()), IteratorUtils.count(target.vertices())); |
| assertEquals(IteratorUtils.count(source.edges()), IteratorUtils.count(target.edges())); |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldTransformGraphMLV2ToV3ViaXSLT() throws Exception { |
| final InputStream stylesheet = Thread.currentThread().getContextClassLoader().getResourceAsStream("tp2-to-tp3-graphml.xslt"); |
| final InputStream datafile = getResourceAsStream(GraphMLResourceAccess.class, "tinkerpop-classic-tp2.xml"); |
| final ByteArrayOutputStream output = new ByteArrayOutputStream(); |
| |
| final TransformerFactory tFactory = TransformerFactory.newInstance(); |
| final StreamSource stylesource = new StreamSource(stylesheet); |
| final Transformer transformer = tFactory.newTransformer(stylesource); |
| |
| final StreamSource source = new StreamSource(datafile); |
| final StreamResult result = new StreamResult(output); |
| transformer.transform(source, result); |
| |
| final GraphReader reader = GraphMLReader.build().create(); |
| reader.readGraph(new ByteArrayInputStream(output.toByteArray()), graph); |
| assertClassicGraph(graph, false, true); |
| } |
| |
| private boolean isGraphMLXSDPresent() { |
| // when the graphml website goes down then tests won't pass - this allows the tests that rely on this |
| // resource to conditionally run |
| try { |
| new URL("http://graphml.graphdrawing.org/xmlns/1.1/graphml-structure.xsd").openConnection().connect(); |
| return true; |
| } catch (Exception ex) { |
| return false; |
| } |
| } |
| } |
| |
| public static final class GryoTest extends AbstractGremlinTest { |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteSelfLoopingEdges() { |
| final Graph source = graph; |
| final Vertex v1 = source.addVertex(); |
| final Vertex v2 = source.addVertex(); |
| v1.addEdge("CONTROL", v2); |
| v1.addEdge("SELFLOOP", v1); |
| |
| final Configuration targetConf = graphProvider.newGraphConfiguration("target", this.getClass(), name.getMethodName(), null); |
| final Graph target = graphProvider.openTestGraph(targetConf); |
| ; |
| try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| source.io(IoCore.gryo()).writer().create().writeGraph(os, source); |
| try (ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray())) { |
| target.io(IoCore.gryo()).reader().create().readGraph(is, target); |
| } |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| |
| assertEquals(IteratorUtils.count(source.vertices()), IteratorUtils.count(target.vertices())); |
| assertEquals(IteratorUtils.count(source.edges()), IteratorUtils.count(target.edges())); |
| } |
| } |
| |
| public static final class GraphSONTest extends AbstractGremlinTest { |
| private Io.Builder<GraphSONIo> graphson; |
| |
| @Before |
| public void setupBeforeEachTest() { |
| graphson = graphson(); |
| } |
| |
| /** |
| * Only need to execute this test with TinkerGraph or other graphs that support user supplied identifiers. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NUMERIC_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = FEATURE_VARIABLES) |
| @LoadGraphWith(LoadGraphWith.GraphData.CLASSIC) |
| public void shouldWriteNormalizedGraphSON() throws Exception { |
| try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V1_0).normalize(true).create(); |
| final GraphSONWriter w = graph.io(graphson).writer().mapper(mapper).create(); |
| w.writeGraph(bos, graph); |
| |
| final String expected = streamToString(getResourceAsStream(GraphSONResourceAccess.class, "tinkerpop-classic-normalized-v1d0.json")); |
| assertEquals(expected.replace("\n", "").replace("\r", ""), bos.toString().replace("\n", "").replace("\r", "")); |
| } |
| } |
| |
| @Test |
| @LoadGraphWith(LoadGraphWith.GraphData.MODERN) |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteModernWrappedInJsonObject() throws Exception { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V1_0).create(); |
| try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| final GraphWriter writer = graph.io(graphson()).writer().wrapAdjacencyList(true).mapper(mapper).create(); |
| writer.writeGraph(os, graph); |
| |
| final Configuration configuration = graphProvider.newGraphConfiguration("readGraph", this.getClass(), name.getMethodName(), LoadGraphWith.GraphData.MODERN); |
| graphProvider.clear(configuration); |
| final Graph g1 = graphProvider.openTestGraph(configuration); |
| final GraphReader reader = graph.io(graphson()).reader().mapper(mapper).unwrapAdjacencyList(true).create(); |
| try (final ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray())) { |
| reader.readGraph(bais, g1); |
| } |
| |
| // modern uses double natively so always assert as such |
| IoTest.assertModernGraph(g1, true, true); |
| |
| graphProvider.clear(g1, configuration); |
| } |
| } |
| |
| /** |
| * This is just a serialization check for JSON. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ANY_IDS) |
| public void shouldProperlySerializeCustomIdWithGraphSON() throws Exception { |
| final UUID id = UUID.fromString("AF4B5965-B176-4552-B3C1-FBBE2F52C305"); |
| graph.addVertex(T.id, new CustomId("vertex", id)); |
| |
| final SimpleModule module = new SimpleModule(); |
| module.addSerializer(CustomId.class, new CustomId.CustomIdJacksonSerializerV1d0()); |
| final GraphWriter writer = graph.io(graphson).writer().mapper( |
| graph.io(graphson).mapper().version(GraphSONVersion.V1_0).addCustomModule(module).typeInfo(TypeInfo.PARTIAL_TYPES).create()).create(); |
| |
| try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { |
| writer.writeGraph(baos, graph); |
| |
| final JsonNode jsonGraph = new ObjectMapper().readTree(baos.toByteArray()); |
| final JsonNode idValue = jsonGraph.get(GraphSONTokens.ID); |
| assertTrue(idValue.has("cluster")); |
| assertEquals("vertex", idValue.get("cluster").asText()); |
| assertTrue(idValue.has("elementId")); |
| assertEquals("AF4B5965-B176-4552-B3C1-FBBE2F52C305".toLowerCase(), idValue.get("elementId").get(1).asText()); |
| |
| // reusing the same config used for creation of "g". |
| final Configuration configuration = graphProvider.newGraphConfiguration("g2", this.getClass(), name.getMethodName(), null); |
| graphProvider.clear(configuration); |
| final Graph g2 = graphProvider.openTestGraph(configuration); |
| |
| try (final InputStream is = new ByteArrayInputStream(baos.toByteArray())) { |
| final GraphReader reader = graph.io(graphson).reader() |
| .mapper(graph.io(graphson).mapper().version(GraphSONVersion.V1_0).typeInfo(TypeInfo.PARTIAL_TYPES).addCustomModule(module).create()).create(); |
| reader.readGraph(is, g2); |
| } |
| |
| final Vertex v2 = g2.vertices().next(); |
| final CustomId customId = (CustomId) v2.id(); |
| assertEquals(id, customId.getElementId()); |
| assertEquals("vertex", customId.getCluster()); |
| |
| // need to manually close the "g2" instance |
| graphProvider.clear(g2, configuration); |
| } |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteSelfLoopingEdges() throws Exception { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V1_0).create(); |
| final Graph source = graph; |
| final Vertex v1 = source.addVertex(); |
| final Vertex v2 = source.addVertex(); |
| v1.addEdge("CONTROL", v2); |
| v1.addEdge("SELFLOOP", v1); |
| |
| final Configuration targetConf = graphProvider.newGraphConfiguration("target", this.getClass(), name.getMethodName(), null); |
| final Graph target = graphProvider.openTestGraph(targetConf); |
| try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| source.io(IoCore.graphson()).writer().mapper(mapper).create().writeGraph(os, source); |
| try (ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray())) { |
| target.io(IoCore.graphson()).reader().mapper(mapper).create().readGraph(is, target); |
| } |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| |
| assertEquals(IteratorUtils.count(source.vertices()), IteratorUtils.count(target.vertices())); |
| assertEquals(IteratorUtils.count(source.edges()), IteratorUtils.count(target.edges())); |
| } |
| } |
| |
| public static final class GraphSONLegacyTest extends AbstractGremlinTest { |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| public void shouldReadLegacyGraphSON() throws IOException { |
| final GraphReader reader = LegacyGraphSONReader.build().create(); |
| try (final InputStream stream = getResourceAsStream(GraphSONResourceAccess.class, "tinkerpop-classic-legacy.json")) { |
| reader.readGraph(stream, graph); |
| } |
| |
| // the id is lossy in migration because TP2 treated ID as String |
| assertClassicGraph(graph, false, true); |
| } |
| } |
| |
| public static final class GraphSONV2D0Test extends AbstractGremlinTest { |
| private Io.Builder<GraphSONIo> graphson; |
| |
| @Before |
| public void setupBeforeEachTest() { |
| graphson = graphson(); |
| } |
| |
| /** |
| * Only need to execute this test with TinkerGraph or other graphs that support user supplied identifiers. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NUMERIC_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = FEATURE_VARIABLES) |
| @LoadGraphWith(LoadGraphWith.GraphData.CLASSIC) |
| public void shouldWriteNormalizedGraphSON() throws Exception { |
| try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V2_0).typeInfo(TypeInfo.NO_TYPES).normalize(true).create(); |
| final GraphSONWriter w = graph.io(graphson).writer().mapper(mapper).create(); |
| w.writeGraph(bos, graph); |
| |
| final String expected = streamToString(getResourceAsStream(GraphSONResourceAccess.class, "tinkerpop-classic-normalized-v2d0.json")); |
| assertEquals(expected.replace("\n", "").replace("\r", ""), bos.toString().replace("\n", "").replace("\r", "")); |
| } |
| } |
| |
| @Test |
| @LoadGraphWith(LoadGraphWith.GraphData.MODERN) |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteModernWrappedInJsonObject() throws Exception { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V2_0).create(); |
| try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| final GraphWriter writer = graph.io(graphson()).writer().wrapAdjacencyList(true).mapper(mapper).create(); |
| writer.writeGraph(os, graph); |
| |
| final Configuration configuration = graphProvider.newGraphConfiguration("readGraph", this.getClass(), name.getMethodName(), LoadGraphWith.GraphData.MODERN); |
| graphProvider.clear(configuration); |
| final Graph g1 = graphProvider.openTestGraph(configuration); |
| final GraphReader reader = graph.io(graphson()).reader().mapper(mapper).unwrapAdjacencyList(true).create(); |
| try (final ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray())) { |
| reader.readGraph(bais, g1); |
| } |
| |
| // modern uses double natively so always assert as such |
| IoTest.assertModernGraph(g1, true, true); |
| |
| graphProvider.clear(g1, configuration); |
| } |
| } |
| |
| /** |
| * This is just a serialization check for JSON. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ANY_IDS) |
| public void shouldProperlySerializeCustomIdWithGraphSON() throws Exception { |
| final UUID id = UUID.fromString("AF4B5965-B176-4552-B3C1-FBBE2F52C305"); |
| graph.addVertex(T.id, new CustomId("vertex", id)); |
| |
| final SimpleModule module = new CustomId.CustomIdTinkerPopJacksonModuleV2d0(); |
| final GraphWriter writer = graph.io(graphson).writer().mapper( |
| graph.io(graphson).mapper().version(GraphSONVersion.V2_0).addCustomModule(module).create()).create(); |
| |
| try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { |
| writer.writeGraph(baos, graph); |
| |
| // reusing the same config used for creation of "g". |
| final Configuration configuration = graphProvider.newGraphConfiguration("g2", this.getClass(), name.getMethodName(), null); |
| graphProvider.clear(configuration); |
| final Graph g2 = graphProvider.openTestGraph(configuration); |
| |
| try (final InputStream is = new ByteArrayInputStream(baos.toByteArray())) { |
| final GraphReader reader = graph.io(graphson).reader() |
| .mapper(graph.io(graphson).mapper().version(GraphSONVersion.V2_0).addCustomModule(module).create()).create(); |
| reader.readGraph(is, g2); |
| } |
| |
| final Vertex v2 = g2.vertices().next(); |
| final CustomId customId = (CustomId) v2.id(); |
| assertEquals(id, customId.getElementId()); |
| assertEquals("vertex", customId.getCluster()); |
| |
| // need to manually close the "g2" instance |
| graphProvider.clear(g2, configuration); |
| } |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteSelfLoopingEdges() throws Exception { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V2_0).create(); |
| final Graph source = graph; |
| final Vertex v1 = source.addVertex(); |
| final Vertex v2 = source.addVertex(); |
| v1.addEdge("CONTROL", v2); |
| v1.addEdge("SELFLOOP", v1); |
| |
| final Configuration targetConf = graphProvider.newGraphConfiguration("target", this.getClass(), name.getMethodName(), null); |
| final Graph target = graphProvider.openTestGraph(targetConf); |
| try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| source.io(IoCore.graphson()).writer().mapper(mapper).create().writeGraph(os, source); |
| try (ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray())) { |
| target.io(IoCore.graphson()).reader().mapper(mapper).create().readGraph(is, target); |
| } |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| |
| assertEquals(IteratorUtils.count(source.vertices()), IteratorUtils.count(target.vertices())); |
| assertEquals(IteratorUtils.count(source.edges()), IteratorUtils.count(target.edges())); |
| } |
| } |
| |
| public static final class GraphSONV3D0Test extends AbstractGremlinTest { |
| private Io.Builder<GraphSONIo> graphson; |
| |
| @Before |
| public void setupBeforeEachTest() { |
| graphson = graphson(); |
| } |
| |
| /** |
| * Only need to execute this test with TinkerGraph or other graphs that support user supplied identifiers. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = VertexPropertyFeatures.class, feature = FEATURE_INTEGER_VALUES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = EdgePropertyFeatures.FEATURE_FLOAT_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_NUMERIC_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexPropertyFeatures.class, feature = Graph.Features.VertexPropertyFeatures.FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VariableFeatures.class, feature = FEATURE_VARIABLES) |
| @LoadGraphWith(LoadGraphWith.GraphData.CLASSIC) |
| public void shouldWriteNormalizedGraphSON() throws Exception { |
| try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V3_0).normalize(true).create(); |
| final GraphSONWriter w = graph.io(graphson).writer().mapper(mapper).create(); |
| w.writeGraph(bos, graph); |
| |
| final String expected = streamToString(getResourceAsStream(GraphSONResourceAccess.class, "tinkerpop-classic-normalized-v3d0.json")); |
| assertEquals(expected.replace("\n", "").replace("\r", ""), bos.toString().replace("\n", "").replace("\r", "")); |
| } |
| } |
| |
| @Test |
| @LoadGraphWith(LoadGraphWith.GraphData.MODERN) |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteModernWrappedInJsonObject() throws Exception { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V3_0).create(); |
| try (final ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| final GraphWriter writer = graph.io(graphson()).writer().wrapAdjacencyList(true).mapper(mapper).create(); |
| writer.writeGraph(os, graph); |
| |
| final Configuration configuration = graphProvider.newGraphConfiguration("readGraph", this.getClass(), name.getMethodName(), LoadGraphWith.GraphData.MODERN); |
| graphProvider.clear(configuration); |
| final Graph g1 = graphProvider.openTestGraph(configuration); |
| final GraphReader reader = graph.io(graphson()).reader().mapper(mapper).unwrapAdjacencyList(true).create(); |
| try (final ByteArrayInputStream bais = new ByteArrayInputStream(os.toByteArray())) { |
| reader.readGraph(bais, g1); |
| } |
| |
| // modern uses double natively so always assert as such |
| IoTest.assertModernGraph(g1, true, true); |
| |
| graphProvider.clear(g1, configuration); |
| } |
| } |
| |
| /** |
| * This is just a serialization check for JSON. |
| */ |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_USER_SUPPLIED_IDS) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = FEATURE_ANY_IDS) |
| public void shouldProperlySerializeCustomIdWithGraphSON() throws Exception { |
| final UUID id = UUID.fromString("AF4B5965-B176-4552-B3C1-FBBE2F52C305"); |
| graph.addVertex(T.id, new CustomId("vertex", id)); |
| |
| final SimpleModule module = new CustomId.CustomIdTinkerPopJacksonModuleV3d0(); |
| final GraphWriter writer = graph.io(graphson).writer().mapper( |
| graph.io(graphson).mapper().version(GraphSONVersion.V3_0).addCustomModule(module).create()).create(); |
| |
| try (final ByteArrayOutputStream baos = new ByteArrayOutputStream()) { |
| writer.writeGraph(baos, graph); |
| |
| // reusing the same config used for creation of "g". |
| final Configuration configuration = graphProvider.newGraphConfiguration("g2", this.getClass(), name.getMethodName(), null); |
| graphProvider.clear(configuration); |
| final Graph g2 = graphProvider.openTestGraph(configuration); |
| |
| try (final InputStream is = new ByteArrayInputStream(baos.toByteArray())) { |
| final GraphReader reader = graph.io(graphson).reader() |
| .mapper(graph.io(graphson).mapper().version(GraphSONVersion.V3_0).addCustomModule(module).create()).create(); |
| reader.readGraph(is, g2); |
| } |
| |
| final Vertex v2 = g2.vertices().next(); |
| final CustomId customId = (CustomId) v2.id(); |
| assertEquals(id, customId.getElementId()); |
| assertEquals("vertex", customId.getCluster()); |
| |
| // need to manually close the "g2" instance |
| graphProvider.clear(g2, configuration); |
| } |
| } |
| |
| @Test |
| @FeatureRequirement(featureClass = Graph.Features.EdgeFeatures.class, feature = Graph.Features.EdgeFeatures.FEATURE_ADD_EDGES) |
| @FeatureRequirement(featureClass = EdgePropertyFeatures.class, feature = FEATURE_STRING_VALUES) |
| @FeatureRequirement(featureClass = Graph.Features.VertexFeatures.class, feature = Graph.Features.VertexFeatures.FEATURE_ADD_VERTICES) |
| public void shouldReadWriteSelfLoopingEdges() throws Exception { |
| final GraphSONMapper mapper = graph.io(graphson).mapper().version(GraphSONVersion.V3_0).create(); |
| final Graph source = graph; |
| final Vertex v1 = source.addVertex(); |
| final Vertex v2 = source.addVertex(); |
| v1.addEdge("CONTROL", v2); |
| v1.addEdge("SELFLOOP", v1); |
| |
| final Configuration targetConf = graphProvider.newGraphConfiguration("target", this.getClass(), name.getMethodName(), null); |
| final Graph target = graphProvider.openTestGraph(targetConf); |
| try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { |
| source.io(IoCore.graphson()).writer().mapper(mapper).create().writeGraph(os, source); |
| try (ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray())) { |
| target.io(IoCore.graphson()).reader().mapper(mapper).create().readGraph(is, target); |
| } |
| } catch (IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| |
| assertEquals(IteratorUtils.count(source.vertices()), IteratorUtils.count(target.vertices())); |
| assertEquals(IteratorUtils.count(source.edges()), IteratorUtils.count(target.edges())); |
| } |
| } |
| |
| public static void assertCrewGraph(final Graph g1, final boolean lossyForId) { |
| assertEquals(new Long(6), g1.traversal().V().count().next()); |
| assertEquals(new Long(14), g1.traversal().E().count().next()); |
| |
| final Vertex v1 = (Vertex) g1.traversal().V().has("name", "marko").next(); |
| assertEquals("person", v1.label()); |
| assertEquals(2, v1.keys().size()); |
| assertEquals(4, (int) IteratorUtils.count(v1.properties("location"))); |
| v1.properties("location").forEachRemaining(vp -> { |
| if (vp.value().equals("san diego")) { |
| assertEquals(1997, (int) vp.value("startTime")); |
| assertEquals(2001, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("santa cruz")) { |
| assertEquals(2001, (int) vp.value("startTime")); |
| assertEquals(2004, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("brussels")) { |
| assertEquals(2004, (int) vp.value("startTime")); |
| assertEquals(2005, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("santa fe")) { |
| assertEquals(2005, (int) vp.value("startTime")); |
| assertEquals(1, (int) IteratorUtils.count(vp.properties())); |
| } else { |
| fail("Found a value that should be there"); |
| } |
| }); |
| assertId(g1, lossyForId, v1, 1); |
| |
| final List<Edge> v1Edges = IteratorUtils.list(v1.edges(Direction.BOTH)); |
| assertEquals(4, v1Edges.size()); |
| v1Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("gremlin") && e.label().equals("develops")) { |
| assertEquals(2009, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 13); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("develops")) { |
| assertEquals(2010, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 14); |
| } else if (e.inVertex().value("name").equals("gremlin") && e.label().equals("uses")) { |
| assertEquals(4, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 15); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("uses")) { |
| assertEquals(5, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 16); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v7 = (Vertex) g1.traversal().V().has("name", "stephen").next(); |
| assertEquals("person", v7.label()); |
| assertEquals(2, v7.keys().size()); |
| assertEquals(3, (int) IteratorUtils.count(v7.properties("location"))); |
| v7.properties("location").forEachRemaining(vp -> { |
| if (vp.value().equals("centreville")) { |
| assertEquals(1990, (int) vp.value("startTime")); |
| assertEquals(2000, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("dulles")) { |
| assertEquals(2000, (int) vp.value("startTime")); |
| assertEquals(2006, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("purcellville")) { |
| assertEquals(2006, (int) vp.value("startTime")); |
| assertEquals(1, (int) IteratorUtils.count(vp.properties())); |
| } else { |
| fail("Found a value that should be there"); |
| } |
| }); |
| assertId(g1, lossyForId, v7, 7); |
| |
| final List<Edge> v7Edges = IteratorUtils.list(v7.edges(Direction.BOTH)); |
| assertEquals(4, v7Edges.size()); |
| v7Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("gremlin") && e.label().equals("develops")) { |
| assertEquals(2010, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 17); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("develops")) { |
| assertEquals(2011, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 18); |
| } else if (e.inVertex().value("name").equals("gremlin") && e.label().equals("uses")) { |
| assertEquals(5, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 19); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("uses")) { |
| assertEquals(4, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 20); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v8 = (Vertex) g1.traversal().V().has("name", "matthias").next(); |
| assertEquals("person", v8.label()); |
| assertEquals(2, v8.keys().size()); |
| assertEquals(4, (int) IteratorUtils.count(v8.properties("location"))); |
| v8.properties("location").forEachRemaining(vp -> { |
| if (vp.value().equals("bremen")) { |
| assertEquals(2004, (int) vp.value("startTime")); |
| assertEquals(2007, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("baltimore")) { |
| assertEquals(2007, (int) vp.value("startTime")); |
| assertEquals(2011, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("oakland")) { |
| assertEquals(2011, (int) vp.value("startTime")); |
| assertEquals(2014, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("seattle")) { |
| assertEquals(2014, (int) vp.value("startTime")); |
| assertEquals(1, (int) IteratorUtils.count(vp.properties())); |
| } else { |
| fail("Found a value that should be there"); |
| } |
| }); |
| assertId(g1, lossyForId, v8, 8); |
| |
| final List<Edge> v8Edges = IteratorUtils.list(v8.edges(Direction.BOTH)); |
| assertEquals(3, v8Edges.size()); |
| v8Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("gremlin") && e.label().equals("develops")) { |
| assertEquals(2012, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 21); |
| } else if (e.inVertex().value("name").equals("gremlin") && e.label().equals("uses")) { |
| assertEquals(3, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 22); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("uses")) { |
| assertEquals(3, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 23); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v9 = (Vertex) g1.traversal().V().has("name", "daniel").next(); |
| assertEquals("person", v9.label()); |
| assertEquals(2, v9.keys().size()); |
| assertEquals(3, (int) IteratorUtils.count(v9.properties("location"))); |
| v9.properties("location").forEachRemaining(vp -> { |
| if (vp.value().equals("spremberg")) { |
| assertEquals(1982, (int) vp.value("startTime")); |
| assertEquals(2005, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("kaiserslautern")) { |
| assertEquals(2005, (int) vp.value("startTime")); |
| assertEquals(2009, (int) vp.value("endTime")); |
| assertEquals(2, (int) IteratorUtils.count(vp.properties())); |
| } else if (vp.value().equals("aachen")) { |
| assertEquals(2009, (int) vp.value("startTime")); |
| assertEquals(1, (int) IteratorUtils.count(vp.properties())); |
| } else { |
| fail("Found a value that should be there"); |
| } |
| }); |
| assertId(g1, lossyForId, v9, 9); |
| |
| final List<Edge> v9Edges = IteratorUtils.list(v9.edges(Direction.BOTH)); |
| assertEquals(2, v9Edges.size()); |
| v9Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("gremlin") && e.label().equals("uses")) { |
| assertEquals(5, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 24); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("uses")) { |
| assertEquals(3, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 25); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v10 = (Vertex) g1.traversal().V().has("name", "gremlin").next(); |
| assertEquals("software", v10.label()); |
| assertEquals(1, v10.keys().size()); |
| assertId(g1, lossyForId, v10, 10); |
| |
| final List<Edge> v10Edges = IteratorUtils.list(v10.edges(Direction.BOTH)); |
| assertEquals(8, v10Edges.size()); |
| v10Edges.forEach(e -> { |
| if (e.outVertex().value("name").equals("marko") && e.label().equals("develops")) { |
| assertEquals(2009, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 13); |
| } else if (e.outVertex().value("name").equals("marko") && e.label().equals("uses")) { |
| assertEquals(4, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 15); |
| } else if (e.outVertex().value("name").equals("stephen") && e.label().equals("develops")) { |
| assertEquals(2010, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 17); |
| } else if (e.outVertex().value("name").equals("stephen") && e.label().equals("uses")) { |
| assertEquals(5, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 19); |
| } else if (e.outVertex().value("name").equals("matthias") && e.label().equals("develops")) { |
| assertEquals(2012, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 21); |
| } else if (e.outVertex().value("name").equals("matthias") && e.label().equals("uses")) { |
| assertEquals(3, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 22); |
| } else if (e.outVertex().value("name").equals("daniel") && e.label().equals("uses")) { |
| assertEquals(5, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 24); |
| } else if (e.inVertex().value("name").equals("tinkergraph") && e.label().equals("traverses")) { |
| assertEquals(0, e.keys().size()); |
| assertId(g1, lossyForId, e, 26); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v11 = (Vertex) g1.traversal().V().has("name", "tinkergraph").next(); |
| assertEquals("software", v11.label()); |
| assertEquals(1, v11.keys().size()); |
| assertId(g1, lossyForId, v11, 11); |
| |
| final List<Edge> v11Edges = IteratorUtils.list(v11.edges(Direction.BOTH)); |
| assertEquals(7, v11Edges.size()); |
| v11Edges.forEach(e -> { |
| if (e.outVertex().value("name").equals("marko") && e.label().equals("develops")) { |
| assertEquals(2010, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 14); |
| } else if (e.outVertex().value("name").equals("marko") && e.label().equals("uses")) { |
| assertEquals(5, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 16); |
| } else if (e.outVertex().value("name").equals("stephen") && e.label().equals("develops")) { |
| assertEquals(2011, (int) e.value("since")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 18); |
| } else if (e.outVertex().value("name").equals("stephen") && e.label().equals("uses")) { |
| assertEquals(4, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 20); |
| } else if (e.outVertex().value("name").equals("matthias") && e.label().equals("uses")) { |
| assertEquals(3, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 23); |
| } else if (e.outVertex().value("name").equals("daniel") && e.label().equals("uses")) { |
| assertEquals(3, (int) e.value("skill")); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 25); |
| } else if (e.outVertex().value("name").equals("gremlin") && e.label().equals("traverses")) { |
| assertEquals(0, e.keys().size()); |
| assertId(g1, lossyForId, e, 26); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| } |
| |
| public static void assertClassicGraph(final Graph g1, final boolean assertDouble, final boolean lossyForId) { |
| assertToyGraph(g1, assertDouble, lossyForId, false); |
| } |
| |
| public static void assertNoEdgeGraph(final Graph g1, final boolean assertDouble, final boolean lossyForId) { |
| assertEquals(2, IteratorUtils.count(g1.vertices())); |
| assertEquals(1, IteratorUtils.count(g1.edges())); |
| |
| final Vertex v1 = g1.traversal().V().has("name", "marko").next(); |
| assertEquals(29, v1.<Integer>value("age").intValue()); |
| assertEquals(2, v1.keys().size()); |
| assertEquals(Vertex.DEFAULT_LABEL, v1.label()); |
| assertId(g1, lossyForId, v1, 1); |
| |
| final List<Edge> v1Edges = IteratorUtils.list(v1.edges(Direction.BOTH)); |
| assertEquals(1, v1Edges.size()); |
| v1Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("vadas")) { |
| assertEquals(Edge.DEFAULT_LABEL, e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.5d, e); |
| else |
| assertWeightLoosely(0.5f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 7); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| } |
| |
| public static void assertModernGraph(final Graph g1, final boolean assertDouble, final boolean lossyForId) { |
| assertToyGraph(g1, assertDouble, lossyForId, true); |
| } |
| |
| private static void assertToyGraph(final Graph g1, final boolean assertDouble, final boolean lossyForId, final boolean assertSpecificLabel) { |
| assertEquals(6, IteratorUtils.count(g1.vertices())); |
| assertEquals(6, IteratorUtils.count(g1.edges())); |
| |
| final Vertex v1 = g1.traversal().V().has("name", "marko").next(); |
| assertEquals(29, v1.<Integer>value("age").intValue()); |
| assertEquals(2, v1.keys().size()); |
| assertEquals(assertSpecificLabel ? "person" : Vertex.DEFAULT_LABEL, v1.label()); |
| assertId(g1, lossyForId, v1, 1); |
| |
| final List<Edge> v1Edges = IteratorUtils.list(v1.edges(Direction.BOTH)); |
| assertEquals(3, v1Edges.size()); |
| v1Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("vadas")) { |
| assertEquals("knows", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.5d, e); |
| else |
| assertWeightLoosely(0.5f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 7); |
| } else if (e.inVertex().value("name").equals("josh")) { |
| assertEquals("knows", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(1.0, e); |
| else |
| assertWeightLoosely(1.0f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 8); |
| } else if (e.inVertex().value("name").equals("lop")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.4d, e); |
| else |
| assertWeightLoosely(0.4f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 9); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v2 = g1.traversal().V().has("name", "vadas").next(); |
| assertEquals(27, v2.<Integer>value("age").intValue()); |
| assertEquals(2, v2.keys().size()); |
| assertEquals(assertSpecificLabel ? "person" : Vertex.DEFAULT_LABEL, v2.label()); |
| assertId(g1, lossyForId, v2, 2); |
| |
| final List<Edge> v2Edges = IteratorUtils.list(v2.edges(Direction.BOTH)); |
| assertEquals(1, v2Edges.size()); |
| v2Edges.forEach(e -> { |
| if (e.outVertex().value("name").equals("marko")) { |
| assertEquals("knows", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.5d, e); |
| else |
| assertWeightLoosely(0.5f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 7); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v3 = g1.traversal().V().has("name", "lop").next(); |
| assertEquals("java", v3.<String>value("lang")); |
| assertEquals(2, v2.keys().size()); |
| assertEquals(assertSpecificLabel ? "software" : Vertex.DEFAULT_LABEL, v3.label()); |
| assertId(g1, lossyForId, v3, 3); |
| |
| final List<Edge> v3Edges = IteratorUtils.list(v3.edges(Direction.BOTH)); |
| assertEquals(3, v3Edges.size()); |
| v3Edges.forEach(e -> { |
| if (e.outVertex().value("name").equals("peter")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.2d, e); |
| else |
| assertWeightLoosely(0.2f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 12); |
| } else if (e.outVertex().value("name").equals("josh")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.4d, e); |
| else |
| assertWeightLoosely(0.4f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 11); |
| } else if (e.outVertex().value("name").equals("marko")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.4d, e); |
| else |
| assertWeightLoosely(0.4f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 9); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v4 = g1.traversal().V().has("name", "josh").next(); |
| assertEquals(32, v4.<Integer>value("age").intValue()); |
| assertEquals(2, v4.keys().size()); |
| assertEquals(assertSpecificLabel ? "person" : Vertex.DEFAULT_LABEL, v4.label()); |
| assertId(g1, lossyForId, v4, 4); |
| |
| final List<Edge> v4Edges = IteratorUtils.list(v4.edges(Direction.BOTH)); |
| assertEquals(3, v4Edges.size()); |
| v4Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("ripple")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(1.0d, e); |
| else |
| assertWeightLoosely(1.0f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 10); |
| } else if (e.inVertex().value("name").equals("lop")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.4d, e); |
| else |
| assertWeightLoosely(0.4f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 11); |
| } else if (e.outVertex().value("name").equals("marko")) { |
| assertEquals("knows", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(1.0d, e); |
| else |
| assertWeightLoosely(1.0f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 8); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v5 = g1.traversal().V().has("name", "ripple").next(); |
| assertEquals("java", v5.<String>value("lang")); |
| assertEquals(2, v5.keys().size()); |
| assertEquals(assertSpecificLabel ? "software" : Vertex.DEFAULT_LABEL, v5.label()); |
| assertId(g1, lossyForId, v5, 5); |
| |
| final List<Edge> v5Edges = IteratorUtils.list(v5.edges(Direction.BOTH)); |
| assertEquals(1, v5Edges.size()); |
| v5Edges.forEach(e -> { |
| if (e.outVertex().value("name").equals("josh")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(1.0d, e); |
| else |
| assertWeightLoosely(1.0f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 10); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| |
| final Vertex v6 = g1.traversal().V().has("name", "peter").next(); |
| assertEquals(35, v6.<Integer>value("age").intValue()); |
| assertEquals(2, v6.keys().size()); |
| assertEquals(assertSpecificLabel ? "person" : Vertex.DEFAULT_LABEL, v6.label()); |
| assertId(g1, lossyForId, v6, 6); |
| |
| final List<Edge> v6Edges = IteratorUtils.list(v6.edges(Direction.BOTH)); |
| assertEquals(1, v6Edges.size()); |
| v6Edges.forEach(e -> { |
| if (e.inVertex().value("name").equals("lop")) { |
| assertEquals("created", e.label()); |
| if (assertDouble) |
| assertWeightLoosely(0.2d, e); |
| else |
| assertWeightLoosely(0.2f, e); |
| assertEquals(1, e.keys().size()); |
| assertId(g1, lossyForId, e, 12); |
| } else { |
| fail("Edge not expected"); |
| } |
| }); |
| } |
| |
| private static void assertWeightLoosely(final double expected, final Edge e) { |
| try { |
| assertEquals(expected, e.value("weight"), 0.0001d); |
| } catch (Exception ex) { |
| // for graphs that have strong typing via schema it is possible that a value that came across as graphson |
| // with lossiness will end up having a value expected to double to be coerced to float by the underlying |
| // graph. |
| logger.warn("Attempting to assert weight as float for {} - if your graph is strongly typed from schema this is likely expected", e); |
| assertEquals(new Double(expected).floatValue(), e.value("weight"), 0.0001f); |
| } |
| } |
| |
| private static void assertWeightLoosely(final float expected, final Edge e) { |
| try { |
| assertEquals(expected, e.value("weight"), 0.0001f); |
| } catch (Exception ex) { |
| // for graphs that have strong typing via schema it is possible that a value that came across as graphson |
| // with lossiness will end up having a value expected to float to be coerced to double by the underlying |
| // graph. |
| logger.warn("Attempting to assert weight as double for {} - if your graph is strongly typed from schema this is likely expected", e); |
| assertEquals(new Float(expected).doubleValue(), e.value("weight"), 0.0001d); |
| } |
| } |
| |
| private static void assertId(final Graph g, final boolean lossyForId, final Element e, final Object expected) { |
| // it is possible that a Graph (e.g. elastic-gremlin) can supportUserSuppliedIds but internally |
| // represent them as a value other than Numeric (which is what's in all of the test/toy data). |
| // as we feature check for userSuppliedIds when asserting the identifier, we also ensure that |
| // the id can be properly asserted for that Element before attempting to do so. By asserting |
| // at this level in this way, graphs can enjoy greater test coverage in IO. |
| if ((e instanceof Vertex && g.features().vertex().supportsUserSuppliedIds() && g.features().vertex().supportsNumericIds()) |
| || (e instanceof Edge && g.features().edge().supportsUserSuppliedIds() && g.features().edge().supportsNumericIds()) |
| || (e instanceof VertexProperty && g.features().vertex().properties().supportsUserSuppliedIds()) && g.features().vertex().properties().supportsNumericIds()) { |
| if (lossyForId) |
| assertEquals(expected.toString(), e.id().toString()); |
| else |
| assertEquals(expected, e.id()); |
| } |
| } |
| |
| private static void validateXmlAgainstGraphMLXsd(final File file) throws Exception { |
| final Source xmlFile = new StreamSource(file); |
| final SchemaFactory schemaFactory = SchemaFactory |
| .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); |
| final Schema schema = schemaFactory.newSchema(new StreamSource(getResourceAsStream(GraphMLResourceAccess.class, "graphml-1.1.xsd"))); |
| final Validator validator = schema.newValidator(); |
| validator.validate(xmlFile); |
| } |
| |
| private static void readGraphMLIntoGraph(final Graph g, final String file) throws IOException { |
| final GraphReader reader = GraphMLReader.build().create(); |
| try (final InputStream stream = getResourceAsStream( GraphMLResourceAccess.class, file )) { |
| reader.readGraph(stream, g); |
| } |
| } |
| |
| public static InputStream getResourceAsStream(Class<?> resourceClass, final String file) { |
| return IoTest.class.getResourceAsStream( "/" |
| + resourceClass.getPackage().getName().replaceAll("\\.", "/") |
| + "/" |
| + file); |
| } |
| |
| private static String streamToString(final InputStream in) throws IOException { |
| final Writer writer = new StringWriter(); |
| final char[] buffer = new char[1024]; |
| try (final Reader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"))) { |
| int n; |
| while ((n = reader.read(buffer)) != -1) { |
| writer.write(buffer, 0, n); |
| } |
| } |
| |
| return writer.toString(); |
| } |
| |
| } |