/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.resourceIndex;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import org.jrdf.graph.ObjectNode;
import org.jrdf.graph.PredicateNode;
import org.jrdf.graph.SubjectNode;
import org.jrdf.graph.Triple;
import org.jrdf.graph.URIReference;
import org.junit.After;
import org.trippi.RDFFormat;
import org.trippi.RDFUtil;
import org.trippi.TripleIterator;
import org.trippi.TriplestoreConnector;
import fedora.common.Models;
import fedora.server.storage.DOReader;
import fedora.server.storage.MockRepositoryReader;
import fedora.server.storage.ServiceDefinitionReader;
import fedora.server.storage.ServiceDeploymentReader;
import fedora.server.storage.SimpleDOReader;
import fedora.server.storage.SimpleServiceDefinitionReader;
import fedora.server.storage.SimpleServiceDeploymentReader;
import fedora.server.storage.types.Datastream;
import fedora.server.storage.types.DigitalObject;
import fedora.server.storage.types.ObjectBuilder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Superclass for <code>ResourceIndex</code> integration tests.
*
* @author Chris Wilper
*/
public abstract class ResourceIndexIntegrationTest {
private static final Logger LOG =
Logger.getLogger(ResourceIndexIntegrationTest.class.getName());
private static final String TEST_DIR = "target";
private static final String DB_DRIVER =
"org.apache.derby.jdbc.EmbeddedDriver";
private static final String DB_URL = "jdbc:derby:test;create=true";
private static final String DB_USERNAME = "test";
private static final String DB_PASSWORD = "test";
// needs to be set in order for object serializers/deserializers to work
static {
Datastream.defaultChecksumType = "DISABLED";
}
/**
* The <code>ResourceIndexImpl</code> instance we'll be using.
*/
private ResourceIndex _ri;
/**
* The flusher instance we'll use.
*/
private Flusher _flusher;
/**
* Initialize the RI at the given level and return it. If the RI is already
* initialized, it will be closed and re-initialized at the given level.
*/
protected void initRI(int indexLevel) throws Exception {
if (_ri != null) {
try {
_ri.close();
} catch (Exception e) {
}
}
TriplestoreConnector connector = getConnector();
TripleGenerator generator = new ModelBasedTripleGenerator();
_ri = new ResourceIndexImpl(connector, generator, indexLevel, false);
}
/**
* Get the <code>TriplestoreConnector</code> to be used in conjunction
* with the <code>ResourceIndexImpl</code>.
*
* @throws Exception
* if constructing the connector fails for any reason.
*/
private static TriplestoreConnector getConnector() throws Exception {
HashMap<String, String> config = new HashMap<String, String>();
///*
config.put("backslashIsEscape", "false");
config.put("ddlGenerator",
"org.nsdl.mptstore.impl.derby.DerbyDDLGenerator");
config.put("autoFlushBufferSize", "1000");
config.put("autoFlushDormantSeconds", "5");
config.put("bufferFlushBatchSize", "1000");
config.put("bufferSafeCapacity", "1000");
config.put("fetchSize", "1000");
config.put("jdbcDriver", DB_DRIVER);
config.put("jdbcURL", DB_URL);
config.put("username", DB_USERNAME);
config.put("password", DB_PASSWORD);
config.put("poolInitialSize", "5");
config.put("poolMaxSize", "10");
return TriplestoreConnector.init("org.trippi.impl.mpt.MPTConnector",
config);
}
// Test tearDown
@After
public void tearDownTest() throws Exception {
if (_ri != null) {
tearDownTriplestore();
}
}
private void tearDownTriplestore() throws Exception {
// delete all triples from the RI
File dump = new File(TEST_DIR + "/all-triples.txt");
FileOutputStream out = null;
try {
// write all to temp file
TripleIterator triples = _ri.findTriples(null, null, null, -1);
out = new FileOutputStream(dump);
triples.toStream(out, RDFFormat.TURTLE);
try {
out.close();
} catch (Exception e) {
}
out = null;
// load all from temp file
triples =
TripleIterator.fromStream(new FileInputStream(dump),
RDFFormat.TURTLE);
_ri.delete(triples, true);
} finally {
if (out != null) {
out.close();
}
dump.delete();
}
_ri.close();
}
// do test methods
protected void doAddDelTest(int riLevel, DigitalObject obj)
throws Exception {
Set<DigitalObject> set = new HashSet<DigitalObject>();
set.add(obj);
doAddDelTest(riLevel, set);
}
protected void doAddDelTest(int riLevel, Set<DigitalObject> objects)
throws Exception {
initRI(riLevel);
addAll(objects, true);
assertTrue("Did not get expected triples after add",
sameTriples(getExpectedTriples(riLevel, objects),
getActualTriples(),
true));
deleteAll(objects, true);
assertEquals("Some triples remained after delete",
0,
getActualTriples().size());
}
protected void doModifyTest(int riLevel,
DigitalObject origObject,
DigitalObject modifiedObject) throws Exception {
Set<DigitalObject> origObjects = new HashSet<DigitalObject>();
origObjects.add(origObject);
doModifyTest(riLevel, origObjects, modifiedObject);
}
// if riLevel is -1, assume original objects have already been added
// and we don't need to change the ri level
protected void doModifyTest(int riLevel,
Set<DigitalObject> origObjects,
DigitalObject modifiedObject) throws Exception {
if (riLevel > -1) {
initRI(riLevel);
addAll(origObjects, true);
}
DigitalObject origObject = null;
// get a set with the modified object in place of its old version
Set<DigitalObject> newObjects = new HashSet<DigitalObject>();
for (DigitalObject orig : origObjects) {
if (orig.getPid().equals(modifiedObject.getPid())) {
origObject = orig;
} else {
newObjects.add(orig);
}
}
newObjects.add(modifiedObject);
modify(origObject, modifiedObject, true);
assertTrue("Did not get expected triples after modify",
sameTriples(getExpectedTriples(riLevel, newObjects),
getActualTriples(),
true));
}
// Utility methods for tests
protected void modify(DigitalObject origObject,
DigitalObject modifiedObject,
boolean flush) throws Exception {
_ri.modifyObject(getDOReader(origObject), getDOReader(modifiedObject));
if (flush) {
_ri.flushBuffer();
}
}
protected ServiceDefinitionReader getServiceDefinitionReader(DigitalObject obj)
throws Exception {
return new SimpleServiceDefinitionReader(null,
null,
null,
null,
null,
obj);
}
protected ServiceDeploymentReader getServiceDeploymentReader(DigitalObject obj)
throws Exception {
return new SimpleServiceDeploymentReader(null,
null,
null,
null,
null,
obj);
}
protected DOReader getDOReader(DigitalObject obj) throws Exception {
return new SimpleDOReader(null, null, null, null, null, obj);
}
protected void addObj(DigitalObject obj, boolean flush) throws Exception {
Set<DigitalObject> set = new HashSet<DigitalObject>();
set.add(obj);
addAll(set, flush);
}
protected void addAll(Set<DigitalObject> objects, boolean flush)
throws Exception {
addOrDelAll(objects, flush, true);
}
protected void deleteAll(Set<DigitalObject> objects, boolean flush)
throws Exception {
addOrDelAll(objects, flush, false);
}
private void addOrDelAll(Set<DigitalObject> objects,
boolean flush,
boolean add) throws Exception {
for (DigitalObject obj : objects) {
if (add) {
_ri.addObject(getDOReader(obj));
} else {
_ri.deleteObject(getDOReader(obj));
}
}
if (flush) {
_ri.flushBuffer();
}
}
protected Set<Triple> getExpectedTriples(int riLevel,
Set<DigitalObject> objects)
throws Exception {
// we can return early in this case
if (riLevel == 0) {
return new HashSet<Triple>();
}
// add all to a mock repository reader
MockRepositoryReader repo = new MockRepositoryReader();
for (DigitalObject obj : objects) {
repo.putObject(obj);
}
// prepare appropriate MethodInfoStore and TripleGenerator
TripleGenerator generator = new ModelBasedTripleGenerator();
Set<Triple> expected = new HashSet<Triple>();
for (DigitalObject obj : objects) {
expected.addAll(generator.getTriplesForObject(getDOReader(obj)));
}
return expected;
}
protected boolean sameTriples(Set<Triple> expected,
Set<Triple> actual,
boolean logDiffs) {
TreeSet<String> eStrings = new TreeSet<String>();
for (Triple triple : expected) {
eStrings.add(RDFUtil.toString(triple));
}
TreeSet<String> aStrings = new TreeSet<String>();
for (Triple triple : actual) {
aStrings.add(RDFUtil.toString(triple));
}
if (eStrings.equals(aStrings)) {
return true;
} else {
if (logDiffs) {
StringBuffer out = new StringBuffer();
out.append("Triple sets differ.\n");
out.append("Expected set has " + expected.size()
+ " triples.\n");
out.append("Actual set has " + actual.size() + " triples.\n\n");
out.append("Expected triples:\n");
for (String t : eStrings) {
out.append(" " + t + "\n");
}
out.append("\nActual triples:\n");
for (String t : aStrings) {
out.append(" " + t + "\n");
}
LOG.warn(out.toString());
}
return false;
}
}
protected Set<Triple> getActualTriples() throws Exception {
return getActualTriples(null, null, null);
}
protected Set<Triple> getActualTriples(SubjectNode subject,
PredicateNode predicate,
ObjectNode object) throws Exception {
Set<Triple> set = new HashSet<Triple>();
TripleIterator iter = _ri.findTriples(subject, predicate, object, -1);
while (iter.hasNext()) {
set.add(iter.next());
}
iter.close();
return set;
}
/**
* Get the DC xml for an object.
*/
protected String getDC(String content) {
StringBuffer x = new StringBuffer();
x.append("<oai_dc:dc xmlns:dc=\"http://purl.org/dc/elements/1.1/\"");
x
.append(" xmlns:oai_dc=\"http://www.openarchives.org/OAI/2.0/oai_dc/\">\n");
x.append(content + "\n");
x.append("</oai_dc:dc>");
return x.toString();
}
/**
* Get the METHODMAP xml for a sDef.
*/
protected static String getMethodMap(Set<ParamDomainMap> methodDefs) {
return getMethodMap(methodDefs, null, false);
}
/**
* Get the METHODMAP xml for a sDef or sDep.
*/
protected static String getMethodMap(Set<ParamDomainMap> methodDefs,
Map<String, Set<String>> inputKeys,
boolean forSDef) {
StringBuffer xml = new StringBuffer();
xml.append("<MethodMap name=\"MethodMap\" xmlns=\"http://fed"
+ "ora.comm.nsdlib.org/service/methodmap\">\n");
for (ParamDomainMap methodDef : methodDefs) {
String method = methodDef.getMethodName();
xml.append(" <Method operationName=\"" + method + "\"");
if (forSDef) {
xml.append(" wsdlMsgName=\"" + method + "Request\"");
xml.append(" wsdlMsgOutput=\"dissemResponse\"");
}
xml.append(">\n");
for (String paramName : methodDef.keySet()) {
ParamDomain domain = methodDef.get(paramName);
xml.append(" <UserInputParm parmName=\"" + paramName
+ "\" passBy=\"VALUE\" defaultValue=\"\" required=\""
+ domain.isRequired() + "\">\n");
if (domain.size() > 0) {
xml.append(" <ValidParmValues>\n");
for (String value : domain) {
xml.append(" <ValidParm value=\"" + value
+ "\"/>\n");
}
xml.append(" </ValidParmValues>\n");
}
xml.append(" </UserInputParm>\n");
}
if (forSDef) {
Set<String> keys = inputKeys.get(method);
if (keys != null) {
for (String key : keys) {
xml.append(" <DatastreamInputParm parmName=\"" + key
+ "\" passBy=\"URL_REF\"/>\n");
}
}
xml.append(" <MethodReturnType wsdlMsgName=\""
+ "dissemResponse\" wsdlMsgTOMIME=\""
+ "application/octet-stream\"/>\n");
}
xml.append(" </Method>\n");
}
xml.append("</MethodMap>");
return xml.toString();
}
/**
* Get the DSINPUTSPEC xml for a sDef.
*/
protected static String getInputSpec(String sDefPID,
Map<String, Set<String>> inputTypes) {
StringBuffer xml = new StringBuffer();
xml.append("<DSInputSpec xmlns=\"http://fedora.comm.nsdlib.org/"
+ "service/bindspec\" label=\"InputSpec\">\n");
for (String key : inputTypes.keySet()) {
xml.append(" <DSInput DSMin=\"1\" DSMax=\"1\" DSOrdinality=\""
+ "false\" wsdlMsgPartName=\"" + key + "\">\n");
xml.append(" <DSInputLabel>label</DSInputLabel>\n");
for (String mimeType : inputTypes.get(key)) {
xml.append(" <DSMIME>" + mimeType + "</DSMIME>\n");
}
xml.append(" <DSInputInstruction>inst</DSInputInstruction>\n");
xml.append(" </DSInput>\n");
}
xml.append("</DSInputSpec>\n");
return xml.toString();
}
private static void addXSDType(String name, StringBuffer xml) {
xml.append(" <xsd:simpleType name=\"" + name + "\">\n");
xml.append(" <xsd:restriction base=\"xsd:string\"/>\n");
xml.append(" </xsd:simpleType>\n");
}
/**
* Get the WSDL xml for a sDef.
*/
protected static String getWSDL(Set<ParamDomainMap> methodDefs,
Map<String, Set<String>> inputKeys,
Map<String, Set<String>> outputTypes) {
StringBuffer xml = new StringBuffer();
xml.append("<definitions xmlns=\"http://schemas.xmlsoap.org/wsdl/\""
+ " xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\""
+ " xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\""
+ " xmlns:this=\"MyService\""
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
+ " name=\"Name\" targetNamespace=\"MyService\">\n");
//
// xsd type definitions
//
xml.append(" <types>\n");
xml.append(" <xsd:schema targetNamespace=\"MyService\">\n");
Set<String> addedTypes = new HashSet<String>();
for (ParamDomainMap methodDef : methodDefs) {
// one type def per distinct user param name
for (String name : methodDef.keySet()) {
if (addedTypes.add(name + "Type")) {
addXSDType(name + "Type", xml);
}
}
// one type def per distinct ds input key
for (String key : inputKeys.get(methodDef.getMethodName())) {
if (addedTypes.add(key + "Type")) {
addXSDType(key + "Type", xml);
}
}
}
xml.append(" </xsd:schema>\n");
xml.append(" </types>\n");
//
// message definitions
//
// one request message per method
for (ParamDomainMap methodDef : methodDefs) {
String method = methodDef.getMethodName();
xml.append(" <message name=\"" + method + "Request\">\n");
// one part per user param
for (String name : methodDef.keySet()) {
xml.append(" <part name=\"" + name + "\" type=\"this:"
+ name + "Type\"/>\n");
}
// one part per ds input key
for (String key : inputKeys.get(method)) {
xml.append(" <part name=\"" + key + "\" type=\"this:" + key
+ "Type\"/>\n");
}
xml.append(" </message>\n");
}
// one dissemResponse output message
xml.append(" <message name=\"dissemResponse\">\n");
xml.append(" <part name=\"response\" type=\"xsd:base64Binary\"/>\n");
xml.append(" </message>\n");
//
// port type (per-method input/output messages)
//
xml.append(" <portType name=\"MyServicePortType\">\n");
for (ParamDomainMap methodDef : methodDefs) {
String method = methodDef.getMethodName();
xml.append(" <operation name=\"" + method + "\">\n");
xml.append(" <input message=\"this:" + method
+ "Request\"/>\n");
xml.append(" <output message=\"this:dissemResponse\"/>\n");
xml.append(" </operation>\n");
}
xml.append(" </portType>\n");
//
// service location
//
xml.append(" <service name=\"MyService\">\n");
xml.append(" <port binding=\"this:MyService_http\" "
+ "name=\"MyService_port\">\n");
xml
.append(" <http:address location=\"http://example.org/MyService/\"/>\n");
xml.append(" </port>\n");
xml.append(" </service>\n");
//
// operation locations and input/output bindings
//
xml
.append(" <binding name=\"MyService_http\" type=\"this:MyServicePortType\">\n");
xml.append(" <http:binding verb=\"GET\"/>\n");
for (ParamDomainMap methodDef : methodDefs) {
String method = methodDef.getMethodName();
xml.append(" <operation name=\"" + method + "\">\n");
// location = ..?userParm1=(userParm1)&key1=KEY1..etc
StringBuffer location = new StringBuffer();
location.append(method + "?");
boolean first = true;
for (String name : methodDef.keySet()) {
if (!first) {
location.append("&");
}
location.append(name + "=(" + name + ")");
first = false;
}
for (String key : inputKeys.get(method)) {
if (!first) {
location.append("&");
}
location.append(key.toLowerCase() + "=(" + key + ")");
first = false;
}
xml.append(" <http:operation location=\""
+ location.toString() + "\"/>\n");
// input is always urlReplacement
xml.append(" <input><http:urlReplacement/></input>\n");
// output lists all possible output mime types
xml.append(" <output>\n");
for (String mimeType : outputTypes.get(method)) {
xml.append(" <mime:content type=\"" + mimeType
+ "\"/>\n");
}
xml.append(" </output>\n");
xml.append(" </operation>\n");
}
xml.append(" </binding>\n");
xml.append("</definitions>\n");
return xml.toString();
}
protected static Set<DigitalObject> getTestObjects(int num,
int datastreamsPerObject) {
Set<DigitalObject> set = new HashSet<DigitalObject>(num);
for (int i = 0; i < num; i++) {
DigitalObject obj = getTestObject("test:" + i, "label" + i);
for (int j = 0; j < datastreamsPerObject; j++) {
addEDatastream(obj, "DS" + j);
}
set.add(obj);
}
return set;
}
protected TripleIterator spo(String query) throws Exception {
return _ri.findTriples("spo", query, -1, false);
}
protected static void addEDatastream(DigitalObject obj, String id) {
ObjectBuilder.addEDatastream(obj, id);
}
protected static void addRDatastream(DigitalObject obj, String id) {
ObjectBuilder.addRDatastream(obj, id);
}
protected static void addXDatastream(DigitalObject obj,
String id,
String xml) {
ObjectBuilder.addXDatastream(obj, id, xml);
}
protected static void addMDatastream(DigitalObject obj, String id) {
ObjectBuilder.addMDatastream(obj, id);
}
protected static DigitalObject getTestObject(String pid, String label) {
return ObjectBuilder.getTestObject(pid, label);
}
protected static DigitalObject getTestSDef(String pid,
String label,
Set<ParamDomainMap> methodDefs) {
Date now = new Date();
URIReference[] models = {Models.SERVICE_DEFINITION_3_0};
DigitalObject obj = ObjectBuilder.getTestObject(pid,
models,
"A",
"someOwnerId",
label,
now,
now);
addXDatastream(obj, "METHODMAP", getMethodMap(methodDefs));
return obj;
}
protected static DigitalObject getTestSDep(String pid,
String label,
String sDefPID,
Set<ParamDomainMap> methodDefs,
Map<String, Set<String>> inputKeys,
Map<String, Set<String>> inputTypes,
Map<String, Set<String>> outputTypes) {
Date now = new Date();
URIReference[] models = {Models.SERVICE_DEPLOYMENT_3_0};
DigitalObject obj = ObjectBuilder.getTestObject(pid,
models,
"A",
"someOwnerId",
label,
now,
now);
String methodMapXML = getMethodMap(methodDefs, inputKeys, true);
addXDatastream(obj, "METHODMAP", methodMapXML);
String inputSpecXML = getInputSpec(sDefPID, inputTypes);
addXDatastream(obj, "DSINPUTSPEC", inputSpecXML);
String wsdlXML = getWSDL(methodDefs, inputKeys, outputTypes);
addXDatastream(obj, "WSDL", wsdlXML);
return obj;
}
// sdef:1 has one no-parameter method
protected static DigitalObject getSDefOne() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
return getTestSDef("test:sdef1", "sdef1", methodDefs);
}
// sdef:1b has two no-parameter methods
protected static DigitalObject getSDefOneB() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
methodDefs.add(methodTwo);
return getTestSDef("test:sdef1b", "sdef1b", methodDefs);
}
// sdef:1c has one no-parameter method (same as sdef:1)
protected static DigitalObject getSDefOneC() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
return getTestSDef("test:sdef1c", "sdef1c", methodDefs);
}
// sdef:2 has one required one-parameter method with two possible values
protected static DigitalObject getSDefTwo() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", true);
argOneDomain.add("val1");
argOneDomain.add("val2");
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
return getTestSDef("test:sdef2", "sdef2", methodDefs);
}
// sdef:2b has two required one-parameter methods with two possible values
protected static DigitalObject getSDefTwoB() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", true);
argOneDomain.add("val1");
argOneDomain.add("val2");
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
methodTwo.put("argOne", argOneDomain);
methodDefs.add(methodTwo);
return getTestSDef("test:sdef2b", "sdef2b", methodDefs);
}
// sdef:3 has one optional one-parameter method with any possible value
protected static DigitalObject getSDefThree() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", false);
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
return getTestSDef("test:sdef3", "sdef3", methodDefs);
}
// sdef:3b has two optional one-parameter methods with any possible value
protected static DigitalObject getSDefThreeB() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", false);
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
methodTwo.put("argOne", argOneDomain);
methodDefs.add(methodTwo);
return getTestSDef("test:sdef3b", "sdef3b", methodDefs);
}
// sdef:4 has two one-parameter methods, one required with two possible
// values and the other optional with any possible value
protected static DigitalObject getSDefFour() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", true);
argOneDomain.add("val1");
argOneDomain.add("val2");
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
argOneDomain = new ParamDomain("argOne", false);
methodTwo.put("argOne", argOneDomain);
methodDefs.add(methodTwo);
return getTestSDef("test:sdef4", "sdef4", methodDefs);
}
// construct a map representing key-to-ds bindings with 1 or 2 keys
protected static Map<String, Set<String>> getMap(String key1,
String[] values1,
String key2,
String[] values2) {
Set<String> valueSet1 = new HashSet<String>();
for (String value : values1) {
valueSet1.add(value);
}
Map<String, Set<String>> map = new HashMap<String, Set<String>>();
map.put(key1, valueSet1);
if (key2 != null) {
Set<String> valueSet2 = new HashSet<String>();
for (String value : values2) {
valueSet2.add(value);
}
map.put(key2, valueSet2);
}
return map;
}
// sdep:1 implements sdef:1 and takes one datastream
protected static DigitalObject getSDepOne() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
return getTestSDep("test:sdep1",
"sdep1",
"test:sdef1",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
null,
null),
getMap("KEY1",
new String[] {"text/xml"},
null,
null),
getMap("methodOne",
new String[] {"text/xml"},
null,
null));
}
// sdep:1b implements sdef:1b and takes one datastream
protected static DigitalObject getSDepOneB() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
methodDefs.add(methodTwo);
return getTestSDep("test:sdep1b",
"sdep1b",
"test:sdef1b",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
"methodTwo",
new String[] {"KEY2"}),
getMap("KEY1",
new String[] {"text/xml"},
"KEY2",
new String[] {"text/xml"}),
getMap("methodOne",
new String[] {"text/xml"},
"methodTwo",
new String[] {"text/xml"}));
}
// sdep:1c implements sdef:1c and takes one datastream
protected static DigitalObject getSDepOneC() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
return getTestSDep("test:sdep1c",
"sdep1c",
"test:sdef1c",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
null,
null),
getMap("KEY1",
new String[] {"text/xml"},
null,
null),
getMap("methodOne",
new String[] {"text/xml"},
null,
null));
}
// sdep:1d implements sdef:1 and takes TWO datastreams
protected static DigitalObject getSDepOneD() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
methodDefs.add(methodOne);
return getTestSDep("test:sdep1d",
"sdep1d",
"test:sdef1",
methodDefs,
getMap("methodOne",
new String[] {"KEY1", "KEY2"},
null,
null),
getMap("KEY1",
new String[] {"text/xml"},
"KEY2",
new String[] {"text/xml"}),
getMap("methodOne",
new String[] {"text/xml"},
null,
null));
}
// sdep:2 implements sdef:2 and takes one datastream
protected static DigitalObject getSDepTwo() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", true);
argOneDomain.add("val1");
argOneDomain.add("val2");
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
return getTestSDep("test:sdep2",
"sdep2",
"test:sdef2",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
null,
null),
getMap("KEY1",
new String[] {"text/xml"},
null,
null),
getMap("methodOne",
new String[] {"text/xml"},
null,
null));
}
// sdep:2b implements zdef:2b and takes one datastream
protected static DigitalObject getSDepTwoB() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", true);
argOneDomain.add("val1");
argOneDomain.add("val2");
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
methodTwo.put("argOne", argOneDomain);
methodDefs.add(methodTwo);
return getTestSDep("test:sdep2b",
"sdep2b",
"test:zdef2b",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
"methodTwo",
new String[] {"KEY2"}),
getMap("KEY1",
new String[] {"text/xml"},
"KEY2",
new String[] {"text/xml"}),
getMap("methodOne",
new String[] {"text/xml"},
"methodTwo",
new String[] {"text/xml"}));
}
// sdep:3 implements sdef:3 and takes one datastream
protected static DigitalObject getSDepThree() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", false);
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
return getTestSDep("test:sdep3",
"sdep3",
"test:sdef3",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
null,
null),
getMap("KEY1",
new String[] {"text/xml"},
null,
null),
getMap("methodOne",
new String[] {"text/xml"},
null,
null));
}
// sdep:3b implements sdef:3b and takes one datastream
protected static DigitalObject getSDepThreeB() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", false);
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
methodTwo.put("argOne", argOneDomain);
methodDefs.add(methodTwo);
return getTestSDep("test:sdep3b",
"sdep3b",
"test:sdef3b",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
"methodTwo",
new String[] {"KEY2"}),
getMap("KEY1",
new String[] {"text/xml"},
"KEY2",
new String[] {"text/xml"}),
getMap("methodOne",
new String[] {"text/xml"},
"methodTwo",
new String[] {"text/xml"}));
}
// adep:4 implements sdef:4 and takes one datastream
protected static DigitalObject getSDepFour() {
Set<ParamDomainMap> methodDefs = new HashSet<ParamDomainMap>();
ParamDomainMap methodOne = new ParamDomainMap("methodOne");
ParamDomain argOneDomain = new ParamDomain("argOne", true);
argOneDomain.add("val1");
argOneDomain.add("val2");
methodOne.put("argOne", argOneDomain);
methodDefs.add(methodOne);
ParamDomainMap methodTwo = new ParamDomainMap("methodTwo");
argOneDomain = new ParamDomain("argOne", false);
methodTwo.put("argOne", argOneDomain);
methodDefs.add(methodTwo);
return getTestSDep("test:sdep4",
"sdep4",
"test:sdef4",
methodDefs,
getMap("methodOne",
new String[] {"KEY1"},
"methodTwo",
new String[] {"KEY2"}),
getMap("KEY1",
new String[] {"text/xml"},
"KEY2",
new String[] {"text/xml"}),
getMap("methodOne",
new String[] {"text/xml"},
"methodTwo",
new String[] {"text/xml"}));
}
protected Map<String, String> getBindings(int numKeys) {
Map<String, String> bindings = new HashMap<String, String>();
for (int i = 1; i <= numKeys; i++) {
bindings.put("KEY" + i, "DS1");
}
return bindings;
}
// get a set containing three digital objects
protected Set<DigitalObject> getObjectSet(DigitalObject o1,
DigitalObject o2,
DigitalObject o3) {
Set<DigitalObject> set = new HashSet<DigitalObject>();
set.add(o1);
set.add(o2);
set.add(o3);
return set;
}
public void startFlushing(int sleepMS) throws Exception {
if (_flusher != null) {
try {
finishFlushing();
} catch (Exception e) {
System.err.println("Error stopping old flusher!!");
e.printStackTrace();
}
throw new Exception("Flusher was already running!");
}
_flusher = new Flusher(_ri, sleepMS);
_flusher.start();
}
// finish async flushing and do a final flush
public void finishFlushing() throws Exception {
_flusher.finish();
_ri.flushBuffer();
_flusher = null;
}
// Inner classes for tests
/**
* A Thread that continuously flushes the buffer.
*/
public class Flusher
extends Thread {
private final ResourceIndex _ri;
private final int _sleepMS;
private boolean _shouldFinish = false;
private Exception _error;
/**
* Construct a flusher that sleeps the given number of milliseconds
* between flush attempts.
*
* @param sleepMS
* milliseconds to sleep. Will simply yield between flush
* attempts if less than 1.
*/
public Flusher(ResourceIndex ri, int sleepMS) {
_ri = ri;
_sleepMS = sleepMS;
}
/**
* Set signal for flusher to finish and wait for it.
*
* @throws Exception
* if the flusher encountered an error any time while it was
* running.
*/
public void finish() throws Exception {
_shouldFinish = true;
while (isAlive()) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
if (_error != null) {
throw _error;
}
}
/**
* Flush the buffer until the finish signal arrives from another thread.
*/
@Override
public void run() {
try {
while (!_shouldFinish) {
if (_sleepMS > 0) {
try {
Thread.sleep(_sleepMS);
} catch (InterruptedException e) {
}
} else {
Thread.yield();
}
_ri.flushBuffer();
}
} catch (Exception e) {
_error = e;
}
}
}
}