// Copyright 2017 JanusGraph Authors // // Licensed 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.janusgraph.graphdb; import org.janusgraph.core.JanusGraphTransaction; import org.janusgraph.core.attribute.Geoshape; import org.janusgraph.core.attribute.JtsGeoshapeHelper; import org.janusgraph.core.schema.JanusGraphManagement; import org.janusgraph.example.GraphOfTheGodsFactory; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Polygon; import org.apache.tinkerpop.gremlin.structure.io.GraphReader; import org.apache.tinkerpop.gremlin.structure.io.GraphWriter; import org.apache.tinkerpop.gremlin.structure.io.IoCore; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.Arrays; import java.util.function.Function; /** * Tests JanusGraph specific serialization classes not covered by the TinkerPop suite. * * @author Stephen Mallette (http://stephen.genoprime.com) */ public abstract class JanusGraphIoTest extends JanusGraphBaseTest { private static final GeometryFactory GF = new GeometryFactory(); private static final JtsGeoshapeHelper HELPER = new JtsGeoshapeHelper(); @Before public void setup() { GraphOfTheGodsFactory.loadWithoutMixedIndex(graph, true); JanusGraphManagement mgmt = graph.openManagement(); mgmt.makePropertyKey("shape").dataType(Geoshape.class).make(); mgmt.commit(); } @Test public void testSerializationReadWriteAsGraphSONEmbedded() throws Exception { testSerializationReadWriteAsGraphSONEmbedded(null); testSerializationReadWriteAsGraphSONEmbedded(makeLine); testSerializationReadWriteAsGraphSONEmbedded(makePoly); testSerializationReadWriteAsGraphSONEmbedded(makeMultiPoint); testSerializationReadWriteAsGraphSONEmbedded(makeMultiLine); testSerializationReadWriteAsGraphSONEmbedded(makeMultiPolygon); } @Test public void testSerializationReadWriteAsGryo() throws Exception { testSerializationReadWriteAsGryo(null); testSerializationReadWriteAsGryo(makeLine); testSerializationReadWriteAsGryo(makePoly); testSerializationReadWriteAsGryo(makeMultiPoint); testSerializationReadWriteAsGryo(makeMultiLine); testSerializationReadWriteAsGryo(makeMultiPolygon); } public void testSerializationReadWriteAsGraphSONEmbedded(Function<Geoshape,Geoshape> makeGeoshape) throws Exception { if (makeGeoshape != null) { addGeoshape(makeGeoshape); } GraphSONMapper m = graph.io(IoCore.graphson()).mapper().embedTypes(true).create(); GraphWriter writer = graph.io(IoCore.graphson()).writer().mapper(m).create(); FileOutputStream fos = new FileOutputStream("/tmp/test.json"); writer.writeGraph(fos, graph); clearGraph(config); open(config); GraphReader reader = graph.io(IoCore.graphson()).reader().mapper(m).create(); FileInputStream fis = new FileInputStream("/tmp/test.json"); reader.readGraph(fis, graph); JanusGraphIndexTest.assertGraphOfTheGods(graph); if (makeGeoshape != null) { assertGeoshape(makeGeoshape); } } private void testSerializationReadWriteAsGryo(Function<Geoshape,Geoshape> makeGeoshape) throws Exception { if (makeGeoshape != null) { addGeoshape(makeGeoshape); } graph.io(IoCore.gryo()).writeGraph("/tmp/test.kryo"); clearGraph(config); open(config); graph.io(IoCore.gryo()).readGraph("/tmp/test.kryo"); JanusGraphIndexTest.assertGraphOfTheGods(graph); if (makeGeoshape != null) { assertGeoshape(makeGeoshape); } } private void addGeoshape(Function<Geoshape,Geoshape> makeGeoshape) { JanusGraphTransaction tx = graph.newTransaction(); graph.traversal().E().has("place").toList().stream().forEach(e-> { Geoshape place = (Geoshape) e.property("place").value(); e.property("shape", makeGeoshape.apply(place)); }); tx.commit(); } private void assertGeoshape(Function<Geoshape,Geoshape> makeGeoshape) { graph.traversal().E().has("place").toList().stream().forEach(e-> { assertTrue(e.property("shape").isPresent()); Geoshape place = (Geoshape) e.property("place").value(); Geoshape expected = makeGeoshape.apply(place); Geoshape actual = (Geoshape) e.property("shape").value(); assertEquals(expected, actual); }); } private static final Function<Geoshape,Geoshape> makePoly = place -> { double x = Math.floor(place.getPoint().getLongitude()); double y = Math.floor(place.getPoint().getLatitude()); return Geoshape.polygon(Arrays.asList(new double[][] {{x,y},{x,y+1},{x+1,y+1},{x+1,y},{x,y},{x,y}})); }; private static final Function<Geoshape,Geoshape> makeLine = place -> { double x = Math.floor(place.getPoint().getLongitude()); double y = Math.floor(place.getPoint().getLatitude()); return Geoshape.line(Arrays.asList(new double[][] {{x,y},{x,y+1},{x+1,y+1},{x+1,y}})); }; private static final Function<Geoshape,Geoshape> makeMultiPoint = place -> { double x = Math.floor(place.getPoint().getLongitude()); double y = Math.floor(place.getPoint().getLatitude()); return HELPER.geoshape(GF.createMultiPoint(new Coordinate[] {new Coordinate(x,y), new Coordinate(x+1,y+1)})); }; private static final Function<Geoshape,Geoshape> makeMultiLine = place -> { double x = Math.floor(place.getPoint().getLongitude()); double y = Math.floor(place.getPoint().getLatitude()); return HELPER.geoshape(GF.createMultiLineString(new LineString[] { GF.createLineString(new Coordinate[] {new Coordinate(x,y), new Coordinate(x+1,y+1)}), GF.createLineString(new Coordinate[] {new Coordinate(x-1,y-1), new Coordinate(x,y)})})); }; private static final Function<Geoshape,Geoshape> makeMultiPolygon = place -> { double x = Math.floor(place.getPoint().getLongitude()); double y = Math.floor(place.getPoint().getLatitude()); return HELPER.geoshape(GF.createMultiPolygon(new Polygon[] { GF.createPolygon(new Coordinate[] {new Coordinate(x,y), new Coordinate(x+1,y), new Coordinate(x+1,y+1), new Coordinate(x,y)}), GF.createPolygon(new Coordinate[] {new Coordinate(x+2,y+2), new Coordinate(x+2,y+3), new Coordinate(x+3,y+3), new Coordinate(x+2,y+2)})})); }; }