diff --git a/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/DisassociateDisposalHoldRequest.java b/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/DisassociateDisposalHoldRequest.java new file mode 100644 index 0000000000..c845be6b85 --- /dev/null +++ b/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/DisassociateDisposalHoldRequest.java @@ -0,0 +1,48 @@ +package org.roda.core.data.v2.ip.disposalhold; + +/** + * @author Miguel Guimarães + */ + +import java.io.Serial; +import java.io.Serializable; + +import org.roda.core.data.v2.generics.select.SelectedItemsRequest; + +public class DisassociateDisposalHoldRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 1324253414733503493L; + + private SelectedItemsRequest selectedItems; + private String details; + private boolean clear; + + public DisassociateDisposalHoldRequest() { + // empty constructor + } + + public SelectedItemsRequest getSelectedItems() { + return selectedItems; + } + + public void setSelectedItems(SelectedItemsRequest selectedItems) { + this.selectedItems = selectedItems; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } + + public boolean getClear() { + return clear; + } + + public void setClear(boolean clear) { + this.clear = clear; + } +} diff --git a/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/LiftDisposalHoldRequest.java b/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/LiftDisposalHoldRequest.java new file mode 100644 index 0000000000..35ce0f4636 --- /dev/null +++ b/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/LiftDisposalHoldRequest.java @@ -0,0 +1,39 @@ +package org.roda.core.data.v2.ip.disposalhold; + +/** + * @author Miguel Guimarães + */ + +import java.io.Serial; +import java.io.Serializable; + +import org.roda.core.data.v2.generics.select.SelectedItemsRequest; + +public class LiftDisposalHoldRequest implements Serializable { + + @Serial + private static final long serialVersionUID = -6983980156805237858L; + + private SelectedItemsRequest selectedItems; + private String details; + + public LiftDisposalHoldRequest() { + // empty constructor + } + + public SelectedItemsRequest getSelectedItems() { + return selectedItems; + } + + public void setSelectedItems(SelectedItemsRequest selectedItems) { + this.selectedItems = selectedItems; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } +} diff --git a/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/UpdateDisposalHoldRequest.java b/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/UpdateDisposalHoldRequest.java new file mode 100644 index 0000000000..a1a7ac03f3 --- /dev/null +++ b/roda-common/roda-common-data/src/main/java/org/roda/core/data/v2/ip/disposalhold/UpdateDisposalHoldRequest.java @@ -0,0 +1,39 @@ +package org.roda.core.data.v2.ip.disposalhold; + +/** + * @author Miguel Guimarães + */ + +import java.io.Serial; +import java.io.Serializable; + +import org.roda.core.data.v2.disposal.hold.DisposalHold; + +public class UpdateDisposalHoldRequest implements Serializable { + + @Serial + private static final long serialVersionUID = 3125581525913041977L; + + private DisposalHold disposalHold; + private String details; + + public UpdateDisposalHoldRequest() { + // empty constructor + } + + public DisposalHold getDisposalHold() { + return disposalHold; + } + + public void setDisposalHold(DisposalHold disposalHold) { + this.disposalHold = disposalHold; + } + + public String getDetails() { + return details; + } + + public void setDetails(String details) { + this.details = details; + } +} diff --git a/roda-core/roda-core/src/main/java/org/roda/core/model/ModelService.java b/roda-core/roda-core/src/main/java/org/roda/core/model/ModelService.java index dd22394ea5..e068fbd6db 100644 --- a/roda-core/roda-core/src/main/java/org/roda/core/model/ModelService.java +++ b/roda-core/roda-core/src/main/java/org/roda/core/model/ModelService.java @@ -3747,16 +3747,17 @@ public DisposalHold createDisposalHold(DisposalHold disposalHold, String created public DisposalHold updateDisposalHoldFirstUseDate(DisposalHold disposalHold, String updatedBy) throws AuthorizationDeniedException, RequestNotValidException, NotFoundException, IllegalOperationException, GenericException { - return updateDisposalHold(disposalHold, updatedBy, true); + return updateDisposalHold(disposalHold, updatedBy, true, null); } - public DisposalHold updateDisposalHold(DisposalHold disposalHold, String updatedBy) + public DisposalHold updateDisposalHold(DisposalHold disposalHold, String updatedBy, String details) throws AuthorizationDeniedException, RequestNotValidException, NotFoundException, IllegalOperationException, GenericException { - return updateDisposalHold(disposalHold, updatedBy, false); + return updateDisposalHold(disposalHold, updatedBy, false, details); } - public DisposalHold updateDisposalHold(DisposalHold disposalHold, String updatedBy, boolean updateFirstUseDate) + public DisposalHold updateDisposalHold(DisposalHold disposalHold, String updatedBy, boolean updateFirstUseDate, + String details) throws RequestNotValidException, NotFoundException, GenericException, AuthorizationDeniedException, IllegalOperationException { RodaCoreFactory.checkIfWriteIsAllowedAndIfFalseThrowException(nodeType); @@ -3787,6 +3788,9 @@ public DisposalHold updateDisposalHold(DisposalHold disposalHold, String updated storage.updateBinaryContent(disposalHoldPath, new StringContentPayload(disposalHoldAsJson), false, true); + createRepositoryEvent(PreservationEventType.UPDATE, "Update disposal hold", PluginState.SUCCESS, "", details, "", + true); + return currentDisposalHold; } diff --git a/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisassociateDisposalHoldFromAIPPlugin.java b/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisassociateDisposalHoldFromAIPPlugin.java index a83e2c4f37..08ce89cbb7 100644 --- a/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisassociateDisposalHoldFromAIPPlugin.java +++ b/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisassociateDisposalHoldFromAIPPlugin.java @@ -13,19 +13,16 @@ import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; import org.roda.core.data.common.RodaConstants; import org.roda.core.data.exceptions.AlreadyExistsException; import org.roda.core.data.exceptions.AuthorizationDeniedException; import org.roda.core.data.exceptions.GenericException; -import org.roda.core.data.exceptions.IllegalOperationException; import org.roda.core.data.exceptions.InvalidParameterException; import org.roda.core.data.exceptions.NotFoundException; import org.roda.core.data.exceptions.RequestNotValidException; import org.roda.core.data.v2.LiteOptionalWithCause; +import org.roda.core.data.v2.common.Pair; import org.roda.core.data.v2.disposal.hold.DisposalHold; -import org.roda.core.data.v2.disposal.hold.DisposalHoldState; -import org.roda.core.data.v2.disposal.metadata.DisposalHoldAIPMetadata; import org.roda.core.data.v2.ip.AIP; import org.roda.core.data.v2.ip.IndexedAIP; import org.roda.core.data.v2.jobs.Job; @@ -65,10 +62,16 @@ public class DisassociateDisposalHoldFromAIPPlugin extends AbstractPlugin { "Disassociate all holds", PluginParameter.PluginParameterType.BOOLEAN).withDefaultValue("false") .isMandatory(true).isReadOnly(false).withDescription("Disassociate all disposal holds associated to AIP") .build()); + + pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, + PluginParameter + .getBuilder(RodaConstants.PLUGIN_PARAMS_DETAILS, "Details", PluginParameter.PluginParameterType.STRING) + .isMandatory(false).withDescription("Details that will be used when creating event").build()); } private String disposalHoldId; private boolean clearAll; + private String details; public static String getStaticName() { return "Disassociate disposal hold from AIP"; @@ -83,6 +86,7 @@ public List getParameters() { ArrayList parameters = new ArrayList<>(); parameters.add(pluginParameters.get(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID)); parameters.add(pluginParameters.get(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_DISASSOCIATE_ALL)); + parameters.add(pluginParameters.get(RodaConstants.PLUGIN_PARAMS_DETAILS)); return parameters; } @@ -97,6 +101,10 @@ public void setParameterValues(Map parameters) throws InvalidPar if (parameters.containsKey(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_DISASSOCIATE_ALL)) { clearAll = Boolean.parseBoolean(parameters.get(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_DISASSOCIATE_ALL)); } + + if (parameters.containsKey(RodaConstants.PLUGIN_PARAMS_DETAILS)) { + details = parameters.get(RodaConstants.PLUGIN_PARAMS_DETAILS); + } } @Override @@ -184,6 +192,8 @@ public void process(IndexService index, ModelService model, StorageService stora private void processAIP(IndexService index, ModelService model, Report report, Job cachedJob, JobPluginInfo jobPluginInfo, List aips) { + report.addPluginDetails(details); + for (AIP aip : aips) { String outcomeText; PluginState state = PluginState.SUCCESS; @@ -195,12 +205,12 @@ private void processAIP(IndexService index, ModelService model, Report report, J try { // lift disposal holds if (aip.getHolds() != null && !aip.getHolds().isEmpty()) { - List holds = new ArrayList<>(aip.getHolds()); outcomeText = "Cannot found any active direct disposal hold for disassociate from AIP : " + aip.getId(); boolean hasAtLeastOneDirectHold = false; for (DisposalHold hold : model.retrieveDirectActiveDisposalHolds(aip.getId())) { hasAtLeastOneDirectHold = true; - outcomeText = DisposalHoldPluginUtils.disassociateDisposalHoldFromAIP(hold.getId(), aip, reportItem); + outcomeText = DisposalHoldPluginUtils.disassociateDisposalHoldFromAIP(hold.getId(), aip, reportItem) + .getSecond(); processTransitiveAIP(model, index, cachedJob, aip, hold.getId(), jobPluginInfo, report); } @@ -233,10 +243,17 @@ private void processAIP(IndexService index, ModelService model, Report report, J } } else { try { - outcomeText = DisposalHoldPluginUtils.liftDisposalHoldFromAIP(aip, disposalHoldId, reportItem); + Pair outcome = DisposalHoldPluginUtils.disassociateDisposalHoldFromAIP(disposalHoldId, aip, + reportItem); + boolean lifted = outcome.getFirst(); + outcomeText = outcome.getSecond(); processTransitiveAIP(model, index, cachedJob, aip, disposalHoldId, jobPluginInfo, report); model.updateAIP(aip, cachedJob.getUsername()); - jobPluginInfo.incrementObjectsProcessedWithSuccess(); + if (lifted) { + jobPluginInfo.incrementObjectsProcessedWithSuccess(); + } else { + jobPluginInfo.incrementObjectsProcessedWithSkipped(); + } reportItem.setPluginState(state); } catch (GenericException | NotFoundException | RequestNotValidException | AuthorizationDeniedException e) { outcomeText = "Error lifting disposal hold" + disposalHoldId + " from AIP " + aip.getId(); @@ -260,17 +277,6 @@ private void processAIP(IndexService index, ModelService model, Report report, J LOGGER.error("Error creating event: {}", e.getMessage(), e); } } - - if (StringUtils.isNotBlank(disposalHoldId)) { - try { - DisposalHold disposalHold = model.retrieveDisposalHold(disposalHoldId); - disposalHold.setState(DisposalHoldState.LIFTED); - model.updateDisposalHold(disposalHold, cachedJob.getUsername()); - } catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException - | IllegalOperationException e) { - LOGGER.error("Unable to update disposal hold {}: {}", disposalHoldId, e.getMessage(), e); - } - } } private void processTransitiveAIP(ModelService model, IndexService index, Job cachedJob, AIP aip, String holdId, diff --git a/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisposalHoldPluginUtils.java b/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisposalHoldPluginUtils.java index eba01ecc36..dec9b5a2c9 100644 --- a/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisposalHoldPluginUtils.java +++ b/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/DisposalHoldPluginUtils.java @@ -19,11 +19,12 @@ import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.exceptions.NotFoundException; import org.roda.core.data.exceptions.RequestNotValidException; +import org.roda.core.data.v2.common.Pair; +import org.roda.core.data.v2.disposal.hold.DisposalHold; +import org.roda.core.data.v2.disposal.hold.DisposalHoldState; import org.roda.core.data.v2.disposal.metadata.DisposalAIPMetadata; import org.roda.core.data.v2.disposal.metadata.DisposalHoldAIPMetadata; import org.roda.core.data.v2.disposal.metadata.DisposalTransitiveHoldAIPMetadata; -import org.roda.core.data.v2.disposal.hold.DisposalHold; -import org.roda.core.data.v2.disposal.hold.DisposalHoldState; import org.roda.core.data.v2.index.filter.Filter; import org.roda.core.data.v2.index.filter.FilterParameter; import org.roda.core.data.v2.index.filter.OrFiltersParameters; @@ -80,21 +81,6 @@ public static void addTransitiveDisposalHoldAIPMetadata(AIP aip, String disposal disposalTransitiveHoldAIPMetadata.addFromAip(fromAIP); } - public static String liftDisposalHoldFromAIP(AIP aip, String disposalHoldId, Report reportItem) { - String outcomeLiftText = "Cannot find disposal hold " + disposalHoldId + " on AIP " + aip.getId(); - DisposalAIPMetadata disposal = aip.getDisposal(); - if (disposal != null) { - List holds = disposal.getHolds(); - for (DisposalHoldAIPMetadata hold : new ArrayList<>(holds)) { - if (disposalHoldId.equals(hold.getId())) { - outcomeLiftText = liftHold(hold, disposal, aip.getId(), reportItem); - break; - } - } - } - return outcomeLiftText; - } - public static String liftTransitiveDisposalHoldFromAIP(AIP aip, String disposalHoldId, Report reportItem) { DisposalAIPMetadata disposal = aip.getDisposal(); String outcomeLiftText = "Cannot find transitive disposal hold " + disposalHoldId + " on AIP " + aip.getId(); @@ -115,21 +101,26 @@ public static void disassociateAllDisposalHoldsFromAIP(ModelService model, Plugi DisposalAIPMetadata disposal = aip.getDisposal(); if (disposal != null) { for (DisposalHoldAIPMetadata disposalHoldAIPMetadata : new ArrayList<>(disposal.getHolds())) { - String outcomeLiftText = disassociateDisposalHoldFromAIP(disposalHoldAIPMetadata.getId(), aip, reportItem); + String outcomeLiftText = disassociateDisposalHoldFromAIP(disposalHoldAIPMetadata.getId(), aip, reportItem) + .getSecond(); model.createEvent(aip.getId(), null, null, null, POLICY_ASSIGNMENT, LiftDisposalHoldPlugin.getStaticName(), null, null, state, outcomeLiftText, "", cachedJob.getUsername(), true); } } } - public static String disassociateDisposalHoldFromAIP(String disposalHoldAIPMetadataID, AIP aip, Report reportItem) { + public static Pair disassociateDisposalHoldFromAIP(String disposalHoldAIPMetadataID, AIP aip, + Report reportItem) { + boolean lifted; String outcomeLiftText; DisposalHold disposalHold = RodaCoreFactory.getDisposalHold(disposalHoldAIPMetadataID); - if (disposalHold.getState().equals(DisposalHoldState.LIFTED)) { + if (disposalHold != null && disposalHold.getState().equals(DisposalHoldState.LIFTED)) { + lifted = false; outcomeLiftText = "Disposal hold '" + disposalHoldAIPMetadataID + "' is lifted and cannot be disassociated from aip '" + aip.getId() + "'"; } else { aip.removeDisposalHold(disposalHoldAIPMetadataID); + lifted = true; if (disposalHold == null) { outcomeLiftText = "Disposal hold '" + disposalHoldAIPMetadataID + "' was successfully disassociated from AIP '" + aip.getId() + "'"; @@ -142,7 +133,7 @@ public static String disassociateDisposalHoldFromAIP(String disposalHoldAIPMetad + ") was successfully disassociated from AIP\n"); } } - return outcomeLiftText; + return new Pair<>(lifted, outcomeLiftText); } public static String disassociateTransitiveDisposalHoldFromAIP(String disposalHoldAIPMetadataID, AIP aip, @@ -188,26 +179,6 @@ private static String liftTransitiveHold(DisposalTransitiveHoldAIPMetadata trans return outcomeLiftText; } - private static String liftHold(DisposalHoldAIPMetadata disposalHold, DisposalAIPMetadata disposal, String aipId, - Report reportItem) { - - // disposal.getHolds().remove(disposalHold); - DisposalHold liftedHold = RodaCoreFactory.getDisposalHold(disposalHold.getId()); - String outcomeLiftText; - if (liftedHold == null) { - outcomeLiftText = "Disposal hold '" + disposalHold.getId() + "' was successfully lifted from AIP '" + aipId + "'"; - reportItem.addPluginDetails( - "Disposal hold '" + disposalHold.getId() + "' was successfully lifted from AIP '" + aipId + "'"); - } else { - outcomeLiftText = "Disposal hold '" + liftedHold.getTitle() + "' (" + liftedHold.getId() - + ") was successfully lifted from AIP '" + aipId + "'"; - reportItem.addPluginDetails("Disposal hold '" + liftedHold.getTitle() + "' (" + liftedHold.getId() - + ") was successfully lifted from AIP '" + aipId + "'"); - } - - return outcomeLiftText; - } - public static IterableIndexResult getTransitivesHoldsAIPs(IndexService index, String aipId) throws NotFoundException, GenericException, RequestNotValidException { final IndexedAIP indexedAip = index.retrieve(IndexedAIP.class, aipId, new ArrayList<>()); diff --git a/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/LiftDisposalHoldPlugin.java b/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/LiftDisposalHoldPlugin.java index d8f7686e93..d1d45c1ffd 100644 --- a/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/LiftDisposalHoldPlugin.java +++ b/roda-core/roda-core/src/main/java/org/roda/core/plugins/base/disposal/hold/LiftDisposalHoldPlugin.java @@ -24,6 +24,7 @@ import org.roda.core.data.exceptions.NotFoundException; import org.roda.core.data.exceptions.RequestNotValidException; import org.roda.core.data.v2.LiteOptionalWithCause; +import org.roda.core.data.v2.common.Pair; import org.roda.core.data.v2.disposal.hold.DisposalHold; import org.roda.core.data.v2.disposal.hold.DisposalHoldState; import org.roda.core.data.v2.ip.AIP; @@ -54,6 +55,7 @@ public class LiftDisposalHoldPlugin extends AbstractPlugin { private static final Logger LOGGER = LoggerFactory.getLogger(LiftDisposalHoldPlugin.class); private String disposalHoldId; + private String details; private static final Map pluginParameters = new HashMap<>(); @@ -62,12 +64,18 @@ public class LiftDisposalHoldPlugin extends AbstractPlugin { PluginParameter.getBuilder(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID, "Disposal hold id", PluginParameter.PluginParameterType.STRING).isMandatory(true).isReadOnly(false) .withDescription("Disposal hold identifier").build()); + + pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, + PluginParameter + .getBuilder(RodaConstants.PLUGIN_PARAMS_DETAILS, "Details", PluginParameter.PluginParameterType.STRING) + .isMandatory(false).withDescription("Details that will be used when creating event").build()); } @Override public List getParameters() { ArrayList parameters = new ArrayList<>(); parameters.add(pluginParameters.get(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID)); + parameters.add(pluginParameters.get(RodaConstants.PLUGIN_PARAMS_DETAILS)); return parameters; } @@ -78,6 +86,10 @@ public void setParameterValues(Map parameters) throws InvalidPar if (parameters.containsKey(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID)) { disposalHoldId = parameters.get(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID); } + + if (parameters.containsKey(RodaConstants.PLUGIN_PARAMS_DETAILS)) { + details = parameters.get(RodaConstants.PLUGIN_PARAMS_DETAILS); + } } @Override @@ -148,6 +160,7 @@ public void process(IndexService index, ModelService model, StorageService stora private void processAIP(IndexService index, ModelService model, Report report, Job cachedJob, JobPluginInfo jobPluginInfo, List aips) { + report.addPluginDetails(details); if (StringUtils.isNotBlank(disposalHoldId)) { try { @@ -155,7 +168,7 @@ private void processAIP(IndexService index, ModelService model, Report report, J disposalHold.setState(DisposalHoldState.LIFTED); disposalHold.setLiftedBy(cachedJob.getUsername()); disposalHold.setLiftedOn(new Date()); - model.updateDisposalHold(disposalHold, cachedJob.getUsername()); + model.updateDisposalHold(disposalHold, cachedJob.getUsername(), details); } catch (RequestNotValidException | NotFoundException | GenericException | AuthorizationDeniedException | IllegalOperationException e) { LOGGER.error("Unable to update disposal hold {}: {}", disposalHoldId, e.getMessage(), e); @@ -170,10 +183,17 @@ private void processAIP(IndexService index, ModelService model, Report report, J LOGGER.debug("Processing AIP {}", aip.getId()); try { - outcomeText = DisposalHoldPluginUtils.liftDisposalHoldFromAIP(aip, disposalHoldId, reportItem); + Pair outcome = DisposalHoldPluginUtils.disassociateDisposalHoldFromAIP(disposalHoldId, aip, + reportItem); + boolean lifted = outcome.getFirst(); + outcomeText = outcome.getSecond(); processTransitiveAIP(model, index, cachedJob, aip, disposalHoldId, jobPluginInfo, report); model.updateAIP(aip, cachedJob.getUsername()); - jobPluginInfo.incrementObjectsProcessedWithSuccess(); + if (lifted) { + jobPluginInfo.incrementObjectsProcessedWithSuccess(); + } else { + jobPluginInfo.incrementObjectsProcessedWithSkipped(); + } reportItem.setPluginState(state); } catch (GenericException | NotFoundException | RequestNotValidException | AuthorizationDeniedException e) { outcomeText = "Error lifting disposal hold" + disposalHoldId + " from AIP " + aip.getId(); diff --git a/roda-core/roda-core/src/main/resources/config/roda-roles.properties b/roda-core/roda-core/src/main/resources/config/roda-roles.properties index 900294a807..5fcd22fd21 100644 --- a/roda-core/roda-core/src/main/resources/config/roda-roles.properties +++ b/roda-core/roda-core/src/main/resources/config/roda-roles.properties @@ -129,7 +129,7 @@ core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.createDisposalH core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.retrieveDisposalHold = disposal_hold.read core.roles.org.roda.wui.api.v2.controller.DisposalRuleController.updateDisposalRule = disposal_hold.manage core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.applyDisposalHold = disposal_hold.apply -core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.liftDisposalHoldBySelectedItems = disposal_hold.apply +core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.liftDisposalHold=disposal_hold.apply core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.disassociateDisposalHold = disposal_hold.apply core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.listTransitiveHolds = disposal_hold.read core.roles.org.roda.wui.api.v2.controller.DisposalHoldController.listDisposalHoldsAssociation = disposal_hold.read diff --git a/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java b/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java index d276a6fa85..22145429b8 100644 --- a/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java +++ b/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java @@ -2149,6 +2149,10 @@ SafeHtml representationInformationAssociatedWithDescription(String field, String String clearDisposalHoldDialogMessage(@PluralCount int size); + String liftDisposalHoldDialogTitle(); + + String liftDisposalHoldDialogMessage(@PluralCount int size); + String disassociateDisposalHoldDialogTitle(); String disassociateDisposalHoldDialogMessage(@PluralCount int size); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/DisposalHoldController.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/DisposalHoldController.java index a1b2fbcfe5..433d565f77 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/DisposalHoldController.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/controller/DisposalHoldController.java @@ -20,6 +20,8 @@ import org.roda.core.data.v2.disposal.metadata.DisposalTransitiveHoldsAIPMetadata; import org.roda.core.data.v2.generics.select.SelectedItemsRequest; import org.roda.core.data.v2.ip.IndexedAIP; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; +import org.roda.core.data.v2.ip.disposalhold.UpdateDisposalHoldRequest; import org.roda.core.data.v2.jobs.Job; import org.roda.core.data.v2.log.LogEntryState; import org.roda.wui.api.v2.exceptions.RESTException; @@ -75,10 +77,11 @@ public DisposalHolds listDisposalHolds() { } @Override - public DisposalHold updateDisposalHold(@RequestBody DisposalHold hold) { + public DisposalHold updateDisposalHold(@RequestBody UpdateDisposalHoldRequest updateDisposalHoldRequest) { final ControllerAssistant controllerAssistant = new ControllerAssistant() {}; RequestContext requestContext = RequestUtils.parseHTTPRequest(request); LogEntryState state = LogEntryState.SUCCESS; + DisposalHold hold = updateDisposalHoldRequest.getDisposalHold(); try { // check user permissions controllerAssistant.checkRoles(requestContext.getUser()); @@ -88,7 +91,8 @@ public DisposalHold updateDisposalHold(@RequestBody DisposalHold hold) { hold = JsonUtils.getObjectFromJson(sanitize, DisposalHold.class); // delegate action to service - return disposalHoldService.updateDisposalHold(hold, requestContext.getUser()); + return disposalHoldService.updateDisposalHold(hold, requestContext.getUser(), + updateDisposalHoldRequest.getDetails()); } catch (AuthorizationDeniedException e) { state = LogEntryState.UNAUTHORIZED; throw new RESTException(e); @@ -183,32 +187,7 @@ public Job applyDisposalHold(@RequestBody SelectedItemsRequest items, String dis } @Override - public Job liftDisposalHoldBySelectedItems(@RequestBody SelectedItemsRequest items, String disposalHoldId) { - final ControllerAssistant controllerAssistant = new ControllerAssistant() {}; - RequestContext requestContext = RequestUtils.parseHTTPRequest(request); - LogEntryState state = LogEntryState.SUCCESS; - - try { - // check user permissions - controllerAssistant.checkRoles(requestContext.getUser()); - // delegate - return disposalHoldService.liftDisposalHold(requestContext.getUser(), - CommonServicesUtils.convertSelectedItems(items, IndexedAIP.class), disposalHoldId); - } catch (AuthorizationDeniedException e) { - state = LogEntryState.UNAUTHORIZED; - throw new RESTException(e); - } catch (GenericException | NotFoundException | RequestNotValidException e) { - state = LogEntryState.FAILURE; - throw new RESTException(e); - } finally { - // register action - controllerAssistant.registerAction(requestContext, state, RodaConstants.CONTROLLER_SELECTED_PARAM, items, - RodaConstants.CONTROLLER_DISPOSAL_HOLD_ID_PARAM, disposalHoldId); - } - } - - @Override - public DisposalHold liftDisposalHold(String id) { + public DisposalHold liftDisposalHold(String id, String details) { final ControllerAssistant controllerAssistant = new ControllerAssistant() {}; RequestContext requestContext = RequestUtils.parseHTTPRequest(request); LogEntryState state = LogEntryState.SUCCESS; @@ -223,7 +202,7 @@ public DisposalHold liftDisposalHold(String id) { disposalHold.setLiftedBy(requestContext.getUser().getName()); disposalHold.setLiftedOn(new Date()); // delegate - return disposalHoldService.updateDisposalHold(disposalHold, requestContext.getUser()); + return disposalHoldService.updateDisposalHold(disposalHold, requestContext.getUser(), details); } catch (AuthorizationDeniedException e) { state = LogEntryState.UNAUTHORIZED; throw new RESTException(e); @@ -238,7 +217,8 @@ public DisposalHold liftDisposalHold(String id) { } @Override - public Job disassociateDisposalHold(@RequestBody SelectedItemsRequest items, String disposalHoldId, boolean clear) { + public Job disassociateDisposalHold(@RequestBody DisassociateDisposalHoldRequest disassociateDisposalHoldRequest, + String disposalHoldId) { final ControllerAssistant controllerAssistant = new ControllerAssistant() {}; RequestContext requestContext = RequestUtils.parseHTTPRequest(request); LogEntryState state = LogEntryState.SUCCESS; @@ -247,8 +227,8 @@ public Job disassociateDisposalHold(@RequestBody SelectedItemsRequest items, Str // check user permissions controllerAssistant.checkRoles(requestContext.getUser()); // delegate - return disposalHoldService.disassociateDisposalHold(requestContext.getUser(), - CommonServicesUtils.convertSelectedItems(items, IndexedAIP.class), disposalHoldId, clear); + return disposalHoldService.disassociateDisposalHold(requestContext.getUser(), disassociateDisposalHoldRequest, + disposalHoldId); } catch (AuthorizationDeniedException e) { state = LogEntryState.UNAUTHORIZED; throw new RESTException(e); @@ -257,9 +237,10 @@ public Job disassociateDisposalHold(@RequestBody SelectedItemsRequest items, Str throw new RESTException(e); } finally { // register action - controllerAssistant.registerAction(requestContext, state, RodaConstants.CONTROLLER_SELECTED_PARAM, items, + controllerAssistant.registerAction(requestContext, state, RodaConstants.CONTROLLER_SELECTED_PARAM, + disassociateDisposalHoldRequest.getSelectedItems(), RodaConstants.CONTROLLER_DISPOSAL_HOLD_ID_PARAM, disposalHoldId, - RodaConstants.CONTROLLER_DISPOSAL_HOLD_DISASSOCIATE_ALL, clear); + RodaConstants.CONTROLLER_DISPOSAL_HOLD_DISASSOCIATE_ALL, disassociateDisposalHoldRequest.getClear()); } } diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/services/DisposalHoldService.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/services/DisposalHoldService.java index 7cc56cbee9..07e530e9ae 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/services/DisposalHoldService.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/api/v2/services/DisposalHoldService.java @@ -13,11 +13,13 @@ import org.roda.core.data.exceptions.IllegalOperationException; import org.roda.core.data.exceptions.NotFoundException; import org.roda.core.data.exceptions.RequestNotValidException; -import org.roda.core.data.v2.disposal.metadata.DisposalTransitiveHoldsAIPMetadata; import org.roda.core.data.v2.disposal.hold.DisposalHold; import org.roda.core.data.v2.disposal.hold.DisposalHolds; +import org.roda.core.data.v2.disposal.metadata.DisposalTransitiveHoldsAIPMetadata; import org.roda.core.data.v2.index.select.SelectedItems; import org.roda.core.data.v2.ip.IndexedAIP; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; +import org.roda.core.data.v2.ip.disposalhold.LiftDisposalHoldRequest; import org.roda.core.data.v2.jobs.Job; import org.roda.core.data.v2.user.User; import org.roda.core.plugins.base.disposal.hold.ApplyDisposalHoldToAIPPlugin; @@ -38,9 +40,10 @@ public DisposalHolds getDisposalHolds() return RodaCoreFactory.getModelService().listDisposalHolds(); } - public DisposalHold updateDisposalHold(DisposalHold hold, User user) throws AuthorizationDeniedException, + public DisposalHold updateDisposalHold(DisposalHold hold, User user, String details) + throws AuthorizationDeniedException, RequestNotValidException, NotFoundException, IllegalOperationException, GenericException { - return RodaCoreFactory.getModelService().updateDisposalHold(hold, user.getName()); + return RodaCoreFactory.getModelService().updateDisposalHold(hold, user.getName(), details); } public DisposalHold createDisposalHold(DisposalHold disposalHold, User user) throws GenericException, @@ -73,22 +76,28 @@ public Job applyDisposalHold(User user, SelectedItems items, String ApplyDisposalHoldToAIPPlugin.class, user, pluginParameters, "Could not execute apply disposal hold action"); } - public Job liftDisposalHold(User user, SelectedItems items, String disposalHoldId) + public Job liftDisposalHold(User user, LiftDisposalHoldRequest request, String disposalHoldId) throws NotFoundException, AuthorizationDeniedException, GenericException, RequestNotValidException { Map pluginParameters = new HashMap<>(); pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID, disposalHoldId); + pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, request.getDetails()); + SelectedItems items = CommonServicesUtils.convertSelectedItems(request.getSelectedItems(), + IndexedAIP.class); return CommonServicesUtils.createAndExecuteInternalJob("Lift disposal hold", items, LiftDisposalHoldPlugin.class, user, pluginParameters, "Could not execute lift disposal hold action"); } - public Job disassociateDisposalHold(User user, SelectedItems items, String disposalHoldId, - boolean clearAll) + public Job disassociateDisposalHold(User user, DisassociateDisposalHoldRequest request, String disposalHoldId) throws NotFoundException, AuthorizationDeniedException, GenericException, RequestNotValidException { Map pluginParameters = new HashMap<>(); pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_ID, disposalHoldId); - pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_DISASSOCIATE_ALL, Boolean.toString(clearAll)); + pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DISPOSAL_HOLD_DISASSOCIATE_ALL, + Boolean.toString(request.getClear())); + pluginParameters.put(RodaConstants.PLUGIN_PARAMS_DETAILS, request.getDetails()); + SelectedItems items = CommonServicesUtils.convertSelectedItems(request.getSelectedItems(), + IndexedAIP.class); return CommonServicesUtils.createAndExecuteInternalJob("Disassociate disposal hold", items, DisassociateDisposalHoldFromAIPPlugin.class, user, pluginParameters, "Could not execute disassociate disposal hold action"); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/AipActions.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/AipActions.java index 2cce5e99a7..3f0dc9551d 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/AipActions.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/AipActions.java @@ -32,6 +32,7 @@ import org.roda.core.data.v2.ip.AIPState; import org.roda.core.data.v2.ip.IndexedAIP; import org.roda.core.data.v2.ip.Permissions; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; import org.roda.core.data.v2.representation.ChangeTypeRequest; import org.roda.wui.client.browse.CreateDescriptiveMetadata; import org.roda.wui.client.browse.EditPermissions; @@ -967,37 +968,52 @@ private void clearDisposalHolds(final SelectedItems aips, final Long @Override public void onSuccess(Boolean result) { if (result) { - Services services = new Services("Disassociate disposal holds", "job"); - services - .disposalHoldResource( - s -> s.disassociateDisposalHold(SelectedItemsUtils.convertToRESTRequest(aips), null, true)) - .whenComplete((job, throwable) -> { - if (throwable != null) { - callback.onFailure(throwable); - HistoryUtils.newHistory(InternalProcess.RESOLVER); - } else { - Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - Toast.showInfo(messages.runningInBackgroundTitle(), messages.runningInBackgroundDescription()); - - Timer timer = new Timer() { - @Override - public void run() { - doActionCallbackUpdated(); - } - }; - - timer.schedule(RodaConstants.ACTION_TIMEOUT); - } + Dialogs.showPromptDialog(messages.outcomeDetailTitle(), null, null, messages.outcomeDetailPlaceholder(), + RegExp.compile(".*"), messages.cancelButton(), messages.confirmButton(), false, false, + new ActionNoAsyncCallback(callback) { + @Override + public void onFailure(Throwable caught) { + // do nothing + } - @Override - public void onSuccess(final Void nothing) { - doActionCallbackNone(); - HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); - } - }); + @Override + public void onSuccess(String details) { + DisassociateDisposalHoldRequest request = new DisassociateDisposalHoldRequest(); + request.setSelectedItems(SelectedItemsUtils.convertToRESTRequest(aips)); + request.setClear(true); + request.setDetails(details); + Services services = new Services("Disassociate disposal holds", "job"); + services.disposalHoldResource(s -> s.disassociateDisposalHold(request, null)) + .whenComplete((job, throwable) -> { + if (throwable != null) { + callback.onFailure(throwable); + HistoryUtils.newHistory(InternalProcess.RESOLVER); + } else { + Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Toast.showInfo(messages.runningInBackgroundTitle(), + messages.runningInBackgroundDescription()); + + Timer timer = new Timer() { + @Override + public void run() { + doActionCallbackUpdated(); + } + }; + + timer.schedule(RodaConstants.ACTION_TIMEOUT); + } + + @Override + public void onSuccess(final Void nothing) { + doActionCallbackNone(); + HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); + } + }); + } + }); } }); } else { diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/DisposalHoldActions.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/DisposalHoldActions.java index 9b7a1c51d2..90cb4779f4 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/DisposalHoldActions.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/DisposalHoldActions.java @@ -17,6 +17,7 @@ import org.roda.core.data.v2.disposal.hold.DisposalHold; import org.roda.core.data.v2.index.select.SelectedItems; import org.roda.core.data.v2.ip.IndexedAIP; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; import org.roda.wui.client.common.actions.callbacks.ActionNoAsyncCallback; import org.roda.wui.client.common.actions.model.ActionableBundle; import org.roda.wui.client.common.actions.model.ActionableGroup; @@ -30,6 +31,7 @@ import org.roda.wui.common.client.widgets.Toast; import com.google.gwt.core.client.GWT; +import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; @@ -103,36 +105,52 @@ public void onSuccess(final Long size) { @Override public void onSuccess(Boolean result) { if (result) { - Services services = new Services("Lift disposal hold", "job"); - services.disposalHoldResource(s -> s.liftDisposalHoldBySelectedItems(SelectedItemsUtils.convertToRESTRequest(aips), disposalHold.getId())) - .whenComplete((job, throwable) -> { - if (throwable != null) { - callback.onFailure(throwable); - HistoryUtils.newHistory(InternalProcess.RESOLVER); - } else { - Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - Toast.showInfo(messages.runningInBackgroundTitle(), - messages.runningInBackgroundDescription()); - - Timer timer = new Timer() { - @Override - public void run() { - doActionCallbackUpdated(); - } - }; - - timer.schedule(RodaConstants.ACTION_TIMEOUT); - } - - @Override - public void onSuccess(final Void nothing) { - doActionCallbackNone(); - HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); - } - }); + Dialogs.showPromptDialog(messages.outcomeDetailTitle(), null, null, messages.outcomeDetailPlaceholder(), + RegExp.compile(".*"), messages.cancelButton(), messages.confirmButton(), false, false, + new ActionNoAsyncCallback(callback) { + @Override + public void onFailure(Throwable caught) { + // do nothing + } + + @Override + public void onSuccess(String details) { + DisassociateDisposalHoldRequest request = new DisassociateDisposalHoldRequest(); + request.setClear(false); + request.setDetails(details); + request.setSelectedItems(SelectedItemsUtils.convertToRESTRequest(aips)); + Services services = new Services("Lift disposal hold", "job"); + services.disposalHoldResource(s -> s.disassociateDisposalHold(request, disposalHold.getId())) + .whenComplete((job, throwable) -> { + if (throwable != null) { + callback.onFailure(throwable); + HistoryUtils.newHistory(InternalProcess.RESOLVER); + } else { + Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Toast.showInfo(messages.runningInBackgroundTitle(), + messages.runningInBackgroundDescription()); + + Timer timer = new Timer() { + @Override + public void run() { + doActionCallbackUpdated(); + } + }; + + timer.schedule(RodaConstants.ACTION_TIMEOUT); + } + + @Override + public void onSuccess(final Void nothing) { + doActionCallbackNone(); + HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); + } + }); + } + }); } }); } else { diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/association/DisposalHoldsPanel.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/association/DisposalHoldsPanel.java index 684cca433c..54d90a851a 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/association/DisposalHoldsPanel.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/association/DisposalHoldsPanel.java @@ -16,9 +16,11 @@ import org.roda.core.data.v2.disposal.hold.DisposalHoldState; import org.roda.core.data.v2.disposal.hold.DisposalHolds; import org.roda.core.data.v2.disposal.metadata.DisposalHoldAIPMetadata; +import org.roda.core.data.v2.generics.select.SelectedItemsRequest; import org.roda.core.data.v2.index.select.SelectedItems; import org.roda.core.data.v2.index.select.SelectedItemsList; import org.roda.core.data.v2.ip.IndexedAIP; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; import org.roda.wui.client.common.NoAsyncCallback; import org.roda.wui.client.common.dialogs.Dialogs; import org.roda.wui.client.common.dialogs.DisposalDialogs; @@ -39,6 +41,7 @@ import com.google.gwt.cell.client.SafeHtmlCell; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.safehtml.shared.SafeHtml; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.uibinder.client.UiBinder; @@ -178,37 +181,64 @@ private void clearDisposalHolds(final SelectedItems aips) { messages.dialogNo(), messages.dialogYes(), new NoAsyncCallback() { @Override public void onSuccess(Boolean result) { - if (result) { - Services services = new Services("Disassociate disposal holds", "job"); - services.disposalHoldResource(s -> s.disassociateDisposalHold(SelectedItemsUtils.convertToRESTRequest(aips), null, true)) - .whenComplete((job, throwable) -> { - if (throwable != null) { - HistoryUtils.newHistory(InternalProcess.RESOLVER); - } else { - Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { + Dialogs.showPromptDialog(messages.outcomeDetailTitle(), null, null, messages.outcomeDetailPlaceholder(), + RegExp.compile(".*"), messages.cancelButton(), messages.confirmButton(), false, false, + new NoAsyncCallback() { + @Override + public void onFailure(Throwable caught) { + Toast.showInfo(messages.runningInBackgroundTitle(), messages.runningInBackgroundDescription()); - @Override - public void onFailure(Throwable caught) { - Toast.showInfo(messages.runningInBackgroundTitle(), messages.runningInBackgroundDescription()); + Timer timer = new Timer() { + @Override + public void run() { + refresh(); + } + }; - Timer timer = new Timer() { - @Override - public void run() { - refresh(); - } - }; - - timer.schedule(RodaConstants.ACTION_TIMEOUT); - } + timer.schedule(RodaConstants.ACTION_TIMEOUT); + } - @Override - public void onSuccess(final Void nothing) { - HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); - } - }); + @Override + public void onSuccess(String details) { + if (result) { + SelectedItemsRequest selectedItemsRequest = SelectedItemsUtils.convertToRESTRequest(aips); + DisassociateDisposalHoldRequest request = new DisassociateDisposalHoldRequest(); + request.setClear(true); + request.setSelectedItems(selectedItemsRequest); + request.setDetails(details); + Services services = new Services("Disassociate disposal holds", "job"); + services.disposalHoldResource(s -> s.disassociateDisposalHold(request, null)) + .whenComplete((job, throwable) -> { + if (throwable != null) { + HistoryUtils.newHistory(InternalProcess.RESOLVER); + } else { + Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Toast.showInfo(messages.runningInBackgroundTitle(), + messages.runningInBackgroundDescription()); + + Timer timer = new Timer() { + @Override + public void run() { + refresh(); + } + }; + + timer.schedule(RodaConstants.ACTION_TIMEOUT); + } + + @Override + public void onSuccess(final Void nothing) { + HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); + } + }); + } + }); } - }); - } + } + }); } }); } diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/EditDisposalHold.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/EditDisposalHold.java index 83a44975db..3b36940fe8 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/EditDisposalHold.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/EditDisposalHold.java @@ -11,6 +11,7 @@ import org.roda.core.data.v2.disposal.hold.DisposalHold; import org.roda.core.data.v2.disposal.hold.DisposalHoldState; +import org.roda.core.data.v2.ip.disposalhold.UpdateDisposalHoldRequest; import org.roda.wui.client.common.UserLogin; import org.roda.wui.client.common.utils.AsyncCallbackUtils; import org.roda.wui.client.common.utils.JavascriptUtils; @@ -118,8 +119,10 @@ void buttonApplyHandler(ClickEvent e) { disposalHold.setMandate(disposalHoldUpdated.getMandate()); disposalHold.setDescription(disposalHoldUpdated.getDescription()); disposalHold.setScopeNotes(disposalHoldUpdated.getScopeNotes()); + UpdateDisposalHoldRequest request = new UpdateDisposalHoldRequest(); + request.setDisposalHold(disposalHold); Services services = new Services("Update disposal hold", "update"); - services.disposalHoldResource(s -> s.updateDisposalHold(disposalHold)).whenComplete((hold, throwable) -> { + services.disposalHoldResource(s -> s.updateDisposalHold(request)).whenComplete((hold, throwable) -> { if (throwable != null) { AsyncCallbackUtils.defaultFailureTreatment(throwable); } else { diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/ShowDisposalHold.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/ShowDisposalHold.java index e5cf7e894f..be4ed5fbbf 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/ShowDisposalHold.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/disposal/hold/ShowDisposalHold.java @@ -11,14 +11,16 @@ import org.roda.core.data.common.RodaConstants; import org.roda.core.data.exceptions.DisposalHoldAlreadyExistsException; -import org.roda.core.data.utils.SelectedItemsUtils; import org.roda.core.data.v2.disposal.hold.DisposalHold; import org.roda.core.data.v2.disposal.hold.DisposalHoldState; +import org.roda.core.data.v2.generics.select.SelectedItemsFilterRequest; +import org.roda.core.data.v2.generics.select.SelectedItemsRequest; import org.roda.core.data.v2.index.CountRequest; import org.roda.core.data.v2.index.filter.Filter; import org.roda.core.data.v2.index.filter.SimpleFilterParameter; -import org.roda.core.data.v2.index.select.SelectedItemsFilter; import org.roda.core.data.v2.ip.IndexedAIP; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; +import org.roda.core.data.v2.ip.disposalhold.UpdateDisposalHoldRequest; import org.roda.wui.client.common.NoAsyncCallback; import org.roda.wui.client.common.TitlePanel; import org.roda.wui.client.common.UserLogin; @@ -44,6 +46,7 @@ import org.roda.wui.common.client.widgets.Toast; import com.google.gwt.core.client.GWT; +import com.google.gwt.regexp.shared.RegExp; import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; @@ -194,6 +197,7 @@ public void initElements() { Label aipTitle = new Label(); aipTitle.addStyleName("h5"); aipTitle.setText(messages.disposalHoldListAips()); + aipListTitle.clear(); aipListTitle.add(aipTitle); aipsListCard.setWidget(aipsSearchWrapper); @@ -223,78 +227,111 @@ public void initButtons() { liftHoldBtn.setText(messages.liftButton()); liftHoldBtn.addClickHandler(clickEvent -> { - if (disposalHold.getFirstTimeUsed() == null) { - disposalHold.setState(DisposalHoldState.LIFTED); - Services services = new Services("Update disposal hold", "update"); - services.disposalHoldResource(s -> s.updateDisposalHold(disposalHold)).whenComplete((hold, throwable) -> { - if (throwable != null) { - AsyncCallbackUtils.defaultFailureTreatment(throwable); - } else { - HistoryUtils.newHistory(DisposalPolicy.RESOLVER); + Dialogs.showConfirmDialog(messages.liftDisposalHoldDialogTitle(), messages.liftDisposalHoldDialogMessage(1), + messages.cancelButton(), messages.confirmButton(), new AsyncCallback() { + @Override + public void onFailure(Throwable throwable) { + // do nothing } - }); - } else { - Filter filter = new Filter( - new SimpleFilterParameter(RodaConstants.AIP_DISPOSAL_HOLDS_ID, disposalHold.getId())); - SelectedItemsFilter selectedItemsFilter = new SelectedItemsFilter<>(filter, - IndexedAIP.class.getName(), true); - - Services services = new Services("Lift disposal hold", "job"); - CountRequest countRequest = new CountRequest(filter, true); - services.rodaEntityRestService(s -> s.count(countRequest), IndexedAIP.class) - .whenComplete((longResponse, throwable) -> { - if (longResponse.getResult() != 0) { - services.disposalHoldResource( - s -> s.liftDisposalHoldBySelectedItems(SelectedItemsUtils.convertToRESTRequest(selectedItemsFilter), - disposalHold.getId())) - .whenComplete((job, cause) -> { - if (cause != null) { - HistoryUtils.newHistory(InternalProcess.RESOLVER); - } else { - Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), new AsyncCallback() { - - @Override - public void onFailure(Throwable caught) { - Toast.showInfo(messages.runningInBackgroundTitle(), - messages.runningInBackgroundDescription()); - - Timer timer = new Timer() { - @Override - public void run() { - refresh(); - } - }; - - timer.schedule(RodaConstants.ACTION_TIMEOUT); - } - @Override - public void onSuccess(final Void nothing) { - HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); - } - }); + @Override + public void onSuccess(Boolean confirm) { + if (confirm) { + Dialogs.showPromptDialog(messages.outcomeDetailTitle(), null, null, messages.outcomeDetailPlaceholder(), + RegExp.compile(".*"), messages.cancelButton(), messages.confirmButton(), false, false, + new AsyncCallback() { + @Override + public void onFailure(Throwable throwable) { + // do nothing } - }); - } else { - services.disposalHoldResource(s -> s.liftDisposalHold(disposalHold.getId())) - .whenComplete((result, cause) -> { - if (cause != null) { - AsyncCallbackUtils.defaultFailureTreatment(cause); - } else { - Toast.showInfo(messages.runningInBackgroundTitle(), messages.updateDisposalHoldMessage()); - Timer timer = new Timer() { - @Override - public void run() { - refresh(); - } - }; - - timer.schedule(RodaConstants.ACTION_TIMEOUT); + + @Override + public void onSuccess(String details) { + if (disposalHold.getFirstTimeUsed() == null) { + disposalHold.setState(DisposalHoldState.LIFTED); + UpdateDisposalHoldRequest request = new UpdateDisposalHoldRequest(); + request.setDisposalHold(disposalHold); + request.setDetails(details); + Services services = new Services("Update disposal hold", "update"); + services.disposalHoldResource(s -> s.updateDisposalHold(request)) + .whenComplete((hold, throwable) -> { + if (throwable != null) { + AsyncCallbackUtils.defaultFailureTreatment(throwable); + } else { + HistoryUtils.newHistory(DisposalPolicy.RESOLVER); + } + }); + } else { + Filter filter = new Filter( + new SimpleFilterParameter(RodaConstants.AIP_DISPOSAL_HOLDS_ID, disposalHold.getId())); + SelectedItemsRequest selectedItems = new SelectedItemsFilterRequest(filter, true); + + Services services = new Services("Lift disposal hold", "job"); + CountRequest countRequest = new CountRequest(filter, true); + services.rodaEntityRestService(s -> s.count(countRequest), IndexedAIP.class) + .whenComplete((longResponse, throwable) -> { + if (longResponse.getResult() != 0) { + DisassociateDisposalHoldRequest request = new DisassociateDisposalHoldRequest(); + request.setClear(false); + request.setDetails(details); + request.setSelectedItems(selectedItems); + services + .disposalHoldResource(s -> s.disassociateDisposalHold(request, disposalHold.getId())) + .whenComplete((job, cause) -> { + if (cause != null) { + HistoryUtils.newHistory(InternalProcess.RESOLVER); + } else { + Dialogs.showJobRedirectDialog(messages.jobCreatedMessage(), + new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Toast.showInfo(messages.runningInBackgroundTitle(), + messages.runningInBackgroundDescription()); + + Timer timer = new Timer() { + @Override + public void run() { + refresh(); + } + }; + + timer.schedule(RodaConstants.ACTION_TIMEOUT); + } + + @Override + public void onSuccess(final Void nothing) { + HistoryUtils.newHistory(ShowJob.RESOLVER, job.getId()); + } + }); + } + }); + } else { + services.disposalHoldResource(s -> s.liftDisposalHold(disposalHold.getId(), details)) + .whenComplete((result, cause) -> { + if (cause != null) { + AsyncCallbackUtils.defaultFailureTreatment(cause); + } else { + Toast.showInfo(messages.runningInBackgroundTitle(), + messages.updateDisposalHoldMessage()); + Timer timer = new Timer() { + @Override + public void run() { + refresh(); + } + }; + + timer.schedule(RodaConstants.ACTION_TIMEOUT); + } + }); + } + }); + } } }); } - }); - } + } + }); }); buttonsPanel.add(liftHoldBtn); } diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/services/DisposalHoldRestService.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/services/DisposalHoldRestService.java index 9a646d9fb9..9ffd0a08e6 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/services/DisposalHoldRestService.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/services/DisposalHoldRestService.java @@ -6,6 +6,8 @@ import org.roda.core.data.v2.disposal.metadata.DisposalHoldsAIPMetadata; import org.roda.core.data.v2.disposal.metadata.DisposalTransitiveHoldsAIPMetadata; import org.roda.core.data.v2.generics.select.SelectedItemsRequest; +import org.roda.core.data.v2.ip.disposalhold.DisassociateDisposalHoldRequest; +import org.roda.core.data.v2.ip.disposalhold.UpdateDisposalHoldRequest; import org.roda.core.data.v2.jobs.Job; import org.roda.wui.api.v2.exceptions.model.ErrorResponseMessage; import org.springframework.http.HttpStatus; @@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -22,7 +25,6 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.web.bind.annotation.ResponseStatus; /** * @author Miguel Guimaraes @@ -40,12 +42,12 @@ public interface DisposalHoldRestService extends DirectRestService { DisposalHolds listDisposalHolds(); @RequestMapping(method = RequestMethod.PUT, path = "", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Update disposal hold", description = "Update existing disposal hold", requestBody = @RequestBody(required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = DisposalHold.class))), responses = { + @Operation(summary = "Update disposal hold", description = "Update existing disposal hold", requestBody = @RequestBody(required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = UpdateDisposalHoldRequest.class))), responses = { @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = DisposalHold.class))), @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class))), @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class))), @ApiResponse(responseCode = "404", description = "Not found", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class)))}) - DisposalHold updateDisposalHold(DisposalHold hold); + DisposalHold updateDisposalHold(UpdateDisposalHoldRequest updateDisposalHoldRequest); @RequestMapping(method = RequestMethod.POST, path = "", produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(HttpStatus.CREATED) @@ -72,15 +74,6 @@ Job applyDisposalHold( @Parameter(description = "Disposal hold id", required = true) @PathVariable(name = "id") String disposalHoldId, @Parameter(name = "override", description = "Lift all disposal holds associated and apply the selected disposal hold") @RequestParam(name = "override", required = false, defaultValue = "false") boolean override); - @RequestMapping(method = RequestMethod.POST, path = "/{id}/lift", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Lift disposal holds from selected AIPs", requestBody = @RequestBody(required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = SelectedItemsRequest.class))), responses = { - @ApiResponse(responseCode = "200", description = "Job created", content = @Content(schema = @Schema(implementation = Job.class))), - @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class))), - @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class))),}) - Job liftDisposalHoldBySelectedItems( - @Parameter(description = "Selected AIPs", required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) SelectedItemsRequest selectedItems, - @Parameter(description = "disposal hold id", required = true) @PathVariable(name = "id") String disposalHoldId); - @RequestMapping(method = RequestMethod.PUT, path = "/{id}/lift", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "Lift specific disposal hold", responses = { @ApiResponse(responseCode = "200", description = "Job created", content = @Content(schema = @Schema(implementation = DisposalHold.class))), @@ -88,17 +81,16 @@ Job liftDisposalHoldBySelectedItems( @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class))), @ApiResponse(responseCode = "404", description = "Disposal hold not found", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class)))}) DisposalHold liftDisposalHold( - @Parameter(description = "Disposal hold id", required = true) @PathVariable(name = "id") String id); + @Parameter(description = "Disposal hold id", required = true) @PathVariable(name = "id") String id, + @Parameter(description = "Outcome details", required = true) @RequestParam(name = "details", required = false, defaultValue = "") String details); - @RequestMapping(method = RequestMethod.POST, path = "/disassociate", produces = MediaType.APPLICATION_JSON_VALUE) - @Operation(summary = "Disassociate disposal hold from selected AIPs", requestBody = @RequestBody(required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = SelectedItemsRequest.class))), responses = { + @RequestMapping(method = RequestMethod.POST, path = "/{id}/disassociate", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "Disassociate disposal hold from selected AIPs", requestBody = @RequestBody(required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = DisassociateDisposalHoldRequest.class))), responses = { @ApiResponse(responseCode = "200", description = "Job created", content = @Content(schema = @Schema(implementation = Job.class))), @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class))), @ApiResponse(responseCode = "403", description = "Forbidden", content = @Content(schema = @Schema(implementation = ErrorResponseMessage.class)))}) - Job disassociateDisposalHold( - @Parameter(description = "Selected AIPs", required = true, content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE)) SelectedItemsRequest selectedItems, - @Parameter(description = "Disposal hold id") @PathVariable(name = "id", required = false) String disposalHoldId, - @Parameter(name = "clear", description = "Disassociate all disposal holds associated to AIP") @RequestParam(name = "clear", required = false, defaultValue = "false") boolean clear); + Job disassociateDisposalHold(DisassociateDisposalHoldRequest request, + @Parameter(description = "Disposal hold id", required = false) @PathVariable(name = "id") String disposalHoldId); @RequestMapping(method = RequestMethod.GET, path = "/transitive/{aip-id}", produces = MediaType.APPLICATION_JSON_VALUE) @Operation(summary = "List transitive holds", responses = { diff --git a/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties b/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties index 23346aa833..98fb0d7977 100644 --- a/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties +++ b/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties @@ -1516,6 +1516,9 @@ overrideDisposalHoldButton:Override disposal hold clearDisposalHoldDialogTitle:Clear disposal holds clearDisposalHoldDialogMessage[one]:Are you sure you want to disassociate all disposal holds from the selected item? clearDisposalHoldDialogMessage:Are you sure you want to disassociate all disposal holds from the selected {0, number} items? +liftDisposalHoldDialogTitle:Lift disposal hold +liftDisposalHoldDialogMessage[\=1]:Are you sure you want to lift the disposal hold? +liftDisposalHoldDialogMessage:Are you sure you want to lift the {0, number} selected disposal holds? disassociateDisposalHoldDialogTitle:Disassociate disposal hold disassociateDisposalHoldDialogMessage[one]:Are you sure you want to disassociate the disposal hold from the selected item? disassociateDisposalHoldDialogMessage:Are you sure you want to disassociate the disposal hold from the selected {0, number} items?