package org.gbif.ipt.action.manage; import org.gbif.api.model.common.DOI; import org.gbif.api.model.common.DoiData; import org.gbif.api.model.common.DoiStatus; import org.gbif.doi.service.DoiService; import org.gbif.doi.service.ServiceConfig; import org.gbif.doi.service.datacite.DataCiteService; import org.gbif.doi.service.ezid.EzidService; import org.gbif.ipt.config.AppConfig; import org.gbif.ipt.config.DataDir; import org.gbif.ipt.model.Organisation; import org.gbif.ipt.model.Resource; import org.gbif.ipt.model.voc.DOIRegistrationAgency; import org.gbif.ipt.model.voc.IdentifierStatus; import org.gbif.ipt.model.voc.PublicationStatus; import org.gbif.ipt.service.admin.ExtensionManager; import org.gbif.ipt.service.admin.RegistrationManager; import org.gbif.ipt.service.admin.UserAccountManager; import org.gbif.ipt.service.admin.VocabulariesManager; import org.gbif.ipt.service.manage.ResourceManager; import org.gbif.ipt.struts2.SimpleTextProvider; import org.gbif.ipt.task.GenerateDwcaFactory; import org.gbif.metadata.eml.Agent; import org.gbif.metadata.eml.Citation; import org.gbif.metadata.eml.Eml; import org.gbif.utils.HttpUtil; import org.gbif.utils.file.FileUtils; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Calendar; import java.util.Date; import java.util.UUID; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import org.apache.log4j.Logger; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; /** * Other ITs for OverviewAction that can't run as parameterized tests for example or that * need a special DOI account. */ public class OverviewActionOtherIT { private static final Logger LOG = Logger.getLogger(OverviewActionIT.class); private static final UUID ORGANISATION_KEY = UUID.fromString("dce7a3c9-ea78-4be7-9abc-e3838de70dc5"); private static ServiceConfig dcCfg; private static DoiService dataCiteService; private Resource r; private OverviewAction action; @BeforeClass public static void setup() throws IOException { // load DataCite account username and password from the properties file ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); InputStream dc = FileUtils.classpathStream("datacite.yaml"); dcCfg = mapper.readValue(dc, ServiceConfig.class); // configure a DataCite service for reuse in various Datacite related tests dataCiteService = new DataCiteService(HttpUtil.newMultithreadedClient(10000, 3, 2), dcCfg); } /** * Generate a new test resource for each test. */ @Before public void before() { r = new Resource(); Eml eml = new Eml(); r.setEml(eml); // mandatory elements r.setTitle("Ants"); r.setShortname("ants"); eml.setTitle("Ants"); Citation citation = new Citation(); citation.setCitation("Smith J (2013). Ants. GBIF. Dataset"); r.getEml().setCitation(citation); // publication date Calendar cal = Calendar.getInstance(); cal.set(2013, Calendar.JANUARY, 9); Date date = cal.getTime(); eml.setDateStamp(date); // creator Agent creator = new Agent(); creator.setFirstName("John"); creator.setLastName("Smith"); eml.addCreator(creator); // publisher Organisation o = new Organisation(); o.setName("GBIF"); r.setOrganisation(o); } /** * Test reserving an existing registered DOI (reusing an existing registered DOI) using GBIF's test DataCite account. * </b> * But, make it fail by making the resource private. */ @Test public void testReuseAndReserveExistingRegisteredDoiFailsNotPublic() throws Exception { // common mock AppConfig AppConfig mockAppConfig = mock(AppConfig.class); DataDir mockDataDir = mock(DataDir.class); when(mockAppConfig.getDataDir()).thenReturn(mockDataDir); // mock returning target URLs when(mockAppConfig.getResourceUri(anyString())).thenReturn(new URI("http://ipt.gbif-uat.org/resource?r=migra3")); RegistrationManager mockRegistrationManagerDataCite = mock(RegistrationManager.class); Organisation oDataCiteGBIF = new Organisation(); oDataCiteGBIF.setKey(ORGANISATION_KEY.toString()); oDataCiteGBIF.setAgencyAccountPrimary(true); oDataCiteGBIF.setName("GBIF"); oDataCiteGBIF.setDoiPrefix("10.15469"); oDataCiteGBIF.setCanHost(true); oDataCiteGBIF.setAgencyAccountUsername(dcCfg.getUsername()); oDataCiteGBIF.setAgencyAccountPassword(dcCfg.getPassword()); oDataCiteGBIF.setDoiRegistrationAgency(DOIRegistrationAgency.DATACITE); when(mockRegistrationManagerDataCite.findPrimaryDoiAgencyAccount()).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.get(any(UUID.class))).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.getDoiService()).thenReturn(dataCiteService); // mock action for DataCite action = new OverviewAction(mock(SimpleTextProvider.class), mockAppConfig, mockRegistrationManagerDataCite, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); LOG.info("Testing DataCite with GBIF test Prefix..."); action.setReserveDoi("true"); action.setResource(r); assertNull(r.getDoi()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertNotNull(r.getEml().getCitation()); assertNull(r.getEml().getCitation().getIdentifier()); DOI existingDOI = new DOI("doi:10.15469/xhav6t"); // set citation identifier equal to existing registered DOI (doi:10.15469/xhav6t) - this should get reused r.setCitationAutoGenerated(true); r.getEml().setCitation(new Citation("Replaced by auto-generated citation", existingDOI.toString())); // start with private resource - error: resource must be public r.setStatus(PublicationStatus.PRIVATE); action.reserveDoi(); // 1 error is expected for the resource not being public assertEquals(1, action.getActionErrors().size()); // make sure the existing DOI was NOT reused assertNull(r.getDoi()); assertNull(r.getDoiOrganisationKey()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertEquals(0, r.getEml().getAlternateIdentifiers().size()); // alternate ids updated LOG.info("Existing DOI was NOT reused because resource was private and had wrong target URI"); } /** * Test reserving an existing registered DOI (reusing an existing registered DOI) using GBIF's test DataCite account. * </b> * But, make it fail by making it use the wrong target URI. */ @Test public void testReuseAndReserveExistingRegisteredDoiFailsWrongTarget() throws Exception { // common mock AppConfig AppConfig mockAppConfig = mock(AppConfig.class); DataDir mockDataDir = mock(DataDir.class); when(mockAppConfig.getDataDir()).thenReturn(mockDataDir); // mock returning target URLs when(mockAppConfig.getResourceUri(anyString())).thenReturn(new URI("http://ipt.gbif-uat.org/resource?r=wrong")); RegistrationManager mockRegistrationManagerDataCite = mock(RegistrationManager.class); Organisation oDataCiteGBIF = new Organisation(); oDataCiteGBIF.setKey(ORGANISATION_KEY.toString()); oDataCiteGBIF.setAgencyAccountPrimary(true); oDataCiteGBIF.setName("GBIF"); oDataCiteGBIF.setDoiPrefix("10.15469"); oDataCiteGBIF.setCanHost(true); oDataCiteGBIF.setAgencyAccountUsername(dcCfg.getUsername()); oDataCiteGBIF.setAgencyAccountPassword(dcCfg.getPassword()); oDataCiteGBIF.setDoiRegistrationAgency(DOIRegistrationAgency.DATACITE); when(mockRegistrationManagerDataCite.findPrimaryDoiAgencyAccount()).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.get(any(UUID.class))).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.getDoiService()).thenReturn(dataCiteService); // mock action for DataCite action = new OverviewAction(mock(SimpleTextProvider.class), mockAppConfig, mockRegistrationManagerDataCite, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); LOG.info("Testing DataCite with GBIF test Prefix..."); action.setReserveDoi("true"); action.setResource(r); assertNull(r.getDoi()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertNotNull(r.getEml().getCitation()); assertNull(r.getEml().getCitation().getIdentifier()); DOI existingDOI = new DOI("doi:10.15469/xhav6t"); // set citation identifier equal to existing registered DOI (doi:10.15469/xhav6t) - this should get reused r.setCitationAutoGenerated(true); r.getEml().setCitation(new Citation("Replaced by auto-generated citation", existingDOI.toString())); // start with private resource - error: resource must be public r.setStatus(PublicationStatus.PUBLIC); action.reserveDoi(); // 1 error is expected for the resource having wrong target URI assertEquals(1, action.getActionErrors().size()); // make sure the existing DOI was NOT reused assertNull(r.getDoi()); assertNull(r.getDoiOrganisationKey()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertEquals(0, r.getEml().getAlternateIdentifiers().size()); // alternate ids updated LOG.info("Existing DOI was NOT reused because resource was private and had wrong target URI"); } /** * Test reserving an existing registered DOI (reusing an existing registered DOI) using GBIF's test DataCite account. * </b> * Make it succeed by making the resource public and using the correct target URI. */ @Test public void testReuseAndReserveExistingRegisteredDoi() throws Exception { // common mock AppConfig AppConfig mockAppConfig = mock(AppConfig.class); DataDir mockDataDir = mock(DataDir.class); when(mockAppConfig.getDataDir()).thenReturn(mockDataDir); // mock returning target URLs when(mockAppConfig.getResourceUri(anyString())).thenReturn(new URI("http://ipt.gbif-uat.org/resource?r=migra3")); RegistrationManager mockRegistrationManagerDataCite = mock(RegistrationManager.class); Organisation oDataCiteGBIF = new Organisation(); oDataCiteGBIF.setKey(ORGANISATION_KEY.toString()); oDataCiteGBIF.setAgencyAccountPrimary(true); oDataCiteGBIF.setName("GBIF"); oDataCiteGBIF.setDoiPrefix("10.15469"); oDataCiteGBIF.setCanHost(true); oDataCiteGBIF.setAgencyAccountUsername(dcCfg.getUsername()); oDataCiteGBIF.setAgencyAccountPassword(dcCfg.getPassword()); oDataCiteGBIF.setDoiRegistrationAgency(DOIRegistrationAgency.DATACITE); when(mockRegistrationManagerDataCite.findPrimaryDoiAgencyAccount()).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.get(any(UUID.class))).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.getDoiService()).thenReturn(dataCiteService); // mock action for DataCite action = new OverviewAction(mock(SimpleTextProvider.class), mockAppConfig, mockRegistrationManagerDataCite, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); LOG.info("Testing DataCite with GBIF test Prefix..."); action.setReserveDoi("true"); action.setResource(r); assertNull(r.getDoi()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertNotNull(r.getEml().getCitation()); assertNull(r.getEml().getCitation().getIdentifier()); DOI existingDOI = new DOI("doi:10.15469/xhav6t"); // set citation identifier equal to existing registered DOI (doi:10.15469/xhav6t) - this should get reused r.setCitationAutoGenerated(true); r.getEml().setCitation(new Citation("Replaced by auto-generated citation", existingDOI.toString())); // resource must be public r.setStatus(PublicationStatus.PUBLIC); action.reserveDoi(); // 0 errors are expected assertEquals(0, action.getActionErrors().size()); // make sure the existing DOI was NOT reused assertNotNull(r.getDoi()); assertEquals(existingDOI.getDoiName(), r.getDoi().getDoiName()); assertEquals(ORGANISATION_KEY, r.getDoiOrganisationKey()); assertEquals(IdentifierStatus.PUBLIC_PENDING_PUBLICATION, r.getIdentifierStatus()); assertEquals(1, r.getEml().getAlternateIdentifiers().size()); // alternate ids updated assertEquals(r.getDoi().getUrl().toString(), r.getEml().getCitation().getIdentifier()); // doi set as citation id LOG.info("Existing registered DOI was reused successfully, DOI=" + existingDOI.getDoiName()); } /** * Test reserving an existing registered DOI (reusing an existing registered DOI). * </b> * Make it succeed by making the resource public and using the correct target URI. */ @Ignore("This test needs an existing DOI registered with EZID plugged into it each time - test DOIs are periodically purged") public void testReuseAndReserveExistingRegisteredDoiEZID() throws Exception { // common mock AppConfig AppConfig mockAppConfig = mock(AppConfig.class); DataDir mockDataDir = mock(DataDir.class); when(mockAppConfig.getDataDir()).thenReturn(mockDataDir); // mock returning target URLs when(mockAppConfig.getResourceUri(anyString())).thenReturn(new URI("http://130.226.238.151:7010/ipt/resource?r=test2&v=3.0")); RegistrationManager mockRegistrationManagerEZID = mock(RegistrationManager.class); Organisation oEZID = new Organisation(); oEZID.setKey(ORGANISATION_KEY.toString()); oEZID.setAgencyAccountPrimary(true); oEZID.setName("GBIF"); oEZID.setDoiPrefix("10.5072/FK2"); oEZID.setCanHost(true); oEZID.setAgencyAccountUsername("apitest"); oEZID.setAgencyAccountPassword("apitest"); oEZID.setDoiRegistrationAgency(DOIRegistrationAgency.EZID); when(mockRegistrationManagerEZID.findPrimaryDoiAgencyAccount()).thenReturn(oEZID); when(mockRegistrationManagerEZID.get(any(UUID.class))).thenReturn(oEZID); // mock returning EZID service ServiceConfig cfgEZID = new ServiceConfig("apitest", "apitest"); EzidService ezidService = new EzidService(HttpUtil.newMultithreadedClient(10000, 2, 2), cfgEZID); when(mockRegistrationManagerEZID.getDoiService()).thenReturn(ezidService); // mock action for EZID action = new OverviewAction(mock(SimpleTextProvider.class), mockAppConfig, mockRegistrationManagerEZID, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); LOG.info("Testing EZID with test Prefix..."); action.setReserveDoi("true"); action.setResource(r); assertNull(r.getDoi()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertNotNull(r.getEml().getCitation()); assertNull(r.getEml().getCitation().getIdentifier()); DOI existingDOI = new DOI("doi:10.5072/FK29OGDWW"); // set citation identifier equal to existing registered DOI - this should get reused r.setCitationAutoGenerated(true); r.getEml().setCitation(new Citation("Replaced by auto-generated citation", existingDOI.toString())); // resource must be public r.setStatus(PublicationStatus.PUBLIC); action.reserveDoi(); // 0 errors are expected assertEquals(0, action.getActionErrors().size()); // make sure the existing DOI was NOT reused assertNotNull(r.getDoi()); assertEquals(existingDOI.getDoiName(), r.getDoi().getDoiName()); assertEquals(ORGANISATION_KEY, r.getDoiOrganisationKey()); assertEquals(IdentifierStatus.PUBLIC_PENDING_PUBLICATION, r.getIdentifierStatus()); assertEquals(1, r.getEml().getAlternateIdentifiers().size()); // alternate ids updated assertEquals(r.getDoi().getUrl().toString(), r.getEml().getCitation().getIdentifier()); // doi set as citation id LOG.info("Existing registered DOI was reused successfully, DOI=" + existingDOI.getDoiName()); } /** * Test deleting a reserved existing DOI registered with EZID. */ @Ignore("This test needs an existing DOI registered with EZID plugged into it each time - test DOIs are periodically purged") public void testDeleteReservedExistingRegisteredDoiEZID() throws Exception { // common mock AppConfig AppConfig mockAppConfig = mock(AppConfig.class); RegistrationManager mockRegistrationManagerEZID = mock(RegistrationManager.class); Organisation oEZID = new Organisation(); oEZID.setKey(ORGANISATION_KEY.toString()); oEZID.setAgencyAccountPrimary(true); oEZID.setName("GBIF"); oEZID.setDoiPrefix("10.5072/FK2"); oEZID.setCanHost(true); oEZID.setAgencyAccountUsername("apitest"); oEZID.setAgencyAccountPassword("apitest"); oEZID.setDoiRegistrationAgency(DOIRegistrationAgency.EZID); when(mockRegistrationManagerEZID.findPrimaryDoiAgencyAccount()).thenReturn(oEZID); when(mockRegistrationManagerEZID.get(any(UUID.class))).thenReturn(oEZID); // mock returning EZID service ServiceConfig cfgEZID = new ServiceConfig("apitest", "apitest"); EzidService ezidService = new EzidService(HttpUtil.newMultithreadedClient(10000, 2, 2), cfgEZID); when(mockRegistrationManagerEZID.getDoiService()).thenReturn(ezidService); // mock action for EZID action = new OverviewAction(mock(SimpleTextProvider.class), mockAppConfig, mockRegistrationManagerEZID, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); LOG.info("Testing EZID with test Prefix..."); action.setDeleteDoi("true"); // mock resource having DOI DOI existingDOI = new DOI("doi:10.5072/FK2KNEMBG"); // set citation identifier equal to existing registered DOI - this should get reused r.setCitationAutoGenerated(true); r.getEml().setCitation(new Citation("Replaced by auto-generated citation", existingDOI.toString())); r.setDoi(existingDOI); r.setIdentifierStatus(IdentifierStatus.PUBLIC_PENDING_PUBLICATION); action.setResource(r); assertNotNull(r.getDoi()); assertEquals(IdentifierStatus.PUBLIC_PENDING_PUBLICATION, r.getIdentifierStatus()); assertNotNull(r.getEml().getCitation()); assertNotNull(r.getEml().getCitation().getIdentifier()); action.deleteDoi(); DoiData doiData = ezidService.resolve(existingDOI); assertNotNull(doiData); assertNotNull(doiData.getStatus()); assertEquals(DoiStatus.REGISTERED, doiData.getStatus()); assertNull(r.getDoi()); assertNull(r.getDoiOrganisationKey()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertEquals(0, r.getEml().getAlternateIdentifiers().size()); // alternate ids updated assertNull(r.getEml().getCitation().getIdentifier()); LOG.info("Existing reserved registered DOI was deleted successfully without making it unavailable, DOI=" + existingDOI.getDoiName()); } /** * Test deleting a reserved existing DOI registered with DataCite. */ @Test public void testDeleteReservedExistingRegisteredDoiDataCite() throws Exception { // common mock AppConfig AppConfig mockAppConfig = mock(AppConfig.class); RegistrationManager mockRegistrationManagerDataCite = mock(RegistrationManager.class); Organisation oDataCiteGBIF = new Organisation(); oDataCiteGBIF.setKey(ORGANISATION_KEY.toString()); oDataCiteGBIF.setAgencyAccountPrimary(true); oDataCiteGBIF.setName("GBIF"); oDataCiteGBIF.setDoiPrefix("10.15469"); oDataCiteGBIF.setCanHost(true); oDataCiteGBIF.setAgencyAccountUsername(dcCfg.getUsername()); oDataCiteGBIF.setAgencyAccountPassword(dcCfg.getPassword()); oDataCiteGBIF.setDoiRegistrationAgency(DOIRegistrationAgency.DATACITE); when(mockRegistrationManagerDataCite.findPrimaryDoiAgencyAccount()).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.get(any(UUID.class))).thenReturn(oDataCiteGBIF); when(mockRegistrationManagerDataCite.getDoiService()).thenReturn(dataCiteService); // mock action for EZID action = new OverviewAction(mock(SimpleTextProvider.class), mockAppConfig, mockRegistrationManagerDataCite, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); LOG.info("Testing EZID with test Prefix..."); action.setDeleteDoi("true"); // mock resource having DOI DOI existingDOI = new DOI("doi:10.15469/xhav6t"); // set citation identifier equal to existing registered DOI - this should get reused r.setCitationAutoGenerated(true); r.getEml().setCitation(new Citation("Replaced by auto-generated citation", existingDOI.toString())); r.setDoi(existingDOI); r.setIdentifierStatus(IdentifierStatus.PUBLIC_PENDING_PUBLICATION); action.setResource(r); assertNotNull(r.getDoi()); assertEquals(IdentifierStatus.PUBLIC_PENDING_PUBLICATION, r.getIdentifierStatus()); assertNotNull(r.getEml().getCitation()); assertNotNull(r.getEml().getCitation().getIdentifier()); action.deleteDoi(); DoiData doiData = dataCiteService.resolve(existingDOI); assertNotNull(doiData); assertNotNull(doiData.getStatus()); assertEquals(DoiStatus.REGISTERED, doiData.getStatus()); assertNull(r.getDoi()); assertNull(r.getDoiOrganisationKey()); assertEquals(IdentifierStatus.UNRESERVED, r.getIdentifierStatus()); assertEquals(0, r.getEml().getAlternateIdentifiers().size()); // alternate ids updated assertNull(r.getEml().getCitation().getIdentifier()); LOG.info("Existing reserved registered DOI was deleted successfully without making it unavailable, DOI=" + existingDOI.getDoiName()); } }