/*
* $Header$
* $Revision: 624 $
* $Date: 2006-06-24 21:02:12 +1000 (Sat, 24 Jun 2006) $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003, 2004 The JRDF Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* the JRDF Project (http://jrdf.sf.net/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The JRDF Project" and "JRDF" must not be used to endorse
* or promote products derived from this software without prior written
* permission. For written permission, please contact
* newmana@users.sourceforge.net.
*
* 5. Products derived from this software may not be called "JRDF"
* nor may "JRDF" appear in their names without prior written
* permission of the JRDF Project.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the JRDF Project. For more
* information on JRDF, please see <http://jrdf.sourceforge.net/>.
*/
package org.jrdf.graph;
// Java packages
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jrdf.util.ClosableIterator;
import org.jrdf.vocabulary.RDF;
import java.net.URI;
/**
* Abstract test case for graph implementations.
*
* @author <a href="mailto:pgearon@users.sourceforge.net">Paula Gearon</a>
* @author Andrew Newman
*
* @version $Revision: 624 $
*/
public abstract class AbstractTripleFactoryTest extends TestCase {
/**
* Instance of a graph object.
*/
private Graph graph;
/**
* Instance of a factory for the graph
*/
protected GraphElementFactory elementFactory;
/**
* Instance of the triple factory for the graph.
*/
private TripleFactory tripleFactory;
// The following are interally used "constants"
private BlankNode blank1;
private BlankNode blank2;
private URI uri1;
private URI uri2;
private URI uri3;
private URIReference ref1;
private URIReference ref2;
private URIReference ref3;
private final String TEST_STR1 = "A test string";
private final String TEST_STR2 = "Another test string";
private Literal l1;
private Literal l2;
/**
* Hook for test runner to obtain an empty test suite from, because this test
* can't be run (it's abstract). This must be overridden in subclasses.
* @return The test suite
*/
public static Test suite() {
TestSuite suite = new TestSuite();
return suite;
}
/**
* Constructs a new test with the given name.
*
* @param name the name of the test
*/
public AbstractTripleFactoryTest(String name) {
super(name);
}
/**
* Create test instance.
*/
public void setUp() throws Exception {
graph = newGraph();
elementFactory = graph.getElementFactory();
tripleFactory = graph.getTripleFactory();
blank1 = elementFactory.createResource();
blank2 = elementFactory.createResource();
uri1 = new URI("http://namespace#somevalue");
uri2 = new URI("http://namespace#someothervalue");
uri3 = new URI("http://namespace#yetanothervalue");
ref1 = elementFactory.createResource(uri1);
ref2 = elementFactory.createResource(uri2);
ref3 = elementFactory.createResource(uri3);
l1 = elementFactory.createLiteral(TEST_STR1);
l2 = elementFactory.createLiteral(TEST_STR2);
}
//
// implementation interfaces
//
/**
* Create a graph implementation.
*
* @return A new GraphImpl.
*/
protected abstract Graph newGraph() throws Exception;
/**
* Get the node used for subject reification.
*
* @return The subject reification node.
*/
protected abstract PredicateNode getReifySubject() throws TripleFactoryException;
/**
* Get the node used for predicate reification.
*
* @return The predicate reification node.
*/
protected abstract PredicateNode getReifyPredicate() throws TripleFactoryException;
/**
* Get the node used for object reification.
*
* @return The object reification node.
*/
protected abstract PredicateNode getReifyObject() throws TripleFactoryException;
/**
* Get the node used for rdf:type.
*
* @return The object rdf:type node.
*/
protected abstract PredicateNode getRdfType() throws TripleFactoryException;
/**
* Get the node used for rdf:Statement.
*
* @return The object rdf:statement node.
*/
protected abstract ObjectNode getRdfStatement() throws TripleFactoryException;
/**
* Create a concrete Collection.
*
* @return the new collection.
*/
protected abstract Collection createCollection(ObjectNode[] objects);
/**
* Create a concrete alternative
*
* @return the new alternative.
*/
protected abstract Alternative createAlternative(ObjectNode[] objects);
/**
* Create a concrete bag
*
* @return the new bag.
*/
protected abstract Bag createBag(ObjectNode[] objects);
/**
* Create a concrete sequence
*
* @return the new sequence.
*/
protected abstract Sequence createSequence(ObjectNode[] objects);
//
// Test cases
//
/**
* Tests reification.
*/
public void testReification() throws Exception {
PredicateNode reifySubject = getReifySubject();
PredicateNode reifyPredicate = getReifyPredicate();
PredicateNode reifyObject = getReifyObject();
PredicateNode rdfType = getRdfType();
ObjectNode rdfStatement = getRdfStatement();
assertTrue(graph.isEmpty());
// Make a reification about a triple that does not exist in the graph.
URIReference u = elementFactory.createResource(uri1);
tripleFactory.reifyTriple(blank1, ref1, blank2, u);
assertEquals(uri1, u.getURI());
assertEquals(4, graph.getNumberOfTriples());
assertTrue(graph.contains(u, rdfType, rdfStatement));
assertTrue(graph.contains(u, reifySubject, blank1));
assertTrue(graph.contains(u, reifyPredicate, ref1));
assertTrue(graph.contains(u, reifyObject, blank2));
// Make a reification about a triple that does exist in the graph.
Triple t = elementFactory.createTriple(blank1, ref2, blank2);
u = elementFactory.createResource(uri2);
graph.add(t);
tripleFactory.reifyTriple(t, u);
assertEquals(uri2, u.getURI());
assertEquals(9, graph.getNumberOfTriples());
assertTrue(graph.contains(u, rdfType, rdfStatement));
assertTrue(graph.contains(u, reifySubject, blank1));
assertTrue(graph.contains(u, reifyPredicate, ref2));
assertTrue(graph.contains(u, reifyObject, blank2));
assertTrue(graph.contains(blank1, ref2, blank2));
// test for double insertion (allowed)
tripleFactory.reifyTriple(blank1, ref1, blank2, elementFactory.createResource(uri1));
assertEquals(9, graph.getNumberOfTriples());
// test for double insertion (allowed)
tripleFactory.reifyTriple(t, elementFactory.createResource(uri2));
assertEquals(9, graph.getNumberOfTriples());
// test for insertion with a different reference (allowed)
tripleFactory.reifyTriple(blank1, ref1, blank2, elementFactory.createResource(uri3));
assertEquals(13, graph.getNumberOfTriples());
// test for insertion of a new triple with an existing reference (disallowed)
testCantInsert(blank2, ref1, blank1, elementFactory.createResource(uri1));
assertEquals(13, graph.getNumberOfTriples());
// test for insertion with a different reference (disallowed)
testCantInsert(t, uri3);
assertEquals(13, graph.getNumberOfTriples());
// test for insertion of a new triple with an existing reference
testCantInsert(elementFactory.createTriple(blank2, ref2, blank2), uri2);
assertEquals(13, graph.getNumberOfTriples());
// do it all again for blank nodes
// Make reification that does not exist in graph
BlankNode b = elementFactory.createResource();
tripleFactory.reifyTriple(blank1, ref1, l1, b);
assertEquals(17, graph.getNumberOfTriples());
assertTrue(graph.contains(b, rdfType, rdfStatement));
assertTrue(graph.contains(b, reifySubject, blank1));
assertTrue(graph.contains(b, reifyPredicate, ref1));
assertTrue(graph.contains(b, reifyObject, l1));
// Make a reification using a blank node for a statement that does exist
// in the graph.
t = elementFactory.createTriple(blank1, ref2, l2);
graph.add(t);
b = elementFactory.createResource();
tripleFactory.reifyTriple(t, b);
assertEquals(22, graph.getNumberOfTriples());
assertTrue(graph.contains(b, rdfType, rdfStatement));
assertTrue(graph.contains(b, reifySubject, blank1));
assertTrue(graph.contains(b, reifyPredicate, ref2));
assertTrue(graph.contains(b, reifyObject, l2));
assertTrue(graph.contains(blank1, ref2, l2));
// test for double insertion
testCanInsert(blank1, ref1, blank2);
// test for insertion with a a used blank reference
testCantInsert(blank1, ref3, blank2, u);
// test that the graph did not change with the invalid insertions
assertEquals(26, graph.getNumberOfTriples());
// test for double insertion
testCanInsert(t);
// test for insertion with a a used blank reference
testCantInsert(elementFactory.createTriple(blank1, ref3, blank2), u.getURI());
// test that the graph did not change with the invalid insertions
assertEquals(30, graph.getNumberOfTriples());
// Test reifying an existing statement
b = elementFactory.createResource();
graph.add(ref3, ref3, ref3);
try {
tripleFactory.reifyTriple(ref3, ref3, ref3, b);
}
catch (AlreadyReifiedException e) {
fail("Should allow reification of an existing");
}
}
/**
* Test collections implmentations.
*/
public void testCollections() throws Exception {
// Ensure graph is empty before starting.
assertTrue(graph.isEmpty());
// Create initial statement
SubjectNode s = (SubjectNode) elementFactory.createResource(
new URI("http://example.org/basket"));
PredicateNode p = (PredicateNode) elementFactory.createResource(
new URI("http://example.org/stuff/1.0/hasFruit"));
ObjectNode o = (ObjectNode)
elementFactory.createResource();
// Add to graph
graph.add(s, p, o);
// Create collection object.
ObjectNode[] fruit = new ObjectNode[3];
fruit[0] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/banana"));
fruit[1] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/kiwi"));
fruit[2] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/pineapple"));
PredicateNode rdfFirst = (PredicateNode) elementFactory.createResource(
RDF.FIRST);
PredicateNode rdfRest = (PredicateNode) elementFactory.createResource(
RDF.REST);
ObjectNode rdfNil = (ObjectNode) elementFactory.createResource(
RDF.NIL);
// Create collection and add
Collection collection = createCollection(fruit);
// Add the collection to the graph.
tripleFactory.addCollection((SubjectNode) o, collection);
// Check we've inserted it correctly.
assertEquals("Should have seven statements", 7, graph.getNumberOfTriples());
assertTrue("Should have first statement", graph.contains(s, p, o));
assertTrue("Should have first object and first collection object",
graph.contains((SubjectNode) o, rdfFirst, fruit[0]));
// Get all rdf:first statements
ClosableIterator<Triple> iter = graph.find(null, rdfFirst, null);
int counter = 0;
while (iter.hasNext()) {
// System.err.println(iter.next());
iter.next();
counter++;
}
assertTrue("Should have three rdf:first statements, not " + counter, 3 ==
counter);
// Find all three parts of the collection.
for (int index = 0; index < fruit.length; index++) {
assertTrue("Should contain: " + fruit[index], graph.contains(
null, rdfFirst, fruit[index]));
}
// Get all rdf:rest statements
iter = graph.find(null, rdfRest, null);
counter = 0;
while (iter.hasNext()) {
// System.err.println(iter.next());
iter.next();
counter++;
}
assertTrue("Should have three rdf:rest statements", 3 == counter);
// Get all rdf:rest with rdf:nil statements
iter = graph.find(null, rdfRest, rdfNil);
counter = 0;
while (iter.hasNext()) {
// System.err.println(iter.next());
iter.next();
counter++;
}
assertTrue("Should have one rdf:rest with rdf:nil statements", 1 ==
counter);
}
/**
* Test altnerative implementation.
*/
public void testAlternative() throws Exception {
// Ensure graph is empty before starting.
assertTrue(graph.isEmpty());
// Create initial statement
SubjectNode s = (SubjectNode) elementFactory.createResource(
new URI("http://example.org/favourite-bananas"));
// Create collection object.
ObjectNode[] fruit = new ObjectNode[4];
fruit[0] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/banana"));
fruit[1] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/cavendish"));
fruit[2] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/ladyfinger"));
fruit[3] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/banana"));
PredicateNode rdfType = (PredicateNode) elementFactory.createResource(
RDF.TYPE);
ObjectNode rdfAlternative = (ObjectNode) elementFactory.createResource(
RDF.ALT);
// Create collection and add
Alternative alt = createAlternative(fruit);
// Add the collection to the graph.
tripleFactory.addAlternative(s, alt);
// Check we've inserted it correctly (banana is in twice should be removed)
assertEquals("Should have five statements", 4, graph.getNumberOfTriples());
assertTrue("Should have statement", graph.contains(s, rdfType, rdfAlternative));
assertTrue("Should have statement", graph.contains(s, null, fruit[0]));
assertTrue("Should have statement", graph.contains(s, null, fruit[1]));
assertTrue("Should have statement", graph.contains(s, null, fruit[2]));
assertTrue("Should have statement", graph.contains(s, null, fruit[3]));
// Check that it doesn't allow duplicates.
ClosableIterator<Triple> iter = graph.find(null, null, fruit[0]);
int count = 0;
while (iter.hasNext()) {
iter.next();
count++;
}
assertTrue("Should have only the same statements: " + fruit[0], 1 == count);
}
/**
* Test bag implementation.
*/
public void testBag() throws Exception {
// Ensure graph is empty before starting.
assertTrue(graph.isEmpty());
// Create initial statement
SubjectNode s = (SubjectNode) elementFactory.createResource(
new URI("http://example.org/favourite-fruit"));
// Create collection object.
ObjectNode[] fruit = new ObjectNode[5];
fruit[0] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/banana"));
fruit[1] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/kiwi"));
fruit[2] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/pineapple"));
fruit[3] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/pineapple"));
fruit[4] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/banana"));
PredicateNode rdfType = (PredicateNode) elementFactory.createResource(
RDF.TYPE);
ObjectNode rdfBag = (ObjectNode) elementFactory.createResource(
RDF.BAG);
// Create collection and add
Bag bag = createBag(fruit);
// Add the collection to the graph.
tripleFactory.addBag(s, bag);
// Check we've inserted it correctly
assertEquals("Should have six statements", 6, graph.getNumberOfTriples());
assertTrue("Should have statement", graph.contains(s, rdfType, rdfBag));
assertTrue("Should have statement", graph.contains(s, null, fruit[0]));
assertTrue("Should have statement", graph.contains(s, null, fruit[1]));
assertTrue("Should have statement", graph.contains(s, null, fruit[2]));
// Check that it allows duplicates.
ClosableIterator<Triple> iter = graph.find(s, null, fruit[2]);
int count = 0;
while (iter.hasNext()) {
iter.next();
count++;
}
assertTrue("Should have two of the same statements: " + fruit[2], 2 ==
count);
}
/**
* Test sequence implmentation.
*/
public void testSequence() throws Exception {
// Ensure graph is empty before starting.
assertTrue(graph.isEmpty());
// Create initial statement
SubjectNode s = (SubjectNode) elementFactory.createResource(
new URI("http://example.org/favourite-fruit"));
// Create collection object.
ObjectNode[] fruit = new ObjectNode[4];
fruit[0] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/banana"));
fruit[1] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/kiwi"));
fruit[2] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/pineapple"));
fruit[3] = (ObjectNode) elementFactory.createResource(new URI(
"http://example.org/kiwi"));
PredicateNode rdfType = (PredicateNode) elementFactory.createResource(
RDF.TYPE);
PredicateNode rdfOne = (PredicateNode) elementFactory.createResource(
new URI(RDF.BASE_URI + "_1"));
PredicateNode rdfTwo = (PredicateNode) elementFactory.createResource(
new URI(RDF.BASE_URI + "_2"));
PredicateNode rdfThree = (PredicateNode) elementFactory.createResource(
new URI(RDF.BASE_URI + "_3"));
PredicateNode rdfFour = (PredicateNode) elementFactory.createResource(
new URI(RDF.BASE_URI + "_4"));
ObjectNode rdfSequence = (ObjectNode) elementFactory.createResource(
RDF.SEQ);
// Create collection and add
Sequence sequence = createSequence(fruit);
// Add the collection to the graph.
tripleFactory.addSequence(s, sequence);
// Check we've inserted it correctly.
assertEquals("Should have five statements", 5, graph.getNumberOfTriples());
assertTrue("Should have statement", graph.contains(s, rdfType, rdfSequence));
assertTrue("Should have statement", graph.contains(s, rdfOne, fruit[0]));
assertTrue("Should have statement", graph.contains(s, rdfTwo, fruit[1]));
assertTrue("Should have statement", graph.contains(s, rdfThree, fruit[2]));
assertTrue("Should have statement", graph.contains(s, rdfFour, fruit[3]));
}
/**
* Utility method to check that a triple cannot be reified.
*
* @param subject The subject for the triple.
* @param predicate The predicate for the triple.
* @param object The object for the triple.
* @param r The reification node for the triple.
* @throws Exception The triple could be reified.
*/
private void testCantInsert(SubjectNode subject, PredicateNode predicate,
ObjectNode object, SubjectNode r) throws Exception {
try {
tripleFactory.reifyTriple(subject, predicate, object, r);
assertTrue(false);
} catch (AlreadyReifiedException e) {
}
}
/**
* Utility method to check that a triple cannot be reified.
*
* @param triple The triple to reify.
* @param r The reification node for the triple.
* @throws Exception The triple could be reified.
*/
private void testCantInsert(Triple triple, URI r) throws Exception {
try {
tripleFactory.reifyTriple(triple, elementFactory.createResource(r));
assertTrue(false);
} catch (AlreadyReifiedException e) {
}
}
/**
* Utility method to check that a triple cannot be reified with a blank node.
*
* @param subject The subject for the triple.
* @param predicate The predicate for the triple.
* @param object The object for the triple.
* @throws Exception The triple could be reified.
*/
private void testCanInsert(SubjectNode subject, PredicateNode predicate,
ObjectNode object) throws Exception {
try {
tripleFactory.reifyTriple(subject, predicate, object,
elementFactory.createResource());
assertTrue(true);
} catch (AlreadyReifiedException e) {
}
}
/**
* Utility method to check that a triple cannot be reified with a blank node.
*
* @param triple The triple to reify.
* @throws Exception The triple could be reified.
*/
private void testCanInsert(Triple triple) throws Exception {
try {
tripleFactory.reifyTriple(triple, elementFactory.createResource());
assertTrue(true);
} catch (AlreadyReifiedException e) {
}
}
}