Package org.fcrepo.server.resourceIndex

Source Code of org.fcrepo.server.resourceIndex.ResourceIndexIntegrationTest$Flusher

/* 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 org.fcrepo.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.slf4j.Logger;
import org.slf4j.LoggerFactory;

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.junit.Before;

import org.trippi.RDFFormat;
import org.trippi.RDFUtil;
import org.trippi.TripleIterator;
import org.trippi.TriplestoreConnector;
import org.trippi.io.TripleIteratorFactory;

import org.fcrepo.common.Models;
import org.fcrepo.server.resourceIndex.ModelBasedTripleGenerator;
import org.fcrepo.server.resourceIndex.ResourceIndex;
import org.fcrepo.server.resourceIndex.ResourceIndexImpl;
import org.fcrepo.server.resourceIndex.TripleGenerator;
import org.fcrepo.server.storage.DOReader;
import org.fcrepo.server.storage.MockRepositoryReader;
import org.fcrepo.server.storage.ServiceDefinitionReader;
import org.fcrepo.server.storage.ServiceDeploymentReader;
import org.fcrepo.server.storage.SimpleDOReader;
import org.fcrepo.server.storage.SimpleServiceDefinitionReader;
import org.fcrepo.server.storage.SimpleServiceDeploymentReader;
import org.fcrepo.server.storage.types.Datastream;
import org.fcrepo.server.storage.types.DigitalObject;
import org.fcrepo.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 logger =
            LoggerFactory.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 <code>org.trippi.io.TripleIteratorFactory</code> used to parse RDF
     */
    private TripleIteratorFactory _factory;

    /**
     * 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 setup
    @Before
    public void setupTest() throws Exception {
        _factory = new TripleIteratorFactory();
    }

    // Test tearDown

    @After
    public void tearDownTest() throws Exception {
        if (_ri != null) {
            tearDownTriplestore();
        }
        _factory.shutdown();
    }

    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 =
                    _factory.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");
                }
                logger.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("&amp;");
                }
                location.append(name + "=(" + name + ")");
                first = false;
            }
            for (String key : inputKeys.get(method)) {
                if (!first) {
                    location.append("&amp;");
                }
                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;
            }
        }
    }
}
TOP

Related Classes of org.fcrepo.server.resourceIndex.ResourceIndexIntegrationTest$Flusher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.