org.dspace.identifier.DOIIdentifierProviderTest.java Source code

Java tutorial

Introduction

Here is the source code for org.dspace.identifier.DOIIdentifierProviderTest.java

Source

/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.identifier;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang.ObjectUtils;
import org.apache.log4j.Logger;
import org.dspace.AbstractUnitTest;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.*;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.CollectionService;
import org.dspace.content.service.CommunityService;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.WorkspaceItemService;
import org.dspace.identifier.factory.IdentifierServiceFactory;
import org.dspace.identifier.service.DOIService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.workflow.WorkflowException;
import org.dspace.workflow.WorkflowItem;
import org.dspace.workflow.factory.WorkflowServiceFactory;
import org.junit.*;
import static org.junit.Assert.*;
import static org.junit.Assume.*;

/**
* Tests for {@link DataCiteIdentifierProvider}.
*
* @author Mark H. Wood
* @author Pascal-Nicolas Becker
*/
public class DOIIdentifierProviderTest extends AbstractUnitTest {
    /** log4j category */
    private static final Logger log = Logger.getLogger(DOIIdentifierProviderTest.class);

    private static final String PREFIX = "10.5072";
    private static final String NAMESPACE_SEPARATOR = "dspaceUnitTests-";

    private static ConfigurationService config = null;

    protected DOIService doiService = IdentifierServiceFactory.getInstance().getDOIService();
    protected CommunityService communityService = ContentServiceFactory.getInstance().getCommunityService();
    protected CollectionService collectionService = ContentServiceFactory.getInstance().getCollectionService();
    protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
    protected WorkspaceItemService workspaceItemService = ContentServiceFactory.getInstance()
            .getWorkspaceItemService();

    private static Community community;
    private static Collection collection;

    private static MockDOIConnector connector;
    private DOIIdentifierProvider provider;

    public DOIIdentifierProviderTest() {
    }

    /**
     * This method will be run before every test as per @Before. It will
     * initialize resources required for the tests.
     *
     * Other methods can be annotated with @Before here or in subclasses
     * but no execution order is guaranteed
     */
    @Before
    @Override
    public void init() {
        super.init();

        try {
            context.turnOffAuthorisationSystem();
            // Create an environment for our test objects to live in.
            community = communityService.create(null, context);
            communityService.setMetadata(context, community, "name", "A Test Community");
            communityService.update(context, community);
            collection = collectionService.create(context, community);
            collectionService.setMetadata(context, collection, "name", "A Test Collection");
            collectionService.update(context, collection);
            //we need to commit the changes so we don't block the table for testing
            context.restoreAuthSystemState();

            config = DSpaceServicesFactory.getInstance().getConfigurationService();
            // Configure the service under test.
            config.setProperty(DOIIdentifierProvider.CFG_PREFIX, PREFIX);
            config.setProperty(DOIIdentifierProvider.CFG_NAMESPACE_SEPARATOR, NAMESPACE_SEPARATOR);

            connector = new MockDOIConnector();

            provider = DSpaceServicesFactory.getInstance().getServiceManager()
                    .getServiceByName(DOIIdentifierProvider.class.getName(), DOIIdentifierProvider.class);
            provider.setConfigurationService(config);
            provider.setDOIConnector(connector);
        } catch (AuthorizeException ex) {
            log.error("Authorization Error in init", ex);
            fail("Authorization Error in init: " + ex.getMessage());
        } catch (SQLException ex) {
            log.error("SQL Error in init", ex);
            fail("SQL Error in init: " + ex.getMessage());
        }

    }

    /**
    * This method will be run after every test as per @After. It will
    * clean resources initialized by the @Before methods.
    *
    * Other methods can be annotated with @After here or in subclasses
    * but no execution order is guaranteed
    */
    @After
    @Override
    public void destroy() {
        community = null;
        collection = null;
        connector.reset();
        connector = null;
        provider = null;
        super.destroy();
    }

