Unverified Commit de1a36e8 authored by Jay Billings's avatar Jay Billings Committed by GitHub

Merge pull request #483 from marshallmcdonnell/marshall/bats_unit_tests_and_delete

Adds unit tests and delete method to BATS
parents 49c5006b dbdaa3bf
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Initial API and implementation and/or initial documentation - * Jay Jay Billings - Initial API and implementation and/or initial docs
* Jay Jay Billings * Marshall McDonnell - Added delete method
*****************************************************************************/ *****************************************************************************/
package org.eclipse.ice.bats; package org.eclipse.ice.bats;
...@@ -20,6 +20,7 @@ import org.apache.http.HttpResponse; ...@@ -20,6 +20,7 @@ import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair; import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
...@@ -57,234 +58,265 @@ import org.apache.logging.log4j.core.Logger; ...@@ -57,234 +58,265 @@ import org.apache.logging.log4j.core.Logger;
*/ */
public class DataSet { public class DataSet {
/** /**
* This is the default name used as the base for all unnamed instances of * This is the default name used as the base for all unnamed instances of
* DataSet. * DataSet.
*/ */
public static final String DEFAULT_NAME = "unnamed-dataset"; public static final String DEFAULT_NAME = "unnamed-dataset";
/** /**
* Log utility * Log utility
*/ */
protected static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(DataSet.class.getName()); protected static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(DataSet.class.getName());
/** /**
* The default host which holds the dataset. * The default host which holds the dataset.
*/ */
private String host = "http://localhost"; private String host = "http://localhost";
/** /**
* The default port of the host which holds the dataset. * The default port of the host which holds the dataset.
*/ */
private int port = 3030; private int port = 3030;
/** /**
* The default name for a dataset. * The default name for a dataset.
*/ */
private String name = DEFAULT_NAME; private String name = DEFAULT_NAME;
/**
* This operation sets the name of the data set. The name of the data set is the /**
* name recognized by the host, not the local machine. It must be set prior to * This operation sets the name of the data set. The name of the data set is the
* calling create() or load(), but calling it after those operations does not * name recognized by the host, not the local machine. It must be set prior to
* change it. * calling create() or load(), but calling it after those operations does not
* * change it.
* @param name *
*/ * @param name
public void setName(final String name) { */
this.name = name; public void setName(final String name) {
} this.name = name;
}
/**
* This operation returns the name of the data set. /**
* * This operation returns the name of the data set.
* @return the name *
*/ * @return the name
public String getName() { */
return name; public String getName() {
} return name;
}
/**
* This operation returns the host of the data set. /**
* * This operation returns the host of the data set.
* @return the host *
*/ * @return the host
public String getHost() { */
return host; public String getHost() {
} return host;
}
/**
* This operation sets the host at which the data set should be created or from /**
* which it should be loaded. * This operation sets the host at which the data set should be created or from
* * which it should be loaded.
* @param host the URI of the remote Fuseki host that hosts the data set *
*/ * @param host the URI of the remote Fuseki host that hosts the data set
public void setHost(final String host) { */
this.host = host; public void setHost(final String host) {
} this.host = host;
}
/**
* This operation returns the port of the host of this data set. /**
* * This operation returns the port of the host of this data set.
* @return the port *
*/ * @return the port
public int getPort() { */
return port; public int getPort() {
} return port;
}
/**
* This operation sets the expected port of the host of this data set. /**
* * This operation sets the expected port of the host of this data set.
* @param port *
*/ * @param port
public void setPort(final int port) { */
this.port = port; public void setPort(final int port) {
} this.port = port;
}
/**
* This operation returns the full URI identifying this data set on the remote /**
* server, including hostname, port, and set name. * This operation returns the full URI identifying this data set on the remote
* * server, including hostname, port, and set name.
* @return the full URI including all parts *
*/ * @return the full URI including all parts
public String getFullURI() { */
return getHost() + ":" + getPort() + "/" + getName(); public String getFullURI() {
} return getHost() + ":" + getPort() + "/" + getName();
}
/**
* This operation creates a dataset with the given name. If no name is provided /**
* to setName(), the default name with a UUID appended to it will be used such * This operation returns the full URI of the Fuseki Data API location
* that the form of the name will be "unnamed-dataset_<UUID>." Note that * for this data set on the remote server
* creation does not imply retrieval, and that the getRootModel() or getModel() * using the hostname, port, and set name.
* functions still need to be called. Likewise (and obviously), if the model *
* already exists on the remote server it can just be retrieved without calling * @return the Fuseki Data API location
* create(). */
* public String getFusekiDatasetsURI() {
* @throws Exception this exception is thrown if the data set cannot be created String fusekiLocation = host + ":" + port + "/";
* for any reason. String fusekiDataAPILoc = "$/datasets";
*/ return getHost() + ":" + getPort() + "/$/datasets";
public void create() throws Exception { }
// Configure the name /**
String dbName = DEFAULT_NAME; * This operation creates a dataset with the given name. If no name is provided
if (name == DEFAULT_NAME) { * to setName(), the default name with a UUID appended to it will be used such
name += "_" + UUID.randomUUID().toString(); * that the form of the name will be "unnamed-dataset_<UUID>." Note that
} * creation does not imply retrieval, and that the getRootModel() or getModel()
dbName = name; * functions still need to be called. Likewise (and obviously), if the model
// Per the spec, always use tdb2. * already exists on the remote server it can just be retrieved without calling
String dbType = "tdb2"; * create().
*
// Connect the HTTP client * @throws Exception this exception is thrown if the data set cannot be created
HttpClient client = HttpClientBuilder.create().build(); * for any reason.
String fusekiLocation = host + ":" + port + "/"; */
String fusekiDataAPILoc = "$/datasets"; public void create() throws Exception {
HttpPost post = new HttpPost((fusekiLocation + fusekiDataAPILoc));
// Configure the name
// Add the database parameters into the form with UTF_8 encoding. String dbName = DEFAULT_NAME;
List<NameValuePair> form = new ArrayList<NameValuePair>(); if (name == DEFAULT_NAME) {
form.add(new BasicNameValuePair("dbName", dbName)); name += "_" + UUID.randomUUID().toString();
form.add(new BasicNameValuePair("dbType", dbType)); }
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(form, Consts.UTF_8); dbName = name;
// Per the spec, always use tdb2.
// Create the data set String dbType = "tdb2";
post.setEntity(formEntity);
HttpResponse response = client.execute(post); // Connect the HTTP client
logger.debug(response.toString()); HttpClient client = HttpClientBuilder.create().build();
String fusekiDataLocation = getFusekiDatasetsURI();
return; HttpPost post = new HttpPost(fusekiDataLocation);
}
// Add the database parameters into the form with UTF_8 encoding.
/** List<NameValuePair> form = new ArrayList<NameValuePair>();
* This operation directs the data set to update and persist any remotely stored form.add(new BasicNameValuePair("dbName", dbName));
* versions of this model with this version of the model. This action is a form.add(new BasicNameValuePair("dbType", dbType));
* complete re-write of the data, with out a merge or any checks. UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(form, Consts.UTF_8);
*
* @param modelName the name of the model that will be updated // Create the data set
* @param model the model that will be updated remotely post.setEntity(formEntity);
*/ HttpResponse response = client.execute(post);
public void updateModel(final String modelName, Model model) { logger.debug(response.toString());
RDFConnectionRemoteBuilder uploadConnBuilder = RDFConnectionFuseki.create() return;
.destination(getFullURI() + "/data"); }
// Open a connection to upload the ICE ontology. /**
try (RDFConnectionFuseki uploadConn = (RDFConnectionFuseki) uploadConnBuilder.build()) { * This operation deletes the data set with the given name.
// Note that transactions must proceed with begin(), some operation(), and *
// commit(). * @throws Exception
uploadConn.begin(ReadWrite.WRITE); */
System.out.println(model.toString()); public void delete() throws Exception {
// uploadConn.load(modelName, model); // Connect the HTTP client
uploadConn.put(modelName, model); HttpClient client = HttpClientBuilder.create().build();
uploadConn.commit(); String fusekiDataLocation = getFusekiDatasetsURI();
logger.debug("Committed model " + modelName + " to data set" + getName()); HttpDelete delete = new HttpDelete(fusekiDataLocation + "/" + name);
} catch (Exception e) {
logger.error("Unable to update model " + modelName + " in data set " + getName() // Delete the data set
+ " on the remote Fuseki server.", e); HttpResponse response = client.execute(delete);
} logger.debug(response.toString());
}
return;
/** }
* This operation returns the root model in the data set, which is called the
* default graph in the Jena jargon. It is referred to as the root model here to /**
* denote that it is the root model in a hierarchy of models describing the same * This operation directs the data set to update and persist any remotely stored
* set. This is a convenience method identically equal to calling getModel(null) * versions of this model with this version of the model. This action is a
* or getModel("default"). * complete re-write of the data, with out a merge or any checks.
* *
* @return the root model if the data set exists, otherwise null * @param modelName the name of the model that will be updated
*/ * @param model the model that will be updated remotely
public Model getRootModel() { */
return getModel(null); public void updateModel(final String modelName, Model model) {
}
RDFConnectionRemoteBuilder uploadConnBuilder = RDFConnectionFuseki.create()
/** .destination(getFullURI() + "/data");
* This operation returns the model with the given name if it exists in the data
* set. // Open a connection to upload the ICE ontology.
* try (RDFConnectionFuseki uploadConn = (RDFConnectionFuseki) uploadConnBuilder.build()) {
* @param modelName the name of the model that should be retrieved from the data // Note that transactions must proceed with begin(), some operation(), and
* set. Note that like Jena, calling with an argument of // commit().
* "default" or "null" will return the default graph/model. uploadConn.begin(ReadWrite.WRITE);
* @return the model if it exists in the data set, otherwise null System.out.println(model.toString());
*/ // uploadConn.load(modelName, model);
public Model getModel(final String modelName) { uploadConn.put(modelName, model);
Model model = null; uploadConn.commit();
RDFConnectionRemoteBuilder getConnBuilder = RDFConnectionFuseki.create() logger.debug("Committed model " + modelName + " to data set" + getName());
.destination(getFullURI() + "/data"); } catch (Exception e) {
logger.error("Unable to update model " + modelName + " in data set " + getName()
try (RDFConnectionFuseki getConn = (RDFConnectionFuseki) getConnBuilder.build()) { + " on the remote Fuseki server.", e);
getConn.begin(ReadWrite.READ); }
model = getConn.fetch(modelName); }
getConn.commit();
logger.debug("Retrieved model " + modelName + " from data set" + getName()); /**
} catch (Exception e) { * This operation returns the root model in the data set, which is called the
logger.error("Unable to find model " + modelName + " in data set " + getName(), e); * default graph in the Jena jargon. It is referred to as the root model here to
} * denote that it is the root model in a hierarchy of models describing the same
* set. This is a convenience method identically equal to calling getModel(null)
return model; * or getModel("default").
} *
* @return the root model if the data set exists, otherwise null
/** */
* This operation returns the raw Jena data set pulled from Fuseki. This could public Model getRootModel() {
* be a long-running operation depending on the size of the remote data. This return getModel(null);
* operation is intended purely as a convenience to advanced users who want to }
* manipulate the data set directly.
* /**
* @return the raw Jena data set * This operation returns the model with the given name if it exists in the data
*/ * set.
public Dataset getJenaDataset() { *
Dataset set = null; * @param modelName the name of the model that should be retrieved from the data
RDFConnectionRemoteBuilder getConnBuilder = RDFConnectionFuseki.create() * set. Note that like Jena, calling with an argument of
.destination(getFullURI() + "/get"); * "default" or "null" will return the default graph/model.
* @return the model if it exists in the data set, otherwise null
try (RDFConnectionFuseki getConn = (RDFConnectionFuseki) getConnBuilder.build()) { */
getConn.begin(ReadWrite.READ); public Model getModel(final String modelName) {
set = getConn.fetchDataset(); Model model = null;
getConn.commit(); RDFConnectionRemoteBuilder getConnBuilder = RDFConnectionFuseki.create()
logger.debug("Retrieved data set" + getName()); .destination(getFullURI() + "/data");
} catch (Exception e) {
logger.error("Unable to find data set " + getName(), e); try (RDFConnectionFuseki getConn = (RDFConnectionFuseki) getConnBuilder.build()) {
} getConn.begin(ReadWrite.READ);
model = getConn.fetch(modelName);
return set; getConn.commit();
} logger.debug("Retrieved model " + modelName + " from data set" + getName());
} catch (Exception e) {
logger.error("Unable to find model " + modelName + " in data set " + getName(), e);
}
return model;
}
/**
* This operation returns the raw Jena data set pulled from Fuseki. This could
* be a long-running operation depending on the size of the remote data. This
* operation is intended purely as a convenience to advanced users who want to
* manipulate the data set directly.
*
* @return the raw Jena data set
*/
public Dataset getJenaDataset() {
Dataset set = null;
RDFConnectionRemoteBuilder getConnBuilder = RDFConnectionFuseki.create()
.destination(getFullURI() + "/get");
try (RDFConnectionFuseki getConn = (RDFConnectionFuseki) getConnBuilder.build()) {
getConn.begin(ReadWrite.READ);
set = getConn.fetchDataset();
getConn.commit();
logger.debug("Retrieved data set" + getName());
} catch (Exception e) {
logger.error("Unable to find data set " + getName(), e);
}
return set;
}
} }
/******************************************************************************
* Copyright (c) 2019- UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0,
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marshall McDonnell - Added initial unit tests
*****************************************************************************/
package org.eclipse.ice.tests.bats;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.eclipse.ice.bats.DataSet;
/**
* These are the unit tests of the BATS Dataset class.
*
* @author Marshall McDonnell
*
*/
public class DataSetTest {
/**
* This operation checks for proper default DataSet object construction
*/
@Test
public void testConstruction() {
DataSet dataset = new DataSet();
assertEquals(dataset.getName(), "unnamed-dataset");
assertEquals(dataset.getHost(), "http://localhost");
assertEquals(dataset.getPort(), 3030);
assertEquals(dataset.getFullURI(), "http://localhost:3030/unnamed-dataset");
}
/**
* This operation checks we can set the dataset name
*/
@Test
public void testSetName() {
DataSet dataset = new DataSet();
dataset.setName("foo");
assertEquals(dataset.getName(), "foo");
}
/**
* This operation checks we can set the hostname
*/
@Test
public void testSetHost() {
DataSet dataset = new DataSet();
dataset.setHost("http://foo.com");
assertEquals(dataset.getHost(), "http://foo.com");
}
/**
* This operation checks we can set the port
*/
@Test
public void testSetPort() {
DataSet dataset = new DataSet();
dataset.setPort(8080);
assertEquals(dataset.getPort(), 8080);
}
/**
* This operation checks we get the correct Fuseki Data API URL
*/
@Test
public void testGetFusekiDatasetsURI() {
DataSet dataset = new DataSet();
assertEquals(
dataset.getFusekiDatasetsURI(),
"http://localhost:3030/$/datasets");
}
}
...@@ -6,12 +6,16 @@ ...@@ -6,12 +6,16 @@
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* Initial API and implementation and/or initial documentation - * Jay Jay Billings - Initial API and implementation and/or initial docs
* Jay Jay Billings * Marshall McDonnell - Added delete method integration test
*****************************************************************************/ *****************************************************************************/
package org.eclipse.ice.tests.bats; package org.eclipse.ice.tests.bats;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
import java.util.UUID; import java.util.UUID;
...@@ -29,164 +33,191 @@ import org.junit.Test; ...@@ -29,164 +33,191 @@ import org.junit.Test;
import org.eclipse.ice.bats.DataSet; import org.eclipse.ice.bats.DataSet;
/**