package com.tinkerpop.blueprints.oupls.sail.pg; import com.tinkerpop.blueprints.Graph; import com.tinkerpop.blueprints.impls.tg.TinkerGraph; import com.tinkerpop.blueprints.util.io.graphml.GraphMLReader; import info.aduna.iteration.CloseableIteration; import net.fortytwo.sesametools.StatementComparator; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.openrdf.model.Literal; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.URI; import org.openrdf.model.Value; import org.openrdf.model.ValueFactory; import org.openrdf.model.vocabulary.RDF; import org.openrdf.query.BindingSet; import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.impl.EmptyBindingSet; import org.openrdf.query.parser.ParsedQuery; import org.openrdf.query.parser.sparql.SPARQLParser; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.sail.SailRepository; import org.openrdf.rio.RDFFormat; import org.openrdf.rio.RDFWriter; import org.openrdf.rio.Rio; import org.openrdf.sail.SailConnection; import org.openrdf.sail.SailException; import java.util.Collection; import java.util.LinkedList; import java.util.Set; import java.util.TreeSet; import static junit.framework.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; /** * @author Joshua Shinavier (http://fortytwo.net) */ public class PropertyGraphSailTest { private final PropertyGraphSail sail; private final ValueFactory vf; private final URI edge, head, id, label, tail, vertex; private final URI age, josh, lang, lop, marko, name, peter, ripple, vadas, weight; private final URI created, knows; private final URI markoKnowsVadas, markoKnowsJosh, markoCreatedLop, joshCreatedRipple, joshCreatedLop, peterCreatedLop; private SailConnection sc; public PropertyGraphSailTest() throws Exception { Graph g = new TinkerGraph(); GraphMLReader r = new GraphMLReader(g); r.inputGraph(GraphMLReader.class.getResourceAsStream("graph-example-1.xml")); sail = new PropertyGraphSail(g); sail.initialize(); vf = sail.getValueFactory(); edge = vf.createURI(PropertyGraphSail.ONTOLOGY_NS + "Edge"); head = vf.createURI(PropertyGraphSail.ONTOLOGY_NS + "head"); id = vf.createURI(PropertyGraphSail.ONTOLOGY_NS + "id"); label = vf.createURI(PropertyGraphSail.ONTOLOGY_NS + "label"); tail = vf.createURI(PropertyGraphSail.ONTOLOGY_NS + "tail"); vertex = vf.createURI(PropertyGraphSail.ONTOLOGY_NS + "Vertex"); age = vf.createURI(PropertyGraphSail.PROPERTY_NS + "age"); lang = vf.createURI(PropertyGraphSail.PROPERTY_NS + "lang"); name = vf.createURI(PropertyGraphSail.PROPERTY_NS + "name"); weight = vf.createURI(PropertyGraphSail.PROPERTY_NS + "weight"); josh = vf.createURI(PropertyGraphSail.VERTEX_NS + "4"); lop = vf.createURI(PropertyGraphSail.VERTEX_NS + "3"); marko = vf.createURI(PropertyGraphSail.VERTEX_NS + "1"); peter = vf.createURI(PropertyGraphSail.VERTEX_NS + "6"); ripple = vf.createURI(PropertyGraphSail.VERTEX_NS + "5"); vadas = vf.createURI(PropertyGraphSail.VERTEX_NS + "2"); markoKnowsVadas = vf.createURI(PropertyGraphSail.EDGE_NS + "7"); markoKnowsJosh = vf.createURI(PropertyGraphSail.EDGE_NS + "8"); markoCreatedLop = vf.createURI(PropertyGraphSail.EDGE_NS + "9"); joshCreatedRipple = vf.createURI(PropertyGraphSail.EDGE_NS + "10"); joshCreatedLop = vf.createURI(PropertyGraphSail.EDGE_NS + "11"); peterCreatedLop = vf.createURI(PropertyGraphSail.EDGE_NS + "12"); created = vf.createURI(PropertyGraphSail.RELATION_NS + "created"); knows = vf.createURI(PropertyGraphSail.RELATION_NS + "knows"); } @Before public void setUp() throws Exception { sc = sail.getConnection(); } @After public void tearDown() throws Exception { sc.close(); } @Test public void testSize() throws Exception { assertEquals(60, sc.size()); } @Test public void testNamespaces() throws Exception { assertEquals(5, count(sc.getNamespaces())); assertEquals("http://tinkerpop.com/pgm/property/", sc.getNamespace("prop")); assertEquals("http://tinkerpop.com/pgm/ontology#", sc.getNamespace("pgm")); assertEquals("http://tinkerpop.com/pgm/vertex/", sc.getNamespace("vertex")); assertEquals("http://tinkerpop.com/pgm/edge/", sc.getNamespace("edge")); assertEquals("http://www.w3.org/1999/02/22-rdf-syntax-ns#", sc.getNamespace("rdf")); } @Test public void testVertexProperties() throws Exception { // s p o assertExpected(get(marko, name, vf.createLiteral("marko")), vf.createStatement(marko, name, vf.createLiteral("marko"))); // s p ? assertExpected(get(marko, name, null), vf.createStatement(marko, name, vf.createLiteral("marko"))); // ? p o assertExpected(get(null, name, vf.createLiteral("marko")), vf.createStatement(marko, name, vf.createLiteral("marko"))); // ? ? o assertExpected(get(null, null, vf.createLiteral("marko")), vf.createStatement(marko, name, vf.createLiteral("marko"))); // ? p ? assertExpected(get(null, name, null), vf.createStatement(josh, name, vf.createLiteral("josh")), vf.createStatement(lop, name, vf.createLiteral("lop")), vf.createStatement(marko, name, vf.createLiteral("marko")), vf.createStatement(peter, name, vf.createLiteral("peter")), vf.createStatement(ripple, name, vf.createLiteral("ripple")), vf.createStatement(vadas, name, vf.createLiteral("vadas"))); // s ? o assertExpected(get(marko, null, vf.createLiteral("marko")), vf.createStatement(marko, name, vf.createLiteral("marko"))); } @Test public void testEdgeProperties() throws Exception { // s p o assertExpected(get(joshCreatedRipple, weight, vf.createLiteral(1.0f)), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f))); // s p ? assertExpected(get(joshCreatedRipple, weight, null), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f))); // ? p o assertExpected(get(null, weight, vf.createLiteral(1.0f)), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f)), vf.createStatement(markoKnowsJosh, weight, vf.createLiteral(1.0f))); // ? ? o assertExpected(get(null, null, vf.createLiteral(1.0f)), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f)), vf.createStatement(markoKnowsJosh, weight, vf.createLiteral(1.0f))); // ? p ? assertExpected(get(null, weight, null), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f)), vf.createStatement(markoKnowsVadas, weight, vf.createLiteral(0.5f)), vf.createStatement(markoCreatedLop, weight, vf.createLiteral(0.4f)), vf.createStatement(joshCreatedLop, weight, vf.createLiteral(0.4f)), vf.createStatement(peterCreatedLop, weight, vf.createLiteral(0.2f)), vf.createStatement(markoKnowsJosh, weight, vf.createLiteral(1.0f))); // s ? o assertExpected(get(joshCreatedRipple, null, vf.createLiteral(1.0f)), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f))); } @Test public void testIds() throws Exception { // s p o assertExpected(get(marko, id, vf.createLiteral("1")), vf.createStatement(marko, id, vf.createLiteral("1"))); // s p ? assertExpected(get(marko, id, null), vf.createStatement(marko, id, vf.createLiteral("1"))); // ? p o assertExpected(get(null, id, vf.createLiteral("1")), vf.createStatement(marko, id, vf.createLiteral("1"))); // ? ? o assertExpected(get(null, null, vf.createLiteral("1")), vf.createStatement(marko, id, vf.createLiteral("1"))); // ? p ? assertExpected(get(null, id, null), vf.createStatement(marko, id, vf.createLiteral("1")), vf.createStatement(vadas, id, vf.createLiteral("2")), vf.createStatement(lop, id, vf.createLiteral("3")), vf.createStatement(josh, id, vf.createLiteral("4")), vf.createStatement(ripple, id, vf.createLiteral("5")), vf.createStatement(peter, id, vf.createLiteral("6")), vf.createStatement(markoKnowsVadas, id, vf.createLiteral("7")), vf.createStatement(markoKnowsJosh, id, vf.createLiteral("8")), vf.createStatement(markoCreatedLop, id, vf.createLiteral("9")), vf.createStatement(joshCreatedRipple, id, vf.createLiteral("10")), vf.createStatement(joshCreatedLop, id, vf.createLiteral("11")), vf.createStatement(peterCreatedLop, id, vf.createLiteral("12"))); // s ? o assertExpected(get(marko, null, vf.createLiteral("1")), vf.createStatement(marko, id, vf.createLiteral("1"))); } @Test public void testLabels() throws Exception { // s p o assertExpected(get(markoKnowsVadas, label, vf.createLiteral("knows")), vf.createStatement(markoKnowsVadas, label, vf.createLiteral("knows"))); // s p ? assertExpected(get(markoKnowsVadas, label, null), vf.createStatement(markoKnowsVadas, label, vf.createLiteral("knows"))); // ? p o assertExpected(get(null, label, vf.createLiteral("knows")), vf.createStatement(markoKnowsVadas, label, vf.createLiteral("knows")), vf.createStatement(markoKnowsJosh, label, vf.createLiteral("knows"))); // ? ? o assertExpected(get(null, null, vf.createLiteral("knows")), vf.createStatement(markoKnowsVadas, label, vf.createLiteral("knows")), vf.createStatement(markoKnowsJosh, label, vf.createLiteral("knows"))); // ? p ? assertExpected(get(null, label, null), vf.createStatement(markoCreatedLop, label, vf.createLiteral("created")), vf.createStatement(joshCreatedLop, label, vf.createLiteral("created")), vf.createStatement(joshCreatedRipple, label, vf.createLiteral("created")), vf.createStatement(peterCreatedLop, label, vf.createLiteral("created")), vf.createStatement(markoKnowsVadas, label, vf.createLiteral("knows")), vf.createStatement(markoKnowsJosh, label, vf.createLiteral("knows"))); // s ? o assertExpected(get(markoKnowsVadas, null, vf.createLiteral("knows")), vf.createStatement(markoKnowsVadas, label, vf.createLiteral("knows"))); } @Test public void testHeads() throws Exception { // s p o assertExpected(get(markoCreatedLop, head, lop), vf.createStatement(markoCreatedLop, head, lop)); // s p ? assertExpected(get(markoCreatedLop, head, null), vf.createStatement(markoCreatedLop, head, lop)); // ? p o assertExpected(get(null, head, lop), vf.createStatement(markoCreatedLop, head, lop), vf.createStatement(joshCreatedLop, head, lop), vf.createStatement(peterCreatedLop, head, lop)); // ? ? o assertExpected(get(null, null, lop), vf.createStatement(markoCreatedLop, head, lop), vf.createStatement(joshCreatedLop, head, lop), vf.createStatement(peterCreatedLop, head, lop)); // ? p ? assertExpected(get(null, head, null), vf.createStatement(markoKnowsJosh, head, josh), vf.createStatement(markoKnowsVadas, head, vadas), vf.createStatement(markoCreatedLop, head, lop), vf.createStatement(joshCreatedRipple, head, ripple), vf.createStatement(joshCreatedLop, head, lop), vf.createStatement(peterCreatedLop, head, lop)); // s ? o assertExpected(get(markoCreatedLop, null, lop), vf.createStatement(markoCreatedLop, head, lop)); } @Test public void testTails() throws Exception { // s p o assertExpected(get(markoCreatedLop, tail, marko), vf.createStatement(markoCreatedLop, tail, marko)); // s p ? assertExpected(get(markoCreatedLop, tail, null), vf.createStatement(markoCreatedLop, tail, marko)); // ? p o assertExpected(get(null, tail, marko), vf.createStatement(markoCreatedLop, tail, marko), vf.createStatement(markoKnowsJosh, tail, marko), vf.createStatement(markoKnowsVadas, tail, marko)); // ? ? o assertExpected(get(null, null, marko), vf.createStatement(markoCreatedLop, tail, marko), vf.createStatement(markoKnowsJosh, tail, marko), vf.createStatement(markoKnowsVadas, tail, marko)); // ? p ? assertExpected(get(null, tail, null), vf.createStatement(markoKnowsJosh, tail, marko), vf.createStatement(markoKnowsVadas, tail, marko), vf.createStatement(markoCreatedLop, tail, marko), vf.createStatement(joshCreatedRipple, tail, josh), vf.createStatement(joshCreatedLop, tail, josh), vf.createStatement(peterCreatedLop, tail, peter)); // s ? o assertExpected(get(markoCreatedLop, null, marko), vf.createStatement(markoCreatedLop, tail, marko)); } @Test public void testTypes() throws Exception { // s p o assertExpected(get(marko, RDF.TYPE, vertex), vf.createStatement(marko, RDF.TYPE, vertex)); // s p ? assertExpected(get(marko, RDF.TYPE, null), vf.createStatement(marko, RDF.TYPE, vertex)); // ? p o assertExpected(get(null, RDF.TYPE, vertex), vf.createStatement(marko, RDF.TYPE, vertex), vf.createStatement(vadas, RDF.TYPE, vertex), vf.createStatement(lop, RDF.TYPE, vertex), vf.createStatement(josh, RDF.TYPE, vertex), vf.createStatement(ripple, RDF.TYPE, vertex), vf.createStatement(peter, RDF.TYPE, vertex)); // ? ? o assertExpected(get(null, null, vertex), vf.createStatement(marko, RDF.TYPE, vertex), vf.createStatement(vadas, RDF.TYPE, vertex), vf.createStatement(lop, RDF.TYPE, vertex), vf.createStatement(josh, RDF.TYPE, vertex), vf.createStatement(ripple, RDF.TYPE, vertex), vf.createStatement(peter, RDF.TYPE, vertex)); // ? p ? assertExpected(get(null, RDF.TYPE, null), vf.createStatement(markoKnowsJosh, RDF.TYPE, edge), vf.createStatement(markoKnowsVadas, RDF.TYPE, edge), vf.createStatement(markoCreatedLop, RDF.TYPE, edge), vf.createStatement(joshCreatedRipple, RDF.TYPE, edge), vf.createStatement(joshCreatedLop, RDF.TYPE, edge), vf.createStatement(peterCreatedLop, RDF.TYPE, edge), vf.createStatement(marko, RDF.TYPE, vertex), vf.createStatement(vadas, RDF.TYPE, vertex), vf.createStatement(lop, RDF.TYPE, vertex), vf.createStatement(josh, RDF.TYPE, vertex), vf.createStatement(ripple, RDF.TYPE, vertex), vf.createStatement(peter, RDF.TYPE, vertex)); // s ? o assertExpected(get(marko, null, vertex), vf.createStatement(marko, RDF.TYPE, vertex)); } @Test public void testxxx() throws Exception { assertEquals(60, get(null, null, null).size()); } @Test public void testSxx() throws Exception { assertExpected(get(ripple, null, null), vf.createStatement(ripple, id, vf.createLiteral("5")), vf.createStatement(ripple, RDF.TYPE, vertex), vf.createStatement(ripple, lang, vf.createLiteral("java")), vf.createStatement(ripple, name, vf.createLiteral("ripple"))); } @Test public void testPropertyTypeSensitivity() throws Exception { assertExpected(get(joshCreatedRipple, weight, vf.createLiteral(1.0f)), vf.createStatement(joshCreatedRipple, weight, vf.createLiteral(1.0f))); assertExpected(get(joshCreatedRipple, weight, vf.createLiteral(1.0))); } @Test public void testRDFDump() throws Exception { Repository repo = new SailRepository(sail); RepositoryConnection rc = repo.getConnection(); try { RDFWriter w = Rio.createWriter(RDFFormat.TURTLE, System.out); rc.export(w); } finally { rc.close(); } } @Test public void testSPARQL() throws Exception { int count; String queryStr = "PREFIX pgm: <" + PropertyGraphSail.ONTOLOGY_NS + ">\n" + "PREFIX prop: <" + PropertyGraphSail.PROPERTY_NS + ">\n" + "SELECT ?project ?name WHERE {\n" + " ?marko prop:name \"marko\".\n" + " ?e1 pgm:label \"knows\".\n" + " ?e1 pgm:tail ?marko.\n" + " ?e1 pgm:head ?friend.\n" + " ?e2 pgm:label \"created\".\n" + " ?e2 pgm:tail ?friend.\n" + " ?e2 pgm:head ?project.\n" + " ?project prop:name ?name.\n" + "}"; System.out.println(queryStr); ParsedQuery query = new SPARQLParser().parseQuery(queryStr, "http://example.org/bogus/"); CloseableIteration<? extends BindingSet, QueryEvaluationException> results = sc.evaluate(query.getTupleExpr(), query.getDataset(), new EmptyBindingSet(), false); try { count = 0; while (results.hasNext()) { count++; BindingSet set = results.next(); URI project = (URI) set.getValue("project"); Literal name = (Literal) set.getValue("name"); assertNotNull(project); assertNotNull(name); System.out.println("project = " + project + ", name = " + name); } } finally { results.close(); } assertEquals(2, count); } @Test public void testSimpleEdges() throws Exception { sail.setFirstClassEdges(false); sc.close(); sc = sail.getConnection(); for (Statement st : get(null, null, null)) { System.out.println("st: " + st); } assertEquals(30, sc.size()); assertEquals(30, count(null, null, null)); assertEquals(6, count(null, RDF.TYPE, vertex)); assertEquals(0, count(null, RDF.TYPE, edge)); assertEquals(0, count(null, label, null)); assertEquals(0, count(null, head, null)); assertEquals(0, count(null, tail, null)); // ... absence of other patterns could be tested, as well // s ? ? assertExpected(get(marko, null, null), vf.createStatement(marko, id, vf.createLiteral("1")), vf.createStatement(marko, RDF.TYPE, vertex), vf.createStatement(marko, age, vf.createLiteral(29)), vf.createStatement(marko, name, vf.createLiteral("marko")), vf.createStatement(marko, knows, vadas), vf.createStatement(marko, created, lop), vf.createStatement(marko, knows, josh)); // s p ? assertExpected(get(marko, knows, null), vf.createStatement(marko, knows, vadas), vf.createStatement(marko, knows, josh)); // s ? o assertExpected(get(marko, null, josh), vf.createStatement(marko, knows, josh)); // s p o assertExpected(get(marko, knows, josh), vf.createStatement(marko, knows, josh)); assertExpected(get(marko, name, vf.createLiteral("marko")), vf.createStatement(marko, name, vf.createLiteral("marko"))); // ? ? o assertExpected(get(null, null, josh), vf.createStatement(marko, knows, josh)); // ? p o assertExpected(get(null, knows, josh), vf.createStatement(marko, knows, josh)); // ? p ? assertExpected(get(null, knows, null), vf.createStatement(marko, knows, vadas), vf.createStatement(marko, knows, josh)); } private long count(final CloseableIteration iter) throws Exception { long count = 0; try { while (iter.hasNext()) { count++; iter.next(); } } finally { iter.close(); } return count; } private void assertExpected(final Collection<Statement> graph, final Statement... expectedStatements) throws Exception { Set<Statement> expected = new TreeSet<Statement>(new StatementComparator()); for (Statement st : expectedStatements) { expected.add(st); } Set<Statement> actual = new TreeSet<Statement>(new StatementComparator()); for (Statement st : graph) { actual.add(st); } for (Statement t : expected) { if (!actual.contains(t)) { fail("expected statement not found: " + t); } } for (Statement t : actual) { if (!expected.contains(t)) { fail("unexpected statement found: " + t); } } } private Collection<Statement> get(final Resource subject, final URI predicate, final Value object) throws SailException { return toCollection(sc.getStatements(subject, predicate, object, false)); } private int count(final Resource subject, final URI predicate, final Value object) throws SailException { return toCollection(sc.getStatements(subject, predicate, object, false)).size(); } private Collection<Statement> toCollection(final CloseableIteration<? extends Statement, SailException> i) throws SailException { try { Collection<Statement> set = new LinkedList<Statement>(); while (i.hasNext()) { set.add(i.next()); } return set; } finally { i.close(); } } }