/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Kowari Metadata Store.
*
* The Initial Developer of the Original Code is Plugged In Software Pty
* Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions
* created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
* Plugged In Software Pty Ltd. All Rights Reserved.
*
* Contributor(s): N/A.
*
* [NOTE: The text of this Exhibit A may differ slightly from the text
* of the notices in the Source Code files of the Original Code. You
* should use the text of this Exhibit A rather than the text found in the
* Original Code Source Code for Your Modifications.]
*
*/
package org.mulgara.client.jrdf.test;
// Java 2 standard packages
import java.io.*;
import java.security.*;
import java.net.*;
// third party packages
import junit.framework.*;
//Log4J
import org.apache.log4j.Logger;
// JRDF
import org.jrdf.graph.*;
import org.jrdf.util.*;
// Local packages
import org.mulgara.client.jrdf.*;
import org.mulgara.client.jrdf.writer.MemoryXMLWriter;
import org.mulgara.itql.ItqlInterpreterBean;
import org.mulgara.query.Answer;
// local classes
/**
* Unit test for client-side JRDF Graph.
*
* @created 2001-08-27
*
* @author <a href="mailto:robert.turner@tucanatech.com">Robert Turner</a>
*
* @version $Revision: 1.9 $
*
* @modified $Date: 2005/01/13 11:55:50 $
*
* @maintenanceAuthor $Author: newmana $
*
* @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A>
*
* @copyright ©2001 <a href="http://www.pisoftware.com/">Plugged In
* Software Pty Ltd</a>
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public class ClientGraphUnitTest extends TestCase {
/**
* the category to send logging info to
*/
private static Logger log = Logger.getLogger(ClientGraphUnitTest.class);
/**
* Server to query against.
*/
protected final static String SERVER_NAME = "server1";
/**
* Description of the Field
*/
protected URI serverURI = null;
/**
* Description of the Field
*/
protected String hostname = null;
/**
* The URI of the test graph to create.
*/
protected URI graphURI = null;
/**
* the ITQL command interpreter. Used to execute iTQL.
*/
private static ItqlInterpreterBean interpreterBean = null;
/**
* the ITQL command interpreter. Used to create graph answers.
*/
private static ItqlInterpreterBean answerBean = null;
/** Small dataset used to test model */
private static final String testStatements =
"<http://mulgara.org/mulgara#test1> <http://mulgara.org/mulgara#test4> <http://mulgara.org/mulgara#test2> " +
"<http://mulgara.org/mulgara#test1> <http://mulgara.org/mulgara#test5> <http://mulgara.org/mulgara#test3> " +
"<http://mulgara.org/mulgara#test1> <http://mulgara.org/mulgara#test6> 'Test1' " +
"<http://mulgara.org/mulgara#test2> <http://mulgara.org/mulgara#test4> <http://mulgara.org/mulgara#test1> " +
"<http://mulgara.org/mulgara#test2> <http://mulgara.org/mulgara#test5> <http://mulgara.org/mulgara#test3> " +
"<http://mulgara.org/mulgara#test2> <http://mulgara.org/mulgara#test6> 'Test2' " +
"<http://mulgara.org/mulgara#test3> <http://mulgara.org/mulgara#test4> <http://mulgara.org/mulgara#test1> " +
"<http://mulgara.org/mulgara#test3> <http://mulgara.org/mulgara#test5> <http://mulgara.org/mulgara#test2> " +
"<http://mulgara.org/mulgara#test3> <http://mulgara.org/mulgara#test6> 'Test3' ";
/**
* Directory for test files
*/
private static String TEST_DIR = System.getProperty("cvs.root") + "/test/";
/**
* Test file used for memory writer
*/
private static String CLIENT_TEST_FILE1 = TEST_DIR + "ClientTest1.rdf";
/**
* Test file used for memory writer
*/
private static String CLIENT_TEST_FILE2 = TEST_DIR + "ClientTest2.rdf";
/**
* Constructs a new ItqlInterpreter unit test.
*
* @param name the name of the test
*/
public ClientGraphUnitTest(String name) throws Exception {
// delegate to super class constructor
super(name);
}
/**
* Returns a test suite containing the tests to be run.
*
* @return the test suite
*/
public static Test suite() throws Exception {
TestSuite suite = new TestSuite();
// TestSuite suite = (TestSuite) JRDFGraphUnitTest.suite();
suite.addTest(new ClientGraphUnitTest("testCreate"));
suite.addTest(new ClientGraphUnitTest("testFind"));
suite.addTest(new ClientGraphUnitTest("testAnswerOutputRDF"));
return suite;
}
/**
* Default text runner.
*
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
junit.textui.TestRunner.run(suite());
}
// suite()
//
// Test cases
//
/**
* Tests the creation of a Client Graph by an AbstractGraphFactory.
*
* @throws Exception
*/
@SuppressWarnings("deprecation") // avoiding the use of a connection
public void testCreate() throws Exception {
// log that we're executing the test
log.debug("Starting Create test");
//-- ANSWER IMPLEMENTATION --
// log that we're executing the test
log.debug("Testing Answer implementation");
//get all statments from the graph
Answer answer = getEntireGraph(graphURI);
//create a Client Graph from it.
ClientGraph client = AbstractGraphFactory.createGraph(answer, answerBean.getSession(serverURI));
//ensure the client is not null
assertNotNull("AbstractGraphFactory.createGraph(Answer) returned a null ClientGraph.", client);
//close the graph
client.close();
// log that we're executing the test
log.debug("Testing Answer implementation successful");
//-- END ANSWER IMPLEMENTATION --
// log that we've completed the test
log.debug("Completed Create test");
}
/**
* Tests the creation of a Client Graph by an AbstractGraphFactory.
*
* @throws Exception
*/
public void testFind() throws Exception {
try {
// log that we're executing the test
log.debug("Starting Find test");
//Answer
log.debug("Testing Answer implementation");
testAnswerFind();
log.debug("Testing Answer implementation successful");
} catch (Exception exception) {
exception.printStackTrace();
throw exception;
}
}
/**
* Tests the creation of a Client Graph by an AbstractGraphFactory.
*
* @throws Exception
*/
@SuppressWarnings("deprecation") // avoiding the use of a connection
public void testAnswerFind() throws Exception {
//create a Client Graph from it.
Answer answer = getEntireGraph(graphURI);
ClientGraph client = AbstractGraphFactory.createGraph(answer, answerBean.getSession(serverURI));
GraphElementFactory factory = client.getElementFactory();
//-- FIND ALL --
//create a triple and use it to filter the objects
Triple triple = factory.createTriple(null, null, null);
ClosableIterator<Triple> iter = client.find(triple);
//compare with answer
compareAnswerToIterator(answer, iter, factory);
//close iterator
iter.close();
//-- FIND SUBJECT (S) --
testAnswerFindSubjects(client, factory);
//-- FIND PREDICATE (S) --
testAnswerFindPredicates(client, factory);
//-- FIND OBJECT (S) --
testAnswerFindObjects(client, factory);
//close graph
client.close();
}
/**
* Tests Searching a graph by Subject.
*
* @throws Exception
*/
public void testAnswerFindSubjects(ClientGraph client,
GraphElementFactory factory) throws
Exception {
//subject 1
String subject = "http://mulgara.org/mulgara#test1";
Triple triple = factory.createTriple(factory.createResource(URI.create(
subject)),
null, null);
ClosableIterator<Triple> iter = client.find(triple);
compareAnswerToIterator(getSubject("<" + subject + ">"), iter,
factory);
iter.close();
//subject 2
subject = "http://mulgara.org/mulgara#test2";
triple = factory.createTriple(factory.createResource(URI.create(subject)),
null, null);
iter = client.find(triple);
compareAnswerToIterator(getSubject("<" + subject + ">"), iter,
factory);
iter.close();
//subject 3
subject = "http://mulgara.org/mulgara#test3";
triple = factory.createTriple(factory.createResource(URI.create(subject)),
null, null);
iter = client.find(triple);
compareAnswerToIterator(getSubject("<" + subject + ">"), iter,
factory);
iter.close();
}
/**
* Tests Searching a graph by Predicate.
*
* @throws Exception
*/
public void testAnswerFindPredicates(ClientGraph client,
GraphElementFactory factory) throws
Exception {
//predicate 4
String predicate = "http://mulgara.org/mulgara#test4";
Triple triple = factory.createTriple(null,
factory.createResource(URI.create(
predicate)),
null);
ClosableIterator<Triple> iter = client.find(triple);
compareAnswerToIterator(getPredicate("<" + predicate + ">"), iter,
factory);
iter.close();
//predicate 5
predicate = "http://mulgara.org/mulgara#test5";
triple = factory.createTriple(null,
factory.createResource(URI.create(predicate)),
null);
iter = client.find(triple);
compareAnswerToIterator(getPredicate("<" + predicate + ">"), iter,
factory);
iter.close();
//predicate 6
predicate = "http://mulgara.org/mulgara#test6";
triple = factory.createTriple(null,
factory.createResource(URI.create(predicate)),
null);
iter = client.find(triple);
compareAnswerToIterator(getPredicate("<" + predicate + ">"), iter,
factory);
iter.close();
}
/**
* Tests Searching a graph by Predicate.
*
* @throws Exception
*/
public void testAnswerFindObjects(ClientGraph client,
GraphElementFactory factory) throws
Exception {
//object 1
String object = "http://mulgara.org/mulgara#test1";
Triple triple = factory.createTriple(null, null,
factory.createResource(URI.
create(object)));
ClosableIterator<Triple> iter = client.find(triple);
compareAnswerToIterator(getObject("<" + object + ">"), iter,
factory);
iter.close();
//object 2
object = "http://mulgara.org/mulgara#test2";
triple = factory.createTriple(null, null,
factory.createResource(URI.create(object)));
iter = client.find(triple);
compareAnswerToIterator(getObject("<" + object + ">"), iter,
factory);
iter.close();
//object 3
object = "http://mulgara.org/mulgara#test3";
triple = factory.createTriple(null, null,
factory.createResource(URI.create(object)));
iter = client.find(triple);
compareAnswerToIterator(getObject("<" + object + ">"), iter,
factory);
iter.close();
//object test 1
object = "Test1";
triple = factory.createTriple(null, null, factory.createLiteral(object));
iter = client.find(triple);
compareAnswerToIterator(getObject("'" + object + "'"), iter,
factory);
iter.close();
//object test 2
object = "Test2";
triple = factory.createTriple(null, null, factory.createLiteral(object));
iter = client.find(triple);
compareAnswerToIterator(getObject("'" + object + "'"), iter,
factory);
iter.close();
//object test 3
object = "Test3";
triple = factory.createTriple(null, null, factory.createLiteral(object));
iter = client.find(triple);
compareAnswerToIterator(getObject("'" + object + "'"), iter,
factory);
iter.close();
}
/**
* Compares the triples from a Closable Iterator to the triples from an Answer
*
* @param answer Answer
* @param iterator ClosableITerator
* @throws Exception
*/
private void compareAnswerToIterator(Answer answer, ClosableIterator<Triple> iterator,
GraphElementFactory factory) throws
Exception {
Triple iterTriple = null;
//compare rows with answer
Triple answerTriple = null;
SubjectNode subject = null;
PredicateNode predicate = null;
ObjectNode object = null;
//iterate to the end of the closable iterator (compare to Answer)
while (iterator.hasNext()) {
//check type and ensure not null
iterTriple = (Triple) iterator.next();
if (iterTriple == null) {
fail("Result contains null Triple");
}
//get next triple from answer
answer.next();
subject = (SubjectNode) answer.getObject(0);
predicate = (PredicateNode) answer.getObject(1);
object = (ObjectNode) answer.getObject(2);
answerTriple = factory.createTriple(subject, predicate, object);
//compare to iterator
assertTrue("Iterator Triple not equal to Answer Triple. " +
"\n\tAnswer: " + answerTriple + ", Iterator: " + iterTriple +
".", (answerTriple.equals(iterTriple)));
}
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer getEntireGraph(URI modelURI) throws Exception {
//select ALL query
String query = "select $s $p $o " +
"from <" + modelURI + "> " +
"where $s $p $o " +
//needed for comparision
"order by $s $p $o ;";
return answerBean.executeQuery(query);
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer getColumn(String uri, String variable) throws Exception {
//select ALL query
String query = "select $s $p $o " +
"from <" + graphURI + "> " +
"where " + variable + "<http://mulgara.org/mulgara#is> " + uri + " " +
"and $s $p $o " +
//needed for comparision
"order by $s $p $o ;";
return interpreterBean.executeQuery(query);
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer getSubject(String subject) throws Exception {
return getColumn(subject, "$s");
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer getPredicate(String predicate) throws Exception {
return getColumn(predicate, "$p");
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer getObject(String object) throws Exception {
return getColumn(object, "$o");
}
/**
* Tests the RDF output of a MemoryXMLWriter. The output is loaded back into
* the graph.
*
* @throws Exception
*/
@SuppressWarnings("deprecation") // avoiding the use of a Connection
public void testAnswerOutputRDF() throws Exception {
//create a Client Graph containing all statments
ClientGraph client1 = AbstractGraphFactory.createGraph(getEntireGraph(graphURI), answerBean.getSession(serverURI));
File rdfOutput1 = new File(CLIENT_TEST_FILE1);
outputRDF(rdfOutput1, client1);
//reload file into new model
URI graph2 = new URI("" + graphURI + "2");
createModel(graph2);
interpreterBean.load(rdfOutput1, graph2);
//output new model
ClientGraph client2 = AbstractGraphFactory.createGraph(getEntireGraph(graph2), answerBean.getSession(serverURI));
File rdfOutput2 = new File(CLIENT_TEST_FILE2);
outputRDF(rdfOutput2, client2);
//compare files
assertTrue("RDF output file is not equal to file that was loaded.",
compareFiles(rdfOutput1, rdfOutput2));
//tidy up
client1.close();
client2.close();
dropModel(graph2);
}
/**
* Compares the contents of one file to another using an MD5 sum.
*
* @param file1 File
* @param file2 File
* @throws Exception
* @return boolean
*/
private boolean compareFiles(File file1, File file2) throws Exception {
//value to be returned
boolean compare = false;
byte[] digest1 = digest(file1);
byte[] digest2 = digest(file2);
//compare the bytes
if (digest1.length == digest2.length) {
for (int i = 0; i < digest1.length; i++) {
if (digest1[i] != digest2[i]) {
return false;
}
}
//got here, arrays are equal
compare = true;
}
return compare;
}
/**
* Returns an MD5 sum for the file
*
* @param file File
* @throws Exception
* @return byte[]
*/
private byte[] digest(File file) throws Exception {
//buffer
final int bufferSize = 1048576;
byte[] buffer = new byte[bufferSize];
DigestInputStream digestIn = new DigestInputStream(new FileInputStream(file),
MessageDigest.getInstance("MD5"));
//read file
int read = 0;
do {
read = digestIn.read(buffer);
} while (read != -1);
//digest
return digestIn.getMessageDigest().digest();
}
/**
* Outputs the contents of the graph to a file.
*
* @param file String
* @param graph Graph
*
* @throws Exception
*/
private void outputRDF(File file, Graph graph) throws Exception {
FileOutputStream fileStream = new FileOutputStream(file, false);
OutputStreamWriter outStream = new OutputStreamWriter(fileStream);
//create writer and write
new MemoryXMLWriter().write(graph, outStream);
outStream.close();
fileStream.close();
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer createModel(URI modelURI) throws Exception {
//select ALL query
String query = "create <" + modelURI + "> ;";
return interpreterBean.executeQuery(query);
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer dropModel(URI modelURI) throws Exception {
//select ALL query
String query = "drop <" + modelURI + "> ;";
return interpreterBean.executeQuery(query);
}
/**
* Returns an answer that contains all the statements for the graph.
*
* @return Answer
*/
private Answer populateModel() throws Exception {
//select ALL query
String query = "insert " + testStatements + "into <" + graphURI + "> ;";
return interpreterBean.executeQuery(query);
}
//set up and tear down
/**
* Initialise members.
*
* @throws Exception if something goes wrong
*/
public void setUp() throws Exception {
// Store persistence files in the temporary directory
try {
hostname = InetAddress.getLocalHost().getCanonicalHostName();
serverURI = new URI("rmi", hostname, "/" + SERVER_NAME, null);
graphURI = new URI("rmi", hostname, "/" + SERVER_NAME, "clientJenaTest");
//create an iTQLInterpreterBean for executing queries with
interpreterBean = new ItqlInterpreterBean();
answerBean = new ItqlInterpreterBean();
//initialize model
createModel(graphURI);
populateModel();
} catch (Exception exception) {
//try to tear down first
try {
tearDown();
} catch (Throwable t) {
// going to throw the original
}
throw exception;
}
}
/**
* The teardown method for JUnit
*
* @throws Exception EXCEPTION TO DO
*/
public void tearDown() throws Exception {
dropModel(graphURI);
interpreterBean.close();
answerBean.close();
}
}