/* * Copyright (C) 2013 lichtflut Forschungs- und Entwicklungsgesellschaft mbH * * 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.arastreju.tck; import org.arastreju.sge.Conversation; import org.arastreju.sge.ConversationContext; import org.arastreju.sge.SNOPS; import org.arastreju.sge.apriori.Aras; import org.arastreju.sge.apriori.RDF; import org.arastreju.sge.apriori.RDFS; import org.arastreju.sge.context.Context; import org.arastreju.sge.context.SimpleContextID; import org.arastreju.sge.io.RdfXmlBinding; import org.arastreju.sge.io.SemanticGraphIO; import org.arastreju.sge.io.SemanticIOException; import org.arastreju.sge.model.ResourceID; import org.arastreju.sge.model.SemanticGraph; import org.arastreju.sge.model.SimpleResourceID; import org.arastreju.sge.model.Statement; import org.arastreju.sge.model.nodes.ResourceNode; import org.arastreju.sge.model.nodes.SNResource; import org.arastreju.sge.model.nodes.ValueNode; import org.arastreju.sge.model.nodes.views.SNClass; import org.arastreju.sge.model.nodes.views.SNEntity; import org.arastreju.sge.model.nodes.views.SNText; import org.arastreju.sge.naming.QualifiedName; import org.arastreju.sge.persistence.TransactionControl; import org.arastreju.sge.query.Query; import org.arastreju.sge.query.QueryResult; import org.arastreju.sge.spi.GraphDataConnection; import org.arastreju.sge.spi.GraphDataStore; import org.arastreju.sge.spi.impl.ConversationImpl; import org.arastreju.sge.spi.impl.GraphDataConnectionImpl; import org.arastreju.sge.spi.impl.WorkingContextImpl; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import static org.arastreju.sge.SNOPS.associate; import static org.arastreju.sge.SNOPS.associations; import static org.arastreju.sge.SNOPS.objects; import static org.arastreju.sge.SNOPS.qualify; import static org.arastreju.sge.SNOPS.remove; /** * <p> * Abstract base for compatibility test of Arastreju bindings. * </p> * * <p> * Created 22.02.13 * </p> * * @author Oliver Tigges */ public abstract class AbstractConversationTest { protected static final QualifiedName qnVehicle = new QualifiedName("http://q#", "Verhicle"); protected static final QualifiedName qnCar = new QualifiedName("http://q#", "Car"); protected static final QualifiedName qnBike = new QualifiedName("http://q#", "Bike"); protected static final QualifiedName qnEmployedBy = new QualifiedName("http://q#", "employedBy"); protected static final QualifiedName qnHasEmployees = new QualifiedName("http://q#", "hasEmployees"); protected static final QualifiedName qnKnows = new QualifiedName("http://q#", "knows"); // ---------------------------------------------------- private GraphDataStore store; private GraphDataConnection connection; private Conversation conversation; // ---------------------------------------------------- /** * TO be overridden by concrete tests. * * @return A new store instance. */ protected abstract GraphDataStore createStore() throws Exception; // ---------------------------------------------------- @Before public void setUp() throws Exception { store = createStore(); connection = new GraphDataConnectionImpl(store); conversation = new ConversationImpl(new WorkingContextImpl(connection)); } @After public void tearDown() throws Exception { conversation.close(); connection.close(); store.close(); } // ---------------------------------------------------- @Test public void testInstantiation() throws IOException { ResourceNode node = new SNResource(new QualifiedName("http://q#", "N1")); conversation.attach(node); } @Test public void testFind() throws IOException { QualifiedName qn = new QualifiedName("http://q#", "N1"); ResourceNode node = new SNResource(qn); conversation.attach(node); ResourceNode node2 = conversation.findResource(qn); Assert.assertNotNull(node2); } @Test public void testResolveAndFind() throws IOException { ResourceNode found = conversation.findResource(qnVehicle); Assert.assertNull(found); ResourceNode resolved = conversation.resolve(SNOPS.id(qnVehicle)); Assert.assertNotNull(resolved); found = conversation.findResource(qnVehicle); Assert.assertNotNull(found); } @Test public void testMerge() throws IOException { QualifiedName qn = new QualifiedName("http://q#", "N1"); ResourceNode node = new SNResource(qn); conversation.attach(node); conversation.attach(node); ResourceNode node2 = conversation.findResource(qn); Assert.assertNotNull(node2); } @Test public void testDetaching() throws IOException { final ResourceNode car = new SNResource(qnCar); conversation.attach(car); final ResourceNode car3 = conversation.findResource(qnCar); Assert.assertEquals(car, car3); conversation.detach(car); final ResourceNode car4 = conversation.findResource(qnCar); Assert.assertNotSame(car, car4); } @Test public void testMerging() throws IOException { final ResourceNode vehicle = new SNResource(qnVehicle); final ResourceNode car1 = new SNResource(qnCar); conversation.attach(car1); SNOPS.associate(car1, Aras.HAS_BRAND_NAME, new SNText("BMW")); // detach conversation.detach(car1); conversation.detach(vehicle); SNOPS.associate(car1, RDFS.SUB_CLASS_OF, vehicle); SNOPS.associate(car1, Aras.HAS_PROPER_NAME, new SNText("Knut")); // attach again conversation.attach(car1); // detach and find again conversation.detach(car1); final ResourceNode car2 = conversation.findResource(qnCar); Assert.assertNotNull(car2); Assert.assertNotSame(car1, car2); final ResourceNode subClasss = SNOPS.singleObject(car2, RDFS.SUB_CLASS_OF).asResource(); Assert.assertEquals(vehicle, subClasss); final ValueNode brandname = SNOPS.singleObject(car2, Aras.HAS_BRAND_NAME).asValue(); Assert.assertEquals(brandname.getStringValue(), "BMW"); final ValueNode propername = SNOPS.singleObject(car2, Aras.HAS_PROPER_NAME).asValue(); Assert.assertEquals(propername.getStringValue(), "Knut"); } @Test public void testPersisting() throws IOException { final ResourceNode vehicle = new SNResource(qnVehicle); final ResourceNode car = new SNResource(qnCar); SNOPS.associate(car, RDFS.SUB_CLASS_OF, vehicle); SNOPS.associate(car, Aras.HAS_PROPER_NAME, new SNText("BMW")); conversation.attach(car); // detach and find again conversation.detach(car); final ResourceNode car2 = conversation.findResource(qnCar); Assert.assertNotSame(car, car2); final ResourceNode res = SNOPS.singleObject(car2, RDFS.SUB_CLASS_OF).asResource(); Assert.assertEquals(vehicle, res); final ValueNode value = SNOPS.singleObject(car2, Aras.HAS_PROPER_NAME).asValue(); Assert.assertEquals(value.getStringValue(), "BMW"); } @Test public void testRemove() { final SNClass vehicle = SNClass.from(new SNResource(qnVehicle)); final SNClass car = SNClass.from(new SNResource(qnCar)); final SNClass bike = SNClass.from(new SNResource(qnBike)); final ResourceNode car1 = car.createInstance(); SNOPS.associate(vehicle, RDFS.SUB_CLASS_OF, RDF.TYPE); SNOPS.associate(car, RDFS.SUB_CLASS_OF, vehicle); SNOPS.associate(bike, RDFS.SUB_CLASS_OF, vehicle); conversation.attach(vehicle); conversation.attach(bike); SNOPS.associate(car1, Aras.HAS_BRAND_NAME, new SNText("BMW")); SNOPS.associate(car1, Aras.HAS_PROPER_NAME, new SNText("Knut")); conversation.attach(car1); conversation.remove(car); Assert.assertNull(conversation.findResource(qnCar)); conversation.remove(car1); Assert.assertFalse(car1.isAttached()); Assert.assertFalse(car.isAttached()); Assert.assertTrue(vehicle.isAttached()); conversation.detach(vehicle); ResourceNode found = conversation.findResource(qnVehicle); Assert.assertNotNull(found); Assert.assertEquals(RDF.TYPE, SNOPS.singleObject(found, RDFS.SUB_CLASS_OF)); } @Test public void testDirectRemoval() { final ResourceNode vehicle = new SNResource(qnVehicle); final ResourceNode car1 = new SNResource(qnCar); final Statement association = SNOPS.associate(car1, Aras.HAS_BRAND_NAME, new SNText("BMW")); SNOPS.associate(car1, RDFS.SUB_CLASS_OF, vehicle); SNOPS.associate(car1, Aras.HAS_PROPER_NAME, new SNText("Knut")); conversation.attach(car1); final Statement stored = SNOPS.singleAssociation(car1, Aras.HAS_BRAND_NAME); Assert.assertEquals(association.hashCode(), stored.hashCode()); Assert.assertEquals(3, car1.getAssociations().size()); Assert.assertFalse(associations(car1, Aras.HAS_BRAND_NAME).isEmpty()); Assert.assertTrue("Association not present", car1.getAssociations().contains(association)); final boolean removedFlag = car1.removeAssociation(association); Assert.assertTrue(removedFlag); Assert.assertEquals(2, car1.getAssociations().size()); Assert.assertTrue(associations(car1, Aras.HAS_BRAND_NAME).isEmpty()); } @Test public void testAttachingRemoval() { final ResourceNode vehicle = new SNResource(qnVehicle); final ResourceNode car1 = new SNResource(qnCar); conversation.attach(car1); final Statement association = SNOPS.associate(car1, Aras.HAS_BRAND_NAME, new SNText("BMW")); SNOPS.associate(car1, RDFS.SUB_CLASS_OF, vehicle); SNOPS.associate(car1, Aras.HAS_PROPER_NAME, new SNText("Knut")); // detach conversation.detach(car1); Assert.assertEquals(3, car1.getAssociations().size()); Assert.assertFalse(associations(car1, Aras.HAS_BRAND_NAME).isEmpty()); Assert.assertTrue("Association not present", car1.getAssociations().contains(association)); final boolean removedFlag = car1.removeAssociation(association); Assert.assertTrue(removedFlag); conversation.attach(car1); final ResourceNode car2 = conversation.findResource(qnCar); Assert.assertNotSame(car1, car2); Assert.assertEquals(2, car2.getAssociations().size()); Assert.assertTrue(associations(car2, Aras.HAS_BRAND_NAME).isEmpty()); } @Test public void testBidirectionalAssociations() { final ResourceNode vehicle = new SNResource(qnVehicle); final ResourceNode car = new SNResource(qnCar); final ResourceID pred1 = new SimpleResourceID("http://arastreju.org/stuff#", "P1"); final ResourceID pred2 = new SimpleResourceID("http://arastreju.org/stuff#", "P2"); SNOPS.associate(vehicle, pred1, car); SNOPS.associate(car, pred2, vehicle); conversation.attach(vehicle); final ResourceNode vehicleLoaded = conversation.findResource(qnVehicle); final ResourceNode carLoaded = conversation.findResource(qnCar); Assert.assertFalse(vehicleLoaded.getAssociations().isEmpty()); Assert.assertFalse(carLoaded.getAssociations().isEmpty()); Assert.assertFalse(associations(vehicleLoaded, pred1).isEmpty()); Assert.assertFalse(associations(carLoaded, pred2).isEmpty()); } @Test public void testValueIndexing() throws IOException { final ResourceNode car = new SNResource(qnCar); SNOPS.associate(car, Aras.HAS_PROPER_NAME, new SNText("BMW")); conversation.attach(car); Query query = conversation.createQuery().addField(Aras.HAS_PROPER_NAME.toURI(), "BMW"); QueryResult result = query.getResult(); Assert.assertNotNull(result); Assert.assertFalse(result.isEmpty()); Assert.assertEquals(qnCar, result.getSingleNode().getQualifiedName()); } @Test public void testDataTypes() throws IOException { final ResourceNode car = new SNResource(qnCar); conversation.attach(car); SNOPS.associate(car, Aras.HAS_PROPER_NAME, new SNText("BMW")); conversation.detach(car); final ResourceNode car2 = conversation.findResource(qnCar); Assert.assertNotSame(car, car2); final ValueNode value = SNOPS.singleObject(car2, Aras.HAS_PROPER_NAME).asValue(); Assert.assertEquals(value.getStringValue(), "BMW"); } @Test public void testSNViews() throws IOException { final QualifiedName qnVehicle = new QualifiedName("http://q#", "Verhicle"); ResourceNode vehicle = new SNResource(qnVehicle); conversation.attach(vehicle); final QualifiedName qnCar = new QualifiedName("http://q#", "Car"); ResourceNode car = new SNResource(qnCar); conversation.attach(car); SNOPS.associate(car, RDFS.SUB_CLASS_OF, vehicle); conversation.getConversationContext().clear(); car = conversation.findResource(qnCar); vehicle = conversation.findResource(qnVehicle); Assert.assertTrue(SNClass.from(car).isSpecializationOf(vehicle)); } @Test public void testGraphImport() throws IOException, SemanticIOException { final SemanticGraphIO io = new RdfXmlBinding(); final SemanticGraph graph = io.read(getClass().getClassLoader().getResourceAsStream("test-statements.rdf.xml")); conversation.attach(graph); final QualifiedName qn = new QualifiedName("http://test.arastreju.org/common#Person"); final ResourceNode node = conversation.findResource(qn); Assert.assertNotNull(node); final ResourceNode hasChild = conversation.findResource(SNOPS.qualify("http://test.arastreju.org/common#hasChild")); Assert.assertNotNull(hasChild); Assert.assertEquals(new SimpleResourceID("http://test.arastreju.org/common#hasParent"), objects(hasChild, Aras.INVERSE_OF).iterator().next()); final ResourceNode marriedTo = conversation.findResource(SNOPS.qualify("http://test.arastreju.org/common#isMarriedTo")); Assert.assertNotNull(marriedTo); Assert.assertEquals(marriedTo, objects(marriedTo, Aras.INVERSE_OF).iterator().next()); } @Test public void testSerialization() throws IOException, SemanticIOException, ClassNotFoundException { final SemanticGraphIO io = new RdfXmlBinding(); final SemanticGraph graph = io.read(getClass().getClassLoader().getResourceAsStream("test-statements.rdf.xml")); conversation.attach(graph); final QualifiedName qn = new QualifiedName("http://test.arastreju.org/common#Person"); final ResourceNode node = conversation.findResource(qn); Assert.assertTrue(node.isAttached()); final ByteArrayOutputStream out = new ByteArrayOutputStream(); new ObjectOutputStream(out).writeObject(node); byte[] bytes = out.toByteArray(); out.close(); final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes)); final ResourceNode read = (ResourceNode) in.readObject(); Assert.assertFalse(read.isAttached()); } @Test public void testInferencingInverseOfBidirectional() { final ResourceNode knows = new SNResource(qnKnows); associate(knows, Aras.INVERSE_OF, knows); conversation.attach(knows); Assert.assertTrue(objects(knows, Aras.INVERSE_OF).contains(knows)); conversation.detach(knows); // preparation done. ResourceNode mike = new SNResource(qualify("http://q#Mike")); ResourceNode kent = new SNResource(qualify("http://q#Kent")); conversation.attach(mike); associate(mike, knows, kent); conversation.detach(kent); kent = conversation.findResource(kent.getQualifiedName()); Assert.assertTrue(objects(kent, knows).contains(mike)); } @Test public void testInferencingInverseOf() { final ResourceNode hasEmployees = new SNResource(qnHasEmployees); final ResourceNode isEmployedBy = new SNResource(qnEmployedBy); associate(hasEmployees, Aras.INVERSE_OF, isEmployedBy); associate(isEmployedBy, Aras.INVERSE_OF, hasEmployees); conversation.attach(hasEmployees); Assert.assertTrue(hasEmployees.isAttached()); Assert.assertTrue(isEmployedBy.isAttached()); // preparation done. ResourceNode mike = new SNResource(qualify("http://q#Mike")); ResourceNode corp = new SNResource(qualify("http://q#Corp")); conversation.attach(mike); Assert.assertTrue(mike.isAttached()); associate(mike, isEmployedBy, corp); Assert.assertTrue(corp.isAttached()); conversation.detach(corp); corp = conversation.findResource(corp.getQualifiedName()); Assert.assertTrue(objects(corp, hasEmployees).contains(mike)); Assert.assertTrue(objects(mike, isEmployedBy).contains(corp)); remove(corp, hasEmployees); Assert.assertFalse(objects(corp, hasEmployees).contains(mike)); mike = conversation.findResource(mike.getQualifiedName()); Assert.assertFalse(objects(mike, isEmployedBy).contains(corp)); } @Test public void testInferencingSubClasses() { final SNClass vehicleClass = SNClass.from(new SNResource(qnVehicle)); final SNClass carClass = SNClass.from(new SNResource(qnCar)); SNOPS.associate(carClass, RDFS.SUB_CLASS_OF, vehicleClass); final SNEntity car = carClass.createInstance(); final SNEntity vehicle = vehicleClass.createInstance(); conversation.attach(vehicle); conversation.attach(car); QueryResult res = conversation.createQuery().addField(RDF.TYPE.toURI(), qnVehicle).getResult(); Assert.assertNotNull(res); Assert.assertEquals(2, res.size()); remove(car, RDF.TYPE); res = conversation.createQuery().addField(RDF.TYPE.toURI(), qnVehicle).getResult(); Assert.assertNotNull(res); Assert.assertEquals(1, res.size()); } @Test public void testMultipleContexts() { final ResourceNode vehicle = new SNResource(qnVehicle); final ResourceNode car1 = new SNResource(qnCar); final String ctxNamepsace = "http://lf.de/ctx#"; final SimpleContextID ctx1 = new SimpleContextID(ctxNamepsace, "ctx1"); final SimpleContextID ctx2 = new SimpleContextID(ctxNamepsace, "ctx2"); final SimpleContextID ctx3 = new SimpleContextID(ctxNamepsace, "ctx3"); final SimpleContextID convCtx1 = new SimpleContextID(ctxNamepsace, "convCtx1"); final SimpleContextID convCtx2 = new SimpleContextID(ctxNamepsace, "convCtx1"); conversation.attach(car1); ConversationContext ctx = conversation.getConversationContext(); ctx.setReadContexts(ctx1, ctx2, ctx3, convCtx1, convCtx2); associate(car1, Aras.HAS_BRAND_NAME, new SNText("BMW"), ctx1); ctx.setPrimaryContext(convCtx1); associate(car1, RDFS.SUB_CLASS_OF, vehicle, ctx1, ctx2); ctx.setPrimaryContext(convCtx2); associate(car1, Aras.HAS_PROPER_NAME, new SNText("Knut"), ctx1, ctx2, ctx3); // detach conversation.detach(car1); final ResourceNode car2 = conversation.findResource(qnCar); Assert.assertNotSame(car1, car2); final Context[] cl1 = SNOPS.singleAssociation(car2, Aras.HAS_BRAND_NAME).getContexts(); final Context[] cl2 = SNOPS.singleAssociation(car2, RDFS.SUB_CLASS_OF).getContexts(); final Context[] cl3 = SNOPS.singleAssociation(car2, Aras.HAS_PROPER_NAME).getContexts(); Assert.assertArrayEquals(new Context[]{ctx1}, cl1); Assert.assertArrayEquals(new Context[]{convCtx1, ctx1, ctx2}, cl2); Assert.assertArrayEquals(new Context[]{convCtx2, ctx1, ctx2, ctx3}, cl3); } @Test public void testNonCommitNodeIndexing() throws IOException { final ResourceNode car = new SNResource(qnCar); SNOPS.associate(car, Aras.HAS_PROPER_NAME, new SNText("BMW")); TransactionControl ctl = conversation.beginTransaction(); conversation.attach(car); /* no commit here */ Query query = conversation.createQuery().addField(Aras.HAS_PROPER_NAME.toURI(), "BMW"); QueryResult result = query.getResult(); Assert.assertNotNull(result); Assert.assertFalse(result.isEmpty()); Assert.assertEquals(qnCar, result.getSingleNode().getQualifiedName()); conversation.remove(car); query = conversation.createQuery().addField(Aras.HAS_PROPER_NAME.toURI(), "BMW"); result = query.getResult(); Assert.assertNotNull(result); Assert.assertTrue(result.isEmpty()); /* commit just for completeness */ ctl.finish(); } @Test public void testNonCommitStmtIndexing() throws IOException { final ResourceNode car = new SNResource(qnCar); Statement st1 = SNOPS.associate(car, Aras.HAS_PROPER_NAME, new SNText("BMW")); TransactionControl ctl = conversation.beginTransaction(); conversation.attach(car); /* no commit here */ Query query = conversation.createQuery().addField(Aras.HAS_PROPER_NAME.toURI(), "BMW"); QueryResult result = query.getResult(); Assert.assertNotNull(result); Assert.assertFalse(result.isEmpty()); Assert.assertEquals(qnCar, result.getSingleNode().getQualifiedName()); conversation.removeStatement(st1); query = conversation.createQuery().addField(Aras.HAS_PROPER_NAME.toURI(), "BMW"); result = query.getResult(); Assert.assertNotNull(result); Assert.assertTrue(result.isEmpty()); /* commit just for completeness */ ctl.finish(); } }