package org.gbif.ipt.service.manage.impl; 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.metadata.datacite.DataCiteMetadata; 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.action.BaseAction; import org.gbif.ipt.action.manage.OverviewAction; import org.gbif.ipt.config.AppConfig; import org.gbif.ipt.config.Constants; import org.gbif.ipt.config.DataDir; import org.gbif.ipt.mock.MockRegistryManager; import org.gbif.ipt.model.Organisation; import org.gbif.ipt.model.Resource; import org.gbif.ipt.model.User; import org.gbif.ipt.model.VersionHistory; import org.gbif.ipt.model.converter.ConceptTermConverter; import org.gbif.ipt.model.converter.ExtensionRowTypeConverter; import org.gbif.ipt.model.converter.JdbcInfoConverter; import org.gbif.ipt.model.converter.OrganisationKeyConverter; import org.gbif.ipt.model.converter.PasswordConverter; import org.gbif.ipt.model.converter.UserEmailConverter; 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.service.manage.SourceManager; import org.gbif.ipt.service.registry.RegistryManager; import org.gbif.ipt.struts2.SimpleTextProvider; import org.gbif.ipt.task.Eml2Rtf; import org.gbif.ipt.task.GenerateDwcaFactory; import org.gbif.ipt.utils.DOIUtils; import org.gbif.ipt.utils.DataCiteMetadataBuilder; import org.gbif.metadata.eml.Agent; import org.gbif.metadata.eml.Eml; import org.gbif.metadata.eml.EmlWriter; import org.gbif.utils.HttpUtil; import org.gbif.utils.file.FileUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.UUID; import javax.ws.rs.core.UriBuilder; 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.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(Parameterized.class) public class ResourceManagerImplIT { private static final Logger LOG = Logger.getLogger(ResourceManagerImplIT.class); private static DataDir MOCK_DATA_DIR = mock(DataDir.class); private static File TMP_EML_FILE; private Resource r; private ResourceManagerImpl manager; private DOIRegistrationAgency type; private DOI doi; private RegistrationManager registrationManager; public ResourceManagerImplIT(ResourceManagerImpl action, DOIRegistrationAgency type, DOI doi, RegistrationManager registrationManager) { this.manager = action; this.type = type; this.doi = doi; this.registrationManager = registrationManager; } @Parameterized.Parameters public static Iterable data() throws IOException { // Mock classes AppConfig mockAppConfig = mock(AppConfig.class); // mock returning resource URI in gbif-uat belong when(mockAppConfig.getResourceUri(anyString())) .thenReturn(UriBuilder.fromPath("http://www.gbif-uat.org:7001/ipt?r=ants").build()); when(mockAppConfig.getResourceVersionUri("ants", new BigDecimal("1.1"))) .thenReturn(UriBuilder.fromPath("http://www.gbif-uat.org:7001/ipt?r=ants&v=1.1").build()); when(mockAppConfig.getMaxThreads()).thenReturn(3); UserAccountManager mockUserAccountManager = mock(UserAccountManager.class); UserEmailConverter mockEmailConverter = new UserEmailConverter(mockUserAccountManager); ExtensionRowTypeConverter mockExtensionRowTypeConverter = mock(ExtensionRowTypeConverter.class); ExtensionManager mockExtensionManager = mock(ExtensionManager.class); JdbcInfoConverter mockJdbcConverter = mock(JdbcInfoConverter.class); SourceManager mockSourceManager = mock(SourceManager.class); RegistryManager mockRegistryManager = MockRegistryManager.buildMock(); GenerateDwcaFactory mockDwcaFactory = mock(GenerateDwcaFactory.class); PasswordConverter mockPasswordConverter = mock(PasswordConverter.class); Eml2Rtf mockEml2Rtf = mock(Eml2Rtf.class); VocabulariesManager mockVocabulariesManager = mock(VocabulariesManager.class); SimpleTextProvider mockSimpleTextProvider = mock(SimpleTextProvider.class); ConceptTermConverter mockConceptTermConverter = mock(ConceptTermConverter.class); // persist eml file for version 1.0 (contents written later) TMP_EML_FILE = File.createTempFile("eml-1.0", ".xml"); when(MOCK_DATA_DIR.resourceEmlFile("ants", new BigDecimal("1.1"))).thenReturn(TMP_EML_FILE); // DataCite parameters.. RegistrationManager mockRegistrationManagerDataCite = mock(RegistrationManager.class); ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); InputStream dc = FileUtils.classpathStream("datacite.yaml"); ServiceConfig dcCfg = mapper.readValue(dc, ServiceConfig.class); //LOG.info("DataCite password (read from Maven property datacite.password)= " + dcCfg.getPassword()); Organisation oDataCite = new Organisation(); oDataCite.setAgencyAccountPrimary(true); oDataCite.setName("GBIF"); oDataCite.setDoiPrefix(Constants.TEST_DOI_PREFIX); oDataCite.setCanHost(true); oDataCite.setAgencyAccountUsername(dcCfg.getUsername()); oDataCite.setAgencyAccountPassword(dcCfg.getPassword()); oDataCite.setDoiRegistrationAgency(DOIRegistrationAgency.DATACITE); // mock returning primary DOI agency account when(mockRegistrationManagerDataCite.findPrimaryDoiAgencyAccount()).thenReturn(oDataCite); // mock returning DataCite service DoiService dataCiteService = new DataCiteService(HttpUtil.newMultithreadedClient(10000, 3, 2), dcCfg); when(mockRegistrationManagerDataCite.getDoiService()).thenReturn(dataCiteService); // mock ResourceManagerImpl for DataCite ResourceManagerImpl managerDataCite = new ResourceManagerImpl(mockAppConfig, MOCK_DATA_DIR, mockEmailConverter, new OrganisationKeyConverter(mockRegistrationManagerDataCite), mockExtensionRowTypeConverter, mockJdbcConverter, mockSourceManager, mockExtensionManager, mockRegistryManager, mockConceptTermConverter, mockDwcaFactory, mockPasswordConverter, mockEml2Rtf, mockVocabulariesManager, mockSimpleTextProvider, mockRegistrationManagerDataCite); // EZID parameters.. RegistrationManager mockRegistrationManagerEZID = mock(RegistrationManager.class); Organisation oEZID = new Organisation(); oEZID.setAgencyAccountPrimary(true); oEZID.setName("GBIF"); oEZID.setDoiPrefix(Constants.EZID_TEST_DOI_SHOULDER); oEZID.setCanHost(true); oEZID.setAgencyAccountUsername("apitest"); oEZID.setAgencyAccountPassword("apitest"); oEZID.setDoiRegistrationAgency(DOIRegistrationAgency.EZID); // mock returning primary DOI agency account when(mockRegistrationManagerEZID.findPrimaryDoiAgencyAccount()).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 OverviewAction actionEZID = new OverviewAction(mock(SimpleTextProvider.class), mock(AppConfig.class), mockRegistrationManagerEZID, mock(ResourceManager.class), mock(UserAccountManager.class), mock(ExtensionManager.class), mock(VocabulariesManager.class), mock(GenerateDwcaFactory.class)); // mock ResourceManagerImpl for EZID ResourceManagerImpl managerEZID = new ResourceManagerImpl(mockAppConfig, MOCK_DATA_DIR, mockEmailConverter, new OrganisationKeyConverter(mockRegistrationManagerEZID), mockExtensionRowTypeConverter, mockJdbcConverter, mockSourceManager, mockExtensionManager, mockRegistryManager, mockConceptTermConverter, mockDwcaFactory, mockPasswordConverter, mockEml2Rtf, mockVocabulariesManager, mockSimpleTextProvider, mockRegistrationManagerEZID); return Arrays.asList(new Object[][] {{managerDataCite, DOIRegistrationAgency.DATACITE, DOIUtils.mintDOI(DOIRegistrationAgency.DATACITE, Constants.TEST_DOI_PREFIX), mockRegistrationManagerDataCite} ,{managerEZID, DOIRegistrationAgency.EZID,DOIUtils.mintDOI(DOIRegistrationAgency.EZID, Constants.EZID_TEST_DOI_SHOULDER), mockRegistrationManagerEZID} }); } /** * Generate a brand new (unpublished) 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"); // 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"); o.setKey(UUID.randomUUID().toString()); r.setOrganisation(o); r.setEmlVersion(Constants.INITIAL_RESOURCE_VERSION); r.setStatus(PublicationStatus.PUBLIC); assertNull(r.getLastPublished()); } /** * Reserve and then register DOI for public resource. * </br> * Then test updating the DOI with a new version number. * </br> * Lastly test replacing this DOI with a new DOI, by reserving and registering a new DOI for the resource. The * replaced DOI should still be registered, but its metadata should reflect the fact it has been replaced by the new * version, and its target URI should point to that version of the resource. */ @Test public void testRegisterDoiWorkflow() throws Exception { LOG.info("Testing " + type + "..."); // reserve DOI to begin with assertNotNull(doi); assertEquals(PublicationStatus.PUBLIC, r.getStatus()); r.setDoi(doi); r.setIdentifierStatus(IdentifierStatus.PUBLIC_PENDING_PUBLICATION); assertEquals(Constants.INITIAL_RESOURCE_VERSION.toPlainString(), r.getEmlVersion().toPlainString()); DataCiteMetadata dataCiteMetadata = DataCiteMetadataBuilder.createDataCiteMetadata(doi, r); registrationManager.getDoiService().reserve(doi, dataCiteMetadata); // check DOI is reserved, and its target is null DoiData doiData = registrationManager.getDoiService().resolve(doi); assertNotNull(doiData.getStatus()); assertEquals(DoiStatus.RESERVED, doiData.getStatus()); assertNull(doiData.getTarget()); // register DOI manager.doRegisterDoi(r, null); assertEquals(IdentifierStatus.PUBLIC, r.getIdentifierStatus()); LOG.info("DOI was registered successfully, DOI=" + doi.getDoiName()); // check DOI was registered, and its target is correct doiData = registrationManager.getDoiService().resolve(doi); assertNotNull(doiData.getStatus()); assertTrue(doiData.getStatus().isRegistered()); assertNotNull(doiData.getTarget()); assertEquals(UriBuilder.fromPath("http://www.gbif-uat.org:7001/ipt%3Fr=ants").build().toString(), doiData.getTarget().toString()); // mock version 1.0 having been published by setting last published, and adding new VersionHistory r.setLastPublished(new Date()); User user = new User(); user.setEmail("jsmith@gbif.org"); VersionHistory history = new VersionHistory(new BigDecimal("1.0"), new Date(), PublicationStatus.PUBLIC); history.setModifiedBy(user); history.setStatus(IdentifierStatus.PUBLIC); history.setDoi(doi); r.addVersionHistory(history); // persist eml file for version 1.0 EmlWriter.writeEmlFile(TMP_EML_FILE, r.getEml()); // update DOI for next published version BigDecimal nextVersion = r.getNextVersion(); r.setEmlVersion(nextVersion); assertEquals("1.1", r.getEmlVersion().toPlainString()); assertEquals("1.0", r.getReplacedEmlVersion().toPlainString()); manager.doUpdateDoi(r); LOG.info("DOI was updated successfully, DOI=" + doi.getDoiName()); // check DOI remains registered, and its target is the same doiData = registrationManager.getDoiService().resolve(doi); assertNotNull(doiData.getStatus()); assertTrue(doiData.getStatus().isRegistered()); assertNotNull(doiData.getTarget()); assertEquals(UriBuilder.fromPath("http://www.gbif-uat.org:7001/ipt%3Fr=ants").build().toString(), doiData.getTarget().toString()); // mock version 1.1 having been published by setting last published, and adding new VersionHistory r.setLastPublished(new Date()); VersionHistory history2 = new VersionHistory(new BigDecimal("1.1"), new Date(), PublicationStatus.PUBLIC); history.setModifiedBy(user); history2.setDoi(doi); history2.setStatus(IdentifierStatus.PUBLIC); r.addVersionHistory(history2); // reserve another new DOI DOI newDoi = DOIUtils.mintDOI(type, registrationManager.findPrimaryDoiAgencyAccount().getDoiPrefix()); r.setDoi(newDoi); r.setIdentifierStatus(IdentifierStatus.PUBLIC_PENDING_PUBLICATION); dataCiteMetadata = DataCiteMetadataBuilder.createDataCiteMetadata(newDoi, r); registrationManager.getDoiService().reserve(newDoi, dataCiteMetadata); // check DOI is reserved, and its target is null doiData = registrationManager.getDoiService().resolve(newDoi); assertNotNull(doiData.getStatus()); assertEquals(DoiStatus.RESERVED, doiData.getStatus()); assertNull(doiData.getTarget()); // replace DOI with new DOI, and publish version 2.0 assertEquals(IdentifierStatus.PUBLIC_PENDING_PUBLICATION, r.getIdentifierStatus()); nextVersion = r.getNextVersion(); // new major version r.setEmlVersion(nextVersion); assertEquals("2.0", r.getEmlVersion().toPlainString()); assertNotNull(r.getAssignedDoi()); assertEquals("1.1", r.getReplacedEmlVersion().toPlainString()); manager.doReplaceDoi(r, r.getEmlVersion(), r.getReplacedEmlVersion()); // check new DOI is registered now, and its target is equal to resource URI doiData = registrationManager.getDoiService().resolve(newDoi); assertNotNull(doiData.getStatus()); assertEquals(DoiStatus.REGISTERED, doiData.getStatus()); assertNotNull(doiData.getTarget()); assertEquals(UriBuilder.fromPath("http://www.gbif-uat.org:7001/ipt%3Fr=ants").build().toString(), doiData.getTarget().toString()); // check replaced DOI is still registered, and its target is equal to resource version URI doiData = registrationManager.getDoiService().resolve(doi); assertNotNull(doiData.getStatus()); assertEquals(DoiStatus.REGISTERED, doiData.getStatus()); assertNotNull(doiData.getTarget()); assertEquals(UriBuilder.fromPath("http://www.gbif-uat.org:7001/ipt%3Fr=ants&v=1.1").build().toString(), doiData.getTarget().toString()); } }