    /**
    * Create a fresh Item, installed in the repository.
    *
    * @throws SQLException if database error
    * @throws AuthorizeException if authorization error
    * @throws IOException if IO error
    */
    private Item newItem() throws SQLException, AuthorizeException, IOException, IllegalAccessException,
            IdentifierException, WorkflowException {
        context.turnOffAuthorisationSystem();

        WorkspaceItem wsItem = workspaceItemService.create(context, collection, false);

        WorkflowItem wfItem = WorkflowServiceFactory.getInstance().getWorkflowService().start(context, wsItem);

        Item item = wfItem.getItem();
        itemService.addMetadata(context, item, "dc", "contributor", "author", null, "Author, A. N.");
        itemService.addMetadata(context, item, "dc", "title", null, null, "A Test Object");
        itemService.addMetadata(context, item, "dc", "publisher", null, null, "DSpace Test Harness");

        // If DOIIdentifierProvider is configured
        // (dspace/conf/spring/api/identifier-service.xml) the new created item
        // gets automatically a DOI. We remove this DOI as it can make problems
        // with the tests.
        provider.delete(context, item);

        List<MetadataValue> metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA,
                DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null);
        List<String> remainder = new ArrayList<String>();

        for (MetadataValue id : metadata) {
            if (!id.getValue().startsWith(DOI.RESOLVER)) {
                remainder.add(id.getValue());
            }
        }

        itemService.clearMetadata(context, item, DOIIdentifierProvider.MD_SCHEMA, DOIIdentifierProvider.DOI_ELEMENT,
                DOIIdentifierProvider.DOI_QUALIFIER, null);
        itemService.addMetadata(context, item, DOIIdentifierProvider.MD_SCHEMA, DOIIdentifierProvider.DOI_ELEMENT,
                DOIIdentifierProvider.DOI_QUALIFIER, null, remainder);

        itemService.update(context, item);
        //we need to commit the changes so we don't block the table for testing
        context.restoreAuthSystemState();

