From 954ce1a87535a3cbb5c4b03a809531d2e5570f15 Mon Sep 17 00:00:00 2001 From: Filipe Dias Lewandowski Date: Fri, 20 Sep 2024 09:35:41 +0200 Subject: [PATCH 1/2] Closes #2506: Removal of harvested DOI (#2523) * Closes #2507: Datacite DOI harvester * Refs #2507: Minor adjustments * Closes #2504: Endpoint to run datacite harvester * Closes #2506: Removal of harvested DOI * review comments * merge conflicts * merge conflicts --- .../api/imports/ImportServiceBean.java | 25 +++ .../harvest/client/DataciteDOIHarvester.java | 25 ++- .../client/DataciteHarvesterParams.java | 11 +- .../harvest/client/OAIHarvester.java | 60 +----- .../client/DataciteDOIHarvesterTest.java | 183 ++++++++++++++++++ 5 files changed, 239 insertions(+), 65 deletions(-) create mode 100644 dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/harvest/client/DataciteDOIHarvesterTest.java diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java index fc005c1be12..46d8e376a0f 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java @@ -7,6 +7,7 @@ import edu.harvard.iq.dataverse.api.dto.DatasetDTO; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.impl.CreateHarvestedDatasetCommand; +import edu.harvard.iq.dataverse.engine.command.impl.DeleteDatasetCommand; import edu.harvard.iq.dataverse.engine.command.impl.DestroyDatasetCommand; import edu.harvard.iq.dataverse.persistence.datafile.DataFile; import edu.harvard.iq.dataverse.persistence.dataset.Dataset; @@ -112,6 +113,30 @@ public Dataset doImportHarvestedDataset(DataverseRequest dataverseRequest, Harve } } + @TransactionAttribute(REQUIRES_NEW) + public void doDeleteHarvestedDataset(DataverseRequest request, HarvestingClient harvestingClient, String identifier) throws ImportException { + Dataset dataset = datasetDao.getDatasetByHarvestInfo(harvestingClient.getDataverse(), identifier); + if (dataset != null) { + // Purge all the SOLR documents associated with this client from the + // index server: + indexService.deleteHarvestedDocuments(dataset); + + // files from harvested datasets are removed unceremoniously, + // directly in the database. no need to bother calling the + // DeleteFileCommand on them. + for (DataFile harvestedFile : dataset.getFiles()) { + DataFile merged = em.merge(harvestedFile); + em.remove(merged); + } + + dataset.setFiles(null); + Dataset merged = em.merge(dataset); + engineSvc.submit(new DeleteDatasetCommand(request, merged)); + } else { + throw new ImportException("No dataset found for " + identifier + ", skipping delete. "); + } + } + private Dataset importDatasetDTOJson(DataverseRequest dataverseRequest, HarvestingClient harvestingClient, String harvestIdentifier, String json) throws ImportException { try { Dataset ds = harvestedJsonParser.parseDataset(json); diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteDOIHarvester.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteDOIHarvester.java index 2b94e164a09..e9ae1666c4a 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteDOIHarvester.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteDOIHarvester.java @@ -18,7 +18,6 @@ @LocalBean public class DataciteDOIHarvester implements Harvester { - @Inject private DataCiteRestApiClient dataCiteRestApiClient; @@ -42,7 +41,7 @@ public Class getParamsClass() { @Override public HarvesterResult harvest(DataverseRequest dataverseRequest, HarvestingClient harvestingClient, Logger hdLogger, DataciteHarvesterParams params) throws ImportException { - if (params.getDoiImport().isEmpty()) { + if (params.getDoiImport().isEmpty() && params.getDoiRemove().isEmpty()) { throw new ImportException("Missing DOI's"); } @@ -52,24 +51,36 @@ public HarvesterResult harvest(DataverseRequest dataverseRequest, HarvestingClie importDOI(rs, dataverseRequest, harvestingClient, hdLogger, doi); } + for (DataciteHarvesterParams.DOIValue doi: params.getDoiRemove()) { + removeDOI(rs, dataverseRequest, harvestingClient, hdLogger, doi); + } + return rs; } // -------------------- PRIVATE -------------------- - private void importDOI(HarvesterResult rs, DataverseRequest dataverseRequest, HarvestingClient harvestingClient, Logger hdLogger, DataciteHarvesterParams.DOIValue doi) throws ImportException { + private void importDOI(HarvesterResult rs, DataverseRequest dataverseRequest, HarvestingClient harvestingClient, Logger hdLogger, DataciteHarvesterParams.DOIValue doi) { try { DatasetDTO dto = dataciteDatasetMapper.toDataset(dataCiteRestApiClient.findDoi(doi.getAuthority(), doi.getId())); importService.doImportHarvestedDataset(dataverseRequest, harvestingClient, doi.getFull(), dto); rs.incrementHarvested(); } catch (Exception e) { rs.incrementFailed(); - String errorMessage = "Failed to import DOI " + hdLogger.log(Level.SEVERE, "Failed to import DOI (" + doi.getFull() + ") " + harvestingClient.getName() + "; " - + e.getMessage(); - hdLogger.log(Level.SEVERE, errorMessage); - throw new ImportException(errorMessage, e); + + e.getMessage()); + } + } + + private void removeDOI(HarvesterResult rs, DataverseRequest dataverseRequest, HarvestingClient harvestingClient, Logger hdLogger, DataciteHarvesterParams.DOIValue doi) { + try { + importService.doDeleteHarvestedDataset(dataverseRequest, harvestingClient, doi.getFull()); + rs.incrementDeleted(); + } catch (Exception e) { + rs.incrementFailed(); + hdLogger.log(Level.SEVERE, "Failed to delete DOI " + doi.getFull() + " (" + harvestingClient.getName() + "): " + e.getMessage()); } } } diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteHarvesterParams.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteHarvesterParams.java index 2c5719e3ce8..9f3ac30c088 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteHarvesterParams.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/DataciteHarvesterParams.java @@ -1,6 +1,5 @@ package edu.harvard.iq.dataverse.harvest.client; -import com.fasterxml.jackson.annotation.JsonCreator; import io.vavr.control.Option; import java.util.Collections; @@ -15,18 +14,28 @@ public class DataciteHarvesterParams extends HarvesterParams { private List doiImport; + private List doiRemove; + // -------------------- GETTERS -------------------- public List getDoiImport() { return Option.of(doiImport).getOrElse(Collections.emptyList()); } + public List getDoiRemove() { + return Option.of(doiRemove).getOrElse(Collections.emptyList()); + } + // -------------------- SETTERS -------------------- public void setDoiImport(List doiImport) { this.doiImport = doiImport; } + public void setDoiRemove(List doiRemove) { + this.doiRemove = doiRemove; + } + // -------------------- INNER CLASSES -------------------- static public class DOIValue { diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/OAIHarvester.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/OAIHarvester.java index f9df522714b..f96e9f654bc 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/OAIHarvester.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/harvest/client/OAIHarvester.java @@ -1,23 +1,14 @@ package edu.harvard.iq.dataverse.harvest.client; -import edu.harvard.iq.dataverse.DatasetDao; -import edu.harvard.iq.dataverse.EjbDataverseEngine; import edu.harvard.iq.dataverse.api.imports.HarvestImporterType; import edu.harvard.iq.dataverse.api.imports.HarvestImporterTypeResolver; import edu.harvard.iq.dataverse.api.imports.ImportException; import edu.harvard.iq.dataverse.api.imports.ImportServiceBean; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; -import edu.harvard.iq.dataverse.engine.command.exception.CommandException; -import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException; -import edu.harvard.iq.dataverse.engine.command.exception.PermissionException; -import edu.harvard.iq.dataverse.engine.command.impl.DeleteDatasetCommand; import edu.harvard.iq.dataverse.harvest.client.oai.OaiHandler; import edu.harvard.iq.dataverse.harvest.client.oai.OaiHandlerException; -import edu.harvard.iq.dataverse.persistence.datafile.DataFile; -import edu.harvard.iq.dataverse.persistence.dataset.Dataset; import edu.harvard.iq.dataverse.persistence.harvest.HarvestType; import edu.harvard.iq.dataverse.persistence.harvest.HarvestingClient; -import edu.harvard.iq.dataverse.search.index.IndexServiceBean; import org.apache.commons.io.FileUtils; import org.dspace.xoai.model.oaipmh.Header; import org.dspace.xoai.serviceprovider.exceptions.HarvestException; @@ -46,21 +37,12 @@ public class OAIHarvester implements Harvester dto.getAuthority().equals(doi.getAuthority()) && dto.getIdentifier().equals(doi.getId()))); + } + assertThat(result.getNumHarvested()).isEqualTo(5); + assertThat(result.getNumDeleted()).isEqualTo(0); + assertThat(result.getNumFailed()).isEqualTo(0); + } + + @Test + public void harvest__delete() throws ImportException { + // given + DataciteHarvesterParams params = new DataciteHarvesterParams(); + params.setDoiRemove(DOI_REPO); + DataverseRequest dataverseRequest = dataverseRequest(); + + // when + HarvesterResult result = dataciteDOIHarvester.harvest(dataverseRequest, harvestingClient, Logger.getLogger("test"), params); + + // then + for (DataciteHarvesterParams.DOIValue doi : DOI_REPO) { + verify(importService, times(1)).doDeleteHarvestedDataset(any(), any(), + eq(doi.getFull())); + } + assertThat(result.getNumHarvested()).isEqualTo(0); + assertThat(result.getNumDeleted()).isEqualTo(5); + assertThat(result.getNumFailed()).isEqualTo(0); + } + + @Test + public void harvest__failed() throws ImportException, IOException { + // given + List impSuccess = Lists.newArrayList(DOI_REPO.get(0)); + List impFail = Lists.newArrayList(DOI_REPO.get(1)); + List delSuccess = Lists.newArrayList(DOI_REPO.get(2), DOI_REPO.get(4)); + List delFail = Lists.newArrayList(DOI_REPO.get(3)); + + for (DataciteHarvesterParams.DOIValue s : impSuccess) { + when(dataCiteRestApiClient.findDoi(s.getAuthority(), s.getId())).thenReturn(newResponse(s)); + } + + for (DataciteHarvesterParams.DOIValue f : impFail) { + when(dataCiteRestApiClient.findDoi(f.getAuthority(), f.getId())).thenThrow(new IOException("Boom!")); + } + + for (DataciteHarvesterParams.DOIValue f : delSuccess) { + doNothing().when(importService).doDeleteHarvestedDataset(any(), any(), eq(f.getFull())); + } + + for (DataciteHarvesterParams.DOIValue f : delFail) { + doThrow(new ImportException("Boom!")).when(importService).doDeleteHarvestedDataset(any(), any(), eq(f.getFull())); + } + + DataciteHarvesterParams params = new DataciteHarvesterParams(); + params.setDoiImport(ListUtils.union(impSuccess, impFail)); + params.setDoiRemove(ListUtils.union(delSuccess, delFail)); + DataverseRequest dataverseRequest = dataverseRequest(); + + // when + HarvesterResult result = dataciteDOIHarvester.harvest(dataverseRequest, harvestingClient, Logger.getLogger("test"), params); + + // then + for (DataciteHarvesterParams.DOIValue rs : impSuccess) { + verify(importService, times(1)).doImportHarvestedDataset(any(), any(), + eq(rs.getFull()), + argThat(dto -> dto.getAuthority().equals(rs.getAuthority()) && dto.getIdentifier().equals(rs.getId()))); + } + for (DataciteHarvesterParams.DOIValue rs : delSuccess) { + verify(importService, times(1)).doDeleteHarvestedDataset(any(), any(), + eq(rs.getFull())); + } + assertThat(result.getNumHarvested()).isEqualTo(1); + assertThat(result.getNumDeleted()).isEqualTo(2); + assertThat(result.getNumFailed()).isEqualTo(2); + } + + @Test + public void harvest__empty_input() throws ImportException { + // given + DataciteHarvesterParams params = new DataciteHarvesterParams(); + + // when & then + assertThatThrownBy(() -> + dataciteDOIHarvester.harvest(dataverseRequest(), harvestingClient, Logger.getLogger("test"), params)) + .hasMessage("Missing DOI's") + .isInstanceOf(ImportException.class); + } + + private DataverseRequest dataverseRequest() { + return new DataverseRequest(GuestUser.get(), IpAddress.valueOf("1.1.1.2")); + } + + private DataciteHarvesterParams.DOIValue newDOI(String doi) { + return new DataciteHarvesterParams.DOIValue(doi); + } + + private static DataCiteFindDoiResponse newResponse(DataciteHarvesterParams.DOIValue doi) { + DataCiteFindDoiResponse response = new DataCiteFindDoiResponse(); + response.setId(RandomStringUtils.random(5)); + response.getAttributes().setCitationCount(3); + response.getAttributes().setPrefix(doi.getAuthority()); + response.getAttributes().setSuffix(doi.getId()); + response.getAttributes().setContributors(Collections.emptyList()); + return response; + } +} From 3c65c1423f538ab1a9bf5124c4f59ec355db96d5 Mon Sep 17 00:00:00 2001 From: Filipe Dias Lewandowski Date: Fri, 20 Sep 2024 09:48:24 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Closes=20#2519:=20Changing=20the=20status?= =?UTF-8?q?=20of=20dataset=20DOI=20from=20findable=20to=20reg=E2=80=A6=20(?= =?UTF-8?q?#2525)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Closes #2519: Changing the status of dataset DOI from findable to registered when deaccessing it * Unregister datafile dois when all versions have been de-accessed * review comments --- .../iq/dataverse/EjbDataverseEngine.java | 8 ++ .../DatasetDeaccessionService.java | 49 +++++++++-- .../engine/command/CommandContext.java | 3 + .../DeaccessionDatasetVersionCommand.java | 44 ---------- .../globalid/DOIDataCiteRegisterService.java | 21 ++--- .../globalid/GlobalIdServiceBean.java | 47 ++--------- .../globalid/GlobalIdServiceBeanResolver.java | 82 +++++++++++++++++++ .../dataverse/engine/TestCommandContext.java | 6 ++ .../DOIDataCiteRegisterServiceTest.java | 1 + .../globalid/GlobalIdServiceBeanTest.java | 22 +---- 10 files changed, 165 insertions(+), 118 deletions(-) delete mode 100644 dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeaccessionDatasetVersionCommand.java create mode 100644 dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanResolver.java diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java index f88881fc653..f11702c533f 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/EjbDataverseEngine.java @@ -24,6 +24,7 @@ import edu.harvard.iq.dataverse.globalid.DOIDataCiteServiceBean; import edu.harvard.iq.dataverse.globalid.DOIEZIdServiceBean; import edu.harvard.iq.dataverse.globalid.FakePidProviderServiceBean; +import edu.harvard.iq.dataverse.globalid.GlobalIdServiceBeanResolver; import edu.harvard.iq.dataverse.globalid.HandlenetServiceBean; import edu.harvard.iq.dataverse.guestbook.GuestbookResponseServiceBean; import edu.harvard.iq.dataverse.guestbook.GuestbookServiceBean; @@ -210,6 +211,8 @@ public class EjbDataverseEngine { @Inject DatasetFieldValidationService fieldValidationService; + @Inject + GlobalIdServiceBeanResolver globalIdServiceBeanResolver; @Resource EJBContext ejbCtxt; @@ -552,6 +555,11 @@ public DownloadDatasetLogDao downloadDatasetDao() { public DatasetFieldValidationService fieldValidationService() { return fieldValidationService; } + + @Override + public GlobalIdServiceBeanResolver globalIdServiceBeanResolver() { + return globalIdServiceBeanResolver; + } }; } diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/deaccession/DatasetDeaccessionService.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/deaccession/DatasetDeaccessionService.java index 9db5970cdcc..c7a6185b9d5 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/deaccession/DatasetDeaccessionService.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/dataset/deaccession/DatasetDeaccessionService.java @@ -1,13 +1,20 @@ package edu.harvard.iq.dataverse.dataset.deaccession; +import edu.harvard.iq.dataverse.DataverseRequestServiceBean; +import edu.harvard.iq.dataverse.EjbDataverseEngine; import edu.harvard.iq.dataverse.annotations.PermissionNeeded; import edu.harvard.iq.dataverse.annotations.processors.permissions.extractors.DatasetFromVersion; +import edu.harvard.iq.dataverse.globalid.GlobalIdServiceBeanResolver; import edu.harvard.iq.dataverse.interceptors.LoggedCall; import edu.harvard.iq.dataverse.interceptors.Restricted; +import edu.harvard.iq.dataverse.persistence.DvObject; import edu.harvard.iq.dataverse.persistence.dataset.Dataset; import edu.harvard.iq.dataverse.persistence.dataset.DatasetVersion; import edu.harvard.iq.dataverse.persistence.user.Permission; import edu.harvard.iq.dataverse.search.index.IndexServiceBean; +import io.vavr.control.Option; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.ejb.Stateless; import javax.inject.Inject; @@ -20,12 +27,23 @@ @Stateless public class DatasetDeaccessionService { + private static final Logger log = LoggerFactory.getLogger(DatasetDeaccessionService.class); + @PersistenceContext private EntityManager em; @Inject private IndexServiceBean indexService; + @Inject + private EjbDataverseEngine commandEngine; + + @Inject + private DataverseRequestServiceBean dvRequestService; + + @Inject + private GlobalIdServiceBeanResolver globalIdServiceBeanResolver; + // -------------------- LOGIC -------------------- @LoggedCall @@ -51,17 +69,34 @@ public List deaccessReleasedVersions( // -------------------- PRIVATE -------------------- - private DatasetVersion deaccessDatasetVersion(DatasetVersion deaccessionVersion, - String deaccessionReason, String deaccessionForwardURLFor) { - deaccessionVersion.setVersionNote(deaccessionReason); - deaccessionVersion.setArchiveNote(deaccessionForwardURLFor); - deaccessionVersion.setVersionState(DatasetVersion.VersionState.DEACCESSIONED); - deaccessionVersion.setLastUpdateTime(new Date()); - DatasetVersion merged = em.merge(deaccessionVersion); + private DatasetVersion deaccessDatasetVersion(DatasetVersion version, String deaccessionReason, String deaccessionForwardURLFor) { + version.setVersionNote(deaccessionReason); + version.setArchiveNote(deaccessionForwardURLFor); + version.setVersionState(DatasetVersion.VersionState.DEACCESSIONED); + version.setLastUpdateTime(new Date()); + DatasetVersion merged = em.merge(version); Dataset dataset = merged.getDataset(); indexService.indexDataset(dataset, true); em.merge(dataset); + + dataset.getFiles().stream() + .filter(df -> df.getFileMetadatas().stream() + .allMatch(fm -> fm.getDatasetVersion().isDeaccessioned())) + .forEach(this::unregisterGlobalId); + + if (dataset.isDeaccessioned()) { + unregisterGlobalId(dataset); + } + return merged; } + + private void unregisterGlobalId(DvObject object) { + if (object.isIdentifierRegistered()) { + Option.of(globalIdServiceBeanResolver.resolve(object.getProtocol())).toTry() + .andThenTry(service -> service.deleteIdentifier(object)) + .onFailure(e -> log.warn("Failed to unregister identifier {}", object.getGlobalId(), e)); + } + } } diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java index 72b1188751b..9a3ad83434d 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/CommandContext.java @@ -29,6 +29,7 @@ import edu.harvard.iq.dataverse.globalid.DOIDataCiteServiceBean; import edu.harvard.iq.dataverse.globalid.DOIEZIdServiceBean; import edu.harvard.iq.dataverse.globalid.FakePidProviderServiceBean; +import edu.harvard.iq.dataverse.globalid.GlobalIdServiceBeanResolver; import edu.harvard.iq.dataverse.globalid.HandlenetServiceBean; import edu.harvard.iq.dataverse.guestbook.GuestbookResponseServiceBean; import edu.harvard.iq.dataverse.guestbook.GuestbookServiceBean; @@ -154,4 +155,6 @@ public interface CommandContext { DownloadDatasetLogDao downloadDatasetDao(); DatasetFieldValidationService fieldValidationService(); + + GlobalIdServiceBeanResolver globalIdServiceBeanResolver(); } diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeaccessionDatasetVersionCommand.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeaccessionDatasetVersionCommand.java deleted file mode 100644 index 35b44bc5a91..00000000000 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeaccessionDatasetVersionCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -package edu.harvard.iq.dataverse.engine.command.impl; - -import edu.harvard.iq.dataverse.engine.command.AbstractCommand; -import edu.harvard.iq.dataverse.engine.command.CommandContext; -import edu.harvard.iq.dataverse.engine.command.DataverseRequest; -import edu.harvard.iq.dataverse.engine.command.RequiredPermissions; -import edu.harvard.iq.dataverse.persistence.dataset.DatasetVersion; -import edu.harvard.iq.dataverse.persistence.user.Permission; - -/** - * @author skraffmiller - */ -@RequiredPermissions(Permission.PublishDataset) -public class DeaccessionDatasetVersionCommand extends AbstractCommand { - - final DatasetVersion theVersion; - - public DeaccessionDatasetVersionCommand(DataverseRequest aRequest, DatasetVersion deaccessionVersion) { - super(aRequest, deaccessionVersion.getDataset()); - theVersion = deaccessionVersion; - } - - - @Override - public DatasetVersion execute(CommandContext ctxt) { - - theVersion.setVersionState(DatasetVersion.VersionState.DEACCESSIONED); - DatasetVersion managed = ctxt.em().merge(theVersion); - - boolean doNormalSolrDocCleanUp = true; - ctxt.index().indexDataset(managed.getDataset(), doNormalSolrDocCleanUp); - - ctxt.em().merge(managed.getDataset()); - - return managed; - } - -} diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterService.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterService.java index d99a09d23ec..bc63de20d21 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterService.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterService.java @@ -87,18 +87,18 @@ public String reserveIdentifier(String identifier, Map metadata, public void registerIdentifier(String identifier, Map metadata, DvObject dvObject) throws IOException { String xmlMetadata = getMetadataFromDvObject(identifier, metadata, dvObject); - DOIDataCiteRegisterCache rc = findByDOI(identifier); + DOIDataCiteRegisterCache rc = Optional.ofNullable(findByDOI(identifier)) + .orElseGet(DOIDataCiteRegisterCache::new); String target = metadata.get("_target"); - if (rc != null) { - rc.setDoi(identifier); - rc.setXml(xmlMetadata); - rc.setStatus("public"); - if (target == null || target.trim().length() == 0) { - target = rc.getUrl(); - } else { - rc.setUrl(target); - } + rc.setDoi(identifier); + rc.setXml(xmlMetadata); + rc.setStatus("public"); + if (target == null || target.trim().length() == 0) { + target = rc.getUrl(); + } else { + rc.setUrl(target); } + em.merge(rc); registerDOI(identifier.split(":")[1], target, xmlMetadata); } @@ -121,6 +121,7 @@ public String getMetadataForDeactivateId(String identifier) { resource.setTitles(Collections.singletonList("This item has been removed from publication")); resource.setPublisher(":unav"); resource.setPublicationYear("9999"); + resource.setCreators(Collections.singletonList(new DataCiteResource.Creator(":unav"))); return convertToXml(resource); } diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBean.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBean.java index cf31b78a6a8..43eb80e9fde 100644 --- a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBean.java +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBean.java @@ -5,15 +5,10 @@ import edu.harvard.iq.dataverse.persistence.GlobalId; import edu.harvard.iq.dataverse.settings.SettingsServiceBean.Key; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Function; -import java.util.logging.Level; import java.util.logging.Logger; -import static edu.harvard.iq.dataverse.globalid.GlobalIdServiceBean.logger; - public interface GlobalIdServiceBean { Logger logger = Logger.getLogger(GlobalIdServiceBean.class.getCanonicalName()); @@ -56,45 +51,19 @@ public interface GlobalIdServiceBean { boolean publicizeIdentifier(DvObject studyIn); + /** + * @deprecated use {@link GlobalIdServiceBeanResolver} instead + */ + @Deprecated static GlobalIdServiceBean getBean(String protocol, CommandContext ctxt) { - final Function protocolHandler = BeanDispatcher.DISPATCHER.get(protocol); - if (protocolHandler != null) { - return protocolHandler.apply(ctxt); - } else { - logger.log(Level.SEVERE, "Unknown protocol: {0}", protocol); - return null; - } + return ctxt.globalIdServiceBeanResolver().resolve(protocol); } + /** + * @deprecated use {@link GlobalIdServiceBeanResolver} instead + */ static GlobalIdServiceBean getBean(CommandContext ctxt) { return getBean(ctxt.settings().getValueForKey(Key.Protocol), ctxt); } } - -/** - * Static utility class for dispatching implementing beans, based on protocol and providers. - * - * @author michael - */ -class BeanDispatcher { - static final Map> DISPATCHER = new HashMap<>(); - - static { - DISPATCHER.put("hdl", ctxt -> ctxt.handleNet()); - DISPATCHER.put("doi", ctxt -> { - String doiProvider = ctxt.settings().getValueForKey(Key.DoiProvider); - switch (doiProvider) { - case "EZID": - return ctxt.doiEZId(); - case "DataCite": - return ctxt.doiDataCite(); - case "FAKE": - return ctxt.fakePidProvider(); - default: - logger.log(Level.SEVERE, "Unknown doiProvider: {0}", doiProvider); - return null; - } - }); - } -} \ No newline at end of file diff --git a/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanResolver.java b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanResolver.java new file mode 100644 index 00000000000..9238840cf12 --- /dev/null +++ b/dataverse-webapp/src/main/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanResolver.java @@ -0,0 +1,82 @@ +package edu.harvard.iq.dataverse.globalid; + +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.PostConstruct; +import javax.ejb.Stateless; +import javax.inject.Inject; +import java.util.HashMap; +import java.util.Map; + +@Stateless +public class GlobalIdServiceBeanResolver { + + private static final Logger log = LoggerFactory.getLogger(GlobalIdServiceBeanResolver.class); + + private final Map serviceBeans = new HashMap<>(); + + private HandlenetServiceBean handlenetService; + + private SettingsServiceBean settingsService; + + private DOIEZIdServiceBean doiEZId; + + private DOIDataCiteServiceBean doiDataCite; + + private FakePidProviderServiceBean fakePidProvider; + + @PostConstruct + protected void setup() { + serviceBeans.put("hdl", handlenetService); + serviceBeans.put("doi", getDoiProvider()); + } + + /** + * @deprecated for use by EJB proxy only. + */ + public GlobalIdServiceBeanResolver() { + } + + @Inject + public GlobalIdServiceBeanResolver(SettingsServiceBean settingsService, HandlenetServiceBean handlenetService, + DOIEZIdServiceBean doiEZId, DOIDataCiteServiceBean doiDataCite, + FakePidProviderServiceBean fakePidProvider) { + this.handlenetService = handlenetService; + this.settingsService = settingsService; + this.doiEZId = doiEZId; + this.doiDataCite = doiDataCite; + this.fakePidProvider = fakePidProvider; + } + + public GlobalIdServiceBean resolve(String protocol) { + final GlobalIdServiceBean globalIdServiceBean = serviceBeans.get(protocol); + + if (globalIdServiceBean == null) { + log.error("Unknown protocol: {}", protocol); + return null; + } + + return globalIdServiceBean; + } + + public GlobalIdServiceBean resolve() { + return resolve(settingsService.getValueForKey(SettingsServiceBean.Key.Protocol)); + } + + private GlobalIdServiceBean getDoiProvider() { + String doiProvider = settingsService.getValueForKey(SettingsServiceBean.Key.DoiProvider); + switch (doiProvider) { + case "EZID": + return doiEZId; + case "DataCite": + return doiDataCite; + case "FAKE": + return fakePidProvider; + default: + log.error("Unknown doiProvider: {}", doiProvider); + return null; + } + } +} diff --git a/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java b/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java index 2fafa7d1a36..2daf8ce3a4b 100644 --- a/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java +++ b/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/engine/TestCommandContext.java @@ -29,6 +29,7 @@ import edu.harvard.iq.dataverse.globalid.DOIDataCiteServiceBean; import edu.harvard.iq.dataverse.globalid.DOIEZIdServiceBean; import edu.harvard.iq.dataverse.globalid.FakePidProviderServiceBean; +import edu.harvard.iq.dataverse.globalid.GlobalIdServiceBeanResolver; import edu.harvard.iq.dataverse.globalid.HandlenetServiceBean; import edu.harvard.iq.dataverse.guestbook.GuestbookResponseServiceBean; import edu.harvard.iq.dataverse.guestbook.GuestbookServiceBean; @@ -287,4 +288,9 @@ public DownloadDatasetLogDao downloadDatasetDao() { public DatasetFieldValidationService fieldValidationService() { return null; } + + @Override + public GlobalIdServiceBeanResolver globalIdServiceBeanResolver() { + return null; + } } diff --git a/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterServiceTest.java b/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterServiceTest.java index c67056a7bf9..34552d11d02 100644 --- a/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterServiceTest.java +++ b/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/DOIDataCiteRegisterServiceTest.java @@ -225,6 +225,7 @@ void getMetadataForDeactivateIdentifier() { " xmlns=\"http://datacite.org/schema/kernel-4\"" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "Testid" + + ":unav" + "" + "This item has been removed from publication" + "" + diff --git a/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanTest.java b/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanTest.java index afab4fb5721..721101eb599 100644 --- a/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanTest.java +++ b/dataverse-webapp/src/test/java/edu/harvard/iq/dataverse/globalid/GlobalIdServiceBeanTest.java @@ -26,25 +26,11 @@ public class GlobalIdServiceBeanTest { public void setup() { ctxt = new TestCommandContext() { @Override - public HandlenetServiceBean handleNet() { - return hdlServiceBean; + public GlobalIdServiceBeanResolver globalIdServiceBeanResolver() { + GlobalIdServiceBeanResolver resolver = new GlobalIdServiceBeanResolver(settings(), hdlServiceBean, ezidServiceBean, dataCiteServiceBean, fakePidProviderServiceBean); + resolver.setup(); + return resolver; } - - @Override - public DOIDataCiteServiceBean doiDataCite() { - return dataCiteServiceBean; - } - - @Override - public DOIEZIdServiceBean doiEZId() { - return ezidServiceBean; - } - - @Override - public FakePidProviderServiceBean fakePidProvider() { - return fakePidProviderServiceBean; - } - }; }