        return item;
    }

    public String createDOI(Item item, Integer status, boolean metadata)
            throws SQLException, IdentifierException, AuthorizeException {
        return this.createDOI(item, status, metadata, null);
    }

    /**
     * Create a DOI to an item.
     * @param item Item the DOI should be created for.
     * @param status The status of the DOI.
     * @param metadata Whether the DOI should be included in the metadata of the item.
     * @param doi The doi or null if we should generate one.
     * @return the DOI
     * @throws SQLException if database error
     */
    public String createDOI(Item item, Integer status, boolean metadata, String doi)
            throws SQLException, IdentifierException, AuthorizeException {
        context.turnOffAuthorisationSystem();
        // we need some random data. UUIDs would be bloated here
        Random random = new Random();
        if (null == doi) {
            doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + Long.toHexString(new Date().getTime()) + "-"
                    + random.nextInt(997);
        }

        DOI doiRow = doiService.create(context);
        doiRow.setDoi(doi.substring(DOI.SCHEME.length()));
        doiRow.setDSpaceObject(item);
        doiRow.setStatus(status);
        doiService.update(context, doiRow);

        if (metadata) {
            itemService.addMetadata(context, item, DOIIdentifierProvider.MD_SCHEMA,
                    DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null,
                    doiService.DOIToExternalForm(doi));
            itemService.update(context, item);
        }

        //we need to commit the changes so we don't block the table for testing
        context.restoreAuthSystemState();
        return doi;
    }

    /**
     * Test of supports method, of class DataCiteIdentifierProvider.
     */
    @Test
    public void testSupports_Class() {
        Class<? extends Identifier> identifier = DOI.class;
        assertTrue("DOI should be supported", provider.supports(identifier));
    }

    @Test
    public void testSupports_valid_String() {
        String[] validDOIs = new String[] { "10.5072/123abc-lkj/kljl",
                PREFIX + "/" + NAMESPACE_SEPARATOR + "lkjljasd1234", DOI.SCHEME + "10.5072/123abc-lkj/kljl",
                "http://dx.doi.org/10.5072/123abc-lkj/kljl", DOI.RESOLVER + "/10.5072/123abc-lkj/kljl" };

        for (String doi : validDOIs) {
            assertTrue("DOI should be supported", provider.supports(doi));
        }
    }

    @Test
    public void testDoes_not_support_invalid_String() {
        String[] invalidDOIs = new String[] { "11.5072/123abc-lkj/kljl",
                "http://hdl.handle.net/handle/10.5072/123abc-lkj/kljl", "", null };

        for (String notADoi : invalidDOIs) {
            assertFalse("Invalid DOIs shouldn't be supported", provider.supports(notADoi));
        }
    }

    @Test
    public void testStore_DOI_as_item_metadata() throws SQLException, AuthorizeException, IOException,
            IdentifierException, IllegalAccessException, WorkflowException {
        Item item = newItem();
        String doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + Long.toHexString(new Date().getTime());
        context.turnOffAuthorisationSystem();
        provider.saveDOIToObject(context, item, doi);
        context.restoreAuthSystemState();

        List<MetadataValue> metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA,
                DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null);
        boolean result = false;
        for (MetadataValue id : metadata) {
            if (id.getValue().equals(doiService.DOIToExternalForm(doi))) {
                result = true;
            }
        }
        assertTrue("Cannot store DOI as item metadata value.", result);
    }

    @Test
    public void testGet_DOI_out_of_item_metadata() throws SQLException, AuthorizeException, IOException,
            IdentifierException, IllegalAccessException, WorkflowException {
        Item item = newItem();
        String doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + Long.toHexString(new Date().getTime());

        context.turnOffAuthorisationSystem();
        itemService.addMetadata(context, item, DOIIdentifierProvider.MD_SCHEMA, DOIIdentifierProvider.DOI_ELEMENT,
                DOIIdentifierProvider.DOI_QUALIFIER, null, doiService.DOIToExternalForm(doi));
        itemService.update(context, item);
        context.restoreAuthSystemState();

        assertTrue("Failed to recognize DOI in item metadata.", doi.equals(provider.getDOIOutOfObject(item)));
    }

    @Test
    public void testRemove_DOI_from_item_metadata() throws SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + Long.toHexString(new Date().getTime());

        context.turnOffAuthorisationSystem();
        itemService.addMetadata(context, item, DOIIdentifierProvider.MD_SCHEMA, DOIIdentifierProvider.DOI_ELEMENT,
                DOIIdentifierProvider.DOI_QUALIFIER, null, doiService.DOIToExternalForm(doi));
        itemService.update(context, item);

        provider.removeDOIFromObject(context, item, doi);
        context.restoreAuthSystemState();

        List<MetadataValue> metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA,
                DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null);
        boolean foundDOI = false;
        for (MetadataValue id : metadata) {
            if (id.getValue().equals(doiService.DOIToExternalForm(doi))) {
                foundDOI = true;
            }
        }
        assertFalse("Cannot remove DOI from item metadata.", foundDOI);
    }

    @Test
    public void testGet_DOI_by_DSpaceObject() throws SQLException, AuthorizeException, IOException,
            IllegalArgumentException, IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false);

        String retrievedDOI = provider.getDOIByObject(context, item);

        assertNotNull("Failed to load DOI by DSpaceObject.", retrievedDOI);
        assertTrue("Loaded wrong DOI by DSpaceObject.", doi.equals(retrievedDOI));
    }

    @Test
    public void testGet_DOI_lookup() throws SQLException, AuthorizeException, IOException, IllegalArgumentException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false);

        String retrievedDOI = provider.lookup(context, (DSpaceObject) item);

        assertNotNull("Failed to loookup doi.", retrievedDOI);
        assertTrue("Loaded wrong DOI on lookup.", doi.equals(retrievedDOI));
    }

    @Test
    public void testGet_DSpaceObject_by_DOI() throws SQLException, AuthorizeException, IOException,
            IllegalArgumentException, IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false);

        DSpaceObject dso = provider.getObjectByDOI(context, doi);

        assertNotNull("Failed to load DSpaceObject by DOI.", dso);
        if (item.getType() != dso.getType() || ObjectUtils.notEqual(item.getID(), dso.getID())) {
            fail("Object loaded by DOI was another object then expected!");
        }
    }

    @Test
    public void testResolve_DOI() throws SQLException, AuthorizeException, IOException, IllegalArgumentException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false);

        DSpaceObject dso = provider.resolve(context, doi);

        assertNotNull("Failed to resolve DOI.", dso);
        if (item.getType() != dso.getType() || ObjectUtils.notEqual(item.getID(), dso.getID())) {
            fail("Object return by DOI lookup was another object then expected!");
        }
    }

    /*
     * The following test seems a bit silly, but it was helpful to debug some
     * problems while deleting DOIs.
     */
    @Test
    public void testRemove_two_DOIs_from_item_metadata() throws SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        // add two DOIs.
        Item item = newItem();
        String doi1 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true);
        String doi2 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true);

        // remove one of it
        context.turnOffAuthorisationSystem();
        provider.removeDOIFromObject(context, item, doi1);
        context.restoreAuthSystemState();

        // assure that the right one was removed
        List<MetadataValue> metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA,
                DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null);
        boolean foundDOI1 = false;
        boolean foundDOI2 = false;
        for (MetadataValue id : metadata) {
            if (id.getValue().equals(doiService.DOIToExternalForm(doi1))) {
                foundDOI1 = true;
            }
            if (id.getValue().equals(doiService.DOIToExternalForm(doi2))) {
                foundDOI2 = true;
            }

        }
        assertFalse("Cannot remove DOI from item metadata.", foundDOI1);
        assertTrue("Removed wrong DOI from item metadata.", foundDOI2);

        // remove the otherone as well.
        context.turnOffAuthorisationSystem();
        provider.removeDOIFromObject(context, item, doi2);
        context.restoreAuthSystemState();

        // check it
        metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA, DOIIdentifierProvider.DOI_ELEMENT,
                DOIIdentifierProvider.DOI_QUALIFIER, null);
        foundDOI1 = false;
        foundDOI2 = false;
        for (MetadataValue id : metadata) {
            if (id.getValue().equals(doiService.DOIToExternalForm(doi1))) {
                foundDOI1 = true;
            }
            if (id.getValue().equals(doiService.DOIToExternalForm(doi2))) {
                foundDOI2 = true;
            }

        }
        assertFalse("Cannot remove DOI from item metadata.", foundDOI1);
        assertFalse("Cannot remove DOI from item metadata.", foundDOI2);
    }

    @Test
    public void testMintDOI() throws SQLException, AuthorizeException, IOException, IllegalAccessException,
            IdentifierException, WorkflowException {
        Item item = newItem();
        String doi = null;
        try {
            // get a DOI:
            doi = provider.mint(context, item);
        } catch (IdentifierException e) {
            e.printStackTrace();
            fail("Got an IdentifierException: " + e.getMessage());
        }

        assertNotNull("Minted DOI is null!", doi);
        assertFalse("Minted DOI is empty!", doi.isEmpty());

        try {
            doiService.formatIdentifier(doi);
        } catch (Exception e) {
            e.printStackTrace();
            fail("Minted an unrecognizable DOI: " + e.getMessage());
        }
    }

    @Test
    public void testMint_returns_existing_DOI() throws SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, null, true);

        String retrievedDOI = provider.mint(context, item);

        assertNotNull("Minted DOI is null?!", retrievedDOI);
        assertEquals("Mint did not returned an existing DOI!", doi, retrievedDOI);
    }

    @Test
    public void testReserve_DOI() throws SQLException, SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, null, true);

        provider.reserve(context, item, doi);

        DOI doiRow = doiService.findByDoi(context, doi.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow);

        assertTrue("Reservation of DOI did not set the corret DOI status.",
                DOIIdentifierProvider.TO_BE_RESERVED.equals(doiRow.getStatus()));
    }

    @Test
    public void testRegister_unreserved_DOI() throws SQLException, SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, null, true);

        provider.register(context, item, doi);

        DOI doiRow = doiService.findByDoi(context, doi.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow);

        assertTrue("Registration of DOI did not set the corret DOI status.",
                DOIIdentifierProvider.TO_BE_REGISTERED.equals(doiRow.getStatus()));
    }

    @Test
    public void testRegister_reserved_DOI() throws SQLException, SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi = this.createDOI(item, DOIIdentifierProvider.IS_RESERVED, true);

        provider.register(context, item, doi);

        DOI doiRow = doiService.findByDoi(context, doi.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow);

        assertTrue("Registration of DOI did not set the corret DOI status.",
                DOIIdentifierProvider.TO_BE_REGISTERED.equals(doiRow.getStatus()));
    }

    @Test
    public void testCreate_and_Register_DOI() throws SQLException, SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();

        String doi = provider.register(context, item);

        // we want the created DOI to be returned in the following format:
        // doi:10.<prefix>/<suffix>.
        String formated_doi = doiService.formatIdentifier(doi);
        assertTrue("DOI was not in the expected format!", doi.equals(formated_doi));

        DOI doiRow = doiService.findByDoi(context, doi.substring(DOI.SCHEME.length()));
        assertNotNull("Created DOI was not stored in database.", doiRow);

        assertTrue("Registration of DOI did not set the corret DOI status.",
                DOIIdentifierProvider.TO_BE_REGISTERED.equals(doiRow.getStatus()));
    }

    @Test
    public void testDelete_specified_DOI() throws SQLException, AuthorizeException, IOException,
            IdentifierException, WorkflowException, IllegalAccessException {
        Item item = newItem();
        String doi1 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true);
        String doi2 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true);

        // remove one of it
        context.turnOffAuthorisationSystem();
        provider.delete(context, item, doi1);
        context.restoreAuthSystemState();

        // assure that the right one was removed
        List<MetadataValue> metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA,
                DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null);
        boolean foundDOI1 = false;
        boolean foundDOI2 = false;
        for (MetadataValue id : metadata) {
            if (id.getValue().equals(doiService.DOIToExternalForm(doi1))) {
                foundDOI1 = true;
            }
            if (id.getValue().equals(doiService.DOIToExternalForm(doi2))) {
                foundDOI2 = true;
            }
        }
        assertFalse("Cannot remove DOI from item metadata.", foundDOI1);
        assertTrue("Removed wrong DOI from item metadata.", foundDOI2);

        DOI doiRow1 = doiService.findByDoi(context, doi1.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow1);
        assertTrue("Status of deleted DOI was not set correctly.",
                DOIIdentifierProvider.TO_BE_DELETED.equals(doiRow1.getStatus()));

        DOI doiRow2 = doiService.findByDoi(context, doi2.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow2);
        assertTrue("While deleting a DOI the status of another changed.",
                DOIIdentifierProvider.IS_REGISTERED.equals(doiRow2.getStatus()));
    }

    @Test
    public void testDelete_all_DOIs() throws SQLException, AuthorizeException, IOException, IdentifierException,
            IllegalAccessException, WorkflowException {
        Item item = newItem();
        String doi1 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true);
        String doi2 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true);

        // remove one of it
        context.turnOffAuthorisationSystem();
        provider.delete(context, item);
        context.restoreAuthSystemState();

        // assure that the right one was removed
        List<MetadataValue> metadata = itemService.getMetadata(item, DOIIdentifierProvider.MD_SCHEMA,
                DOIIdentifierProvider.DOI_ELEMENT, DOIIdentifierProvider.DOI_QUALIFIER, null);
        boolean foundDOI1 = false;
        boolean foundDOI2 = false;
        for (MetadataValue id : metadata) {
            if (id.getValue().equals(doiService.DOIToExternalForm(doi1))) {
                foundDOI1 = true;
            }
            if (id.getValue().equals(doiService.DOIToExternalForm(doi2))) {
                foundDOI2 = true;
            }
        }
        assertFalse("Cannot remove DOI from item metadata.", foundDOI1);
        assertFalse("Did not removed all DOIs from item metadata.", foundDOI2);

        DOI doiRow1 = doiService.findByDoi(context, doi1.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow1);
        assertTrue("Status of deleted DOI was not set correctly.",
                DOIIdentifierProvider.TO_BE_DELETED.equals(doiRow1.getStatus()));

        DOI doiRow2 = doiService.findByDoi(context, doi1.substring(DOI.SCHEME.length()));
        assumeNotNull(doiRow2);
        assertTrue("Did not set the status of all deleted DOIs as expected.",
                DOIIdentifierProvider.TO_BE_DELETED.equals(doiRow2.getStatus()));
    }

    // test the following methods using the MockDOIConnector.
    // updateMetadataOnline
    // registerOnline
    // reserveOnline

}