From 380fb450fc2355b772f181ee9dbbd8c6fbc86d18 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 13 Aug 2024 16:47:13 +0200 Subject: [PATCH 01/54] added provenance metadata for update, remove and add --- .../DSpaceObjectMetadataAddOperation.java | 36 ++++++++++++ .../DSpaceObjectMetadataRemoveOperation.java | 56 +++++++++++++++++-- .../DSpaceObjectMetadataReplaceOperation.java | 46 ++++++++++++++- 3 files changed, 132 insertions(+), 6 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 4b27ae963ab0..c1352be8e770 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -12,11 +12,18 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; import org.dspace.content.MetadataField; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; +import org.dspace.content.service.InstallItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -69,9 +76,38 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi dsoService.addAndShiftRightMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), metadataValue.getLanguage(), metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); + + if (dso.getType() != Constants.ITEM) + return; + + Item item = (Item) dso; + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item metadata (").append(metadataField.toString() + .replace('_', '.')).append(") were added by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + dsoService.update(context, item); } catch (SQLException e) { throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + "metadata to dso.", e); + } catch (AuthorizeException e) { + throw new DSpaceBadRequestException( + "AuthorizeException in DspaceObjectMetadataAddOperation.add " + + "trying to add metadata to dso.", e); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 3164ae377aeb..372cfdf4694b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -9,18 +9,26 @@ import java.sql.SQLException; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; +import org.dspace.content.service.InstallItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -76,12 +84,51 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe List metadataValues = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); + Map oldMtdValues = null; + if (dso.getType() == Constants.ITEM) { + oldMtdValues = new HashMap<>(); + for (MetadataValue mv : metadataValues) { + oldMtdValues.put(mv.getMetadataField().toString().replace('_', '.'), mv.getValue()); + } + } int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { // remove that metadata dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); + + if (dso.getType() != Constants.ITEM) + return; + + Item item = (Item) dso; + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + + for (Map.Entry mv : oldMtdValues.entrySet()) { + try { + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + prov.append("Item metadata (").append(mv.getKey()).append(": ") + .append(mv.getValue()).append(") were deleted by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + dsoService.update(context, item); + } catch (AuthorizeException ex) { + throw new DSpaceBadRequestException( + "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + + "trying to replace metadata from dso.", ex); + } + } } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + "this type at that index"); @@ -91,13 +138,14 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe throw new IllegalArgumentException("This index (" + index + ") is not valid number.", e); } catch (ArrayIndexOutOfBoundsException e) { throw new UnprocessableEntityException("There is no metadata of this type at that index"); - } catch (SQLException e) { - throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataRemoveOperation.remove " + - "trying to remove metadata from dso.", e); + } catch (SQLException ex) { + throw new DSpaceBadRequestException( + "SQLException in DspaceObjectMetadataRemoveOperation.remove " + + "trying to remove metadata from dso.", ex); } } - @Override + @Override public boolean supports(Object objectToMatch, Operation operation) { return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH) && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 1cf15684587b..db1fbc99e1d3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -14,13 +14,19 @@ import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; +import org.dspace.content.service.InstallItemService; +import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -91,7 +97,7 @@ private void replace(Context context, DSpaceObject dso, DSpaceObjectService dsoS } // replace single existing metadata value if (propertyOfMd == null) { - this.replaceSingleMetadataValue(dso, dsoService, metadataField, metadataValue, index); + this.replaceSingleMetadataValue(context, dso, dsoService, metadataField, metadataValue, index); return; } // replace single property of exiting metadata value @@ -145,7 +151,7 @@ private void replaceMetadataFieldMetadata(Context context, DSpaceObject dso, DSp * @param index index of md being replaced */ // replace single existing metadata value - private void replaceSingleMetadataValue(DSpaceObject dso, DSpaceObjectService dsoService, + private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpaceObjectService dsoService, MetadataField metadataField, MetadataValueRest metadataValue, String index) { try { @@ -155,18 +161,54 @@ private void replaceSingleMetadataValue(DSpaceObject dso, DSpaceObjectService ds int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { + // Alter this existing md MetadataValue existingMdv = metadataValues.get(indexInt); + String oldValue = existingMdv.getValue(); existingMdv.setAuthority(metadataValue.getAuthority()); existingMdv.setConfidence(metadataValue.getConfidence()); existingMdv.setLanguage(metadataValue.getLanguage()); existingMdv.setValue(metadataValue.getValue()); dsoService.setMetadataModified(dso); + + if (dso.getType() != Constants.ITEM) + return; + + Item item = (Item) dso; + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item metadata (").append(existingMdv.getMetadataField().toString() + .replace('_', '.')).append(": ") + .append(oldValue).append(") were updated by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + dsoService.update(context, item); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } } catch (NumberFormatException e) { throw new IllegalArgumentException("This index (" + index + ") is not valid number.", e); + } catch (SQLException e) { + throw new DSpaceBadRequestException( + "SQLException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + + "trying to replace metadata from dso.", e); + } catch (AuthorizeException e) { + throw new DSpaceBadRequestException( + "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + + "trying to replace metadata from dso.", e); } } From ffe630a9065932430c56d7a2e0d0d23b8de8f4c1 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 14 Aug 2024 06:26:28 +0200 Subject: [PATCH 02/54] checkstyle violations --- .../patch/operation/DSpaceObjectMetadataAddOperation.java | 3 ++- .../patch/operation/DSpaceObjectMetadataRemoveOperation.java | 5 +++-- .../operation/DSpaceObjectMetadataReplaceOperation.java | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index c1352be8e770..3918d321fa5b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -77,8 +77,9 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi metadataField.getElement(), metadataField.getQualifier(), metadataValue.getLanguage(), metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); - if (dso.getType() != Constants.ITEM) + if (dso.getType() != Constants.ITEM) { return; + } Item item = (Item) dso; InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 372cfdf4694b..48384fdaf784 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -98,8 +98,9 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); - if (dso.getType() != Constants.ITEM) + if (dso.getType() != Constants.ITEM) { return; + } Item item = (Item) dso; InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); @@ -145,7 +146,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe } } - @Override + @Override public boolean supports(Object objectToMatch, Operation operation) { return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH) && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index db1fbc99e1d3..609f8ea836c7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -171,8 +171,9 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac existingMdv.setValue(metadataValue.getValue()); dsoService.setMetadataModified(dso); - if (dso.getType() != Constants.ITEM) + if (dso.getType() != Constants.ITEM) { return; + } Item item = (Item) dso; InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); From 46335a1e83a3f079e3f3b1948cf3d7c2f39251e3 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 14 Aug 2024 09:30:12 +0200 Subject: [PATCH 03/54] added provenance metadata for update and remove bitstream --- .../operation/BitstreamRemoveOperation.java | 48 ++++++++++++++- .../DSpaceObjectMetadataAddOperation.java | 61 +++++++++++++++---- .../DSpaceObjectMetadataReplaceOperation.java | 58 +++++++++++++++++- 3 files changed, 151 insertions(+), 16 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index b0e2a45c9d23..c31daba0df0a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -9,16 +9,27 @@ import java.io.IOException; import java.sql.SQLException; +import java.util.List; import java.util.UUID; +import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.RESTBitstreamNotFoundException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Bitstream; +import org.dspace.content.DCDate; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.factory.ClarinServiceFactory; +import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamService; +import org.dspace.content.service.DSpaceObjectService; +import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Component; @@ -55,8 +66,43 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio authorizeBitstreamRemoveAction(context, bitstreamToDelete, Constants.DELETE); try { + ClarinItemService itemService = ClarinServiceFactory.getInstance().getClarinItemService(); + List items = itemService.findByBitstreamUUID(context, UUID.fromString(bitstreamIDtoDelete)); + StringBuilder bitstreamMsg = new StringBuilder(); + bitstreamMsg.append(bitstreamToDelete.getName()).append(": ") + .append(bitstreamToDelete.getSizeBytes()).append(" bytes, checksum: ") + .append(bitstreamToDelete.getChecksum()).append(" (") + .append(bitstreamToDelete.getChecksumAlgorithm()).append(")\n"); bitstreamService.delete(context, bitstreamToDelete); - } catch (AuthorizeException | IOException e) { + + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + DSpaceObjectService dsoService = ContentServiceFactory.getInstance() + .getDSpaceObjectService(Constants.ITEM); + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + + for (Item item : items) { + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item was deleted a bitstream (").append(bitstreamMsg).append(") by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + dsoService.update(context, item); + } + } catch (AuthorizeException e) { + throw new DSpaceBadRequestException( + "AuthorizeException in BitstreamRemoveOperation.perform " + + "trying to replace metadata from bitstream.", e); + } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } return null; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 3918d321fa5b..e1c2a435a623 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -8,19 +8,23 @@ package org.dspace.app.rest.repository.patch.operation; import java.sql.SQLException; +import java.util.List; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Bitstream; import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.EPerson; @@ -77,31 +81,62 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi metadataField.getElement(), metadataField.getQualifier(), metadataValue.getLanguage(), metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); - if (dso.getType() != Constants.ITEM) { + if (dso.getType() != Constants.ITEM && dso.getType() != Constants.BITSTREAM) { return; } - Item item = (Item) dso; InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); String timestamp = DCDate.getCurrent().toString(); - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + // bitstream checksums EPerson e = context.getCurrentUser(); - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); + if (dso.getType() == Constants.ITEM) { + Item item = (Item) dso; + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item metadata (").append(metadataField.toString() + .replace('_', '.')).append(") were added by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - prov.append("Item metadata (").append(metadataField.toString() - .replace('_', '.')).append(") were added by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + dsoService.update(context, item); + } + + if (dso.getType() == Constants.BITSTREAM) { + Bitstream bitstream = (Bitstream) dso; + ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); + List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); + StringBuilder bitstreamMsg = new StringBuilder(); + bitstreamMsg.append(bitstream.getName()).append(": ") + .append(bitstream.getSizeBytes()).append(" bytes, checksum: ") + .append(bitstream.getChecksum()).append(" (") + .append(bitstream.getChecksumAlgorithm()).append(")\n"); + DSpaceObjectService dsoItemService = ContentServiceFactory.getInstance() + .getDSpaceObjectService(Constants.ITEM); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + for (Item item : items) { + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); - dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - dsoService.update(context, item); + prov.append("Item was added a bitstream (").append(bitstreamMsg).append(") metadata (") + .append(metadataField.toString().replace('_', '.')).append(" by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + dsoItemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + dsoItemService.update(context, item); + } + } } catch (SQLException e) { throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + "metadata to dso.", e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 609f8ea836c7..d81f89761a7c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -15,15 +15,19 @@ import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Bitstream; import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; +import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; +import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.eperson.EPerson; @@ -101,7 +105,7 @@ private void replace(Context context, DSpaceObject dso, DSpaceObjectService dsoS return; } // replace single property of exiting metadata value - this.replaceSinglePropertyOfMdValue(dso, dsoService, metadataField, index, propertyOfMd, valueMdProperty); + this.replaceSinglePropertyOfMdValue(context, dso, dsoService, metadataField, index, propertyOfMd, valueMdProperty); } /** @@ -222,7 +226,7 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac * @param propertyOfMd property of md being replaced * @param valueMdProperty new value of property of md being replaced */ - private void replaceSinglePropertyOfMdValue(DSpaceObject dso, DSpaceObjectService dsoService, + private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, DSpaceObjectService dsoService, MetadataField metadataField, String index, String propertyOfMd, String valueMdProperty) { try { @@ -233,6 +237,8 @@ private void replaceSinglePropertyOfMdValue(DSpaceObject dso, DSpaceObjectServic if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { // Alter only asked propertyOfMd MetadataValue existingMdv = metadataValues.get(indexInt); + String oldValue = existingMdv.getValue(); + if (propertyOfMd.equals("authority")) { existingMdv.setAuthority(valueMdProperty); } @@ -246,12 +252,60 @@ private void replaceSinglePropertyOfMdValue(DSpaceObject dso, DSpaceObjectServic existingMdv.setValue(valueMdProperty); } dsoService.setMetadataModified(dso); + + if (dso.getType() != Constants.BITSTREAM) { + return; + } + Bitstream bitstream = (Bitstream) dso; + ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); + ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); + + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + + StringBuilder bitstreamMsg = new StringBuilder(); + bitstreamMsg.append(bitstream.getName()).append(": ") + .append(bitstream.getSizeBytes()).append(" bytes, checksum: ") + .append(bitstream.getChecksum()).append(" (") + .append(bitstream.getChecksumAlgorithm()).append(")\n"); + + for (Item item : items) { + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item was updated a bitstream (").append(bitstreamMsg).append(") metadata (") + .append(existingMdv.getMetadataField().toString() + .replace('_', '.')).append(".").append(propertyOfMd).append(": ") + .append(oldValue).append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) + .append(") on ").append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + itemService.update(context, item); + } + } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } } catch (NumberFormatException e) { throw new IllegalArgumentException("Not all numbers are valid numbers. " + "(Index and confidence should be nr)", e); + } catch (SQLException e) { + throw new DSpaceBadRequestException( + "SQLException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + + "trying to replace metadata from dso.", e); + } catch (AuthorizeException e) { + throw new DSpaceBadRequestException( + "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + + "trying to replace metadata from dso.", e); } } From 96158a568133304b52c44addb4d62a092144c6bc Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 14 Aug 2024 13:55:59 +0200 Subject: [PATCH 04/54] item test json added metadata provenance --- .../DSpaceObjectMetadataReplaceOperation.java | 3 +- .../app/rest/test/MetadataPatchSuite.java | 37 ++++++++-- .../app/rest/test/metadata-patch-suite.json | 69 ++++++++++++++++++- 3 files changed, 100 insertions(+), 9 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index d81f89761a7c..a9ca6045f5d1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -105,7 +105,8 @@ private void replace(Context context, DSpaceObject dso, DSpaceObjectService dsoS return; } // replace single property of exiting metadata value - this.replaceSinglePropertyOfMdValue(context, dso, dsoService, metadataField, index, propertyOfMd, valueMdProperty); + this.replaceSinglePropertyOfMdValue(context, dso, dsoService, metadataField, + index, propertyOfMd, valueMdProperty); } /** diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java index 423a4cbe3513..6730e6823e0d 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java @@ -11,10 +11,13 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.ws.rs.core.MediaType; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.junit.Assert; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; @@ -24,6 +27,7 @@ * Utility class for performing metadata patch tests sourced from a common json file (see constructor). */ public class MetadataPatchSuite { + static String PROVENANCE = "dc.description.provenance"; private final ObjectMapper objectMapper = new ObjectMapper(); private final JsonNode suite; @@ -78,13 +82,32 @@ private void checkResponse(String verb, MockMvc client, MockHttpServletRequestBu .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().is(expectedStatus)); if (expectedStatus >= 200 && expectedStatus < 300) { - String responseBody = resultActions.andReturn().getResponse().getContentAsString(); - JsonNode responseJson = objectMapper.readTree(responseBody); - String responseMetadata = responseJson.get("metadata").toString(); - if (!responseMetadata.equals(expectedMetadata)) { - Assert.fail("Expected metadata in " + verb + " response: " + expectedMetadata - + "\nGot metadata in " + verb + " response: " + responseMetadata); - } + String responseBody = resultActions.andReturn().getResponse().getContentAsString(); + JsonNode responseJson = objectMapper.readTree(responseBody); + + JsonNode responseMetadataJson = responseJson.get("metadata"); + if (responseMetadataJson.get(PROVENANCE) != null) { + String rspProvenance = responseMetadataJson.get(PROVENANCE).toString(); + // Regex to match the date pattern + String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; + Pattern pattern = Pattern.compile(datePattern); + Matcher matcher = pattern.matcher(rspProvenance); + String rspModifiedProvenance = rspProvenance; + while (matcher.find()) { + String dateString = matcher.group(0); + rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); + } + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNodePrv = objectMapper.readTree(rspModifiedProvenance); + ((ObjectNode) responseJson.get("metadata")).put(PROVENANCE, jsonNodePrv); + } + + String responseMetadata = responseJson.get("metadata").toString(); + + if (!responseMetadata.equals(expectedMetadata)) { + Assert.fail("Expected metadata in " + verb + " response: " + expectedMetadata + + "\nGot metadata in " + verb + " response: " + responseMetadata); + } } } } diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json index a09ecf1ba91e..ba2abc7e83ce 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json @@ -22,6 +22,9 @@ } ], "expect": { + "dc.description.provenance" : [ + { "value" : "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} + ], "dc.title": [ { "value": "title 1", "language": null, "authority": null, "confidence": -1, "place": 0} ] @@ -37,6 +40,12 @@ } ], "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1} + ], "dc.title": [ { "value": "title 1", "language": null, "authority": null, "confidence": -1,"place": 0 }, { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 1} @@ -55,6 +64,14 @@ } ], "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 1 }, @@ -72,6 +89,14 @@ } ], "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 1 }, @@ -94,6 +119,14 @@ } ], "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 1 }, @@ -111,6 +144,14 @@ } ], "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 1 }, @@ -132,6 +173,18 @@ } ], "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2}, + {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":3}, + {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":4} + ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 1 } @@ -146,7 +199,21 @@ "path": "/metadata/dc.title" } ], - "expect": {} + "expect": { + "dc.description.provenance": [ + { + "value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 0}, + {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 1}, + {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 2}, + {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 3}, + {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 4} + ] + } } ] } From 9d6097fbd635ede1fa9106438262ee48797f2663 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 14 Aug 2024 14:10:33 +0200 Subject: [PATCH 05/54] removed unwanted lines --- .../test/java/org/dspace/app/rest/test/MetadataPatchSuite.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java index 6730e6823e0d..77a20a620648 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java @@ -101,9 +101,7 @@ private void checkResponse(String verb, MockMvc client, MockHttpServletRequestBu JsonNode jsonNodePrv = objectMapper.readTree(rspModifiedProvenance); ((ObjectNode) responseJson.get("metadata")).put(PROVENANCE, jsonNodePrv); } - String responseMetadata = responseJson.get("metadata").toString(); - if (!responseMetadata.equals(expectedMetadata)) { Assert.fail("Expected metadata in " + verb + " response: " + expectedMetadata + "\nGot metadata in " + verb + " response: " + responseMetadata); From a0c500affa37ee92dfcd9cc3b83396055657520f Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 15 Aug 2024 10:32:07 +0200 Subject: [PATCH 06/54] control provenance only by tests of item --- .../dspace/app/rest/ItemRestRepositoryIT.java | 3 +- .../app/rest/test/MetadataPatchSuite.java | 11 + .../rest/test/item-metadata-patch-suite.json | 219 ++++++++++++++++++ .../app/rest/test/metadata-patch-suite.json | 69 +----- 4 files changed, 233 insertions(+), 69 deletions(-) create mode 100644 dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index 8f139a03f5d2..7db55b1fa39c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -2439,7 +2439,8 @@ private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Ex context.restoreAuthSystemState(); String token = getAuthToken(asUser.getEmail(), password); - new MetadataPatchSuite().runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); + new MetadataPatchSuite("item-metadata-patch-suite.json") + .runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); } /** diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java index 77a20a620648..d72942e915f0 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java @@ -40,6 +40,16 @@ public MetadataPatchSuite() throws Exception { suite = objectMapper.readTree(getClass().getResourceAsStream("metadata-patch-suite.json")); } + /** + * Initializes the suite by parsing the json file of tests. + * + * @param name name of resource + * @throws Exception if there is an error reading the file. + */ + public MetadataPatchSuite(String name) throws Exception { + suite = objectMapper.readTree(getClass().getResourceAsStream(name)); + } + /** * Runs all tests in the file using the given client and url, expecting the given status. * @@ -101,6 +111,7 @@ private void checkResponse(String verb, MockMvc client, MockHttpServletRequestBu JsonNode jsonNodePrv = objectMapper.readTree(rspModifiedProvenance); ((ObjectNode) responseJson.get("metadata")).put(PROVENANCE, jsonNodePrv); } + String responseMetadata = responseJson.get("metadata").toString(); if (!responseMetadata.equals(expectedMetadata)) { Assert.fail("Expected metadata in " + verb + " response: " + expectedMetadata diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json new file mode 100644 index 000000000000..ba2abc7e83ce --- /dev/null +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json @@ -0,0 +1,219 @@ +{ + "tests": [ + { + "name": "clear metadata", + "patch": [ + { "op": "replace", + "path": "/metadata", + "value": {} + } + ], + "expect": {} + }, + { + "name": "add first title", + "patch": [ + { + "op": "add", + "path": "/metadata/dc.title", + "value": [ + { "value": "title 1" } + ] + } + ], + "expect": { + "dc.description.provenance" : [ + { "value" : "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} + ], + "dc.title": [ + { "value": "title 1", "language": null, "authority": null, "confidence": -1, "place": 0} + ] + } + }, + { + "name": "add second title", + "patch": [ + { + "op": "add", + "path": "/metadata/dc.title/-", + "value": { "value": "最後のタイトル", "language": "ja_JP" } + } + ], + "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1} + ], + "dc.title": [ + { "value": "title 1", "language": null, "authority": null, "confidence": -1,"place": 0 }, + { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 1} + ] + } + }, + { + "name": "insert zeroth title", + "patch": [ + { + "op": "add", + "path": "/metadata/dc.title/0", + "value": { + "value": "title 0" + } + } + ], + "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], + "dc.title": [ + { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, + { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 1 }, + { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 2 } + ] + } + }, + { + "name": "move last title up one", + "patch": [ + { + "op": "move", + "from": "/metadata/dc.title/2", + "path": "/metadata/dc.title/1" + } + ], + "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], + "dc.title": [ + { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, + { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 1 }, + { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 2 } + ] + } + }, + { + "name": "replace title 2 value and language in two operations", + "patch": [ + { + "op": "replace", + "path": "/metadata/dc.title/1/value", + "value": "title A" + }, + { + "op": "replace", + "path": "/metadata/dc.title/1/language", + "value": "en_US" + } + ], + "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], + "dc.title": [ + { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, + { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 1 }, + { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 2 } + ] + } + }, + { + "name": "copy title A to end of list", + "patch": [ + { + "op": "copy", + "from": "/metadata/dc.title/1", + "path": "/metadata/dc.title/-" + } + ], + "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2} + ], + "dc.title": [ + { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, + { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 1 }, + { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 2 }, + { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 3 } + ] + } + }, + { + "name": "remove both title A copies", + "patch": [ + { + "op": "remove", + "path": "/metadata/dc.title/1" + }, + { + "op": "remove", + "path": "/metadata/dc.title/2" + } + ], + "expect": { + "dc.description.provenance":[ + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":0}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":1}, + {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":2}, + {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":3}, + {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language":"en","authority":null,"confidence":-1,"place":4} + ], + "dc.title": [ + { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, + { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 1 } + ] + } + }, + { + "name": "remove all titles", + "patch": [ + { + "op": "remove", + "path": "/metadata/dc.title" + } + ], + "expect": { + "dc.description.provenance": [ + { + "value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 0}, + {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 1}, + {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 2}, + {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 3}, + {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "language": "en", "authority": null, "confidence": -1, "place": 4} + ] + } + } + ] +} diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json index ba2abc7e83ce..a09ecf1ba91e 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/metadata-patch-suite.json @@ -22,9 +22,6 @@ } ], "expect": { - "dc.description.provenance" : [ - { "value" : "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} - ], "dc.title": [ { "value": "title 1", "language": null, "authority": null, "confidence": -1, "place": 0} ] @@ -40,12 +37,6 @@ } ], "expect": { - "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":1} - ], "dc.title": [ { "value": "title 1", "language": null, "authority": null, "confidence": -1,"place": 0 }, { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 1} @@ -64,14 +55,6 @@ } ], "expect": { - "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":2} - ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 1 }, @@ -89,14 +72,6 @@ } ], "expect": { - "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":2} - ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "最後のタイトル", "language": "ja_JP", "authority": null, "confidence": -1 ,"place": 1 }, @@ -119,14 +94,6 @@ } ], "expect": { - "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":2} - ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 1 }, @@ -144,14 +111,6 @@ } ], "expect": { - "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":2} - ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title A", "language": "en_US", "authority": null, "confidence": -1 ,"place": 1 }, @@ -173,18 +132,6 @@ } ], "expect": { - "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":2}, - {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":3}, - {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language":"en","authority":null,"confidence":-1,"place":4} - ], "dc.title": [ { "value": "title 0", "language": null, "authority": null, "confidence": -1 ,"place": 0 }, { "value": "title 1", "language": null, "authority": null, "confidence": -1 ,"place": 1 } @@ -199,21 +146,7 @@ "path": "/metadata/dc.title" } ], - "expect": { - "dc.description.provenance": [ - { - "value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language": "en", "authority": null, "confidence": -1, "place": 0}, - {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language": "en", "authority": null, "confidence": -1, "place": 1}, - {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language": "en", "authority": null, "confidence": -1, "place": 2}, - {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language": "en", "authority": null, "confidence": -1, "place": 3}, - {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "language": "en", "authority": null, "confidence": -1, "place": 4} - ] - } + "expect": {} } ] } From c79c00020e7f8dc65918e7c3a6d011f88d8d9dcf Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 19 Aug 2024 11:25:35 +0200 Subject: [PATCH 07/54] update and remove license --- .../app/rest/ItemAddBundleController.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index b3444a739e77..66ba00adc4c3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -31,13 +31,18 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; +import org.dspace.content.DCDate; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.clarin.ClarinLicense; +import org.dspace.content.clarin.ClarinLicenseResourceMapping; +import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -98,6 +103,9 @@ public class ItemAddBundleController { @Autowired ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; + @Autowired + InstallItemService installItemService; + /** * Method to add a Bundle to an Item with the given UUID in the URL. This will create a Bundle with the * name provided in the request and attach this to the Item that matches the UUID in the URL. @@ -166,9 +174,18 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, "but the new one will not be attached."); } List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); + String oldLicense = null; for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); for (Bitstream bundleBitstream : bitstreamList) { + if (Objects.isNull(oldLicense)) { + List mappings = + this.clarinLicenseResourceMappingService.findByBitstreamUUID( + context, bundleBitstream.getID()); + if (!mappings.isEmpty()) { + oldLicense = mappings.get(0).getLicense().getName(); + } + } // in case bitstream ID exists in license table for some reason .. just remove it this.clarinLicenseResourceMappingService.detachLicenses(context, bundleBitstream); if (Objects.nonNull(clarinLicense)) { @@ -182,6 +199,23 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, clarinLicenseService.addLicenseMetadataToItem(context, clarinLicense, item); } + // Add suitable provenance - includes old license, action, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + String timestamp = DCDate.getCurrent().toString(); + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("License (").append(Objects.isNull(oldLicense) ? "empty" : oldLicense).append(") was ") + .append(Objects.isNull(clarinLicense) ? "removed" : "updated").append(" by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + + // Update item in DB itemService.update(context, item); context.commit(); From c55d418a2d38104dac3133bb99b190312e0bec28 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 20 Aug 2024 09:05:20 +0200 Subject: [PATCH 08/54] provenance access control and upload bitstream --- .../bulkaccesscontrol/BulkAccessControl.java | 149 ++++++++++++++++++ .../rest/BundleUploadBitstreamController.java | 42 +++++ 2 files changed, 191 insertions(+) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 7bef232f0450..28f337ca3414 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -45,14 +45,20 @@ import org.dspace.app.util.DSpaceObjectUtilsImpl; import org.dspace.app.util.service.DSpaceObjectUtils; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.Bitstream; import org.dspace.content.Collection; +import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.discovery.DiscoverQuery; @@ -458,6 +464,13 @@ private void updateItemPolicies(Item item, BulkAccessControlInput accessControl) private void setItemPolicies(Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + String resPoliciesStr = accessControl + .getItem() + .getAccessConditions() + .stream() + .map(accessCondition -> accessCondition.getName()) + .collect(Collectors.joining(";")); + accessControl .getItem() .getAccessConditions() @@ -465,6 +478,33 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) itemAccessConditions.get(accessCondition.getName()))); itemService.adjustItemPolicies(context, item, item.getOwningCollection(), false); + + if (resPoliciesStr.isEmpty()) { + return; + } + + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + + // Add suitable provenance - includes access condition, item, action, user, date + + // bitstream checksums + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Access conditions (").append(resPoliciesStr).append(") for item (").append(item.getID()).append(") were added by ") + .append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + + // Update item in DB + itemService.update(context, item); + //context.commit(); } /** @@ -552,7 +592,81 @@ private void updateBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessC */ private void removeReadPolicies(DSpaceObject dso, String type) { try { + List resPolicies = resourcePolicyService.find(context, dso, type); + if (resPolicies.isEmpty()) { + return; + } + + String resPoliciesStr = resPolicies.stream() + .filter(rp -> rp.getAction() == Constants.READ) // Filter out non-READ actions + .map(rp -> { + return "[" + rp.getRpName() + ", " + + rp.getRpType() + ", " + + rp.getAction() + ", " + + (rp.getEPerson() == null ? null : rp.getEPerson().getEmail()) + ", " + + (rp.getGroup() == null ? null : rp.getGroup().getName()) + ", " + + (rp.getStartDate() == null ? null : rp.getStartDate().toString()) + ", " + + (rp.getEndDate() == null ? null : rp.getEndDate().toString()) + "]"; + }) + .collect(Collectors.joining(";")); + resourcePolicyService.removePolicies(context, dso, type, Constants.READ); + + if (dso.getType() != Constants.BITSTREAM && dso.getType() != Constants.ITEM) { + return; + } + + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + + if (dso.getType() == Constants.ITEM) { + // Add suitable provenance - includes old resource policies, item, action, user, date + + // bitstream checksums + Item item = (Item) dso; + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : resPoliciesStr).append(") for item (").append(item.getID()).append(") were removed by ") + .append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + + // Update item in DB + itemService.update(context, item); + //context.commit(); + } + + if (dso.getType() == Constants.BITSTREAM) { + // Add suitable provenance - includes old resource policices, bitstream, action, user, date + + // bitstream checksums + Bitstream bitstream = (Bitstream) dso; + ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : resPoliciesStr).append(") for bitstream (").append(bitstream.getID()).append(") were removed by ") + .append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + + List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); + for (Item item : items) { + // Build some provenance data while we're at it. + StringBuilder provItem = new StringBuilder(); + provItem.append(prov).append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", provItem.toString()); + //Update item in DB + itemService.update(context, item); + } + //context.commit(); + } } catch (SQLException | AuthorizeException e) { throw new BulkAccessControlException(e); } @@ -573,6 +687,13 @@ private void removeReadPolicies(DSpaceObject dso, String type) { private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + String accConditionsScr = accessControl + .getBitstream() + .getAccessConditions() + .stream() + .map(accessCondition -> accessCondition.getName()) + .collect(Collectors.joining(";")); + accessControl.getBitstream() .getAccessConditions() .forEach(accessCondition -> createResourcePolicy(bitstream, accessCondition, @@ -580,6 +701,34 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream); mediaFilterService.updatePoliciesOfDerivativeBitstreams(context, item, bitstream); + + if (accConditionsScr.isEmpty()) { + return; + } + + // Add suitable provenance - includes old resource policices, bitstream, action, user, date + + // bitstream checksums + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + + // Add suitable provenance - includes access condition, item, action, user, date + + // bitstream checksums + + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + prov.append("Access conditions (").append(accConditionsScr).append(") for bitstream (") + .append(bitstream.getID()).append(") of item(").append(item.getID()).append(") were added by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + + //context.commit(); } /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index 0cb6bc47e033..d725aec55661 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; +import java.util.List; import java.util.UUID; import javax.servlet.http.HttpServletRequest; @@ -25,9 +26,17 @@ import org.dspace.app.rest.repository.BundleRestRepository; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.Utils; +import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bundle; +import org.dspace.content.DCDate; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BundleService; +import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; @@ -111,6 +120,39 @@ public ResponseEntity> uploadBitstream( throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e); } + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + ItemService itemService = ContentServiceFactory.getInstance() + .getItemService(); + + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + + // bitstream checksums + EPerson e = context.getCurrentUser(); + + List items = bundle.getItems(); + for (Item item : items) { + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Bitstream was added to bundle (").append(bundle.getID()).append(") of item (") + .append(item.getID()).append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) + .append(") on ").append(timestamp).append("\n"); + try { + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } catch (SQLException ex) { + throw new RuntimeException("SQLException in BundleUploadBitstreamConverter.uploadBitstream " + + "when provenance metadata are adding.", ex); + } catch (AuthorizeException ex) { + throw new RuntimeException("AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + + "when provenance metadata are adding.", ex); + } + } + BitstreamRest bitstreamRest = bundleRestRepository.uploadBitstream( context, bundle, uploadfile.getOriginalFilename(), fileInputStream, properties); BitstreamResource bitstreamResource = converter.toResource(bitstreamRest); From 499aac48c0bd8a044f945093f54e0f2c64dafcc9 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 20 Aug 2024 09:34:47 +0200 Subject: [PATCH 09/54] provenance move item to different collection --- ...mOwningCollectionUpdateRestController.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index b5a0c957f265..4e9d6bcae884 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -26,12 +26,16 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Collection; +import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.CollectionService; +import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.prepost.PostAuthorize; @@ -52,6 +56,8 @@ public class ItemOwningCollectionUpdateRestController { @Autowired ItemService itemService; + @Autowired + InstallItemService installItemService; @Autowired CollectionService collectionService; @@ -125,6 +131,24 @@ private Collection moveItem(final Context context, final Item item, final Collec final boolean inheritPolicies) throws SQLException, IOException, AuthorizeException { itemService.move(context, item, currentCollection, targetCollection, inheritPolicies); + + String timestamp = DCDate.getCurrent().toString(); + // Add suitable provenance + EPerson e = context.getCurrentUser(); + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item (").append(item.getID()).append(") was moved from collection (") + .append(currentCollection.getID()).append(") to new collection by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + itemService.update(context, item); + // Necessary because Controller does not pass through general RestResourceController, and as such does not do // its commit in DSpaceRestRepository.createAndReturn() or similar context.commit(); From 9c361d9e8182ba2054d95b44be7ba198cd35f62d Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 20 Aug 2024 09:57:29 +0200 Subject: [PATCH 10/54] provenance make item non-discoverable --- .../ItemDiscoverableReplaceOperation.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index df17d4e92da3..b40fe0a5da43 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -10,10 +10,20 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.content.Collection; +import org.dspace.content.DCDate; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.stereotype.Component; +import java.sql.SQLException; +import java.util.List; + /** * This is the implementation for Item 'discoverable' patches. * @@ -40,6 +50,34 @@ public R perform(Context context, R object, Operation operation) { if (discoverable && item.getTemplateItemOf() != null) { throw new UnprocessableEntityException("A template item cannot be discoverable."); } + + String timestamp = DCDate.getCurrent().toString(); + + // Add suitable provenance - includes user, date, collections + + // bitstream checksums + EPerson e = context.getCurrentUser(); + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + + prov.append("Item made ").append( discoverable ? "" : "non-").append("discoverable by ").append(e.getFullName()).append(" (") + .append(e.getEmail()).append(") on ").append(timestamp).append("\n") + .append("Item was in collections:\n"); + + List colls = item.getCollections(); + + for (Collection coll : colls) { + prov.append(coll.getName()).append(" (ID: ").append(coll.getID()).append(")\n"); + } + try { + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", "provenance", "en", prov.toString()); + context.commit(); + } catch (SQLException ex) { + throw new RuntimeException("SQLException occured when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); + } item.setDiscoverable(discoverable); return object; } else { From 9f94913982a8663de4034074af4a373270b03cef Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 21 Aug 2024 14:51:49 +0200 Subject: [PATCH 11/54] checkstyle violations and test failures --- .../bulkaccesscontrol/BulkAccessControl.java | 16 +++++++++------- ...mOwningCollectionUpdateRestController.java | 4 +++- .../ItemDiscoverableReplaceOperation.java | 19 ++++++++++--------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 28f337ca3414..296b83f169b2 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -494,9 +494,9 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Access conditions (").append(resPoliciesStr).append(") for item (").append(item.getID()).append(") were added by ") - .append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + prov.append("Access conditions (").append(resPoliciesStr).append(") for item (").append(item.getID()) + .append(") were added by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), @@ -629,7 +629,8 @@ private void removeReadPolicies(DSpaceObject dso, String type) { // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : resPoliciesStr).append(") for item (").append(item.getID()).append(") were removed by ") + prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : + resPoliciesStr).append(") for item (").append(item.getID()).append(") were removed by ") .append(e.getFullName()) .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); @@ -651,9 +652,10 @@ private void removeReadPolicies(DSpaceObject dso, String type) { // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : resPoliciesStr).append(") for bitstream (").append(bitstream.getID()).append(") were removed by ") - .append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : resPoliciesStr) + .append(") for bitstream (").append(bitstream.getID()).append(") were removed by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); for (Item item : items) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index 4e9d6bcae884..f158ab15dec7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -147,8 +147,10 @@ private Collection moveItem(final Context context, final Item item, final Collec itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", "provenance", "en", prov.toString()); // Update item in DB + // Update the item + context.turnOffAuthorisationSystem(); itemService.update(context, item); - + context.restoreAuthSystemState(); // Necessary because Controller does not pass through general RestResourceController, and as such does not do // its commit in DSpaceRestRepository.createAndReturn() or similar context.commit(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index b40fe0a5da43..128725919087 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -7,6 +7,9 @@ */ package org.dspace.app.rest.repository.patch.operation; +import java.sql.SQLException; +import java.util.List; + import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; @@ -21,9 +24,6 @@ import org.dspace.eperson.EPerson; import org.springframework.stereotype.Component; -import java.sql.SQLException; -import java.util.List; - /** * This is the implementation for Item 'discoverable' patches. * @@ -61,9 +61,9 @@ public R perform(Context context, R object, Operation operation) { // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Item made ").append( discoverable ? "" : "non-").append("discoverable by ").append(e.getFullName()).append(" (") - .append(e.getEmail()).append(") on ").append(timestamp).append("\n") - .append("Item was in collections:\n"); + prov.append("Item made ").append( discoverable ? "" : "non-").append("discoverable by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp) + .append("\n").append("Item was in collections:\n"); List colls = item.getCollections(); @@ -73,10 +73,11 @@ public R perform(Context context, R object, Operation operation) { try { prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", "provenance", "en", prov.toString()); - context.commit(); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", + "provenance", "en", prov.toString()); } catch (SQLException ex) { - throw new RuntimeException("SQLException occured when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); + throw new RuntimeException("SQLException occured when item making " + (discoverable ? "" : "non-") + + "discoverable.", ex); } item.setDiscoverable(discoverable); return object; From 2a0d919b94d43cc6a51dc53b195541661ef8b23a Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 21 Aug 2024 17:21:05 +0200 Subject: [PATCH 12/54] make code more readable --- .../rest/BundleUploadBitstreamController.java | 55 +++++----- .../app/rest/ItemAddBundleController.java | 5 +- ...mOwningCollectionUpdateRestController.java | 6 +- .../operation/BitstreamRemoveOperation.java | 65 +++++++----- .../DSpaceObjectMetadataAddOperation.java | 85 +++++++-------- .../DSpaceObjectMetadataRemoveOperation.java | 60 +++++------ .../DSpaceObjectMetadataReplaceOperation.java | 100 ++++++++---------- .../ItemDiscoverableReplaceOperation.java | 28 ++--- .../app/rest/test/MetadataPatchSuite.java | 5 +- 9 files changed, 200 insertions(+), 209 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index d725aec55661..8868637ee072 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -80,6 +80,12 @@ public class BundleUploadBitstreamController { @Autowired private BundleService bundleService; + @Autowired + private ItemService itemService; + + @Autowired + private InstallItemService installItemService; + @Autowired private BundleRestRepository bundleRestRepository; @@ -120,37 +126,28 @@ public ResponseEntity> uploadBitstream( throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e); } - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - ItemService itemService = ContentServiceFactory.getInstance() - .getItemService(); - - String timestamp = DCDate.getCurrent().toString(); - - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + - // bitstream checksums + // We do this before calling `updateBitstream` because that function calls `context.commit` + // Add suitable provenance EPerson e = context.getCurrentUser(); + String timestamp = DCDate.getCurrent().toString(); + Item item = bundle.getItems().get(0); - List items = bundle.getItems(); - for (Item item : items) { - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Bitstream was added to bundle (").append(bundle.getID()).append(") of item (") - .append(item.getID()).append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) - .append(") on ").append(timestamp).append("\n"); - try { - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - } catch (SQLException ex) { - throw new RuntimeException("SQLException in BundleUploadBitstreamConverter.uploadBitstream " + - "when provenance metadata are adding.", ex); - } catch (AuthorizeException ex) { - throw new RuntimeException("AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + - "when provenance metadata are adding.", ex); - } + StringBuilder prov = new StringBuilder(); + prov.append("Bitstream was added to bundle (").append(bundle.getID()).append(") of item (") + .append(item.getID()).append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) + .append(") on ").append(timestamp).append("\n"); + try { + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } catch (SQLException ex) { + throw new RuntimeException("SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + + "adding new provenance metadata.", ex); + } catch (AuthorizeException ex) { + throw new RuntimeException("AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + + "when adding new provenance metadata.", ex); } BitstreamRest bitstreamRest = bundleRestRepository.uploadBitstream( diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 66ba00adc4c3..c3a8cf3e584e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -199,12 +199,9 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, clarinLicenseService.addLicenseMetadataToItem(context, clarinLicense, item); } - // Add suitable provenance - includes old license, action, user, date + - // bitstream checksums + // Add suitable provenance EPerson e = context.getCurrentUser(); String timestamp = DCDate.getCurrent().toString(); - - // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); prov.append("License (").append(Objects.isNull(oldLicense) ? "empty" : oldLicense).append(") was ") diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index f158ab15dec7..4be633d8273d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -132,10 +132,9 @@ private Collection moveItem(final Context context, final Item item, final Collec throws SQLException, IOException, AuthorizeException { itemService.move(context, item, currentCollection, targetCollection, inheritPolicies); - String timestamp = DCDate.getCurrent().toString(); // Add suitable provenance + String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); - // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); prov.append("Item (").append(item.getID()).append(") was moved from collection (") @@ -147,10 +146,11 @@ private Collection moveItem(final Context context, final Item item, final Collec itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", "provenance", "en", prov.toString()); // Update item in DB - // Update the item + // Because a user can move an item without authorization turn off authorization context.turnOffAuthorisationSystem(); itemService.update(context, item); context.restoreAuthSystemState(); + // Necessary because Controller does not pass through general RestResourceController, and as such does not do // its commit in DSpaceRestRepository.createAndReturn() or similar context.commit(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index c31daba0df0a..fbcf7a315e02 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.UUID; +import org.apache.commons.collections4.CollectionUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.RESTBitstreamNotFoundException; import org.dspace.app.rest.model.patch.Operation; @@ -21,11 +22,9 @@ import org.dspace.content.DCDate; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ClarinServiceFactory; -import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamService; -import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -52,6 +51,16 @@ public class BitstreamRemoveOperation extends PatchOperation { @Autowired BitstreamService bitstreamService; + + @Autowired + ItemService itemService; + + @Autowired + ClarinItemService clarinItemService; + + @Autowired + InstallItemService installItemService; + @Autowired AuthorizeService authorizeService; public static final String OPERATION_PATH_BITSTREAM_REMOVE = "/bitstreams/"; @@ -66,42 +75,46 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio authorizeBitstreamRemoveAction(context, bitstreamToDelete, Constants.DELETE); try { - ClarinItemService itemService = ClarinServiceFactory.getInstance().getClarinItemService(); - List items = itemService.findByBitstreamUUID(context, UUID.fromString(bitstreamIDtoDelete)); + List items = clarinItemService.findByBitstreamUUID(context, UUID.fromString(bitstreamIDtoDelete)); + // The bitstream is assigned only into one Item. + Item item = null; + if (!CollectionUtils.isEmpty(items)) { + item = items.get(0); + } + + // values of deleted bitstream StringBuilder bitstreamMsg = new StringBuilder(); bitstreamMsg.append(bitstreamToDelete.getName()).append(": ") .append(bitstreamToDelete.getSizeBytes()).append(" bytes, checksum: ") .append(bitstreamToDelete.getChecksum()).append(" (") .append(bitstreamToDelete.getChecksumAlgorithm()).append(")\n"); + + //delete bitstream bitstreamService.delete(context, bitstreamToDelete); - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - DSpaceObjectService dsoService = ContentServiceFactory.getInstance() - .getDSpaceObjectService(Constants.ITEM); - String timestamp = DCDate.getCurrent().toString(); + if (item == null) { + return null; + } - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + - // bitstream checksums + // Add suitable provenance + String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); - for (Item item : items) { - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Item was deleted a bitstream (").append(bitstreamMsg).append(") by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + prov.append("Item was deleted a bitstream (").append(bitstreamMsg).append(") by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - dsoService.update(context, item); - } + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); } catch (AuthorizeException e) { throw new DSpaceBadRequestException( - "AuthorizeException in BitstreamRemoveOperation.perform " + - "trying to replace metadata from bitstream.", e); + "AuthorizeException in BitstreamRemoveOperation.perform while adding provenance metadata " + + "about the deleted item's bitstream.", e); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index e1c2a435a623..10a4637d25c4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -10,6 +10,7 @@ import java.sql.SQLException; import java.util.List; +import org.apache.commons.collections4.CollectionUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; @@ -20,10 +21,10 @@ import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; @@ -48,6 +49,15 @@ public class DSpaceObjectMetadataAddOperation extends Pa @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; + @Autowired + InstallItemService installItemService; + + @Autowired + ItemService itemService; + + @Autowired + ClarinItemService clarinItemService; + @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -85,57 +95,29 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi return; } - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - String timestamp = DCDate.getCurrent().toString(); - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + - // bitstream checksums - EPerson e = context.getCurrentUser(); - if (dso.getType() == Constants.ITEM) { + // Add suitable provenance Item item = (Item) dso; - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Item metadata (").append(metadataField.toString() - .replace('_', '.')).append(") were added by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - dsoService.update(context, item); + String msg = "metadata (" + metadataField.toString() + .replace('_', '.') + ")"; + addProvenanceMetadata(context, item, msg); } if (dso.getType() == Constants.BITSTREAM) { + // Add suitable provenance Bitstream bitstream = (Bitstream) dso; - ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - StringBuilder bitstreamMsg = new StringBuilder(); - bitstreamMsg.append(bitstream.getName()).append(": ") - .append(bitstream.getSizeBytes()).append(" bytes, checksum: ") - .append(bitstream.getChecksum()).append(" (") - .append(bitstream.getChecksumAlgorithm()).append(")\n"); - DSpaceObjectService dsoItemService = ContentServiceFactory.getInstance() - .getDSpaceObjectService(Constants.ITEM); - - for (Item item : items) { - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Item was added a bitstream (").append(bitstreamMsg).append(") metadata (") - .append(metadataField.toString().replace('_', '.')).append(" by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - dsoItemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - dsoItemService.update(context, item); + // The bitstream is assigned only into one Item. + Item item = null; + if (!CollectionUtils.isEmpty(items)) { + item = items.get(0); } + String msg = "bitstream (" + bitstream.getName() + ": " + + bitstream.getSizeBytes() + " bytes, checksum: " + + bitstream.getChecksum() + " (" + + bitstream.getChecksumAlgorithm() + ")" + ") metadata (" + + metadataField.toString().replace('_', '.') + ")"; + addProvenanceMetadata(context, item, msg); } } catch (SQLException e) { throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + @@ -147,6 +129,21 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi } } + private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException{ + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + StringBuilder prov = new StringBuilder(); + + prov.append("Item ").append(msg).append(" was added by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } + @Override public boolean supports(Object objectToMatch, Operation operation) { return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 48384fdaf784..23b75f66d8db 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -9,9 +9,7 @@ import java.sql.SQLException; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; @@ -52,6 +50,9 @@ public class DSpaceObjectMetadataRemoveOperation extends @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; + @Autowired + InstallItemService installItemService; + @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -84,16 +85,18 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe List metadataValues = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); - Map oldMtdValues = null; - if (dso.getType() == Constants.ITEM) { - oldMtdValues = new HashMap<>(); - for (MetadataValue mv : metadataValues) { - oldMtdValues.put(mv.getMetadataField().toString().replace('_', '.'), mv.getValue()); - } - } + int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { + // Remember removed mtd + String oldMtdKey = null; + String oldMtdValue = null; + if (dso.getType() == Constants.ITEM) { + oldMtdKey = metadataValues.get(indexInt).getMetadataField().toString() + .replace('_', '.'); + oldMtdValue = metadataValues.get(indexInt).getValue(); + } // remove that metadata dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); @@ -102,33 +105,26 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe return; } + // Add suitable provenance Item item = (Item) dso; - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); String timestamp = DCDate.getCurrent().toString(); - - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + - // bitstream checksums EPerson e = context.getCurrentUser(); + try { + // Build some provenance data while we're at it. + StringBuilder prov = new StringBuilder(); + prov.append("Item metadata (").append(oldMtdKey).append(": ") + .append(oldMtdValue).append(") were deleted by ").append(e.getFullName()) + .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - for (Map.Entry mv : oldMtdValues.entrySet()) { - try { - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - prov.append("Item metadata (").append(mv.getKey()).append(": ") - .append(mv.getValue()).append(") were deleted by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - dsoService.update(context, item); - } catch (AuthorizeException ex) { - throw new DSpaceBadRequestException( - "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + - "trying to replace metadata from dso.", ex); - } + dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + // Update item in DB + dsoService.update(context, item); + } catch (AuthorizeException ex) { + throw new DSpaceBadRequestException( + "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + + "trying to replace metadata from dso.", ex); } } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index a9ca6045f5d1..ead8747aefda 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -10,6 +10,7 @@ import java.sql.SQLException; import java.util.List; +import org.apache.commons.collections4.CollectionUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; @@ -22,7 +23,6 @@ import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; -import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; @@ -52,6 +52,15 @@ public class DSpaceObjectMetadataReplaceOperation extend @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; + @Autowired + InstallItemService installItemService; + + @Autowired + ItemService itemService; + + @Autowired + ClarinItemService clarinItemService; + @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -166,10 +175,9 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { - // Alter this existing md MetadataValue existingMdv = metadataValues.get(indexInt); - String oldValue = existingMdv.getValue(); + String oldMtdVal = existingMdv.getValue(); existingMdv.setAuthority(metadataValue.getAuthority()); existingMdv.setConfidence(metadataValue.getConfidence()); existingMdv.setLanguage(metadataValue.getLanguage()); @@ -180,28 +188,11 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac return; } + // Add suitable provenance Item item = (Item) dso; - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - String timestamp = DCDate.getCurrent().toString(); - - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + - // bitstream checksums - EPerson e = context.getCurrentUser(); - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Item metadata (").append(existingMdv.getMetadataField().toString() - .replace('_', '.')).append(": ") - .append(oldValue).append(") were updated by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - dsoService.update(context, item); + String msg = "metadata (" + metadataField.toString() + .replace('_', '.') + ": " + oldMtdVal + ")"; + addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } @@ -238,7 +229,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { // Alter only asked propertyOfMd MetadataValue existingMdv = metadataValues.get(indexInt); - String oldValue = existingMdv.getValue(); + String oldMtdVal = existingMdv.getValue(); if (propertyOfMd.equals("authority")) { existingMdv.setAuthority(valueMdProperty); @@ -257,42 +248,23 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D if (dso.getType() != Constants.BITSTREAM) { return; } - Bitstream bitstream = (Bitstream) dso; - ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); - ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + // Add suitable provenance + Bitstream bitstream = (Bitstream) dso; String timestamp = DCDate.getCurrent().toString(); - - // Add suitable provenance - includes mtd field, old mtd, new mtd, user, date + - // bitstream checksums EPerson e = context.getCurrentUser(); - - StringBuilder bitstreamMsg = new StringBuilder(); - bitstreamMsg.append(bitstream.getName()).append(": ") - .append(bitstream.getSizeBytes()).append(" bytes, checksum: ") - .append(bitstream.getChecksum()).append(" (") - .append(bitstream.getChecksumAlgorithm()).append(")\n"); - - for (Item item : items) { - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Item was updated a bitstream (").append(bitstreamMsg).append(") metadata (") - .append(existingMdv.getMetadataField().toString() - .replace('_', '.')).append(".").append(propertyOfMd).append(": ") - .append(oldValue).append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) - .append(") on ").append(timestamp).append("\n"); - - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - itemService.update(context, item); + List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); + // The bitstream is assigned only into one Item. + Item item = null; + if (!CollectionUtils.isEmpty(items)) { + item = items.get(0); } - + String msg = "bitstream (" + bitstream.getName() + ": " + + bitstream.getSizeBytes() + " bytes, checksum: " + + bitstream.getChecksum() + " (" + + bitstream.getChecksumAlgorithm() + ")" + ") metadata (" + + metadataField.toString().replace('_', '.') + ")"; + addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } @@ -310,6 +282,20 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D } } + private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException{ + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + StringBuilder prov = new StringBuilder(); + prov.append("Item ").append(msg).append(" was updated by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } + @Override public boolean supports(Object objectToMatch, Operation operation) { return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index 128725919087..a21706b9b659 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -13,15 +13,16 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; import org.dspace.content.DCDate; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; import org.dspace.eperson.EPerson; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -41,6 +42,12 @@ public class ItemDiscoverableReplaceOperation extends PatchOperation { */ private static final String OPERATION_PATH_DISCOVERABLE = "/discoverable"; + @Autowired + ItemService itemService; + + @Autowired + InstallItemService installItemService; + @Override public R perform(Context context, R object, Operation operation) { checkOperationValue(operation.getValue()); @@ -50,36 +57,33 @@ public R perform(Context context, R object, Operation operation) { if (discoverable && item.getTemplateItemOf() != null) { throw new UnprocessableEntityException("A template item cannot be discoverable."); } + item.setDiscoverable(discoverable); - String timestamp = DCDate.getCurrent().toString(); - - // Add suitable provenance - includes user, date, collections + - // bitstream checksums + // Add suitable provenance EPerson e = context.getCurrentUser(); - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + String timestamp = DCDate.getCurrent().toString(); // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Item made ").append( discoverable ? "" : "non-").append("discoverable by ") .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp) .append("\n").append("Item was in collections:\n"); - List colls = item.getCollections(); - for (Collection coll : colls) { prov.append(coll.getName()).append(" (ID: ").append(coll.getID()).append(")\n"); } + try { prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", "provenance", "en", prov.toString()); + itemService.update(context, item); } catch (SQLException ex) { throw new RuntimeException("SQLException occured when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); + } catch (AuthorizeException ex) { + throw new RuntimeException("AuthorizeException occured when item making " + (discoverable ? "" : "non-") + + "discoverable.", ex); } - item.setDiscoverable(discoverable); return object; } else { throw new DSpaceBadRequestException("ItemDiscoverableReplaceOperation does not support this operation"); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java index d72942e915f0..97e1491d03c9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/test/MetadataPatchSuite.java @@ -94,9 +94,10 @@ private void checkResponse(String verb, MockMvc client, MockHttpServletRequestBu if (expectedStatus >= 200 && expectedStatus < 300) { String responseBody = resultActions.andReturn().getResponse().getContentAsString(); JsonNode responseJson = objectMapper.readTree(responseBody); - JsonNode responseMetadataJson = responseJson.get("metadata"); if (responseMetadataJson.get(PROVENANCE) != null) { + // In the provenance metadata, there is a timestamp indicating when they were added. + // To ensure accurate comparison, remove that date. String rspProvenance = responseMetadataJson.get(PROVENANCE).toString(); // Regex to match the date pattern String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; @@ -109,9 +110,9 @@ private void checkResponse(String verb, MockMvc client, MockHttpServletRequestBu } ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNodePrv = objectMapper.readTree(rspModifiedProvenance); + // Replace the origin metadata with a value with the timestamp removed ((ObjectNode) responseJson.get("metadata")).put(PROVENANCE, jsonNodePrv); } - String responseMetadata = responseJson.get("metadata").toString(); if (!responseMetadata.equals(expectedMetadata)) { Assert.fail("Expected metadata in " + verb + " response: " + expectedMetadata From 1922907d15350491560f6c6cb08a8edaff720d50 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 22 Aug 2024 10:03:52 +0200 Subject: [PATCH 13/54] provenance for mapped collection --- .../rest/MappedCollectionRestController.java | 27 +++++++++++++++++++ .../ItemDiscoverableReplaceOperation.java | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index 14dae21ebec0..8cacad9927cd 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -25,11 +25,15 @@ import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; +import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.CollectionService; +import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; @@ -51,6 +55,9 @@ public class MappedCollectionRestController { @Autowired private ItemService itemService; + @Autowired + private InstallItemService installItemService; + @Autowired private CollectionService collectionService; @@ -104,6 +111,11 @@ public void createCollectionToItemRelation(@PathVariable UUID uuid, collectionService.addItem(context, collectionToMapTo, item); collectionService.update(context, collectionToMapTo); + + // Add suitable provenance + String msg = "was mapped to collection"; + addApprovedProvenance(context, item, msg, collectionToMapTo); + itemService.update(context, item); } else { throw new UnprocessableEntityException("Not a valid collection or item uuid."); @@ -150,13 +162,28 @@ public void deleteCollectionToItemRelation(@PathVariable UUID uuid, @PathVariabl if (collection.getID() != owningCollectionUuid && item.getCollections().contains(collection)) { collectionService.removeItem(context, collection, item); collectionService.update(context, collection); + + // Add suitable provenance + String msg = "was deleted from mapped collection"; + addApprovedProvenance(context, item, msg, collection); + itemService.update(context, item); context.commit(); } } else { throw new UnprocessableEntityException("Not a valid collection or item uuid."); } + } + public void addApprovedProvenance(Context context, Item item, String msg, Collection col) throws SQLException { + EPerson e = context.getCurrentUser(); + String timestamp = DCDate.getCurrent().toString(); + StringBuilder prov = new StringBuilder(); + prov.append("Item ").append(msg).append(" (").append(col.getID()).append(") by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", + "provenance", "en", prov.toString()); } private void checkIfItemIsTemplate(Item item) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index a21706b9b659..a08cc095107b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -78,7 +78,7 @@ public R perform(Context context, R object, Operation operation) { "provenance", "en", prov.toString()); itemService.update(context, item); } catch (SQLException ex) { - throw new RuntimeException("SQLException occured when item making " + (discoverable ? "" : "non-") + throw new RuntimeException("SQLException occurred when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); } catch (AuthorizeException ex) { throw new RuntimeException("AuthorizeException occured when item making " + (discoverable ? "" : "non-") From d9dd689567390ddd09a8c14497d3dbe548b6d56d Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 22 Aug 2024 10:31:15 +0200 Subject: [PATCH 14/54] grammer check --- .../dspace/app/bulkaccesscontrol/BulkAccessControl.java | 7 +++---- .../dspace/app/rest/BundleUploadBitstreamController.java | 6 ++---- .../java/org/dspace/app/rest/ItemAddBundleController.java | 5 +++-- .../app/rest/ItemOwningCollectionUpdateRestController.java | 4 ++-- .../patch/operation/BitstreamRemoveOperation.java | 2 +- .../patch/operation/DSpaceObjectMetadataAddOperation.java | 2 +- .../operation/DSpaceObjectMetadataRemoveOperation.java | 2 +- .../operation/DSpaceObjectMetadataReplaceOperation.java | 2 +- .../patch/operation/ItemDiscoverableReplaceOperation.java | 4 ++-- 9 files changed, 16 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 296b83f169b2..031edd79953f 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -719,10 +719,9 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Access conditions (").append(accConditionsScr).append(") for bitstream (") - .append(bitstream.getID()).append(") of item(").append(item.getID()).append(") were added by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); + prov.append("Access condition (").append(accConditionsScr).append(") was added to bitstream (") + .append(bitstream.getID()).append(") by ").append(e.getFullName()).append(" (") + .append(e.getEmail()).append(") on ").append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index 8868637ee072..9bf42de43f10 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -12,7 +12,6 @@ import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; -import java.util.List; import java.util.UUID; import javax.servlet.http.HttpServletRequest; @@ -31,7 +30,6 @@ import org.dspace.content.DCDate; import org.dspace.content.Item; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BundleService; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; @@ -133,8 +131,8 @@ public ResponseEntity> uploadBitstream( Item item = bundle.getItems().get(0); StringBuilder prov = new StringBuilder(); - prov.append("Bitstream was added to bundle (").append(bundle.getID()).append(") of item (") - .append(item.getID()).append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) + prov.append("Item was added bitstream to bundle (").append(bundle.getID()) + .append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) .append(") on ").append(timestamp).append("\n"); try { prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index c3a8cf3e584e..846264c29bd3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -205,8 +205,9 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, StringBuilder prov = new StringBuilder(); prov.append("License (").append(Objects.isNull(oldLicense) ? "empty" : oldLicense).append(") was ") - .append(Objects.isNull(clarinLicense) ? "removed" : "updated").append(" by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); + .append(Objects.isNull(clarinLicense) ? "removed" : Objects.isNull(oldLicense) ? "added" : "updated") + .append(" by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index 4be633d8273d..76831cb67409 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -137,8 +137,8 @@ private Collection moveItem(final Context context, final Item item, final Collec EPerson e = context.getCurrentUser(); StringBuilder prov = new StringBuilder(); - prov.append("Item (").append(item.getID()).append(") was moved from collection (") - .append(currentCollection.getID()).append(") to new collection by ").append(e.getFullName()) + prov.append("Item was moved from collection (") + .append(currentCollection.getID()).append(") to different collection by ").append(e.getFullName()) .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index fbcf7a315e02..14d8c623304d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -102,7 +102,7 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Item was deleted a bitstream (").append(bitstreamMsg).append(") by ") + prov.append("Item was deleted bitstream (").append(bitstreamMsg).append(") by ") .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") .append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 10a4637d25c4..69eadd99a61d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -129,7 +129,7 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi } } - private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException{ + private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); StringBuilder prov = new StringBuilder(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 23b75f66d8db..5992422c567c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -113,7 +113,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); prov.append("Item metadata (").append(oldMtdKey).append(": ") - .append(oldMtdValue).append(") were deleted by ").append(e.getFullName()) + .append(oldMtdValue).append(") was deleted by ").append(e.getFullName()) .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index ead8747aefda..853369987949 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -282,7 +282,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D } } - private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException{ + private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); StringBuilder prov = new StringBuilder(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index a08cc095107b..d6df97994d67 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -64,7 +64,7 @@ public R perform(Context context, R object, Operation operation) { String timestamp = DCDate.getCurrent().toString(); // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Item made ").append( discoverable ? "" : "non-").append("discoverable by ") + prov.append("Item was made ").append( discoverable ? "" : "non-").append("discoverable by ") .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp) .append("\n").append("Item was in collections:\n"); List colls = item.getCollections(); @@ -81,7 +81,7 @@ public R perform(Context context, R object, Operation operation) { throw new RuntimeException("SQLException occurred when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); } catch (AuthorizeException ex) { - throw new RuntimeException("AuthorizeException occured when item making " + (discoverable ? "" : "non-") + throw new RuntimeException("AuthorizeException occurred when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); } return object; From 5cddf35a07b8aa31c153b1901c0ac62aba0b6cb7 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 22 Aug 2024 12:42:00 +0200 Subject: [PATCH 15/54] don't write provenance for bitstream without item --- .../DSpaceObjectMetadataAddOperation.java | 5 +- .../DSpaceObjectMetadataReplaceOperation.java | 5 +- .../rest/test/item-metadata-patch-suite.json | 50 +++++++++---------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 69eadd99a61d..02df14ff92c7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -109,9 +109,10 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); // The bitstream is assigned only into one Item. Item item = null; - if (!CollectionUtils.isEmpty(items)) { - item = items.get(0); + if (CollectionUtils.isEmpty(items)) { + return; } + item = items.get(0); String msg = "bitstream (" + bitstream.getName() + ": " + bitstream.getSizeBytes() + " bytes, checksum: " + bitstream.getChecksum() + " (" + diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 853369987949..f2f9501a7c32 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -256,9 +256,10 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); // The bitstream is assigned only into one Item. Item item = null; - if (!CollectionUtils.isEmpty(items)) { - item = items.get(0); + if (CollectionUtils.isEmpty(items)) { + return; } + item = items.get(0); String msg = "bitstream (" + bitstream.getName() + ": " + bitstream.getSizeBytes() + " bytes, checksum: " + bitstream.getChecksum() + " (" + diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json index ba2abc7e83ce..1966f304ad00 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json @@ -23,7 +23,7 @@ ], "expect": { "dc.description.provenance" : [ - { "value" : "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} + { "value" : "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} ], "dc.title": [ { "value": "title 1", "language": null, "authority": null, "confidence": -1, "place": 0} @@ -41,9 +41,9 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":1} ], "dc.title": [ @@ -65,11 +65,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -90,11 +90,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -120,11 +120,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -145,11 +145,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -174,15 +174,15 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":2}, - {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":3}, - {"value":"Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":4} ], "dc.title": [ @@ -202,15 +202,15 @@ "expect": { "dc.description.provenance": [ { - "value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 0}, - {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 1}, - {"value": "Item metadata (dc.title) were added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 2}, - {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 3}, - {"value": "Item metadata (dc.title: title A) were deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 4} ] } From 4a6072a662ecfcf52b83a628a413db4b42571a1f Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 22 Aug 2024 14:44:22 +0200 Subject: [PATCH 16/54] move addProvenance to parent class --- .../bulkaccesscontrol/BulkAccessControl.java | 77 +++++++++++-------- .../DSpaceObjectMetadataAddOperation.java | 29 ++----- .../DSpaceObjectMetadataRemoveOperation.java | 67 ++++++++++------ .../DSpaceObjectMetadataReplaceOperation.java | 19 +---- .../ItemDiscoverableReplaceOperation.java | 4 +- .../patch/operation/PatchOperation.java | 41 ++++++++++ 6 files changed, 139 insertions(+), 98 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 031edd79953f..503a1b367fa2 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -494,8 +494,8 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - prov.append("Access conditions (").append(resPoliciesStr).append(") for item (").append(item.getID()) - .append(") were added by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + prov.append("Access condition (").append(resPoliciesStr).append(") was added to item by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") .append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); @@ -628,19 +628,9 @@ private void removeReadPolicies(DSpaceObject dso, String type) { // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - - prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : - resPoliciesStr).append(") for item (").append(item.getID()).append(") were removed by ") - .append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - - // Update item in DB - itemService.update(context, item); - //context.commit(); + String msg = "("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + + ") of item (" + item.getID() + ")"; + addProvenanceMetadata(context, item, msg); } if (dso.getType() == Constants.BITSTREAM) { @@ -648,32 +638,51 @@ private void removeReadPolicies(DSpaceObject dso, String type) { // bitstream checksums Bitstream bitstream = (Bitstream) dso; ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Resource policies (").append(Objects.isNull(resPoliciesStr) ? "empty" : resPoliciesStr) - .append(") for bitstream (").append(bitstream.getID()).append(") were removed by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - for (Item item : items) { - // Build some provenance data while we're at it. - StringBuilder provItem = new StringBuilder(); - provItem.append(prov).append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", provItem.toString()); - //Update item in DB - itemService.update(context, item); + if (items.isEmpty()) { + return; } - //context.commit(); + Item item = items.get(0); + // Build some provenance data while we're at it. + String msg = "("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + + ") of bitstream (" + bitstream.getID() + ")"; + addProvenanceMetadata(context, item, msg); } } catch (SQLException | AuthorizeException e) { throw new BulkAccessControlException(e); } } + /** + * Adds provenance metadata to an item, documenting changes made to its resource policies + * and bitstream. This method records the user who performed the action, the action taken, + * and the timestamp of the action. It also appends a bitstream provenance message generated + * by the InstallItemService. + * + * @param context the current DSpace context, which provides details about the current user + * and authorization information. + * @param item the DSpace item to which the provenance metadata should be added. + * @param msg a custom message describing the action taken on the resource policies. + * @throws SQLException if there is a database access error while updating the item. + * @throws AuthorizeException if the current user is not authorized to add metadata to the item. + */ + protected void addProvenanceMetadata(Context context, Item item, String msg) + throws SQLException, AuthorizeException { + ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + StringBuilder prov = new StringBuilder(); + prov.append("Resource policies ").append(msg).append(" were removed by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } + /** * create the new resource policies of bitstream. * then, call {@link ItemService#adjustItemPolicies( @@ -720,7 +729,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); prov.append("Access condition (").append(accConditionsScr).append(") was added to bitstream (") - .append(bitstream.getID()).append(") by ").append(e.getFullName()).append(" (") + .append(bitstream.getID()).append(") of item by ").append(e.getFullName()).append(" (") .append(e.getEmail()).append(") on ").append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 02df14ff92c7..b909c4a38ebc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -16,11 +16,9 @@ import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; -import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; @@ -28,7 +26,6 @@ import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -99,7 +96,7 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi // Add suitable provenance Item item = (Item) dso; String msg = "metadata (" + metadataField.toString() - .replace('_', '.') + ")"; + .replace('_', '.') + ") was added"; addProvenanceMetadata(context, item, msg); } @@ -113,11 +110,12 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi return; } item = items.get(0); - String msg = "bitstream (" + bitstream.getName() + ": " + - bitstream.getSizeBytes() + " bytes, checksum: " + + String msg = "metadata (" + + metadataField.toString().replace('_', '.') + ") was added" + + " to bitstream (" + bitstream.getName() + ": " + + bitstream.getSizeBytes() + " bytes, checksum: " + bitstream.getChecksum() + " (" + - bitstream.getChecksumAlgorithm() + ")" + ") metadata (" + - metadataField.toString().replace('_', '.') + ")"; + bitstream.getChecksumAlgorithm() + ")"; addProvenanceMetadata(context, item, msg); } } catch (SQLException e) { @@ -130,21 +128,6 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi } } - private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - StringBuilder prov = new StringBuilder(); - - prov.append("Item ").append(msg).append(" was added by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - } - @Override public boolean supports(Object objectToMatch, Operation operation) { return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 5992422c567c..eaf9e8e3244e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -11,22 +11,23 @@ import java.util.Arrays; import java.util.List; +import org.apache.commons.collections4.CollectionUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.DCDate; +import org.dspace.content.Bitstream; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; +import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -53,6 +54,12 @@ public class DSpaceObjectMetadataRemoveOperation extends @Autowired InstallItemService installItemService; + @Autowired + private ClarinItemService clarinItemService; + + @Autowired + private ItemService itemService; + @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -77,9 +84,38 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe metadataPatchUtils.checkMetadataFieldNotNull(metadataField); try { if (index == null) { + String oldMtdKey = null; + String oldMtdValue = null; + if (dso.getType() == Constants.BITSTREAM) { + List mtd = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), + metadataField.getElement(), metadataField.getQualifier(), Item.ANY); + if (!CollectionUtils.isEmpty(mtd)) { + oldMtdKey = mtd.get(0).getMetadataField().getElement(); + oldMtdValue = mtd.get(0).getValue(); + } + } // remove all metadata of this type dsoService.clearMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); + if (dso.getType() != Constants.BITSTREAM) { + return; + } + // Add suitable provenance + Bitstream bitstream = (Bitstream) dso; + List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); + // The bitstream is assigned only into one Item. + Item item = null; + if (CollectionUtils.isEmpty(items)) { + return; + } + item = items.get(0); + String msg = + " metadata (" + oldMtdKey + ": " + oldMtdValue + + ") was removed from bitstream (" + bitstream.getName() + ": " + + bitstream.getSizeBytes() + " bytes, checksum: " + + bitstream.getChecksum() + " (" + + bitstream.getChecksumAlgorithm() + "))"; + addProvenanceMetadata(context, item, msg); } else { // remove metadata at index List metadataValues = dsoService.getMetadata(dso, @@ -107,25 +143,8 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe // Add suitable provenance Item item = (Item) dso; - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - try { - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - prov.append("Item metadata (").append(oldMtdKey).append(": ") - .append(oldMtdValue).append(") was deleted by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - dsoService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - dsoService.update(context, item); - } catch (AuthorizeException ex) { - throw new DSpaceBadRequestException( - "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + - "trying to replace metadata from dso.", ex); - } + String msg = "metadata (" + oldMtdKey + ": " + oldMtdValue + ") was removed"; + addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + "this type at that index"); @@ -139,6 +158,10 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe throw new DSpaceBadRequestException( "SQLException in DspaceObjectMetadataRemoveOperation.remove " + "trying to remove metadata from dso.", ex); + } catch (AuthorizeException ex) { + throw new DSpaceBadRequestException( + "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + + "trying to replace metadata from dso.", ex); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index f2f9501a7c32..8b767beeba83 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -21,7 +21,6 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; @@ -191,7 +190,7 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac // Add suitable provenance Item item = (Item) dso; String msg = "metadata (" + metadataField.toString() - .replace('_', '.') + ": " + oldMtdVal + ")"; + .replace('_', '.') + ": " + oldMtdVal + ")" + " was updated"; addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); @@ -264,7 +263,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D bitstream.getSizeBytes() + " bytes, checksum: " + bitstream.getChecksum() + " (" + bitstream.getChecksumAlgorithm() + ")" + ") metadata (" + - metadataField.toString().replace('_', '.') + ")"; + metadataField.toString().replace('_', '.') + ": " + oldMtdVal + ") was updated"; addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); @@ -283,20 +282,6 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D } } - private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - StringBuilder prov = new StringBuilder(); - prov.append("Item ").append(msg).append(" was updated by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - } - @Override public boolean supports(Object objectToMatch, Operation operation) { return (operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index d6df97994d67..0b12aab61fa7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -81,8 +81,8 @@ public R perform(Context context, R object, Operation operation) { throw new RuntimeException("SQLException occurred when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); } catch (AuthorizeException ex) { - throw new RuntimeException("AuthorizeException occurred when item making " + (discoverable ? "" : "non-") - + "discoverable.", ex); + throw new RuntimeException("AuthorizeException occurred when item making " + + (discoverable ? "" : "non-") + "discoverable.", ex); } return object; } else { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index 0842746f329d..8c5b7021ef21 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -12,7 +12,15 @@ import org.apache.commons.lang3.BooleanUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCDate; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.eperson.EPerson; +import org.springframework.beans.factory.annotation.Autowired; /** * Base class for all resource patch operations. @@ -26,6 +34,12 @@ public abstract class PatchOperation { public static final String OPERATION_MOVE = "move"; public static final String OPERATION_REMOVE = "remove"; + @Autowired + InstallItemService installItemService; + + @Autowired + ItemService itemService; + /** * Updates the rest model by applying the patch operation. * @@ -74,6 +88,33 @@ Boolean getBooleanOperationValue(Object value) { return bool; } + /** + * Adds provenance metadata to an item, documenting an action taken on the item. + * This method logs the user who performed the action, the action description, + * and the timestamp when the action occurred. It also appends a bitstream provenance + * message generated by the InstallItemService. + * + * @param context the current DSpace context, which provides details about the current user + * and authorization information. + * @param item the DSpace item to which the provenance metadata should be added. + * @param msg a custom message describing the action taken on the item. + * @throws SQLException if there is a database access error while updating the item. + * @throws AuthorizeException if the current user is not authorized to add metadata to the item. + */ + protected void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + StringBuilder prov = new StringBuilder(); + prov.append("Item ").append(msg).append(" by ") + .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } + /** * Determines whether or not this Patch Operation can do this patch (Object of operation and path gets checked) * @param objectToMatch Object whose class must be instance of type object From e468c90581440c11d0317861264336d9d1f93613 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 22 Aug 2024 14:56:04 +0200 Subject: [PATCH 17/54] refactoring --- .../bulkaccesscontrol/BulkAccessControl.java | 62 ++++--------------- 1 file changed, 11 insertions(+), 51 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 503a1b367fa2..d4c7cc300b36 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -482,29 +482,8 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) if (resPoliciesStr.isEmpty()) { return; } - - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - - // Add suitable provenance - includes access condition, item, action, user, date + - // bitstream checksums - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - - prov.append("Access condition (").append(resPoliciesStr).append(") was added to item by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - - // Update item in DB - itemService.update(context, item); - //context.commit(); + String msg = "Access condition (" + resPoliciesStr + ") was added to item"; + addProvenanceMetadata(context, item, msg); } /** @@ -628,8 +607,8 @@ private void removeReadPolicies(DSpaceObject dso, String type) { // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - String msg = "("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) - + ") of item (" + item.getID() + ")"; + String msg = "Resource policies ("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + + ") of item (" + item.getID() + ") were removed"; addProvenanceMetadata(context, item, msg); } @@ -644,8 +623,8 @@ private void removeReadPolicies(DSpaceObject dso, String type) { } Item item = items.get(0); // Build some provenance data while we're at it. - String msg = "("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) - + ") of bitstream (" + bitstream.getID() + ")"; + String msg = "Resource policies ("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + + ") of bitstream (" + bitstream.getID() + ") were removed"; addProvenanceMetadata(context, item, msg); } } catch (SQLException | AuthorizeException e) { @@ -673,8 +652,7 @@ protected void addProvenanceMetadata(Context context, Item item, String msg) String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); StringBuilder prov = new StringBuilder(); - prov.append("Resource policies ").append(msg).append(" were removed by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + prov.append(msg).append(" by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") .append(timestamp).append("\n"); prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), @@ -717,28 +695,10 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont return; } - // Add suitable provenance - includes old resource policices, bitstream, action, user, date + - // bitstream checksums - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - - // Add suitable provenance - includes access condition, item, action, user, date + - // bitstream checksums - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - prov.append("Access condition (").append(accConditionsScr).append(") was added to bitstream (") - .append(bitstream.getID()).append(") of item by ").append(e.getFullName()).append(" (") - .append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - - //context.commit(); + // Add suitable provenance + String msg = "Access condition (" + accConditionsScr + ") was added to bitstream (" + + bitstream.getID() + ") of item"; + addProvenanceMetadata(context, item, msg); } /** From 9910c9013ebab1be024ee8cd5667d7217336be50 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 22 Aug 2024 16:44:09 +0200 Subject: [PATCH 18/54] checkstyle violations and test failures --- .../org/dspace/app/bulkaccesscontrol/BulkAccessControl.java | 6 +++--- .../operation/DSpaceObjectMetadataRemoveOperation.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index d4c7cc300b36..8c2c8369eec8 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -607,7 +607,7 @@ private void removeReadPolicies(DSpaceObject dso, String type) { // Build some provenance data while we're at it. StringBuilder prov = new StringBuilder(); - String msg = "Resource policies ("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + String msg = "Resource policies (" + (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + ") of item (" + item.getID() + ") were removed"; addProvenanceMetadata(context, item, msg); } @@ -623,7 +623,7 @@ private void removeReadPolicies(DSpaceObject dso, String type) { } Item item = items.get(0); // Build some provenance data while we're at it. - String msg = "Resource policies ("+ (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + String msg = "Resource policies (" + (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + ") of bitstream (" + bitstream.getID() + ") were removed"; addProvenanceMetadata(context, item, msg); } @@ -698,7 +698,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont // Add suitable provenance String msg = "Access condition (" + accConditionsScr + ") was added to bitstream (" + bitstream.getID() + ") of item"; - addProvenanceMetadata(context, item, msg); + addProvenanceMetadata(context, item, msg) ; } /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index eaf9e8e3244e..bb203c31b893 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -111,7 +111,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe item = items.get(0); String msg = " metadata (" + oldMtdKey + ": " + oldMtdValue + - ") was removed from bitstream (" + bitstream.getName() + ": " + + ") was deleted from bitstream (" + bitstream.getName() + ": " + bitstream.getSizeBytes() + " bytes, checksum: " + bitstream.getChecksum() + " (" + bitstream.getChecksumAlgorithm() + "))"; @@ -143,7 +143,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe // Add suitable provenance Item item = (Item) dso; - String msg = "metadata (" + oldMtdKey + ": " + oldMtdValue + ") was removed"; + String msg = "metadata (" + oldMtdKey + ": " + oldMtdValue + ") was deleted"; addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + From 18607a55e66a49d0b090e5826073aa52d0398085 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 10 Sep 2024 09:00:11 +0200 Subject: [PATCH 19/54] removed unnecessary variables, added logs and checkstyle --- .../app/bulkaccesscontrol/BulkAccessControl.java | 16 +++------------- .../DSpaceObjectMetadataAddOperation.java | 9 ++++++--- .../DSpaceObjectMetadataRemoveOperation.java | 14 +++++++------- .../DSpaceObjectMetadataReplaceOperation.java | 7 ++++++- .../ItemDiscoverableReplaceOperation.java | 2 +- .../patch/operation/PatchOperation.java | 3 ++- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 8c2c8369eec8..d96997cf9f5d 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -595,26 +595,17 @@ private void removeReadPolicies(DSpaceObject dso, String type) { return; } - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - if (dso.getType() == Constants.ITEM) { - // Add suitable provenance - includes old resource policies, item, action, user, date + - // bitstream checksums + // Add suitable provenance Item item = (Item) dso; - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); + // Build some provenance data. String msg = "Resource policies (" + (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) + ") of item (" + item.getID() + ") were removed"; addProvenanceMetadata(context, item, msg); } if (dso.getType() == Constants.BITSTREAM) { - // Add suitable provenance - includes old resource policices, bitstream, action, user, date + - // bitstream checksums + // Add suitable provenance Bitstream bitstream = (Bitstream) dso; ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); @@ -647,7 +638,6 @@ private void removeReadPolicies(DSpaceObject dso, String type) { */ protected void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { - ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index b909c4a38ebc..49af741bf675 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -11,6 +11,8 @@ import java.util.List; import org.apache.commons.collections4.CollectionUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; @@ -42,6 +44,7 @@ */ @Component public class DSpaceObjectMetadataAddOperation extends PatchOperation { + private static final Logger log = LogManager.getLogger(); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; @@ -107,14 +110,14 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi // The bitstream is assigned only into one Item. Item item = null; if (CollectionUtils.isEmpty(items)) { + log.warn("Bitstream (" + dso.getID() + ") is not assigned to any item."); return; } item = items.get(0); String msg = "metadata (" + metadataField.toString().replace('_', '.') + ") was added" - + " to bitstream (" + bitstream.getName() + ": " + - bitstream.getSizeBytes() + " bytes, checksum: " + - bitstream.getChecksum() + " (" + + + " to bitstream (" + bitstream.getName() + ": " + bitstream.getSizeBytes() + + " bytes, checksum: " + bitstream.getChecksum() + " (" + bitstream.getChecksumAlgorithm() + ")"; addProvenanceMetadata(context, item, msg); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index bb203c31b893..119325bd4997 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -12,6 +12,8 @@ import java.util.List; import org.apache.commons.collections4.CollectionUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; @@ -47,6 +49,7 @@ */ @Component public class DSpaceObjectMetadataRemoveOperation extends PatchOperation { + private static final Logger log = LogManager.getLogger(); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; @@ -106,22 +109,19 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe // The bitstream is assigned only into one Item. Item item = null; if (CollectionUtils.isEmpty(items)) { + log.warn("Bitstream (" + dso.getID() + ") is not assigned to any item."); return; } item = items.get(0); - String msg = - " metadata (" + oldMtdKey + ": " + oldMtdValue + - ") was deleted from bitstream (" + bitstream.getName() + ": " + - bitstream.getSizeBytes() + " bytes, checksum: " + - bitstream.getChecksum() + " (" + - bitstream.getChecksumAlgorithm() + "))"; + String msg = " metadata (" + oldMtdKey + ": " + oldMtdValue + ") was deleted from bitstream (" + + bitstream.getName() + ": " + bitstream.getSizeBytes() + " bytes, checksum: " + + bitstream.getChecksum() + " (" + bitstream.getChecksumAlgorithm() + "))"; addProvenanceMetadata(context, item, msg); } else { // remove metadata at index List metadataValues = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); - int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 8b767beeba83..141300c2175c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -11,6 +11,8 @@ import java.util.List; import org.apache.commons.collections4.CollectionUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; @@ -47,6 +49,7 @@ */ @Component public class DSpaceObjectMetadataReplaceOperation extends PatchOperation { + private static final Logger log = LogManager.getLogger(); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; @@ -256,6 +259,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D // The bitstream is assigned only into one Item. Item item = null; if (CollectionUtils.isEmpty(items)) { + log.warn("Bitstream (" + dso.getID() + ") is not assigned to any item."); return; } item = items.get(0); @@ -263,7 +267,8 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D bitstream.getSizeBytes() + " bytes, checksum: " + bitstream.getChecksum() + " (" + bitstream.getChecksumAlgorithm() + ")" + ") metadata (" + - metadataField.toString().replace('_', '.') + ": " + oldMtdVal + ") was updated"; + metadataField.toString().replace('_', '.') + ": " + oldMtdVal + ") was updated " + + "by " + e.getFullName() + "(" + e.getEmail() + ") on " + timestamp; addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index 0b12aab61fa7..66b5226ad404 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -62,7 +62,7 @@ public R perform(Context context, R object, Operation operation) { // Add suitable provenance EPerson e = context.getCurrentUser(); String timestamp = DCDate.getCurrent().toString(); - // Build some provenance data while we're at it. + // Build some provenance data. StringBuilder prov = new StringBuilder(); prov.append("Item was made ").append( discoverable ? "" : "non-").append("discoverable by ") .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index 8c5b7021ef21..02388421bdda 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -101,7 +101,8 @@ Boolean getBooleanOperationValue(Object value) { * @throws SQLException if there is a database access error while updating the item. * @throws AuthorizeException if the current user is not authorized to add metadata to the item. */ - protected void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { + protected void addProvenanceMetadata(Context context, Item item, String msg) + throws SQLException, AuthorizeException { String timestamp = DCDate.getCurrent().toString(); EPerson e = context.getCurrentUser(); StringBuilder prov = new StringBuilder(); From aae82ccb238845a77ee1ec7851ec05a9be6713c5 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 25 Sep 2024 08:13:54 +0200 Subject: [PATCH 20/54] separated class for provenance --- .../bulkaccesscontrol/BulkAccessControl.java | 118 ++------------- .../org/dspace/core/ProvenanceService.java | 17 +++ .../dspace/core/ProvenanceServiceImpl.java | 134 ++++++++++++++++++ .../core/factory/CoreServiceFactory.java | 3 + .../core/factory/CoreServiceFactoryImpl.java | 9 ++ dspace/config/spring/api/core-services.xml | 1 + 6 files changed, 179 insertions(+), 103 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceService.java create mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index d96997cf9f5d..a2d89375bf5c 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -50,17 +50,16 @@ import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.Bitstream; import org.dspace.content.Collection; -import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; +import org.dspace.core.factory.CoreServiceFactory; import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.SearchService; import org.dspace.discovery.SearchServiceException; @@ -117,6 +116,8 @@ public class BulkAccessControl extends DSpaceRunnable accessCondition.getName()) - .collect(Collectors.joining(";")); + //String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); accessControl .getItem() @@ -479,11 +477,11 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) itemService.adjustItemPolicies(context, item, item.getOwningCollection(), false); - if (resPoliciesStr.isEmpty()) { - return; - } - String msg = "Access condition (" + resPoliciesStr + ") was added to item"; - addProvenanceMetadata(context, item, msg); +// if (resPoliciesStr.isEmpty()) { +// String msg = "Access condition (" + resPoliciesStr + ") was added to item"; +// addProvenanceMetadata(context, item, msg); +// } + provenanceService.setItemPolicies(context, item, accessControl); } /** @@ -571,86 +569,16 @@ private void updateBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessC */ private void removeReadPolicies(DSpaceObject dso, String type) { try { - List resPolicies = resourcePolicyService.find(context, dso, type); - if (resPolicies.isEmpty()) { + String resPoliciesStr = provenanceService.removedReadPolicies(context, dso, type); + if (Objects.isNull(resPoliciesStr)) { return; } - - String resPoliciesStr = resPolicies.stream() - .filter(rp -> rp.getAction() == Constants.READ) // Filter out non-READ actions - .map(rp -> { - return "[" + rp.getRpName() + ", " - + rp.getRpType() + ", " - + rp.getAction() + ", " - + (rp.getEPerson() == null ? null : rp.getEPerson().getEmail()) + ", " - + (rp.getGroup() == null ? null : rp.getGroup().getName()) + ", " - + (rp.getStartDate() == null ? null : rp.getStartDate().toString()) + ", " - + (rp.getEndDate() == null ? null : rp.getEndDate().toString()) + "]"; - }) - .collect(Collectors.joining(";")); - resourcePolicyService.removePolicies(context, dso, type, Constants.READ); - - if (dso.getType() != Constants.BITSTREAM && dso.getType() != Constants.ITEM) { - return; - } - - if (dso.getType() == Constants.ITEM) { - // Add suitable provenance - Item item = (Item) dso; - // Build some provenance data. - String msg = "Resource policies (" + (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) - + ") of item (" + item.getID() + ") were removed"; - addProvenanceMetadata(context, item, msg); - } - - if (dso.getType() == Constants.BITSTREAM) { - // Add suitable provenance - Bitstream bitstream = (Bitstream) dso; - ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); - List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - if (items.isEmpty()) { - return; - } - Item item = items.get(0); - // Build some provenance data while we're at it. - String msg = "Resource policies (" + (Objects.equals(resPoliciesStr, "") ? "empty" : resPoliciesStr) - + ") of bitstream (" + bitstream.getID() + ") were removed"; - addProvenanceMetadata(context, item, msg); - } } catch (SQLException | AuthorizeException e) { throw new BulkAccessControlException(e); } } - /** - * Adds provenance metadata to an item, documenting changes made to its resource policies - * and bitstream. This method records the user who performed the action, the action taken, - * and the timestamp of the action. It also appends a bitstream provenance message generated - * by the InstallItemService. - * - * @param context the current DSpace context, which provides details about the current user - * and authorization information. - * @param item the DSpace item to which the provenance metadata should be added. - * @param msg a custom message describing the action taken on the resource policies. - * @throws SQLException if there is a database access error while updating the item. - * @throws AuthorizeException if the current user is not authorized to add metadata to the item. - */ - protected void addProvenanceMetadata(Context context, Item item, String msg) - throws SQLException, AuthorizeException { - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - StringBuilder prov = new StringBuilder(); - prov.append(msg).append(" by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - } - /** * create the new resource policies of bitstream. * then, call {@link ItemService#adjustItemPolicies( @@ -665,14 +593,6 @@ protected void addProvenanceMetadata(Context context, Item item, String msg) */ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { - - String accConditionsScr = accessControl - .getBitstream() - .getAccessConditions() - .stream() - .map(accessCondition -> accessCondition.getName()) - .collect(Collectors.joining(";")); - accessControl.getBitstream() .getAccessConditions() .forEach(accessCondition -> createResourcePolicy(bitstream, accessCondition, @@ -680,15 +600,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream); mediaFilterService.updatePoliciesOfDerivativeBitstreams(context, item, bitstream); - - if (accConditionsScr.isEmpty()) { - return; - } - - // Add suitable provenance - String msg = "Access condition (" + accConditionsScr + ") was added to bitstream (" + - bitstream.getID() + ") of item"; - addProvenanceMetadata(context, item, msg) ; + provenanceService.setBitstreaPolicies(context, bitstream, item, accessControl); } /** diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java new file mode 100644 index 000000000000..5f7ce1d59b09 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java @@ -0,0 +1,17 @@ +package org.dspace.core; + +import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Bitstream; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; + +import java.sql.SQLException; + +public interface ProvenanceService { + public void setBitstreaPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; + + public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; + + public String removedReadPolicies(Context context, DSpaceObject dso, String type) throws SQLException, AuthorizeException; +} diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java new file mode 100644 index 000000000000..c0672edca657 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -0,0 +1,134 @@ +package org.dspace.core; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.dspace.app.bulkaccesscontrol.model.AccessCondition; +import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.authorize.service.ResourcePolicyService; +import org.dspace.content.Bitstream; +import org.dspace.content.DCDate; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchemaEnum; +import org.dspace.content.factory.ClarinServiceFactory; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; +import org.dspace.content.service.ItemService; +import org.dspace.content.service.clarin.ClarinItemService; +import org.dspace.eperson.EPerson; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ProvenanceServiceImpl implements ProvenanceService { + @Autowired + private ItemService itemService; + @Autowired + private ResourcePolicyService resourcePolicyService; + + protected ProvenanceServiceImpl() { + } + + private String extractAccessConditions(List accessConditions) { + return accessConditions.stream() + .map(AccessCondition::getName) + .collect(Collectors.joining(";")); + } + + @Override + public String removedReadPolicies(Context context, DSpaceObject dso, String type) throws SQLException, AuthorizeException { + List resPolicies = resourcePolicyService.find(context, dso, type); + if (resPolicies.isEmpty()) { + return null; + } + String resPoliciesStr = extractResourcePolicies(resPolicies); + if (dso.getType() == Constants.ITEM) { + addProvenanceForItem(context, (Item) dso, resPoliciesStr); + } else if (dso.getType() == Constants.BITSTREAM) { + addProvenanceForBitstream(context, (Bitstream) dso, resPoliciesStr); + } + return resPoliciesStr; + } + + private String extractResourcePolicies(List resPolicies) { + return resPolicies.stream() + .filter(rp -> rp.getAction() == Constants.READ) + .map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]", + rp.getRpName(), rp.getRpType(), rp.getAction(), + rp.getEPerson() != null ? rp.getEPerson().getEmail() : null, + rp.getGroup() != null ? rp.getGroup().getName() : null, + rp.getStartDate() != null ? rp.getStartDate().toString() : null, + rp.getEndDate() != null ? rp.getEndDate().toString() : null)) + .collect(Collectors.joining(";")); + } + + @Override + public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); + if (!resPoliciesStr.isEmpty()) { + String msg = "Access condition (" + resPoliciesStr + ") was added to item"; + addProvenanceMetadata(context, item, msg); + } + } + + @Override + public void setBitstreaPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); + if (!accConditionsStr.isEmpty()) { + // Add suitable provenance + String msg = "Access condition (" + accConditionsStr + ") was added to bitstream (" + + bitstream.getID() + ") of item"; + addProvenanceMetadata(context, item, msg); + } + } + + /** + * Adds provenance metadata to an item, documenting changes made to its resource policies + * and bitstream. This method records the user who performed the action, the action taken, + * and the timestamp of the action. It also appends a bitstream provenance message generated + * by the InstallItemService. + * + * @param context the current DSpace context, which provides details about the current user + * and authorization information. + * @param item the DSpace item to which the provenance metadata should be added. + * @param msg a custom message describing the action taken on the resource policies. + * @throws SQLException if there is a database access error while updating the item. + * @throws AuthorizeException if the current user is not authorized to add metadata to the item. + */ + private void addProvenanceMetadata(Context context, Item item, String msg) + throws SQLException, AuthorizeException { + InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + String timestamp = DCDate.getCurrent().toString(); + EPerson e = context.getCurrentUser(); + StringBuilder prov = new StringBuilder(); + prov.append(msg).append(" by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") + .append(timestamp).append("\n"); + prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", prov.toString()); + //Update item in DB + itemService.update(context, item); + } + private void addProvenanceForItem(Context context, Item item, String resPoliciesStr) throws SQLException, AuthorizeException { + String msg = "Resource policies (" + (resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr) + + ") of item (" + item.getID() + ") were removed"; + addProvenanceMetadata(context, item, msg); + } + + private void addProvenanceForBitstream(Context context, Bitstream bitstream, String resPoliciesStr) throws SQLException, AuthorizeException { + ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); + List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); + if (!items.isEmpty()) { + Item item = items.get(0); + String msg = "Resource policies (" + (resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr) + + ") of bitstream (" + bitstream.getID() + ") were removed"; + addProvenanceMetadata(context, item, msg); + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java index e7260fc2b4f4..4b9621faf478 100644 --- a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java +++ b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java @@ -7,6 +7,7 @@ */ package org.dspace.core.factory; +import org.dspace.core.ProvenanceService; import org.dspace.core.service.LicenseService; import org.dspace.core.service.NewsService; import org.dspace.core.service.PluginService; @@ -29,6 +30,8 @@ public abstract class CoreServiceFactory { public abstract ClientInfoService getClientInfoService(); + public abstract ProvenanceService getProvenanceService(); + public static CoreServiceFactory getInstance() { return DSpaceServicesFactory.getInstance().getServiceManager() .getServiceByName("coreServiceFactory", CoreServiceFactory.class); diff --git a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java index 7db3ad24d78b..6af8209a2ecf 100644 --- a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java @@ -7,6 +7,7 @@ */ package org.dspace.core.factory; +import org.dspace.core.ProvenanceService; import org.dspace.core.service.LicenseService; import org.dspace.core.service.NewsService; import org.dspace.core.service.PluginService; @@ -33,6 +34,9 @@ public class CoreServiceFactoryImpl extends CoreServiceFactory { @Autowired(required = true) private ClientInfoService clientInfoService; + @Autowired(required = true) + private ProvenanceService provenanceService; + @Override public LicenseService getLicenseService() { return licenseService; @@ -51,4 +55,9 @@ public PluginService getPluginService() { public ClientInfoService getClientInfoService() { return clientInfoService; } + + @Override + public ProvenanceService getProvenanceService() { + return provenanceService; + } } diff --git a/dspace/config/spring/api/core-services.xml b/dspace/config/spring/api/core-services.xml index 305d41f64ee5..e1480cb9e981 100644 --- a/dspace/config/spring/api/core-services.xml +++ b/dspace/config/spring/api/core-services.xml @@ -82,6 +82,7 @@ + From 0b3c0d7532064f817de0f181402cf31ba5991724 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Fri, 27 Sep 2024 10:54:54 +0200 Subject: [PATCH 21/54] create class for provenance management --- .../bulkaccesscontrol/BulkAccessControl.java | 9 +- .../core/ProvenanceMessageProvider.java | 28 ++ .../core/ProvenanceMessageProviderImpl.java | 122 ++++++++ .../org/dspace/core/ProvenanceService.java | 28 +- .../dspace/core/ProvenanceServiceImpl.java | 292 +++++++++++++----- .../org/dspace/core/provenance_messages.json | 15 + .../rest/BundleUploadBitstreamController.java | 35 +-- .../app/rest/ItemAddBundleController.java | 29 +- ...mOwningCollectionUpdateRestController.java | 27 +- .../rest/MappedCollectionRestController.java | 24 +- .../operation/BitstreamRemoveOperation.java | 52 +--- .../DSpaceObjectMetadataAddOperation.java | 45 +-- .../DSpaceObjectMetadataRemoveOperation.java | 55 +--- .../DSpaceObjectMetadataReplaceOperation.java | 46 +-- .../ItemDiscoverableReplaceOperation.java | 26 +- .../patch/operation/PatchOperation.java | 32 +- .../dspace/app/rest/ProvenanceServiceIT.java | 192 ++++++++++++ .../app/rest/provenance-patch-suite.json | 5 + 18 files changed, 647 insertions(+), 415 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java create mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java create mode 100644 dspace-api/src/main/java/org/dspace/core/provenance_messages.json create mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java create mode 100644 dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index a2d89375bf5c..4e9ad7fe9935 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -466,9 +466,6 @@ private void updateItemPolicies(Item item, BulkAccessControlInput accessControl) */ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { - - //String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); - accessControl .getItem() .getAccessConditions() @@ -477,10 +474,6 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) itemService.adjustItemPolicies(context, item, item.getOwningCollection(), false); -// if (resPoliciesStr.isEmpty()) { -// String msg = "Access condition (" + resPoliciesStr + ") was added to item"; -// addProvenanceMetadata(context, item, msg); -// } provenanceService.setItemPolicies(context, item, accessControl); } @@ -600,7 +593,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream); mediaFilterService.updatePoliciesOfDerivativeBitstreams(context, item, bitstream); - provenanceService.setBitstreaPolicies(context, bitstream, item, accessControl); + provenanceService.setBitstreamPolicies(context, bitstream, item, accessControl); } /** diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java new file mode 100644 index 000000000000..56c827ce82b7 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -0,0 +1,28 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.core; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.Bitstream; +import org.dspace.content.Item; +import org.dspace.content.MetadataField; + +import java.sql.SQLException; +import java.util.List; + +public interface ProvenanceMessageProvider { + public String getMessage(Context context, String templateKey, Object... args) throws SQLException, AuthorizeException; + public String getMessage(Context context, String templateKey, Item item, Object... args) throws SQLException, AuthorizeException; + public String getMessage(String templateKey, Object... args); + public String addCollectionsToMessage(Item item) throws SQLException, AuthorizeException; + public String getBitstreamMessage(Bitstream bitstream); + public String getResourcePoliciesMessage(List resPolicies); + public String getMetadata(String oldMtdKey, String oldMtdValue); + public String getMetadataField(MetadataField metadataField); +} diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java new file mode 100644 index 000000000000..cdef2dbddfe9 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java @@ -0,0 +1,122 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.core; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.Bitstream; +import org.dspace.content.Collection; +import org.dspace.content.DCDate; +import org.dspace.content.Item; +import org.dspace.content.MetadataField; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; +import org.dspace.eperson.EPerson; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider { + private Map messageTemplates; + + @Autowired + private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + + @Autowired + public ProvenanceMessageProviderImpl() { + loadMessageTemplates(); + } + + private void loadMessageTemplates() { + ObjectMapper mapper = new ObjectMapper(); + try { + messageTemplates = mapper.readValue(Files.readAllBytes(Paths.get("C:\\workspace\\DSpace\\dspace-api\\src\\main\\java\\org\\dspace\\core\\provenance_messages.json")), Map.class); + } catch (IOException e) { + throw new RuntimeException("Failed to load message templates", e); + } + } + + @Override + public String getMessage(Context context, String templateKey, Item item, Object... args) throws SQLException, AuthorizeException { + String msg = getMessage(context, templateKey, args); + msg = msg + "\n" + installItemService.getBitstreamProvenanceMessage(context, item); + return msg; + } + + @Override + public String getMessage(String templateKey, Object... args) { + String template = messageTemplates.get(templateKey); + if (template == null) { + throw new IllegalArgumentException("No message template found for key: " + templateKey); + } + return String.format(template, args); + } + + @Override + public String getMessage(Context context, String templateKey, Object... args) { + EPerson currentUser = context.getCurrentUser(); + String timestamp = DCDate.getCurrent().toString(); + String details = getMessage(templateKey, args); + return String.format("%s by %s (%s) on %s", + details, + currentUser.getFullName(), + currentUser.getEmail(), + timestamp); + } + + @Override + public String addCollectionsToMessage(Item item) throws SQLException, AuthorizeException { + String msg = "Item was in collections:\n"; + List collsList = item.getCollections(); + for (Collection coll : collsList) { + msg = msg + coll.getName() + " (ID: " + coll.getID() + ")\n"; + } + return msg; + } + + @Override + public String getBitstreamMessage(Bitstream bitstream) { + // values of deleted bitstream + String msg = bitstream.getName() + ": " + + bitstream.getSizeBytes() + " bytes, checksum: " + + bitstream.getChecksum() + " (" + + bitstream.getChecksumAlgorithm() + ")\n"; + return msg; + } + + @Override + public String getResourcePoliciesMessage(List resPolicies) { + return resPolicies.stream() + .filter(rp -> rp.getAction() == Constants.READ) + .map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]", + rp.getRpName(), rp.getRpType(), rp.getAction(), + rp.getEPerson() != null ? rp.getEPerson().getEmail() : null, + rp.getGroup() != null ? rp.getGroup().getName() : null, + rp.getStartDate() != null ? rp.getStartDate().toString() : null, + rp.getEndDate() != null ? rp.getEndDate().toString() : null)) + .collect(Collectors.joining(";")); + } + + @Override + public String getMetadata(String oldMtdKey, String oldMtdValue) { + return oldMtdKey + ": " + oldMtdValue; + } + + @Override + public String getMetadataField(MetadataField metadataField) { + return metadataField.toString() + .replace('_', '.'); + } +} diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java index 5f7ce1d59b09..6f8fa5592678 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java @@ -1,17 +1,43 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ package org.dspace.core; import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataField; +import org.dspace.content.MetadataValue; import java.sql.SQLException; +import java.util.List; public interface ProvenanceService { - public void setBitstreaPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; + public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; public String removedReadPolicies(Context context, DSpaceObject dso, String type) throws SQLException, AuthorizeException; + public void uploadBitstream(Context context, Bundle bundle) throws SQLException, AuthorizeException; + public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException; + + public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; + public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; + public void deletedItemFromMapped(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; + public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException; + public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException; + public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException; + public void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, + int indexInt) throws SQLException, AuthorizeException; + public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) throws SQLException, AuthorizeException; + public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) throws SQLException, AuthorizeException; + public void makeDiscoverable(Context context, Item item, boolean discoverable) throws SQLException, AuthorizeException; } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index c0672edca657..6e7aba1ab5a3 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -1,38 +1,64 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ package org.dspace.core; -import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.dspace.app.bulkaccesscontrol.model.AccessCondition; import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.Bitstream; -import org.dspace.content.DCDate; +import org.dspace.content.Bundle; +import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.factory.ClarinServiceFactory; -import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.InstallItemService; +import org.dspace.content.MetadataValue; +import org.dspace.content.clarin.ClarinLicenseResourceMapping; +import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinItemService; -import org.dspace.eperson.EPerson; +import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; import org.springframework.beans.factory.annotation.Autowired; -import java.io.File; -import java.io.IOException; import java.sql.SQLException; import java.util.List; -import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; public class ProvenanceServiceImpl implements ProvenanceService { + private static final Logger log = LogManager.getLogger(); + @Autowired private ItemService itemService; @Autowired private ResourcePolicyService resourcePolicyService; + @Autowired + private ClarinItemService clarinItemService; + @Autowired + private ClarinLicenseResourceMappingService clarinResourceMappingService; + @Autowired + private BitstreamService bitstreamService; + + private ProvenanceMessageProvider messageProvider = new ProvenanceMessageProviderImpl(); + - protected ProvenanceServiceImpl() { + + private void addProvenanceMetadata(Context context, Item item, String msg) + throws SQLException, AuthorizeException { + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", msg.toString()); + itemService.update(context, item); // Update item in DB + //context.commit(); } private String extractAccessConditions(List accessConditions) { @@ -41,94 +67,220 @@ private String extractAccessConditions(List accessConditions) { .collect(Collectors.joining(";")); } + private Item getItem(Context context, Bitstream bitstream) throws SQLException { + List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); + if (items.isEmpty()) { + log.warn("Bitstream (" + bitstream.getID() + ") is not assigned to any item."); + return null; + } + return items.get(0); + } + + @Override + public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); + if (!resPoliciesStr.isEmpty()) { + String msg = messageProvider.getMessage(context,"accessCondition", resPoliciesStr, + "item", item.getID()); + addProvenanceMetadata(context, item, msg); + } + } + @Override public String removedReadPolicies(Context context, DSpaceObject dso, String type) throws SQLException, AuthorizeException { List resPolicies = resourcePolicyService.find(context, dso, type); if (resPolicies.isEmpty()) { return null; } - String resPoliciesStr = extractResourcePolicies(resPolicies); + String resPoliciesStr = messageProvider.getResourcePoliciesMessage(resPolicies); if (dso.getType() == Constants.ITEM) { - addProvenanceForItem(context, (Item) dso, resPoliciesStr); + Item item = (Item) dso; + String msg = messageProvider.getMessage(context,"resourcePoliciesRemoved", + resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "item", item.getID()); + addProvenanceMetadata(context, item, msg); } else if (dso.getType() == Constants.BITSTREAM) { - addProvenanceForBitstream(context, (Bitstream) dso, resPoliciesStr); + Bitstream bitstream = (Bitstream) dso; + Item item = getItem(context, bitstream); + if (!Objects.isNull(item)) { + String msg = messageProvider.getMessage(context,"resourcePoliciesRemoved", + resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "bitstream", bitstream.getID()); + addProvenanceMetadata(context, item, msg); + } } return resPoliciesStr; } - private String extractResourcePolicies(List resPolicies) { - return resPolicies.stream() - .filter(rp -> rp.getAction() == Constants.READ) - .map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]", - rp.getRpName(), rp.getRpType(), rp.getAction(), - rp.getEPerson() != null ? rp.getEPerson().getEmail() : null, - rp.getGroup() != null ? rp.getGroup().getName() : null, - rp.getStartDate() != null ? rp.getStartDate().toString() : null, - rp.getEndDate() != null ? rp.getEndDate().toString() : null)) - .collect(Collectors.joining(";")); + @Override + public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); + if (!accConditionsStr.isEmpty()) { + String msg = messageProvider.getMessage(context,"accessCondition", accConditionsStr, + "bitstream", bitstream.getID()); + addProvenanceMetadata(context, item, msg); + } } @Override - public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { - String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); - if (!resPoliciesStr.isEmpty()) { - String msg = "Access condition (" + resPoliciesStr + ") was added to item"; + public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { + String oldLicense = null; + List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); + for (Bundle clarinBundle : bundles) { + List bitstreamList = clarinBundle.getBitstreams(); + for (Bitstream bundleBitstream : bitstreamList) { + if (Objects.isNull(oldLicense)) { + List mappings = + this.clarinResourceMappingService.findByBitstreamUUID( + context, bundleBitstream.getID()); + if (!mappings.isEmpty()) { + oldLicense = mappings.get(0).getLicense().getName(); + } + } + } + } + + String msg = messageProvider.getMessage(context, "editLicense", item, + Objects.isNull(oldLicense) ? "empty" : oldLicense, + !newLicense ? "removed" : Objects.isNull(oldLicense) ? "added" : "updated"); + addProvenanceMetadata(context, item, msg); + } + + + @Override + public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { + String msg = messageProvider.getMessage(context, "moveItem", item, collection.getID()); + // Update item in DB + // Because a user can move an item without authorization turn off authorization + context.turnOffAuthorisationSystem(); + addProvenanceMetadata(context, item, msg); + context.restoreAuthSystemState(); + } + + @Override + public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { + String msg = messageProvider.getMessage(context, "mappedItem", + item.getID(), collection.getID()); + addProvenanceMetadata(context, item, msg); + } + + @Override + public void deletedItemFromMapped(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { + String msg = messageProvider.getMessage(context, "deletedItemFromMapped", + item.getID(), collection.getID()); + addProvenanceMetadata(context, item, msg); + } + + @Override + public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException { + Item item = getItem(context, bitstream); + if (!Objects.isNull(item)) { + String msg = messageProvider.getMessage(context, "editBitstream", item, + item.getID(), messageProvider.getBitstreamMessage(bitstream)); addProvenanceMetadata(context, item, msg); } } @Override - public void setBitstreaPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { - String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); - if (!accConditionsStr.isEmpty()) { + public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { + if (Constants.ITEM == dso.getType()) { // Add suitable provenance - String msg = "Access condition (" + accConditionsStr + ") was added to bitstream (" + - bitstream.getID() + ") of item"; + String msg = messageProvider.getMessage(context, "itemMetadata", + messageProvider.getMetadataField(metadataField), "added"); + addProvenanceMetadata(context, (Item) dso, msg); + } + + if (dso.getType() == Constants.BITSTREAM) { + // Add suitable provenance + Bitstream bitstream = (Bitstream) dso; + Item item = getItem(context, bitstream); + if (!Objects.isNull(item)) { + String msg = messageProvider.getMessage(context, "bitstreamMetadata", item, + messageProvider.getMetadataField(metadataField), "added by", + messageProvider.getBitstreamMessage(bitstream)); + addProvenanceMetadata(context, item, msg); + } + } + } + + @Override + public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { + if (dso.getType() != Constants.BITSTREAM) { + return; + } + String oldMtdKey = null; + String oldMtdValue = null; + List mtd = bitstreamService.getMetadata((Bitstream) dso, metadataField.getMetadataSchema().getName(), + metadataField.getElement(), metadataField.getQualifier(), Item.ANY); + if (!CollectionUtils.isEmpty(mtd)) { + oldMtdKey = mtd.get(0).getMetadataField().getElement(); + oldMtdValue = mtd.get(0).getValue(); + } + // Add suitable provenance + Bitstream bitstream = (Bitstream) dso; + Item item = getItem(context, bitstream); + if (!Objects.isNull(item)) { + String msg = messageProvider.getMessage(context, "bitstreamMetadata", item, + messageProvider.getMetadata(oldMtdKey, oldMtdValue), + "deleted from", messageProvider.getBitstreamMessage(bitstream)); addProvenanceMetadata(context, item, msg); } } - /** - * Adds provenance metadata to an item, documenting changes made to its resource policies - * and bitstream. This method records the user who performed the action, the action taken, - * and the timestamp of the action. It also appends a bitstream provenance message generated - * by the InstallItemService. - * - * @param context the current DSpace context, which provides details about the current user - * and authorization information. - * @param item the DSpace item to which the provenance metadata should be added. - * @param msg a custom message describing the action taken on the resource policies. - * @throws SQLException if there is a database access error while updating the item. - * @throws AuthorizeException if the current user is not authorized to add metadata to the item. - */ - private void addProvenanceMetadata(Context context, Item item, String msg) - throws SQLException, AuthorizeException { - InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - StringBuilder prov = new StringBuilder(); - prov.append(msg).append(" by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); + @Override + public void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, + int indexInt) throws SQLException, AuthorizeException { + if (dso.getType() != Constants.ITEM) { + return; + } + // Remember removed mtd + String oldMtdKey = messageProvider.getMetadataField(metadataValues.get(indexInt).getMetadataField()); + String oldMtdValue = metadataValues.get(indexInt).getValue(); + // Add suitable provenance + String msg = messageProvider.getMessage(context, "itemMetadata", + (Item) dso, messageProvider.getMetadata(oldMtdKey, oldMtdValue), "deleted"); + addProvenanceMetadata(context, (Item) dso, msg); } - private void addProvenanceForItem(Context context, Item item, String resPoliciesStr) throws SQLException, AuthorizeException { - String msg = "Resource policies (" + (resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr) - + ") of item (" + item.getID() + ") were removed"; - addProvenanceMetadata(context, item, msg); + + @Override + public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) throws SQLException, AuthorizeException { + if (dso.getType() != Constants.ITEM) { + return; + } + String msg = messageProvider.getMessage(context, "itemMetadata",(Item) dso, + messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), oldMtdVal), + "updated"); + addProvenanceMetadata(context, (Item) dso, msg); } - private void addProvenanceForBitstream(Context context, Bitstream bitstream, String resPoliciesStr) throws SQLException, AuthorizeException { - ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); - List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); - if (!items.isEmpty()) { - Item item = items.get(0); - String msg = "Resource policies (" + (resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr) - + ") of bitstream (" + bitstream.getID() + ") were removed"; - addProvenanceMetadata(context, item, msg); + @Override + public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) throws SQLException, AuthorizeException { + if (dso.getType() != Constants.BITSTREAM) { + return; } + + // Add suitable provenance + Bitstream bitstream = (Bitstream) dso; + Item item = getItem(context, bitstream); + if (!Objects.isNull(item)) { + String msg = messageProvider.getMessage(context, "itemReplaceSingleMetadata", item, + messageProvider.getBitstreamMessage(bitstream), + messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), oldMtdVal)); + addProvenanceMetadata(context, item, msg);; + } + } + + @Override + public void makeDiscoverable(Context context, Item item, boolean discoverable) throws SQLException, AuthorizeException { + // Add suitable provenance + String msg = messageProvider.getMessage(context, "discoverable", + item, discoverable ? "" : "non-") + messageProvider.addCollectionsToMessage(item); + addProvenanceMetadata(context, item, msg); + } + + @Override + public void uploadBitstream(Context context, Bundle bundle) throws SQLException, AuthorizeException { + Item item = bundle.getItems().get(0); + String msg = messageProvider.getMessage(context, "bundleAdded", item, bundle.getID()); + addProvenanceMetadata(context,item, msg); + itemService.update(context, item); } } diff --git a/dspace-api/src/main/java/org/dspace/core/provenance_messages.json b/dspace-api/src/main/java/org/dspace/core/provenance_messages.json new file mode 100644 index 000000000000..155e1d3d7a00 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/provenance_messages.json @@ -0,0 +1,15 @@ +{ + "accessCondition": "Access condition (%s) was added to %s (%s)", + "resourcePoliciesRemoved": "Resource policies (%s) of (%s) (%s) were removed", + "bundleAdded": "Item was added bitstream to bundle (%s)", + "editLicense": "License (%s) was %s", + "moveItem": "Item was moved from collection (%s) to different collection", + "mappedItem": "Item (%s) was mapped to collection (%s)", + "deletedItemFromMapped": "Item (%s) was deleted from mapped collection (%s)", + "editBitstream": "Item (%s) was deleted bitstream (%s)", + "itemMetadata": "Item metadata (%s) was %s", + "bitstreamMetadata": "Item metadata (%s) was %s bitstream (%s)", + "itemMetadata": "Item metadata (%s) was %s", + "itemReplaceSingleMetadata": "Item bitstream (%s) metadata (%s) was updated", + "discoverable": "Item was made %sdiscoverable" +} \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index 9bf42de43f10..749cd788a4c3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -27,14 +27,9 @@ import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bundle; -import org.dspace.content.DCDate; -import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.BundleService; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; import org.dspace.core.Context; -import org.dspace.eperson.EPerson; +import org.dspace.core.ProvenanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; @@ -78,18 +73,15 @@ public class BundleUploadBitstreamController { @Autowired private BundleService bundleService; - @Autowired - private ItemService itemService; - - @Autowired - private InstallItemService installItemService; - @Autowired private BundleRestRepository bundleRestRepository; @Autowired private ConverterService converter; + @Autowired + private ProvenanceService provenanceService; + /** * Method to upload a Bitstream to a Bundle with the given UUID in the URL. This will create a Bitstream with the * file provided in the request and attach this to the Item that matches the UUID in the URL. @@ -123,26 +115,11 @@ public ResponseEntity> uploadBitstream( e); throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e); } - - // We do this before calling `updateBitstream` because that function calls `context.commit` - // Add suitable provenance - EPerson e = context.getCurrentUser(); - String timestamp = DCDate.getCurrent().toString(); - Item item = bundle.getItems().get(0); - - StringBuilder prov = new StringBuilder(); - prov.append("Item was added bitstream to bundle (").append(bundle.getID()) - .append(") by ").append(e.getFullName()).append(" (").append(e.getEmail()) - .append(") on ").append(timestamp).append("\n"); try { - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); + provenanceService.uploadBitstream(context, bundle); } catch (SQLException ex) { throw new RuntimeException("SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + - "adding new provenance metadata.", ex); + "adding new provenance metadata.", ex); } catch (AuthorizeException ex) { throw new RuntimeException("AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + "when adding new provenance metadata.", ex); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 846264c29bd3..a4dafe630dfc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -42,6 +42,7 @@ import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.dspace.eperson.EPerson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -104,7 +105,7 @@ public class ItemAddBundleController { ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; @Autowired - InstallItemService installItemService; + ProvenanceService provenanceService; /** * Method to add a Bundle to an Item with the given UUID in the URL. This will create a Bundle with the @@ -173,19 +174,11 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, log.warn("Cannot find clarin license with id: " + licenseId + ". The old license will be detached, " + "but the new one will not be attached."); } + provenanceService.editLicense(context, item, Objects.isNull(clarinLicense)); List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); - String oldLicense = null; for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); for (Bitstream bundleBitstream : bitstreamList) { - if (Objects.isNull(oldLicense)) { - List mappings = - this.clarinLicenseResourceMappingService.findByBitstreamUUID( - context, bundleBitstream.getID()); - if (!mappings.isEmpty()) { - oldLicense = mappings.get(0).getLicense().getName(); - } - } // in case bitstream ID exists in license table for some reason .. just remove it this.clarinLicenseResourceMappingService.detachLicenses(context, bundleBitstream); if (Objects.nonNull(clarinLicense)) { @@ -198,22 +191,6 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, if (Objects.nonNull(clarinLicense)) { clarinLicenseService.addLicenseMetadataToItem(context, clarinLicense, item); } - - // Add suitable provenance - EPerson e = context.getCurrentUser(); - String timestamp = DCDate.getCurrent().toString(); - StringBuilder prov = new StringBuilder(); - - prov.append("License (").append(Objects.isNull(oldLicense) ? "empty" : oldLicense).append(") was ") - .append(Objects.isNull(clarinLicense) ? "removed" : Objects.isNull(oldLicense) ? "added" : "updated") - .append(" by ").append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - - // Update item in DB itemService.update(context, item); context.commit(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index 76831cb67409..c9cbb4ea9a10 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -35,6 +35,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; @@ -56,8 +57,6 @@ public class ItemOwningCollectionUpdateRestController { @Autowired ItemService itemService; - @Autowired - InstallItemService installItemService; @Autowired CollectionService collectionService; @@ -71,6 +70,9 @@ public class ItemOwningCollectionUpdateRestController { @Autowired Utils utils; + @Autowired + ProvenanceService provenanceService; + /** * This method will update the owning collection of the item that correspond to the provided item uuid, effectively * moving the item to the new collection. @@ -131,26 +133,7 @@ private Collection moveItem(final Context context, final Item item, final Collec final boolean inheritPolicies) throws SQLException, IOException, AuthorizeException { itemService.move(context, item, currentCollection, targetCollection, inheritPolicies); - - // Add suitable provenance - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - StringBuilder prov = new StringBuilder(); - - prov.append("Item was moved from collection (") - .append(currentCollection.getID()).append(") to different collection by ").append(e.getFullName()) - .append(" (").append(e.getEmail()).append(") on ").append(timestamp).append("\n"); - - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - // Update item in DB - // Because a user can move an item without authorization turn off authorization - context.turnOffAuthorisationSystem(); - itemService.update(context, item); - context.restoreAuthSystemState(); - + provenanceService.moveItem(context, item, currentCollection); // Necessary because Controller does not pass through general RestResourceController, and as such does not do // its commit in DSpaceRestRepository.createAndReturn() or similar context.commit(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index 8cacad9927cd..2ba35bbac229 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -33,6 +33,7 @@ import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -55,15 +56,15 @@ public class MappedCollectionRestController { @Autowired private ItemService itemService; - @Autowired - private InstallItemService installItemService; - @Autowired private CollectionService collectionService; @Autowired Utils utils; + @Autowired + ProvenanceService provenanceService; + /** * This method will add an Item to a Collection. The Collection object is encapsulated in the request due to the * text/uri-list consumer and the Item UUID comes from the path in the URL @@ -113,8 +114,7 @@ public void createCollectionToItemRelation(@PathVariable UUID uuid, collectionService.update(context, collectionToMapTo); // Add suitable provenance - String msg = "was mapped to collection"; - addApprovedProvenance(context, item, msg, collectionToMapTo); + provenanceService.mappedItem(context, item, collectionToMapTo); itemService.update(context, item); } else { @@ -164,8 +164,7 @@ public void deleteCollectionToItemRelation(@PathVariable UUID uuid, @PathVariabl collectionService.update(context, collection); // Add suitable provenance - String msg = "was deleted from mapped collection"; - addApprovedProvenance(context, item, msg, collection); + provenanceService.deletedItemFromMapped(context,item, collection); itemService.update(context, item); context.commit(); @@ -175,17 +174,6 @@ public void deleteCollectionToItemRelation(@PathVariable UUID uuid, @PathVariabl } } - public void addApprovedProvenance(Context context, Item item, String msg, Collection col) throws SQLException { - EPerson e = context.getCurrentUser(); - String timestamp = DCDate.getCurrent().toString(); - StringBuilder prov = new StringBuilder(); - prov.append("Item ").append(msg).append(" (").append(col.getID()).append(") by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", - "provenance", "en", prov.toString()); - } - private void checkIfItemIsTemplate(Item item) { if (item.getTemplateItemOf() != null) { throw new MethodNotAllowedException("Given item is a template item."); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index 14d8c623304d..3de199de7319 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -52,15 +52,6 @@ public class BitstreamRemoveOperation extends PatchOperation { @Autowired BitstreamService bitstreamService; - @Autowired - ItemService itemService; - - @Autowired - ClarinItemService clarinItemService; - - @Autowired - InstallItemService installItemService; - @Autowired AuthorizeService authorizeService; public static final String OPERATION_PATH_BITSTREAM_REMOVE = "/bitstreams/"; @@ -73,49 +64,10 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio throw new RESTBitstreamNotFoundException(bitstreamIDtoDelete); } authorizeBitstreamRemoveAction(context, bitstreamToDelete, Constants.DELETE); - try { - List items = clarinItemService.findByBitstreamUUID(context, UUID.fromString(bitstreamIDtoDelete)); - // The bitstream is assigned only into one Item. - Item item = null; - if (!CollectionUtils.isEmpty(items)) { - item = items.get(0); - } - - // values of deleted bitstream - StringBuilder bitstreamMsg = new StringBuilder(); - bitstreamMsg.append(bitstreamToDelete.getName()).append(": ") - .append(bitstreamToDelete.getSizeBytes()).append(" bytes, checksum: ") - .append(bitstreamToDelete.getChecksum()).append(" (") - .append(bitstreamToDelete.getChecksumAlgorithm()).append(")\n"); - - //delete bitstream + provenanceService.deleteBitstream(context, bitstreamToDelete); bitstreamService.delete(context, bitstreamToDelete); - - if (item == null) { - return null; - } - - // Add suitable provenance - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - - // Build some provenance data while we're at it. - StringBuilder prov = new StringBuilder(); - prov.append("Item was deleted bitstream (").append(bitstreamMsg).append(") by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - } catch (AuthorizeException e) { - throw new DSpaceBadRequestException( - "AuthorizeException in BitstreamRemoveOperation.perform while adding provenance metadata " + - "about the deleted item's bitstream.", e); - } catch (IOException e) { + } catch (AuthorizeException | IOException e) { throw new RuntimeException(e.getMessage(), e); } return null; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 49af741bf675..67fd804b1622 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -49,15 +49,6 @@ public class DSpaceObjectMetadataAddOperation extends Pa @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; - @Autowired - InstallItemService installItemService; - - @Autowired - ItemService itemService; - - @Autowired - ClarinItemService clarinItemService; - @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -90,40 +81,10 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi dsoService.addAndShiftRightMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), metadataValue.getLanguage(), metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); - - if (dso.getType() != Constants.ITEM && dso.getType() != Constants.BITSTREAM) { - return; - } - - if (dso.getType() == Constants.ITEM) { - // Add suitable provenance - Item item = (Item) dso; - String msg = "metadata (" + metadataField.toString() - .replace('_', '.') + ") was added"; - addProvenanceMetadata(context, item, msg); - } - - if (dso.getType() == Constants.BITSTREAM) { - // Add suitable provenance - Bitstream bitstream = (Bitstream) dso; - List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - // The bitstream is assigned only into one Item. - Item item = null; - if (CollectionUtils.isEmpty(items)) { - log.warn("Bitstream (" + dso.getID() + ") is not assigned to any item."); - return; - } - item = items.get(0); - String msg = "metadata (" + - metadataField.toString().replace('_', '.') + ") was added" - + " to bitstream (" + bitstream.getName() + ": " + bitstream.getSizeBytes() - + " bytes, checksum: " + bitstream.getChecksum() + " (" + - bitstream.getChecksumAlgorithm() + ")"; - addProvenanceMetadata(context, item, msg); - } + provenanceService.addMetadata(context, dso, metadataField); } catch (SQLException e) { - throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + - "metadata to dso.", e); + throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + + "metadata to dso.", e); } catch (AuthorizeException e) { throw new DSpaceBadRequestException( "AuthorizeException in DspaceObjectMetadataAddOperation.add " + diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 119325bd4997..c024edf561f2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -54,15 +54,6 @@ public class DSpaceObjectMetadataRemoveOperation extends @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; - @Autowired - InstallItemService installItemService; - - @Autowired - private ClarinItemService clarinItemService; - - @Autowired - private ItemService itemService; - @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -87,36 +78,10 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe metadataPatchUtils.checkMetadataFieldNotNull(metadataField); try { if (index == null) { - String oldMtdKey = null; - String oldMtdValue = null; - if (dso.getType() == Constants.BITSTREAM) { - List mtd = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), - metadataField.getElement(), metadataField.getQualifier(), Item.ANY); - if (!CollectionUtils.isEmpty(mtd)) { - oldMtdKey = mtd.get(0).getMetadataField().getElement(); - oldMtdValue = mtd.get(0).getValue(); - } - } + provenanceService.removeMetadata(context, dso, metadataField); // remove all metadata of this type dsoService.clearMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); - if (dso.getType() != Constants.BITSTREAM) { - return; - } - // Add suitable provenance - Bitstream bitstream = (Bitstream) dso; - List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - // The bitstream is assigned only into one Item. - Item item = null; - if (CollectionUtils.isEmpty(items)) { - log.warn("Bitstream (" + dso.getID() + ") is not assigned to any item."); - return; - } - item = items.get(0); - String msg = " metadata (" + oldMtdKey + ": " + oldMtdValue + ") was deleted from bitstream (" + - bitstream.getName() + ": " + bitstream.getSizeBytes() + " bytes, checksum: " + - bitstream.getChecksum() + " (" + bitstream.getChecksumAlgorithm() + "))"; - addProvenanceMetadata(context, item, msg); } else { // remove metadata at index List metadataValues = dsoService.getMetadata(dso, @@ -125,26 +90,10 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { - // Remember removed mtd - String oldMtdKey = null; - String oldMtdValue = null; - if (dso.getType() == Constants.ITEM) { - oldMtdKey = metadataValues.get(indexInt).getMetadataField().toString() - .replace('_', '.'); - oldMtdValue = metadataValues.get(indexInt).getValue(); - } + provenanceService.removeMetadataAtIndex(context, dso, metadataValues, indexInt); // remove that metadata dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); - - if (dso.getType() != Constants.ITEM) { - return; - } - - // Add suitable provenance - Item item = (Item) dso; - String msg = "metadata (" + oldMtdKey + ": " + oldMtdValue + ") was deleted"; - addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + "this type at that index"); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 141300c2175c..490358eddb65 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -49,20 +49,9 @@ */ @Component public class DSpaceObjectMetadataReplaceOperation extends PatchOperation { - private static final Logger log = LogManager.getLogger(); - @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; - @Autowired - InstallItemService installItemService; - - @Autowired - ItemService itemService; - - @Autowired - ClarinItemService clarinItemService; - @Override public R perform(Context context, R resource, Operation operation) throws SQLException { DSpaceObjectService dsoService = ContentServiceFactory.getInstance().getDSpaceObjectService(resource); @@ -185,16 +174,8 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac existingMdv.setLanguage(metadataValue.getLanguage()); existingMdv.setValue(metadataValue.getValue()); dsoService.setMetadataModified(dso); + provenanceService.replaceMetadata(context, dso, metadataField, oldMtdVal); - if (dso.getType() != Constants.ITEM) { - return; - } - - // Add suitable provenance - Item item = (Item) dso; - String msg = "metadata (" + metadataField.toString() - .replace('_', '.') + ": " + oldMtdVal + ")" + " was updated"; - addProvenanceMetadata(context, item, msg); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } @@ -246,30 +227,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D existingMdv.setValue(valueMdProperty); } dsoService.setMetadataModified(dso); - - if (dso.getType() != Constants.BITSTREAM) { - return; - } - - // Add suitable provenance - Bitstream bitstream = (Bitstream) dso; - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - List items = clarinItemService.findByBitstreamUUID(context, dso.getID()); - // The bitstream is assigned only into one Item. - Item item = null; - if (CollectionUtils.isEmpty(items)) { - log.warn("Bitstream (" + dso.getID() + ") is not assigned to any item."); - return; - } - item = items.get(0); - String msg = "bitstream (" + bitstream.getName() + ": " + - bitstream.getSizeBytes() + " bytes, checksum: " + - bitstream.getChecksum() + " (" + - bitstream.getChecksumAlgorithm() + ")" + ") metadata (" + - metadataField.toString().replace('_', '.') + ": " + oldMtdVal + ") was updated " + - "by " + e.getFullName() + "(" + e.getEmail() + ") on " + timestamp; - addProvenanceMetadata(context, item, msg); + provenanceService.replaceMetadataSingle(context, dso, metadataField, oldMtdVal); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index 66b5226ad404..e664005e4cf6 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -42,12 +42,6 @@ public class ItemDiscoverableReplaceOperation extends PatchOperation { */ private static final String OPERATION_PATH_DISCOVERABLE = "/discoverable"; - @Autowired - ItemService itemService; - - @Autowired - InstallItemService installItemService; - @Override public R perform(Context context, R object, Operation operation) { checkOperationValue(operation.getValue()); @@ -58,25 +52,9 @@ public R perform(Context context, R object, Operation operation) { throw new UnprocessableEntityException("A template item cannot be discoverable."); } item.setDiscoverable(discoverable); - - // Add suitable provenance - EPerson e = context.getCurrentUser(); - String timestamp = DCDate.getCurrent().toString(); - // Build some provenance data. - StringBuilder prov = new StringBuilder(); - prov.append("Item was made ").append( discoverable ? "" : "non-").append("discoverable by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ").append(timestamp) - .append("\n").append("Item was in collections:\n"); - List colls = item.getCollections(); - for (Collection coll : colls) { - prov.append(coll.getName()).append(" (ID: ").append(coll.getID()).append(")\n"); - } - try { - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), "description", - "provenance", "en", prov.toString()); - itemService.update(context, item); + provenanceService.makeDiscoverable(context, item, discoverable); + //tu } catch (SQLException ex) { throw new RuntimeException("SQLException occurred when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index 02388421bdda..a737eea74c58 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -19,6 +19,7 @@ import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; @@ -40,6 +41,9 @@ public abstract class PatchOperation { @Autowired ItemService itemService; + @Autowired + ProvenanceService provenanceService; + /** * Updates the rest model by applying the patch operation. * @@ -88,34 +92,6 @@ Boolean getBooleanOperationValue(Object value) { return bool; } - /** - * Adds provenance metadata to an item, documenting an action taken on the item. - * This method logs the user who performed the action, the action description, - * and the timestamp when the action occurred. It also appends a bitstream provenance - * message generated by the InstallItemService. - * - * @param context the current DSpace context, which provides details about the current user - * and authorization information. - * @param item the DSpace item to which the provenance metadata should be added. - * @param msg a custom message describing the action taken on the item. - * @throws SQLException if there is a database access error while updating the item. - * @throws AuthorizeException if the current user is not authorized to add metadata to the item. - */ - protected void addProvenanceMetadata(Context context, Item item, String msg) - throws SQLException, AuthorizeException { - String timestamp = DCDate.getCurrent().toString(); - EPerson e = context.getCurrentUser(); - StringBuilder prov = new StringBuilder(); - prov.append("Item ").append(msg).append(" by ") - .append(e.getFullName()).append(" (").append(e.getEmail()).append(") on ") - .append(timestamp).append("\n"); - prov.append(installItemService.getBitstreamProvenanceMessage(context, item)); - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", prov.toString()); - //Update item in DB - itemService.update(context, item); - } - /** * Determines whether or not this Patch Operation can do this patch (Object of operation and path gets checked) * @param objectToMatch Object whose class must be instance of type object diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java new file mode 100644 index 000000000000..a7b72c058b9d --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -0,0 +1,192 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.dspace.app.rest.matcher.CollectionMatcher; +import org.dspace.app.rest.matcher.ItemMatcher; +import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.ReplaceOperation; +import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.content.MetadataValue; +import org.dspace.content.service.ItemService; +import org.hamcrest.Matchers; +import org.hamcrest.core.StringContains; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.web.servlet.MvcResult; + +import javax.ws.rs.core.MediaType; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata; +import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist; +import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; +import static org.springframework.http.MediaType.parseMediaType; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { + static String PROVENANCE = "dc.description.provenance"; + private Collection collection; + private ObjectMapper objectMapper = new ObjectMapper(); + private JsonNode suite; + + @Autowired + private ItemService itemService; + + @Before + public void setup() throws Exception { + suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); + context.turnOffAuthorisationSystem(); + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + collection = CollectionBuilder.createCollection(context, parentCommunity).build(); + } + + private JsonNode preprocessingProvenance(String responseBody) throws JsonProcessingException { + //String responseBody = resultActions.andReturn().getResponse().getContentAsString(); + JsonNode responseJson = objectMapper.readTree(responseBody); + JsonNode responseMetadataJson = responseJson.get("metadata"); + if (responseMetadataJson.get(PROVENANCE) != null) { + // In the provenance metadata, there is a timestamp indicating when they were added. + // To ensure accurate comparison, remove that date. + String rspProvenance = responseMetadataJson.get(PROVENANCE).toString(); + // Regex to match the date pattern + String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; + Pattern pattern = Pattern.compile(datePattern); + Matcher matcher = pattern.matcher(rspProvenance); + String rspModifiedProvenance = rspProvenance; + while (matcher.find()) { + String dateString = matcher.group(0); + rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); + } + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNodePrv = objectMapper.readTree(rspModifiedProvenance); + // Replace the origin metadata with a value with the timestamp removed + ((ObjectNode) responseJson.get("metadata")).put(PROVENANCE, jsonNodePrv); + return responseJson; + } + return null; + } + + private Item createItem() { + context.turnOffAuthorisationSystem(); + Item item = ItemBuilder.createItem(context, collection) + .withTitle("Public item 1") + .withIssueDate("2017-10-17") + .withAuthor("Smith, Donald") + .makeUnDiscoverable() + .build(); + context.restoreAuthSystemState(); + return item; + } + + private void responseCheck(JsonNode response, String respKey) { + JsonNode expectedSubStr = suite.get(respKey); + JsonNode responseMetadata = response.get("metadata").get("dc.description.provenance"); + for (JsonNode expNode : expectedSubStr) { + boolean contains = false; + for (JsonNode node : responseMetadata) { + if (node.get("value").asText().contains(expNode.asText())) { + contains = true; + break; + } + } + if (!contains) { + Assert.fail("Metadata provenance do not contain expected data: " + expNode.asText()); + } + } + } + + private void itemCheck(Item item, String respKey) { + String expectedSubStr = suite.get(respKey).asText(); + List metadata = item.getMetadata(); + boolean contain = false; + for (MetadataValue value : metadata) { + if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { + continue; + } + if (value.getValue().contains(expectedSubStr)) { + contain = true; + break; + } + } + if (!contain) { + Assert.fail("Metadata provenance do not contain expected data: " + expectedSubStr); + } + } + + @Test + public void makeDsicoverableTest() throws Exception { + String token = getAuthToken(admin.getEmail(), password); + Item item = createItem(); +// List ops = new ArrayList(); +// ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", true); +// ops.add(replaceOperation); +// String patchBody = getPatchContent(ops); + + // make discoverable + MvcResult mvcResult = getClient(token).perform(patch("/api/core/items/" + item.getID() + + "/discoverable") +// .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.uuid", Matchers.is(item.getID().toString()))) + .andExpect(jsonPath("$.discoverable", Matchers.is(true))) + .andReturn(); + responseCheck(Objects.requireNonNull(preprocessingProvenance(mvcResult.getResponse().getContentAsString())), + "discoverable"); + } + + @Test + public void mappedCollection() throws Exception { + context.turnOffAuthorisationSystem(); + Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); + Item item = createItem(); + context.restoreAuthSystemState(); + + String adminToken = getAuthToken(admin.getEmail(), password); + + getClient(adminToken).perform( + post("/api/core/items/" + item.getID() + "/mappedCollections/") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content( + "https://localhost:8080/spring-rest/api/core/collections/" + col1.getID() + "\n" + ) + ); + + getClient().perform(get("/api/core/items/" + item.getID() + "/mappedCollections")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.mappedCollections", Matchers.containsInAnyOrder( + CollectionMatcher.matchCollectionEntry("Collection 1", col1.getID(), col1.getHandle()) + ))) + .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/core/items"))) + ; + itemCheck(itemService.find(context, item.getID()), "mapped"); + } +} diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json new file mode 100644 index 000000000000..812099d9bc27 --- /dev/null +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json @@ -0,0 +1,5 @@ +{ + "discoverable": "Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", + "mapped": "was mapped to collection" +} + From 64d84a11d5a3b523bbf7a2cec3ba3b63daf5a89a Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 1 Oct 2024 11:57:53 +0200 Subject: [PATCH 22/54] added metadata item and bitstream tests --- .../dspace/app/rest/ProvenanceServiceIT.java | 180 ++++++++++++++++-- .../app/rest/provenance-patch-suite.json | 7 +- 2 files changed, 172 insertions(+), 15 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index a7b72c058b9d..166adaaa77dc 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -11,18 +11,29 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import org.apache.lucene.util.Bits; +import org.checkerframework.checker.units.qual.A; import org.dspace.app.rest.matcher.CollectionMatcher; import org.dspace.app.rest.matcher.ItemMatcher; +import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; +import org.dspace.app.rest.model.patch.RemoveOperation; import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.authorize.AuthorizeException; +import org.dspace.builder.BitstreamBuilder; +import org.dspace.builder.BundleBuilder; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; +import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; import org.hamcrest.Matchers; import org.hamcrest.core.StringContains; @@ -31,9 +42,13 @@ import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultActions; import javax.ws.rs.core.MediaType; +import java.io.IOException; +import java.sql.SQLException; import java.util.ArrayList; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -41,8 +56,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import static java.nio.charset.Charset.defaultCharset; +import static org.apache.commons.io.IOUtils.toInputStream; import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata; import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist; +import static org.hamcrest.Matchers.is; import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; import static org.springframework.http.MediaType.parseMediaType; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -57,6 +75,8 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { @Autowired private ItemService itemService; + @Autowired + private BitstreamService bitstreamService; @Before public void setup() throws Exception { @@ -68,6 +88,19 @@ public void setup() throws Exception { collection = CollectionBuilder.createCollection(context, parentCommunity).build(); } + private String provenanceMetadataModified(String metadata) { + // Regex to match the date pattern + String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; + Pattern pattern = Pattern.compile(datePattern); + Matcher matcher = pattern.matcher(metadata); + String rspModifiedProvenance = metadata; + while (matcher.find()) { + String dateString = matcher.group(0); + rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); + } + return rspModifiedProvenance; + } + private JsonNode preprocessingProvenance(String responseBody) throws JsonProcessingException { //String responseBody = resultActions.andReturn().getResponse().getContentAsString(); JsonNode responseJson = objectMapper.readTree(responseBody); @@ -106,6 +139,15 @@ private Item createItem() { return item; } + private Bitstream createBitstream(Item item) throws SQLException, AuthorizeException, IOException { + context.turnOffAuthorisationSystem(); + Bundle bundle = BundleBuilder.createBundle(context, item).withName("test").build(); + Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, + toInputStream("Test Content", defaultCharset())).build(); + context.restoreAuthSystemState(); + return bitstream; + } + private void responseCheck(JsonNode response, String respKey) { JsonNode expectedSubStr = suite.get(respKey); JsonNode responseMetadata = response.get("metadata").get("dc.description.provenance"); @@ -123,15 +165,15 @@ private void responseCheck(JsonNode response, String respKey) { } } - private void itemCheck(Item item, String respKey) { + private void objectCheck(DSpaceObject obj, String respKey) { String expectedSubStr = suite.get(respKey).asText(); - List metadata = item.getMetadata(); + List metadata = obj.getMetadata(); boolean contain = false; for (MetadataValue value : metadata) { if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { continue; } - if (value.getValue().contains(expectedSubStr)) { + if (provenanceMetadataModified(value.getValue()).contains(expectedSubStr)) { contain = true; break; } @@ -142,25 +184,25 @@ private void itemCheck(Item item, String respKey) { } @Test - public void makeDsicoverableTest() throws Exception { + public void makeDiscoverableTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); Item item = createItem(); -// List ops = new ArrayList(); -// ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", true); -// ops.add(replaceOperation); -// String patchBody = getPatchContent(ops); + List ops = new ArrayList<>(); + ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", true); + ops.add(replaceOperation); + String patchBody = getPatchContent(ops); // make discoverable - MvcResult mvcResult = getClient(token).perform(patch("/api/core/items/" + item.getID() - + "/discoverable") -// .content(patchBody) + getClient(token).perform(patch("/api/core/items/" + item.getID()) + .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.uuid", Matchers.is(item.getID().toString()))) .andExpect(jsonPath("$.discoverable", Matchers.is(true))) .andReturn(); - responseCheck(Objects.requireNonNull(preprocessingProvenance(mvcResult.getResponse().getContentAsString())), - "discoverable"); + objectCheck(itemService.find(context, item.getID()), "discoverable"); + //responseCheck(Objects.requireNonNull(preprocessingProvenance(mvcResult.getResponse().getContentAsString())), + // "discoverable"); } @Test @@ -187,6 +229,116 @@ public void mappedCollection() throws Exception { ))) .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/core/items"))) ; - itemCheck(itemService.find(context, item.getID()), "mapped"); + objectCheck(itemService.find(context, item.getID()), "mapped"); + } + + @Test + public void addMetadata() throws Exception { + Item item = createItem(); + + String adminToken = getAuthToken(admin.getEmail(), password); + + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + AddOperation addOperation = new AddOperation("/metadata/dc.title", "Test"); + ops.add(addOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/items/" + item.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + + objectCheck(itemService.find(context, item.getID()), "addMetadata"); + } + + @Test + public void replaceMetadata() throws Exception { + Item item = createItem(); + + String adminToken = getAuthToken(admin.getEmail(), password); + int index = 0; + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title/" + index, "Test"); + ops.add(replaceOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/items/" + item.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + + objectCheck(itemService.find(context, item.getID()), "replaceMetadata"); + } + + @Test + public void removeMetadata() throws Exception { + Item item = createItem(); + + String adminToken = getAuthToken(admin.getEmail(), password); + int index = 0; + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + RemoveOperation removeOperation = new RemoveOperation("/metadata/dc.title" + index); + ops.add(removeOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/items/" + item.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + + objectCheck(itemService.find(context, item.getID()), "removeMetadata"); + } + + @Test + public void removeMetadataBitstream() throws Exception { + Item item = createItem(); + Bitstream bitstream = createBitstream(item); + String adminToken = getAuthToken(admin.getEmail(), password); + int index = 0; + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + AddOperation addOperation = new AddOperation("/metadata/dc.description", "test"); + ops.add(addOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/bitstreams/" + bitstream.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + } + + @Test + public void addMetadataBitstream() throws Exception { + Item item = createItem(); + Bitstream bitstream = createBitstream(item); + String adminToken = getAuthToken(admin.getEmail(), password); + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + AddOperation addOperation = new AddOperation("/metadata/dc.description", "test"); + ops.add(addOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/bitstreams/" + bitstream.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + } + + @Test + public void updateMetadataBitstream() throws Exception { + Item item = createItem(); + Bitstream bitstream = createBitstream(item); + String adminToken = getAuthToken(admin.getEmail(), password); + int index = 0; + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title" + index, "test 1"); + ops.add(replaceOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/bitstreams/" + bitstream.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); } } diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json index 812099d9bc27..27b65624771c 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json @@ -1,5 +1,10 @@ { "discoverable": "Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", - "mapped": "was mapped to collection" + "mapped": "was mapped to collection", + "addMetadata": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on", + "replaceMetadata": "Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "removeMetadata": "Item metadata (dc.title: Public item 1) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "removeBitstreamMtd": "Item metadata (dc.description) was added by bitstream", + "replaceBitstreamMtd": "Item metadata (dc.description: test) was updated by bitstream" } From 7c8f7e5d9122855783d5363db6e1dcbec1f058af Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 2 Oct 2024 10:14:32 +0200 Subject: [PATCH 23/54] tests for metadata provenance --- .../dspace/core/ProvenanceServiceImpl.java | 2 +- .../org/dspace/core/provenance_messages.json | 4 +- .../app/rest/ItemAddBundleController.java | 2 +- .../dspace/app/rest/ProvenanceServiceIT.java | 372 ++++++++++++++++-- .../app/rest/provenance-patch-suite.json | 16 +- 5 files changed, 354 insertions(+), 42 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index 6e7aba1ab5a3..4af5de728c50 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -123,7 +123,7 @@ public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item @Override public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { String oldLicense = null; - List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); + List bundles = item.getBundles(Constants.LICENSE_BUNDLE_NAME); for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); for (Bitstream bundleBitstream : bitstreamList) { diff --git a/dspace-api/src/main/java/org/dspace/core/provenance_messages.json b/dspace-api/src/main/java/org/dspace/core/provenance_messages.json index 155e1d3d7a00..07bc5486b7ac 100644 --- a/dspace-api/src/main/java/org/dspace/core/provenance_messages.json +++ b/dspace-api/src/main/java/org/dspace/core/provenance_messages.json @@ -11,5 +11,7 @@ "bitstreamMetadata": "Item metadata (%s) was %s bitstream (%s)", "itemMetadata": "Item metadata (%s) was %s", "itemReplaceSingleMetadata": "Item bitstream (%s) metadata (%s) was updated", - "discoverable": "Item was made %sdiscoverable" + "discoverable": "Item was made %sdiscoverable", + "movedToCol": "Item was moved from collection", + "removedFromCol": "Item was removed from collection" } \ No newline at end of file diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index a4dafe630dfc..c1095d2f1b19 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -174,7 +174,7 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, log.warn("Cannot find clarin license with id: " + licenseId + ". The old license will be detached, " + "but the new one will not be attached."); } - provenanceService.editLicense(context, item, Objects.isNull(clarinLicense)); + provenanceService.editLicense(context, item, !Objects.isNull(clarinLicense)); List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 166adaaa77dc..e10ee6d706ac 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -11,56 +11,66 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.lucene.util.Bits; -import org.checkerframework.checker.units.qual.A; -import org.dspace.app.rest.matcher.CollectionMatcher; -import org.dspace.app.rest.matcher.ItemMatcher; +import org.apache.commons.codec.CharEncoding; +import org.apache.commons.io.IOUtils; +import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.RemoveOperation; import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; import org.dspace.builder.BitstreamBuilder; import org.dspace.builder.BundleBuilder; +import org.dspace.builder.ClarinLicenseBuilder; +import org.dspace.builder.ClarinLicenseLabelBuilder; +import org.dspace.builder.ClarinLicenseResourceMappingBuilder; import org.dspace.builder.CollectionBuilder; import org.dspace.builder.CommunityBuilder; import org.dspace.builder.ItemBuilder; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; -import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; +import org.dspace.content.clarin.ClarinLicense; +import org.dspace.content.clarin.ClarinLicenseLabel; +import org.dspace.content.clarin.ClarinLicenseResourceMapping; import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; +import org.dspace.content.service.clarin.ClarinLicenseLabelService; +import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; +import org.dspace.content.service.clarin.ClarinLicenseService; +import org.dspace.core.Constants; import org.hamcrest.Matchers; -import org.hamcrest.core.StringContains; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.web.servlet.MvcResult; -import org.springframework.test.web.servlet.ResultActions; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import javax.ws.rs.core.MediaType; +import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.sql.SQLException; import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.nio.charset.Charset.defaultCharset; import static org.apache.commons.io.IOUtils.toInputStream; -import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadata; -import static org.dspace.app.rest.matcher.MetadataMatcher.matchMetadataDoesNotExist; -import static org.hamcrest.Matchers.is; import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; import static org.springframework.http.MediaType.parseMediaType; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; @@ -77,15 +87,30 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { private ItemService itemService; @Autowired private BitstreamService bitstreamService; + @Autowired + private ClarinLicenseResourceMappingService resourceMappingService; + @Autowired + private ClarinLicenseLabelService clarinLicenseLabelService; + @Autowired + private ClarinLicenseService clarinLicenseService; + @Autowired + private ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; + + private Path tempDir; + private String tempFilePath; @Before public void setup() throws Exception { + super.setUp(); suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) .withName("Parent Community") .build(); collection = CollectionBuilder.createCollection(context, parentCommunity).build(); + + tempDir = Files.createTempDirectory("bulkAccessTest"); + tempFilePath = tempDir + "/bulk-access.json"; } private String provenanceMetadataModified(String metadata) { @@ -131,17 +156,29 @@ private Item createItem() { context.turnOffAuthorisationSystem(); Item item = ItemBuilder.createItem(context, collection) .withTitle("Public item 1") - .withIssueDate("2017-10-17") - .withAuthor("Smith, Donald") - .makeUnDiscoverable() .build(); context.restoreAuthSystemState(); return item; } - private Bitstream createBitstream(Item item) throws SQLException, AuthorizeException, IOException { + private Bundle createBundle(Item item, String bundleName) throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + Bundle bundle = BundleBuilder.createBundle(context, item).withName(bundleName).build(); + context.restoreAuthSystemState(); + return bundle; + } + + private ClarinLicense createLicense(String name) throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + ClarinLicense clarinLicense = ClarinLicenseBuilder.createClarinLicense(context).build(); + clarinLicense.setName(name); + context.restoreAuthSystemState(); + return clarinLicense; + } + + private Bitstream createBitstream(Item item, String bundleName) throws SQLException, AuthorizeException, IOException { context.turnOffAuthorisationSystem(); - Bundle bundle = BundleBuilder.createBundle(context, item).withName("test").build(); + Bundle bundle = createBundle(item, Objects.isNull(bundleName) ? "test" : bundleName); Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, toInputStream("Test Content", defaultCharset())).build(); context.restoreAuthSystemState(); @@ -201,12 +238,29 @@ public void makeDiscoverableTest() throws Exception { .andExpect(jsonPath("$.discoverable", Matchers.is(true))) .andReturn(); objectCheck(itemService.find(context, item.getID()), "discoverable"); - //responseCheck(Objects.requireNonNull(preprocessingProvenance(mvcResult.getResponse().getContentAsString())), - // "discoverable"); } @Test - public void mappedCollection() throws Exception { + public void makeNonDiscoverableTest() throws Exception { + String token = getAuthToken(admin.getEmail(), password); + Item item = createItem(); + //item.setDiscoverable(true); + List ops = new ArrayList<>(); + ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", false); + ops.add(replaceOperation); + String patchBody = getPatchContent(ops); + + // make non-discoverable + getClient(token).perform(patch("/api/core/items/" + item.getID()) + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); + } + + + @Test + public void addedToMappedCollTest() throws Exception { context.turnOffAuthorisationSystem(); Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); Item item = createItem(); @@ -221,17 +275,13 @@ public void mappedCollection() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + col1.getID() + "\n" ) ); - - getClient().perform(get("/api/core/items/" + item.getID() + "/mappedCollections")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$._embedded.mappedCollections", Matchers.containsInAnyOrder( - CollectionMatcher.matchCollectionEntry("Collection 1", col1.getID(), col1.getHandle()) - ))) - .andExpect(jsonPath("$._links.self.href", Matchers.containsString("/api/core/items"))) - ; objectCheck(itemService.find(context, item.getID()), "mapped"); } + @Test + public void deletedFromMappedCollTest() throws Exception { + } + @Test public void addMetadata() throws Exception { Item item = createItem(); @@ -273,12 +323,11 @@ public void replaceMetadata() throws Exception { @Test public void removeMetadata() throws Exception { Item item = createItem(); - String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); - RemoveOperation removeOperation = new RemoveOperation("/metadata/dc.title" + index); + RemoveOperation removeOperation = new RemoveOperation("/metadata/dc.title/" + index); ops.add(removeOperation); String patchBody = getPatchContent(ops); getClient(adminToken).perform(patch("/api/core/items/" + item.getID()) @@ -292,7 +341,7 @@ public void removeMetadata() throws Exception { @Test public void removeMetadataBitstream() throws Exception { Item item = createItem(); - Bitstream bitstream = createBitstream(item); + Bitstream bitstream = createBitstream(item, "test"); String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; // Modify the entityType and verify the response already contains this modification @@ -310,7 +359,7 @@ public void removeMetadataBitstream() throws Exception { @Test public void addMetadataBitstream() throws Exception { Item item = createItem(); - Bitstream bitstream = createBitstream(item); + Bitstream bitstream = createBitstream(item, "test"); String adminToken = getAuthToken(admin.getEmail(), password); // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); @@ -327,12 +376,12 @@ public void addMetadataBitstream() throws Exception { @Test public void updateMetadataBitstream() throws Exception { Item item = createItem(); - Bitstream bitstream = createBitstream(item); + Bitstream bitstream = createBitstream(item, "test"); String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; - // Modify the entityType and verify the response already contains this modification + //Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); - ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title" + index, "test 1"); + ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title", "test 1"); ops.add(replaceOperation); String patchBody = getPatchContent(ops); getClient(adminToken).perform(patch("/api/core/bitstreams/" + bitstream.getID()) @@ -341,4 +390,253 @@ public void updateMetadataBitstream() throws Exception { .andExpect(status().isOk()); objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); } + + @Test + public void removeBitstreamFromItem() throws Exception { + Item item = createItem(); + Bitstream bitstream = createBitstream(item, "test"); + String adminToken = getAuthToken(admin.getEmail(), password); + // Modify the entityType and verify the response already contains this modification + List ops = new ArrayList<>(); + RemoveOperation removeOperation = new RemoveOperation("/bitstreams/" + bitstream.getID()); + ops.add(removeOperation); + String patchBody = getPatchContent(ops); + getClient(adminToken).perform(patch("/api/core/bitstreams") + .content(patchBody) + .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)); + objectCheck(itemService.find(context, item.getID()), "removeBitstream"); + } + + @Test + public void addBitstreamToItem() throws Exception { + Item item = createItem(); + Bundle bundle = createBundle(item, "test"); + + String token = getAuthToken(admin.getEmail(), password); + String input = "Hello, World!"; + context.turnOffAuthorisationSystem(); + MockMultipartFile file = new MockMultipartFile("file", "hello.txt", org.springframework.http.MediaType.TEXT_PLAIN_VALUE, + input.getBytes()); + context.restoreAuthSystemState(); + getClient(token) + .perform(MockMvcRequestBuilders.multipart("/api/core/bundles/" + bundle.getID() + "/bitstreams") + .file(file)) + .andExpect(status().isCreated()); + objectCheck(itemService.find(context, item.getID()), "addBitstream"); + } + + /** + * Create Clarin License Label object for testing purposes. + */ + private ClarinLicenseLabel createClarinLicenseLabel(String label, boolean extended, String title) + throws SQLException, AuthorizeException { + ClarinLicenseLabel clarinLicenseLabel = ClarinLicenseLabelBuilder.createClarinLicenseLabel(context).build(); + clarinLicenseLabel.setLabel(label); + clarinLicenseLabel.setExtended(extended); + clarinLicenseLabel.setTitle(title); + + clarinLicenseLabelService.update(context, clarinLicenseLabel); + return clarinLicenseLabel; + } + + private ClarinLicense createClarinLicense(String name, String definition) + throws SQLException, AuthorizeException { + ClarinLicense clarinLicense = ClarinLicenseBuilder.createClarinLicense(context).build(); + clarinLicense.setDefinition(definition); + clarinLicense.setName(name); + + // add ClarinLicenseLabels to the ClarinLicense + HashSet clarinLicenseLabels = new HashSet<>(); + ClarinLicenseLabel clarinLicenseLabel = createClarinLicenseLabel("lbl", false, "Test Title"); + clarinLicenseLabels.add(clarinLicenseLabel); + clarinLicense.setLicenseLabels(clarinLicenseLabels); + + clarinLicenseService.update(context, clarinLicense); + return clarinLicense; + } + + private ClarinLicenseResourceMapping createResourceMapping(ClarinLicense license, Bitstream bitstream) throws SQLException, AuthorizeException { + ClarinLicenseResourceMapping resourceMapping = ClarinLicenseResourceMappingBuilder.createClarinLicenseResourceMapping(context).build(); + resourceMapping.setLicense(license); + resourceMapping.setBitstream(bitstream); + return resourceMapping; + } + + @Test + public void updateLicenseTest() throws Exception { + Item item = createItem(); + Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); + ClarinLicense clarinLicense1 = createClarinLicense("Test 1", "Test Def"); + ClarinLicenseResourceMapping resourceMapping = createResourceMapping(clarinLicense1, bitstream); + ClarinLicense clarinLicense2 = createClarinLicense("Test 2", "Test Def"); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") + .param("licenseID", clarinLicense2.getID().toString())) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "updateLicense"); + } + + @Test + public void addLicenseTest() throws Exception { + Item item = createItem(); + ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") + .param("licenseID", clarinLicense.getID().toString())) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "addLicense"); + } + + @Test + public void removeLicenseTest() throws Exception { + Item item = createItem(); + Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); + ClarinLicense clarinLicense1 = createClarinLicense("Test", "Test Def"); + ClarinLicenseResourceMapping resourceMapping = createResourceMapping(clarinLicense1, bitstream); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles")) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "removeLicense"); + } + + private void buildJsonFile(String json) throws IOException { + File file = new File(tempDir + "/bulk-access.json"); + Path path = Paths.get(file.getAbsolutePath()); + Files.writeString(path, json, StandardCharsets.UTF_8); + } + + @Test + public void itemResourcePoliciesTest() throws Exception { +// context.turnOffAuthorisationSystem(); +//// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); +//// context.restoreAuthSystemState(); +//// String json = "{ \"item\": {\n" + +//// " \"mode\": \"add\",\n" + +//// " \"accessConditions\": [\n" + +//// " {\n" + +//// " \"name\": \"openaccess\"\n" + +//// " }\n" + +//// " ]\n" + +//// " }}\n"; +//// +//// buildJsonFile(json); +//// +//// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, +//// "-e", eperson.getEmail()}; +//// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); +//// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); +//// +//// item = itemService.find(context, item.getID()); +//// //objectCheck(item, "removeResPoliciesItem"); +//// objectCheck(item, "addAccessCondItem"); +// context.turnOffAuthorisationSystem(); +// +// Community community = CommunityBuilder.createCommunity(context) +// .withName("community") +// .build(); +// +// Collection collection = CollectionBuilder.createCollection(context, community) +// .withName("collection") +// .build(); +// +// Item item = ItemBuilder.createItem(context, collection).build(); +// +// context.restoreAuthSystemState(); + Item item = createItem(); + + String json = "{ \"item\": {\n" + + " \"mode\": \"add\",\n" + + " \"accessConditions\": [\n" + + " {\n" + + " \"name\": \"openaccess\"\n" + + " }\n" + + " ]\n" + + " }}\n"; + + buildJsonFile(json); + + String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath}; + + TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); + ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); + objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); + } + + + @Test + public void addRemoveBitstreamResourcePoliciesTest() throws Exception { + context.turnOffAuthorisationSystem(); + Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); + context.restoreAuthSystemState(); + Bundle bundle = createBundle(item, Constants.DEFAULT_BUNDLE_NAME); + context.turnOffAuthorisationSystem(); + String bitstreamOneContent = "Dummy content one"; + Bitstream bitstreamOne; + try (InputStream is = IOUtils.toInputStream(bitstreamOneContent, CharEncoding.UTF_8)) { + bitstreamOne = BitstreamBuilder.createBitstream(context, bundle, is) + .withName("bistream") + .build(); + } + + + context.restoreAuthSystemState(); + + String jsonOne = "{ \"bitstream\": {\n" + + " \"constraints\": {\n" + + " \"uuid\": [\"" + bitstreamOne.getID().toString() + "\"]\n" + + " },\n" + + " \"mode\": \"replace\",\n" + + " \"accessConditions\": [\n" + + " {\n" + + " \"name\": \"embargo\",\n" + + " \"startDate\": \"2024-06-24\"\n" + + " }\n" + + " ]\n" + + " }\n" + + "}\n"; + + buildJsonFile(jsonOne); + + String[] args = + new String[] {"bulk-access-control", + "-u", item.getID().toString(), + "-f", tempFilePath, + "-e", admin.getEmail()}; + + TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); + ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); + //objectCheck(item, "removeResPoliciesBitstream"); + objectCheck(item, "addAccessCondBitstream"); + } + + private Collection createCollection() { + context.turnOffAuthorisationSystem(); + Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); + context.restoreAuthSystemState(); + return col; + } + + @Test + public void moveItemToColTest() throws Exception { + Item item = createItem(); + Collection col = createCollection(); + + String token = getAuthToken(admin.getEmail(), password); + + getClient(token) + .perform(put("/api/core/items/" + item.getID() + "/owningCollection/") + .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) + .content( + "https://localhost:8080/spring-rest/api/core/collections/" + col.getID() + )) + .andExpect(status().isOk()); + objectCheck(item, "movedToCol"); + } + + @Test + public void moveItemFromColTest() throws Exception { + + } } diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json index 27b65624771c..3042378f6610 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json @@ -1,10 +1,22 @@ { "discoverable": "Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", + "nonDiscoverable": "Item was made non-discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", "mapped": "was mapped to collection", "addMetadata": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on", + "removedMapped": "was deleted from mapped collection", "replaceMetadata": "Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "removeMetadata": "Item metadata (dc.title: Public item 1) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "removeMetadata": "Item metadata (dc.title: Public item 1) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "removeBitstreamMtd": "Item metadata (dc.description) was added by bitstream", - "replaceBitstreamMtd": "Item metadata (dc.description: test) was updated by bitstream" + "replaceBitstreamMtd": "metadata (dc.title: test2) was updated by admin user (test@test.edu) on \nNo. of bitstreams: 1", + "removeBitstream": "was deleted bitstream", + "addBitstream": "Item was added bitstream to bundle", + "updateLicense": "License (Test 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", + "addLicense": "License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", + "removeLicense": "License (Test 1) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", + "removeResPoliciesItem": "were removed by admin user (test@test.edu) on", + "addAccessCondItem": "Access condition (embargo) was added to item", + "removeResPoliciesBitstream": "were removed by admin user (test@test.edu) on", + "addAccessCondBitstream": "Access condition (embargo) was added to bitstream", + "movedToCol": "Item was moved from collection " } From 43c5eb261e1c8c658f6c1d2a0b67a453233ddee5 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 2 Oct 2024 10:52:14 +0200 Subject: [PATCH 24/54] problem with access control test --- .../app/rest/ProvenanceMetadataCheck.java | 55 ++++++ .../dspace/app/rest/ProvenanceServiceIT.java | 182 +++++++++++------- .../rest/ProvenanceServiceWithDatabaseIT.java | 173 +++++++++++++++++ 3 files changed, 343 insertions(+), 67 deletions(-) create mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java create mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java new file mode 100644 index 000000000000..b1e4d7cd1b98 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java @@ -0,0 +1,55 @@ +package org.dspace.app.rest; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.content.DSpaceObject; +import org.dspace.content.MetadataValue; +import org.junit.Assert; + +import java.nio.file.Files; +import java.util.List; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ProvenanceMetadataCheck { + private JsonNode suite; + private ObjectMapper objectMapper = new ObjectMapper(); + + public void ProvenanceMetadataCheck() throws Exception { + suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); + } + + private String provenanceMetadataModified(String metadata) { + // Regex to match the date pattern + String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; + Pattern pattern = Pattern.compile(datePattern); + Matcher matcher = pattern.matcher(metadata); + String rspModifiedProvenance = metadata; + while (matcher.find()) { + String dateString = matcher.group(0); + rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); + } + return rspModifiedProvenance; + } + + public void objectCheck(DSpaceObject obj, String respKey) { + String expectedSubStr = suite.get(respKey).asText(); + List metadata = obj.getMetadata(); + boolean contain = false; + for (MetadataValue value : metadata) { + if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { + continue; + } + if (provenanceMetadataModified(value.getValue()).contains(expectedSubStr)) { + contain = true; + break; + } + } + if (!contain) { + Assert.fail("Metadata provenance do not contain expected data: " + expectedSubStr); + } + } +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index e10ee6d706ac..15a3855b1861 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -13,6 +13,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.file.PathUtils; +import org.dspace.AbstractIntegrationTestWithDatabase; import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; @@ -33,6 +35,7 @@ import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; +import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; @@ -46,6 +49,7 @@ import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.hamcrest.Matchers; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -81,7 +85,8 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { static String PROVENANCE = "dc.description.provenance"; private Collection collection; private ObjectMapper objectMapper = new ObjectMapper(); - private JsonNode suite; + private ProvenanceMetadataCheck provenanceCheck = new ProvenanceMetadataCheck(); + @Autowired private ItemService itemService; @@ -100,9 +105,10 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { private String tempFilePath; @Before - public void setup() throws Exception { + @Override + public void setUp() throws Exception { super.setUp(); - suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); + //suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) .withName("Parent Community") @@ -113,18 +119,7 @@ public void setup() throws Exception { tempFilePath = tempDir + "/bulk-access.json"; } - private String provenanceMetadataModified(String metadata) { - // Regex to match the date pattern - String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; - Pattern pattern = Pattern.compile(datePattern); - Matcher matcher = pattern.matcher(metadata); - String rspModifiedProvenance = metadata; - while (matcher.find()) { - String dateString = matcher.group(0); - rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); - } - return rspModifiedProvenance; - } + private JsonNode preprocessingProvenance(String responseBody) throws JsonProcessingException { //String responseBody = resultActions.andReturn().getResponse().getContentAsString(); @@ -185,40 +180,24 @@ private Bitstream createBitstream(Item item, String bundleName) throws SQLExcept return bitstream; } - private void responseCheck(JsonNode response, String respKey) { - JsonNode expectedSubStr = suite.get(respKey); - JsonNode responseMetadata = response.get("metadata").get("dc.description.provenance"); - for (JsonNode expNode : expectedSubStr) { - boolean contains = false; - for (JsonNode node : responseMetadata) { - if (node.get("value").asText().contains(expNode.asText())) { - contains = true; - break; - } - } - if (!contains) { - Assert.fail("Metadata provenance do not contain expected data: " + expNode.asText()); - } - } - } +// private void responseCheck(JsonNode response, String respKey) { +// JsonNode expectedSubStr = suite.get(respKey); +// JsonNode responseMetadata = response.get("metadata").get("dc.description.provenance"); +// for (JsonNode expNode : expectedSubStr) { +// boolean contains = false; +// for (JsonNode node : responseMetadata) { +// if (node.get("value").asText().contains(expNode.asText())) { +// contains = true; +// break; +// } +// } +// if (!contains) { +// Assert.fail("Metadata provenance do not contain expected data: " + expNode.asText()); +// } +// } +// } + - private void objectCheck(DSpaceObject obj, String respKey) { - String expectedSubStr = suite.get(respKey).asText(); - List metadata = obj.getMetadata(); - boolean contain = false; - for (MetadataValue value : metadata) { - if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { - continue; - } - if (provenanceMetadataModified(value.getValue()).contains(expectedSubStr)) { - contain = true; - break; - } - } - if (!contain) { - Assert.fail("Metadata provenance do not contain expected data: " + expectedSubStr); - } - } @Test public void makeDiscoverableTest() throws Exception { @@ -237,7 +216,7 @@ public void makeDiscoverableTest() throws Exception { .andExpect(jsonPath("$.uuid", Matchers.is(item.getID().toString()))) .andExpect(jsonPath("$.discoverable", Matchers.is(true))) .andReturn(); - objectCheck(itemService.find(context, item.getID()), "discoverable"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "discoverable"); } @Test @@ -255,7 +234,7 @@ public void makeNonDiscoverableTest() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); } @@ -275,7 +254,7 @@ public void addedToMappedCollTest() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + col1.getID() + "\n" ) ); - objectCheck(itemService.find(context, item.getID()), "mapped"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "mapped"); } @Test @@ -298,7 +277,7 @@ public void addMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "addMetadata"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addMetadata"); } @Test @@ -317,7 +296,7 @@ public void replaceMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "replaceMetadata"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "replaceMetadata"); } @Test @@ -335,7 +314,7 @@ public void removeMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeMetadata"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeMetadata"); } @Test @@ -353,7 +332,7 @@ public void removeMetadataBitstream() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); } @Test @@ -370,7 +349,7 @@ public void addMetadataBitstream() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); } @Test @@ -388,7 +367,7 @@ public void updateMetadataBitstream() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); } @Test @@ -404,7 +383,7 @@ public void removeBitstreamFromItem() throws Exception { getClient(adminToken).perform(patch("/api/core/bitstreams") .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)); - objectCheck(itemService.find(context, item.getID()), "removeBitstream"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeBitstream"); } @Test @@ -422,7 +401,7 @@ public void addBitstreamToItem() throws Exception { .perform(MockMvcRequestBuilders.multipart("/api/core/bundles/" + bundle.getID() + "/bitstreams") .file(file)) .andExpect(status().isCreated()); - objectCheck(itemService.find(context, item.getID()), "addBitstream"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addBitstream"); } /** @@ -474,7 +453,7 @@ public void updateLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", clarinLicense2.getID().toString())) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "updateLicense"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "updateLicense"); } @Test @@ -485,7 +464,7 @@ public void addLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", clarinLicense.getID().toString())) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "addLicense"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addLicense"); } @Test @@ -498,7 +477,7 @@ public void removeLicenseTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles")) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeLicense"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeLicense"); } private void buildJsonFile(String json) throws IOException { @@ -544,7 +523,68 @@ public void itemResourcePoliciesTest() throws Exception { // Item item = ItemBuilder.createItem(context, collection).build(); // // context.restoreAuthSystemState(); - Item item = createItem(); +// Item item = createItem(); +// +// String json = "{ \"item\": {\n" + +// " \"mode\": \"add\",\n" + +// " \"accessConditions\": [\n" + +// " {\n" + +// " \"name\": \"openaccess\"\n" + +// " }\n" + +// " ]\n" + +// " }}\n"; +// +// buildJsonFile(json); +// +// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, "-e", eperson.getEmail()}; +// +// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); +// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); +// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); +// context.turnOffAuthorisationSystem(); +// +// Community community = CommunityBuilder.createCommunity(context) +// .withName("community") +// .build(); +// +// Collection collection = CollectionBuilder.createCollection(context, community) +// .withName("collection") +// .build(); +// +// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); +// +// context.restoreAuthSystemState(); +// +// String json = "{ \"item\": {\n" + +// " \"mode\": \"add\",\n" + +// " \"accessConditions\": [\n" + +// " {\n" + +// " \"name\": \"openaccess\"\n" + +// " }\n" + +// " ]\n" + +// " }}\n"; +// +// buildJsonFile(json); +// +// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, +// "-e", eperson.getEmail()}; +// +// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); +// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); +// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("collection") + .build(); + + Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); + + context.restoreAuthSystemState(); String json = "{ \"item\": {\n" + " \"mode\": \"add\",\n" + @@ -557,11 +597,12 @@ public void itemResourcePoliciesTest() throws Exception { buildJsonFile(json); - String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath}; + String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, + "-e", eperson.getEmail()}; TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); - objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); } @@ -608,7 +649,7 @@ public void addRemoveBitstreamResourcePoliciesTest() throws Exception { TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); //objectCheck(item, "removeResPoliciesBitstream"); - objectCheck(item, "addAccessCondBitstream"); + provenanceCheck.objectCheck(item, "addAccessCondBitstream"); } private Collection createCollection() { @@ -632,7 +673,14 @@ public void moveItemToColTest() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + col.getID() )) .andExpect(status().isOk()); - objectCheck(item, "movedToCol"); + provenanceCheck.objectCheck(item, "movedToCol"); + } + + @After + @Override + public void destroy() throws Exception { + PathUtils.deleteDirectory(tempDir); + super.destroy(); } @Test diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java new file mode 100644 index 000000000000..cb9ab349c36b --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java @@ -0,0 +1,173 @@ +package org.dspace.app.rest; + +import org.apache.commons.io.file.PathUtils; +import org.dspace.AbstractIntegrationTestWithDatabase; +import org.dspace.app.launcher.ScriptLauncher; +import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.Item; +import org.dspace.content.service.ItemService; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class ProvenanceServiceWithDatabaseIT extends AbstractIntegrationTestWithDatabase { + + private Path tempDir; + private String tempFilePath; + private ProvenanceMetadataCheck provenanceCheck = new ProvenanceMetadataCheck(); + @Autowired + private ItemService itemService; + + @Before + @Override + public void setUp() throws Exception { + super.setUp(); + tempDir = Files.createTempDirectory("bulkAccessTest"); + tempFilePath = tempDir + "/bulk-access.json"; + } + + @After + @Override + public void destroy() throws Exception { + PathUtils.deleteDirectory(tempDir); + super.destroy(); + } + + private void buildJsonFile(String json) throws IOException { + File file = new File(tempDir + "/bulk-access.json"); + Path path = Paths.get(file.getAbsolutePath()); + Files.writeString(path, json, StandardCharsets.UTF_8); + } + + @Test + public void itemResourcePoliciesTest() throws Exception { +// context.turnOffAuthorisationSystem(); +//// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); +//// context.restoreAuthSystemState(); +//// String json = "{ \"item\": {\n" + +//// " \"mode\": \"add\",\n" + +//// " \"accessConditions\": [\n" + +//// " {\n" + +//// " \"name\": \"openaccess\"\n" + +//// " }\n" + +//// " ]\n" + +//// " }}\n"; +//// +//// buildJsonFile(json); +//// +//// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, +//// "-e", eperson.getEmail()}; +//// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); +//// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); +//// +//// item = itemService.find(context, item.getID()); +//// //objectCheck(item, "removeResPoliciesItem"); +//// objectCheck(item, "addAccessCondItem"); +// context.turnOffAuthorisationSystem(); +// +// Community community = CommunityBuilder.createCommunity(context) +// .withName("community") +// .build(); +// +// Collection collection = CollectionBuilder.createCollection(context, community) +// .withName("collection") +// .build(); +// +// Item item = ItemBuilder.createItem(context, collection).build(); +// +// context.restoreAuthSystemState(); +// Item item = createItem(); +// +// String json = "{ \"item\": {\n" + +// " \"mode\": \"add\",\n" + +// " \"accessConditions\": [\n" + +// " {\n" + +// " \"name\": \"openaccess\"\n" + +// " }\n" + +// " ]\n" + +// " }}\n"; +// +// buildJsonFile(json); +// +// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, "-e", eperson.getEmail()}; +// +// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); +// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); +// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); +// context.turnOffAuthorisationSystem(); +// +// Community community = CommunityBuilder.createCommunity(context) +// .withName("community") +// .build(); +// +// Collection collection = CollectionBuilder.createCollection(context, community) +// .withName("collection") +// .build(); +// +// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); +// +// context.restoreAuthSystemState(); +// +// String json = "{ \"item\": {\n" + +// " \"mode\": \"add\",\n" + +// " \"accessConditions\": [\n" + +// " {\n" + +// " \"name\": \"openaccess\"\n" + +// " }\n" + +// " ]\n" + +// " }}\n"; +// +// buildJsonFile(json); +// +// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, +// "-e", eperson.getEmail()}; +// +// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); +// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); +// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); + context.turnOffAuthorisationSystem(); + + Community community = CommunityBuilder.createCommunity(context) + .withName("community") + .build(); + + Collection collection = CollectionBuilder.createCollection(context, community) + .withName("collection") + .build(); + + Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); + + context.restoreAuthSystemState(); + + String json = "{ \"item\": {\n" + + " \"mode\": \"add\",\n" + + " \"accessConditions\": [\n" + + " {\n" + + " \"name\": \"openaccess\"\n" + + " }\n" + + " ]\n" + + " }}\n"; + + buildJsonFile(json); + + String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, + "-e", eperson.getEmail()}; + + TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); + ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); + provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); + } +} From b67b4b34fa94412afd296a6c1d746c028ea3cfb6 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 2 Oct 2024 13:52:18 +0200 Subject: [PATCH 25/54] tests do not work --- .../app/rest/ProvenanceMetadataCheck.java | 55 ---- .../dspace/app/rest/ProvenanceServiceIT.java | 301 +++--------------- .../rest/ProvenanceServiceWithDatabaseIT.java | 173 ---------- .../app/rest/provenance-patch-suite.json | 4 +- 4 files changed, 54 insertions(+), 479 deletions(-) delete mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java delete mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java deleted file mode 100644 index b1e4d7cd1b98..000000000000 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceMetadataCheck.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.dspace.app.rest; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.dspace.builder.CollectionBuilder; -import org.dspace.builder.CommunityBuilder; -import org.dspace.content.DSpaceObject; -import org.dspace.content.MetadataValue; -import org.junit.Assert; - -import java.nio.file.Files; -import java.util.List; -import java.util.Objects; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ProvenanceMetadataCheck { - private JsonNode suite; - private ObjectMapper objectMapper = new ObjectMapper(); - - public void ProvenanceMetadataCheck() throws Exception { - suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); - } - - private String provenanceMetadataModified(String metadata) { - // Regex to match the date pattern - String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; - Pattern pattern = Pattern.compile(datePattern); - Matcher matcher = pattern.matcher(metadata); - String rspModifiedProvenance = metadata; - while (matcher.find()) { - String dateString = matcher.group(0); - rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); - } - return rspModifiedProvenance; - } - - public void objectCheck(DSpaceObject obj, String respKey) { - String expectedSubStr = suite.get(respKey).asText(); - List metadata = obj.getMetadata(); - boolean contain = false; - for (MetadataValue value : metadata) { - if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { - continue; - } - if (provenanceMetadataModified(value.getValue()).contains(expectedSubStr)) { - contain = true; - break; - } - } - if (!contain) { - Assert.fail("Metadata provenance do not contain expected data: " + expectedSubStr); - } - } -} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 15a3855b1861..27723a58a745 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -11,19 +11,12 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; -import org.apache.commons.codec.CharEncoding; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.file.PathUtils; -import org.dspace.AbstractIntegrationTestWithDatabase; -import org.dspace.app.launcher.ScriptLauncher; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.RemoveOperation; import org.dspace.app.rest.model.patch.ReplaceOperation; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; -import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; import org.dspace.authorize.AuthorizeException; -import org.dspace.authorize.ResourcePolicy; import org.dspace.builder.BitstreamBuilder; import org.dspace.builder.BundleBuilder; import org.dspace.builder.ClarinLicenseBuilder; @@ -35,7 +28,6 @@ import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; -import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataValue; @@ -49,7 +41,6 @@ import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.hamcrest.Matchers; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -58,13 +49,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import javax.ws.rs.core.MediaType; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashSet; @@ -85,8 +70,7 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { static String PROVENANCE = "dc.description.provenance"; private Collection collection; private ObjectMapper objectMapper = new ObjectMapper(); - private ProvenanceMetadataCheck provenanceCheck = new ProvenanceMetadataCheck(); - + private JsonNode suite; @Autowired private ItemService itemService; @@ -101,9 +85,6 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { @Autowired private ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; - private Path tempDir; - private String tempFilePath; - @Before @Override public void setUp() throws Exception { @@ -114,12 +95,40 @@ public void setUp() throws Exception { .withName("Parent Community") .build(); collection = CollectionBuilder.createCollection(context, parentCommunity).build(); - - tempDir = Files.createTempDirectory("bulkAccessTest"); - tempFilePath = tempDir + "/bulk-access.json"; + suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); } + private String provenanceMetadataModified(String metadata) { + // Regex to match the date pattern + String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; + Pattern pattern = Pattern.compile(datePattern); + Matcher matcher = pattern.matcher(metadata); + String rspModifiedProvenance = metadata; + while (matcher.find()) { + String dateString = matcher.group(0); + rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); + } + return rspModifiedProvenance; + } + + public void objectCheck(DSpaceObject obj, String respKey) { + String expectedSubStr = suite.get(respKey).asText(); + List metadata = obj.getMetadata(); + boolean contain = false; + for (MetadataValue value : metadata) { + if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { + continue; + } + if (provenanceMetadataModified(value.getValue()).contains(expectedSubStr)) { + contain = true; + break; + } + } + if (!contain) { + Assert.fail("Metadata provenance do not contain expected data: " + expectedSubStr); + } + } private JsonNode preprocessingProvenance(String responseBody) throws JsonProcessingException { //String responseBody = resultActions.andReturn().getResponse().getContentAsString(); @@ -180,25 +189,6 @@ private Bitstream createBitstream(Item item, String bundleName) throws SQLExcept return bitstream; } -// private void responseCheck(JsonNode response, String respKey) { -// JsonNode expectedSubStr = suite.get(respKey); -// JsonNode responseMetadata = response.get("metadata").get("dc.description.provenance"); -// for (JsonNode expNode : expectedSubStr) { -// boolean contains = false; -// for (JsonNode node : responseMetadata) { -// if (node.get("value").asText().contains(expNode.asText())) { -// contains = true; -// break; -// } -// } -// if (!contains) { -// Assert.fail("Metadata provenance do not contain expected data: " + expNode.asText()); -// } -// } -// } - - - @Test public void makeDiscoverableTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); @@ -216,7 +206,7 @@ public void makeDiscoverableTest() throws Exception { .andExpect(jsonPath("$.uuid", Matchers.is(item.getID().toString()))) .andExpect(jsonPath("$.discoverable", Matchers.is(true))) .andReturn(); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "discoverable"); + objectCheck(itemService.find(context, item.getID()), "discoverable"); } @Test @@ -234,7 +224,7 @@ public void makeNonDiscoverableTest() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); + objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); } @@ -254,11 +244,7 @@ public void addedToMappedCollTest() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + col1.getID() + "\n" ) ); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "mapped"); - } - - @Test - public void deletedFromMappedCollTest() throws Exception { + objectCheck(itemService.find(context, item.getID()), "mapped"); } @Test @@ -277,7 +263,7 @@ public void addMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addMetadata"); + objectCheck(itemService.find(context, item.getID()), "addMetadata"); } @Test @@ -296,7 +282,7 @@ public void replaceMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "replaceMetadata"); + objectCheck(itemService.find(context, item.getID()), "replaceMetadata"); } @Test @@ -314,7 +300,7 @@ public void removeMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeMetadata"); + objectCheck(itemService.find(context, item.getID()), "removeMetadata"); } @Test @@ -332,7 +318,7 @@ public void removeMetadataBitstream() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); } @Test @@ -349,25 +335,26 @@ public void addMetadataBitstream() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); } @Test public void updateMetadataBitstream() throws Exception { Item item = createItem(); Bitstream bitstream = createBitstream(item, "test"); + bitstream.setName(context, "test"); String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; //Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); - ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title", "test 1"); + ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title/" + index, "test 1"); ops.add(replaceOperation); String patchBody = getPatchContent(ops); getClient(adminToken).perform(patch("/api/core/bitstreams/" + bitstream.getID()) .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); + objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); } @Test @@ -383,7 +370,7 @@ public void removeBitstreamFromItem() throws Exception { getClient(adminToken).perform(patch("/api/core/bitstreams") .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeBitstream"); + objectCheck(itemService.find(context, item.getID()), "removeBitstream"); } @Test @@ -401,7 +388,7 @@ public void addBitstreamToItem() throws Exception { .perform(MockMvcRequestBuilders.multipart("/api/core/bundles/" + bundle.getID() + "/bitstreams") .file(file)) .andExpect(status().isCreated()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addBitstream"); + objectCheck(itemService.find(context, item.getID()), "addBitstream"); } /** @@ -453,7 +440,7 @@ public void updateLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", clarinLicense2.getID().toString())) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "updateLicense"); + objectCheck(itemService.find(context, item.getID()), "updateLicense"); } @Test @@ -464,192 +451,20 @@ public void addLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", clarinLicense.getID().toString())) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addLicense"); + objectCheck(itemService.find(context, item.getID()), "addLicense"); } @Test public void removeLicenseTest() throws Exception { Item item = createItem(); Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); - ClarinLicense clarinLicense1 = createClarinLicense("Test", "Test Def"); - ClarinLicenseResourceMapping resourceMapping = createResourceMapping(clarinLicense1, bitstream); + ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); + ClarinLicenseResourceMapping resourceMapping = createResourceMapping(clarinLicense, bitstream); String token = getAuthToken(admin.getEmail(), password); getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles")) .andExpect(status().isOk()); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "removeLicense"); - } - - private void buildJsonFile(String json) throws IOException { - File file = new File(tempDir + "/bulk-access.json"); - Path path = Paths.get(file.getAbsolutePath()); - Files.writeString(path, json, StandardCharsets.UTF_8); - } - - @Test - public void itemResourcePoliciesTest() throws Exception { -// context.turnOffAuthorisationSystem(); -//// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); -//// context.restoreAuthSystemState(); -//// String json = "{ \"item\": {\n" + -//// " \"mode\": \"add\",\n" + -//// " \"accessConditions\": [\n" + -//// " {\n" + -//// " \"name\": \"openaccess\"\n" + -//// " }\n" + -//// " ]\n" + -//// " }}\n"; -//// -//// buildJsonFile(json); -//// -//// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, -//// "-e", eperson.getEmail()}; -//// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); -//// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); -//// -//// item = itemService.find(context, item.getID()); -//// //objectCheck(item, "removeResPoliciesItem"); -//// objectCheck(item, "addAccessCondItem"); -// context.turnOffAuthorisationSystem(); -// -// Community community = CommunityBuilder.createCommunity(context) -// .withName("community") -// .build(); -// -// Collection collection = CollectionBuilder.createCollection(context, community) -// .withName("collection") -// .build(); -// -// Item item = ItemBuilder.createItem(context, collection).build(); -// -// context.restoreAuthSystemState(); -// Item item = createItem(); -// -// String json = "{ \"item\": {\n" + -// " \"mode\": \"add\",\n" + -// " \"accessConditions\": [\n" + -// " {\n" + -// " \"name\": \"openaccess\"\n" + -// " }\n" + -// " ]\n" + -// " }}\n"; -// -// buildJsonFile(json); -// -// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, "-e", eperson.getEmail()}; -// -// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); -// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); -// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); -// context.turnOffAuthorisationSystem(); -// -// Community community = CommunityBuilder.createCommunity(context) -// .withName("community") -// .build(); -// -// Collection collection = CollectionBuilder.createCollection(context, community) -// .withName("collection") -// .build(); -// -// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); -// -// context.restoreAuthSystemState(); -// -// String json = "{ \"item\": {\n" + -// " \"mode\": \"add\",\n" + -// " \"accessConditions\": [\n" + -// " {\n" + -// " \"name\": \"openaccess\"\n" + -// " }\n" + -// " ]\n" + -// " }}\n"; -// -// buildJsonFile(json); -// -// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, -// "-e", eperson.getEmail()}; -// -// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); -// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); -// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); - context.turnOffAuthorisationSystem(); - - Community community = CommunityBuilder.createCommunity(context) - .withName("community") - .build(); - - Collection collection = CollectionBuilder.createCollection(context, community) - .withName("collection") - .build(); - - Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); - - context.restoreAuthSystemState(); - - String json = "{ \"item\": {\n" + - " \"mode\": \"add\",\n" + - " \"accessConditions\": [\n" + - " {\n" + - " \"name\": \"openaccess\"\n" + - " }\n" + - " ]\n" + - " }}\n"; - - buildJsonFile(json); - - String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, - "-e", eperson.getEmail()}; - - TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); - ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); - } - - - @Test - public void addRemoveBitstreamResourcePoliciesTest() throws Exception { - context.turnOffAuthorisationSystem(); - Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); - context.restoreAuthSystemState(); - Bundle bundle = createBundle(item, Constants.DEFAULT_BUNDLE_NAME); - context.turnOffAuthorisationSystem(); - String bitstreamOneContent = "Dummy content one"; - Bitstream bitstreamOne; - try (InputStream is = IOUtils.toInputStream(bitstreamOneContent, CharEncoding.UTF_8)) { - bitstreamOne = BitstreamBuilder.createBitstream(context, bundle, is) - .withName("bistream") - .build(); - } - - - context.restoreAuthSystemState(); - - String jsonOne = "{ \"bitstream\": {\n" + - " \"constraints\": {\n" + - " \"uuid\": [\"" + bitstreamOne.getID().toString() + "\"]\n" + - " },\n" + - " \"mode\": \"replace\",\n" + - " \"accessConditions\": [\n" + - " {\n" + - " \"name\": \"embargo\",\n" + - " \"startDate\": \"2024-06-24\"\n" + - " }\n" + - " ]\n" + - " }\n" + - "}\n"; - - buildJsonFile(jsonOne); - - String[] args = - new String[] {"bulk-access-control", - "-u", item.getID().toString(), - "-f", tempFilePath, - "-e", admin.getEmail()}; - - TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); - ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); - //objectCheck(item, "removeResPoliciesBitstream"); - provenanceCheck.objectCheck(item, "addAccessCondBitstream"); + objectCheck(itemService.find(context, item.getID()), "removeLicense"); } private Collection createCollection() { @@ -660,7 +475,7 @@ private Collection createCollection() { } @Test - public void moveItemToColTest() throws Exception { + public void moveItemColTest() throws Exception { Item item = createItem(); Collection col = createCollection(); @@ -673,18 +488,6 @@ public void moveItemToColTest() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + col.getID() )) .andExpect(status().isOk()); - provenanceCheck.objectCheck(item, "movedToCol"); - } - - @After - @Override - public void destroy() throws Exception { - PathUtils.deleteDirectory(tempDir); - super.destroy(); - } - - @Test - public void moveItemFromColTest() throws Exception { - + objectCheck(itemService.find(context, item.getID()), "movedItemCol"); } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java deleted file mode 100644 index cb9ab349c36b..000000000000 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceWithDatabaseIT.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.dspace.app.rest; - -import org.apache.commons.io.file.PathUtils; -import org.dspace.AbstractIntegrationTestWithDatabase; -import org.dspace.app.launcher.ScriptLauncher; -import org.dspace.app.scripts.handler.impl.TestDSpaceRunnableHandler; -import org.dspace.builder.CollectionBuilder; -import org.dspace.builder.CommunityBuilder; -import org.dspace.builder.ItemBuilder; -import org.dspace.content.Collection; -import org.dspace.content.Community; -import org.dspace.content.Item; -import org.dspace.content.service.ItemService; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class ProvenanceServiceWithDatabaseIT extends AbstractIntegrationTestWithDatabase { - - private Path tempDir; - private String tempFilePath; - private ProvenanceMetadataCheck provenanceCheck = new ProvenanceMetadataCheck(); - @Autowired - private ItemService itemService; - - @Before - @Override - public void setUp() throws Exception { - super.setUp(); - tempDir = Files.createTempDirectory("bulkAccessTest"); - tempFilePath = tempDir + "/bulk-access.json"; - } - - @After - @Override - public void destroy() throws Exception { - PathUtils.deleteDirectory(tempDir); - super.destroy(); - } - - private void buildJsonFile(String json) throws IOException { - File file = new File(tempDir + "/bulk-access.json"); - Path path = Paths.get(file.getAbsolutePath()); - Files.writeString(path, json, StandardCharsets.UTF_8); - } - - @Test - public void itemResourcePoliciesTest() throws Exception { -// context.turnOffAuthorisationSystem(); -//// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); -//// context.restoreAuthSystemState(); -//// String json = "{ \"item\": {\n" + -//// " \"mode\": \"add\",\n" + -//// " \"accessConditions\": [\n" + -//// " {\n" + -//// " \"name\": \"openaccess\"\n" + -//// " }\n" + -//// " ]\n" + -//// " }}\n"; -//// -//// buildJsonFile(json); -//// -//// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, -//// "-e", eperson.getEmail()}; -//// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); -//// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); -//// -//// item = itemService.find(context, item.getID()); -//// //objectCheck(item, "removeResPoliciesItem"); -//// objectCheck(item, "addAccessCondItem"); -// context.turnOffAuthorisationSystem(); -// -// Community community = CommunityBuilder.createCommunity(context) -// .withName("community") -// .build(); -// -// Collection collection = CollectionBuilder.createCollection(context, community) -// .withName("collection") -// .build(); -// -// Item item = ItemBuilder.createItem(context, collection).build(); -// -// context.restoreAuthSystemState(); -// Item item = createItem(); -// -// String json = "{ \"item\": {\n" + -// " \"mode\": \"add\",\n" + -// " \"accessConditions\": [\n" + -// " {\n" + -// " \"name\": \"openaccess\"\n" + -// " }\n" + -// " ]\n" + -// " }}\n"; -// -// buildJsonFile(json); -// -// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, "-e", eperson.getEmail()}; -// -// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); -// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); -// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); -// context.turnOffAuthorisationSystem(); -// -// Community community = CommunityBuilder.createCommunity(context) -// .withName("community") -// .build(); -// -// Collection collection = CollectionBuilder.createCollection(context, community) -// .withName("collection") -// .build(); -// -// Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); -// -// context.restoreAuthSystemState(); -// -// String json = "{ \"item\": {\n" + -// " \"mode\": \"add\",\n" + -// " \"accessConditions\": [\n" + -// " {\n" + -// " \"name\": \"openaccess\"\n" + -// " }\n" + -// " ]\n" + -// " }}\n"; -// -// buildJsonFile(json); -// -// String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, -// "-e", eperson.getEmail()}; -// -// TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); -// ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); -// objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); - context.turnOffAuthorisationSystem(); - - Community community = CommunityBuilder.createCommunity(context) - .withName("community") - .build(); - - Collection collection = CollectionBuilder.createCollection(context, community) - .withName("collection") - .build(); - - Item item = ItemBuilder.createItem(context, collection).withAdminUser(eperson).build(); - - context.restoreAuthSystemState(); - - String json = "{ \"item\": {\n" + - " \"mode\": \"add\",\n" + - " \"accessConditions\": [\n" + - " {\n" + - " \"name\": \"openaccess\"\n" + - " }\n" + - " ]\n" + - " }}\n"; - - buildJsonFile(json); - - String[] args = new String[] {"bulk-access-control", "-u", item.getID().toString(), "-f", tempFilePath, - "-e", eperson.getEmail()}; - - TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler(); - ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl); - provenanceCheck.objectCheck(itemService.find(context, item.getID()), "addAccessCondBitstream"); - } -} diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json index 3042378f6610..840267f3c3c6 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json @@ -12,11 +12,11 @@ "addBitstream": "Item was added bitstream to bundle", "updateLicense": "License (Test 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", "addLicense": "License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", - "removeLicense": "License (Test 1) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", + "removeLicense": "License (Test) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", "removeResPoliciesItem": "were removed by admin user (test@test.edu) on", "addAccessCondItem": "Access condition (embargo) was added to item", "removeResPoliciesBitstream": "were removed by admin user (test@test.edu) on", "addAccessCondBitstream": "Access condition (embargo) was added to bitstream", - "movedToCol": "Item was moved from collection " + "movedItemCol": "Item was moved from collection " } From d7a270bcf3c70666b5689afdac71fb042f3de685 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 18:21:34 +0200 Subject: [PATCH 26/54] better service management: --- .../org/dspace/core/provenance_messages.json | 5 +- .../dspace/app/rest/ProvenanceServiceIT.java | 369 +++++++++--------- .../app/rest/provenance-patch-suite.json | 22 +- 3 files changed, 190 insertions(+), 206 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/provenance_messages.json b/dspace-api/src/main/java/org/dspace/core/provenance_messages.json index 07bc5486b7ac..877ce7032d23 100644 --- a/dspace-api/src/main/java/org/dspace/core/provenance_messages.json +++ b/dspace-api/src/main/java/org/dspace/core/provenance_messages.json @@ -9,9 +9,6 @@ "editBitstream": "Item (%s) was deleted bitstream (%s)", "itemMetadata": "Item metadata (%s) was %s", "bitstreamMetadata": "Item metadata (%s) was %s bitstream (%s)", - "itemMetadata": "Item metadata (%s) was %s", "itemReplaceSingleMetadata": "Item bitstream (%s) metadata (%s) was updated", - "discoverable": "Item was made %sdiscoverable", - "movedToCol": "Item was moved from collection", - "removedFromCol": "Item was removed from collection" + "discoverable": "Item was made %sdiscoverable" } \ No newline at end of file diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 27723a58a745..326c4072a00e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -7,10 +7,8 @@ */ package org.dspace.app.rest; -import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; import org.dspace.app.rest.model.patch.AddOperation; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.RemoveOperation; @@ -34,13 +32,15 @@ import org.dspace.content.clarin.ClarinLicense; import org.dspace.content.clarin.ClarinLicenseLabel; import org.dspace.content.clarin.ClarinLicenseResourceMapping; -import org.dspace.content.service.BitstreamService; +import org.dspace.content.factory.ClarinServiceFactory; +import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinLicenseLabelService; -import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; +import org.dspace.discovery.SearchServiceException; import org.hamcrest.Matchers; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -55,6 +55,7 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; +import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -67,37 +68,50 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { - static String PROVENANCE = "dc.description.provenance"; + private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); + private ClarinLicenseLabelService clarinLicenseLabelService = ClarinServiceFactory.getInstance().getClarinLicenseLabelService(); + private ClarinLicenseService clarinLicenseService = ClarinServiceFactory.getInstance().getClarinLicenseService(); + private Collection collection; - private ObjectMapper objectMapper = new ObjectMapper(); + private Item item; + private final ObjectMapper objectMapper = new ObjectMapper(); private JsonNode suite; - @Autowired - private ItemService itemService; - @Autowired - private BitstreamService bitstreamService; - @Autowired - private ClarinLicenseResourceMappingService resourceMappingService; - @Autowired - private ClarinLicenseLabelService clarinLicenseLabelService; - @Autowired - private ClarinLicenseService clarinLicenseService; - @Autowired - private ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; - @Before @Override public void setUp() throws Exception { super.setUp(); - //suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); context.turnOffAuthorisationSystem(); parentCommunity = CommunityBuilder.createCommunity(context) .withName("Parent Community") .build(); collection = CollectionBuilder.createCollection(context, parentCommunity).build(); + item = ItemBuilder.createItem(context, collection) + .withTitle("Public item 1") + .build(); + context.restoreAuthSystemState(); suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); } + @After + @Override + public void destroy() throws Exception { + context.turnOffAuthorisationSystem(); + // Delete community created in init() + try { + ItemBuilder.deleteItem(item.getID()); + CollectionBuilder.deleteCollection(collection.getID()); + CommunityBuilder.deleteCommunity(parentCommunity.getID()); + } catch (Exception e) { + // ignore + } + context.restoreAuthSystemState(); + + item = null; + collection = null; + parentCommunity = null; + super.destroy(); + } private String provenanceMetadataModified(String metadata) { // Regex to match the date pattern @@ -112,7 +126,7 @@ private String provenanceMetadataModified(String metadata) { return rspModifiedProvenance; } - public void objectCheck(DSpaceObject obj, String respKey) { + private void objectCheck(DSpaceObject obj, String respKey) { String expectedSubStr = suite.get(respKey).asText(); List metadata = obj.getMetadata(); boolean contain = false; @@ -130,130 +144,194 @@ public void objectCheck(DSpaceObject obj, String respKey) { } } - private JsonNode preprocessingProvenance(String responseBody) throws JsonProcessingException { - //String responseBody = resultActions.andReturn().getResponse().getContentAsString(); - JsonNode responseJson = objectMapper.readTree(responseBody); - JsonNode responseMetadataJson = responseJson.get("metadata"); - if (responseMetadataJson.get(PROVENANCE) != null) { - // In the provenance metadata, there is a timestamp indicating when they were added. - // To ensure accurate comparison, remove that date. - String rspProvenance = responseMetadataJson.get(PROVENANCE).toString(); - // Regex to match the date pattern - String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; - Pattern pattern = Pattern.compile(datePattern); - Matcher matcher = pattern.matcher(rspProvenance); - String rspModifiedProvenance = rspProvenance; - while (matcher.find()) { - String dateString = matcher.group(0); - rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); - } - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode jsonNodePrv = objectMapper.readTree(rspModifiedProvenance); - // Replace the origin metadata with a value with the timestamp removed - ((ObjectNode) responseJson.get("metadata")).put(PROVENANCE, jsonNodePrv); - return responseJson; - } - return null; + private Bundle createBundle(Item item, String bundleName) throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + Bundle bundle = BundleBuilder.createBundle(context, item).withName(bundleName).build(); + context.restoreAuthSystemState(); + return bundle; } - private Item createItem() { + private Bitstream createBitstream(Item item, String bundleName) throws SQLException, AuthorizeException, IOException { context.turnOffAuthorisationSystem(); - Item item = ItemBuilder.createItem(context, collection) - .withTitle("Public item 1") - .build(); + Bundle bundle = createBundle(item, Objects.isNull(bundleName) ? "test" : bundleName); + Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, + toInputStream("Test Content", defaultCharset())).build(); context.restoreAuthSystemState(); - return item; + return bitstream; } - private Bundle createBundle(Item item, String bundleName) throws SQLException, AuthorizeException { + private void deleteBitstream(Bitstream bitstream) throws SQLException, IOException { + while (!bitstream.getBundles().isEmpty()) { + deleteBundle(bitstream.getBundles().get(0).getID()); + } + BitstreamBuilder.deleteBitstream(bitstream.getID()); + } + + + private void deleteBundle(UUID uuid) throws SQLException, IOException { + BundleBuilder.deleteBundle(uuid); + } + + private ClarinLicenseLabel createClarinLicenseLabel(String label, boolean extended, String title) + throws SQLException, AuthorizeException { context.turnOffAuthorisationSystem(); - Bundle bundle = BundleBuilder.createBundle(context, item).withName(bundleName).build(); + ClarinLicenseLabel clarinLicenseLabel = ClarinLicenseLabelBuilder.createClarinLicenseLabel(context).build(); + clarinLicenseLabel.setLabel(label); + clarinLicenseLabel.setExtended(extended); + clarinLicenseLabel.setTitle(title); + clarinLicenseLabelService.update(context, clarinLicenseLabel); context.restoreAuthSystemState(); - return bundle; + return clarinLicenseLabel; } - private ClarinLicense createLicense(String name) throws SQLException, AuthorizeException { + private ClarinLicense createClarinLicense(String name, String definition) + throws SQLException, AuthorizeException { context.turnOffAuthorisationSystem(); ClarinLicense clarinLicense = ClarinLicenseBuilder.createClarinLicense(context).build(); + clarinLicense.setDefinition(definition); clarinLicense.setName(name); + HashSet clarinLicenseLabels = new HashSet<>(); + ClarinLicenseLabel clarinLicenseLabel = createClarinLicenseLabel("lbl", false, "Test Title"); + clarinLicenseLabels.add(clarinLicenseLabel); + clarinLicense.setLicenseLabels(clarinLicenseLabels); + clarinLicenseService.update(context, clarinLicense); context.restoreAuthSystemState(); return clarinLicense; } - private Bitstream createBitstream(Item item, String bundleName) throws SQLException, AuthorizeException, IOException { + private void deleteClarinLicenseLable(Integer id) throws Exception { + ClarinLicenseLabelBuilder.deleteClarinLicenseLabel(id); + } + + private void deleteClarinLicense(ClarinLicense license) throws Exception { + while (!license.getLicenseLabels().isEmpty()) { + deleteClarinLicenseLable(license.getLicenseLabels().get(0).getID()); + } + ClarinLicenseBuilder.deleteClarinLicense(license.getID()); + } + + private Collection createCollection() { context.turnOffAuthorisationSystem(); - Bundle bundle = createBundle(item, Objects.isNull(bundleName) ? "test" : bundleName); - Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, - toInputStream("Test Content", defaultCharset())).build(); + Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); context.restoreAuthSystemState(); - return bitstream; + return col; + } + + private void deleteCollection(UUID uuid) throws SearchServiceException, SQLException, IOException { + CollectionBuilder.deleteCollection(uuid); + } + + private ClarinLicenseResourceMapping createResourceMapping(ClarinLicense license, Bitstream bitstream) throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + ClarinLicenseResourceMapping resourceMapping = ClarinLicenseResourceMappingBuilder.createClarinLicenseResourceMapping(context).build(); + context.restoreAuthSystemState(); + resourceMapping.setLicense(license); + resourceMapping.setBitstream(bitstream); + return resourceMapping; + } + + @Test + public void updateLicenseTest() throws Exception { + Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); + ClarinLicense clarinLicense1 = createClarinLicense("Test 1", "Test Def"); + createResourceMapping(clarinLicense1, bitstream); + ClarinLicense clarinLicense2 = createClarinLicense("Test 2", "Test Def"); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") + .param("licenseID", clarinLicense2.getID().toString())) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "updateLicense"); + + deleteBitstream(bitstream); + deleteClarinLicense(clarinLicense1); + deleteClarinLicense(clarinLicense2); + } + + @Test + public void addLicenseTest() throws Exception { + ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") + .param("licenseID", clarinLicense.getID().toString())) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "addLicense"); + + deleteClarinLicense(clarinLicense); + } + + @Test + public void removeLicenseTest() throws Exception { + Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); + ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); + createResourceMapping(clarinLicense, bitstream); + + String token = getAuthToken(admin.getEmail(), password); + getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") + .param("licenseID", "-1")) + .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "removeLicense"); + + deleteBitstream(bitstream); + deleteClarinLicense(clarinLicense); } @Test public void makeDiscoverableTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); - Item item = createItem(); List ops = new ArrayList<>(); ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", true); ops.add(replaceOperation); String patchBody = getPatchContent(ops); - // make discoverable getClient(token).perform(patch("/api/core/items/" + item.getID()) .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$.uuid", Matchers.is(item.getID().toString()))) - .andExpect(jsonPath("$.discoverable", Matchers.is(true))) - .andReturn(); + .andExpect(jsonPath("$.discoverable", Matchers.is(true))); + objectCheck(itemService.find(context, item.getID()), "discoverable"); } @Test public void makeNonDiscoverableTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); - Item item = createItem(); - //item.setDiscoverable(true); List ops = new ArrayList<>(); ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", false); ops.add(replaceOperation); String patchBody = getPatchContent(ops); - // make non-discoverable getClient(token).perform(patch("/api/core/items/" + item.getID()) .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); + objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); } @Test public void addedToMappedCollTest() throws Exception { - context.turnOffAuthorisationSystem(); - Collection col1 = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); - Item item = createItem(); - context.restoreAuthSystemState(); + Collection coll = createCollection(); String adminToken = getAuthToken(admin.getEmail(), password); - getClient(adminToken).perform( post("/api/core/items/" + item.getID() + "/mappedCollections/") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) .content( - "https://localhost:8080/spring-rest/api/core/collections/" + col1.getID() + "\n" + "https://localhost:8080/spring-rest/api/core/collections/" + coll.getID() + "\n" ) ); - objectCheck(itemService.find(context, item.getID()), "mapped"); + objectCheck(itemService.find(context, item.getID()), "mappedCol"); + + deleteCollection(coll.getID()); } @Test - public void addMetadata() throws Exception { - Item item = createItem(); - + public void addItemMetadataTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); - - // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); AddOperation addOperation = new AddOperation("/metadata/dc.title", "Test"); ops.add(addOperation); @@ -263,13 +341,11 @@ public void addMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "addMetadata"); + objectCheck(itemService.find(context, item.getID()), "addItemMtd"); } @Test - public void replaceMetadata() throws Exception { - Item item = createItem(); - + public void replaceItemMetadataTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; // Modify the entityType and verify the response already contains this modification @@ -282,15 +358,13 @@ public void replaceMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "replaceMetadata"); + objectCheck(itemService.find(context, item.getID()), "replaceItemMtd"); } @Test - public void removeMetadata() throws Exception { - Item item = createItem(); - String adminToken = getAuthToken(admin.getEmail(), password); + public void removeItemMetadataTest() throws Exception { int index = 0; - // Modify the entityType and verify the response already contains this modification + String adminToken = getAuthToken(admin.getEmail(), password); List ops = new ArrayList<>(); RemoveOperation removeOperation = new RemoveOperation("/metadata/dc.title/" + index); ops.add(removeOperation); @@ -300,16 +374,14 @@ public void removeMetadata() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeMetadata"); + objectCheck(itemService.find(context, item.getID()), "removeItemMtd"); } @Test - public void removeMetadataBitstream() throws Exception { - Item item = createItem(); + public void removeBitstreamMetadataTest() throws Exception { Bitstream bitstream = createBitstream(item, "test"); + String adminToken = getAuthToken(admin.getEmail(), password); - int index = 0; - // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); AddOperation addOperation = new AddOperation("/metadata/dc.description", "test"); ops.add(addOperation); @@ -319,14 +391,15 @@ public void removeMetadataBitstream() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + + deleteBitstream(bitstream); } @Test - public void addMetadataBitstream() throws Exception { - Item item = createItem(); + public void addBitstreamMetadataTest() throws Exception { Bitstream bitstream = createBitstream(item, "test"); + String adminToken = getAuthToken(admin.getEmail(), password); - // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); AddOperation addOperation = new AddOperation("/metadata/dc.description", "test"); ops.add(addOperation); @@ -339,15 +412,14 @@ public void addMetadataBitstream() throws Exception { } @Test - public void updateMetadataBitstream() throws Exception { - Item item = createItem(); + public void updateMetadataBitstreamTest() throws Exception { Bitstream bitstream = createBitstream(item, "test"); bitstream.setName(context, "test"); + String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; - //Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); - ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title/" + index, "test 1"); + ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title/" + index + "/value", "test 1"); ops.add(replaceOperation); String patchBody = getPatchContent(ops); getClient(adminToken).perform(patch("/api/core/bitstreams/" + bitstream.getID()) @@ -355,14 +427,15 @@ public void updateMetadataBitstream() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); + + deleteBitstream(bitstream); } @Test - public void removeBitstreamFromItem() throws Exception { - Item item = createItem(); + public void removeBitstreamFromItemTest() throws Exception { Bitstream bitstream = createBitstream(item, "test"); + String adminToken = getAuthToken(admin.getEmail(), password); - // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); RemoveOperation removeOperation = new RemoveOperation("/bitstreams/" + bitstream.getID()); ops.add(removeOperation); @@ -371,11 +444,12 @@ public void removeBitstreamFromItem() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)); objectCheck(itemService.find(context, item.getID()), "removeBitstream"); + + deleteBitstream(bitstream); } @Test - public void addBitstreamToItem() throws Exception { - Item item = createItem(); + public void addBitstreamToItemTest() throws Exception { Bundle bundle = createBundle(item, "test"); String token = getAuthToken(admin.getEmail(), password); @@ -389,98 +463,15 @@ public void addBitstreamToItem() throws Exception { .file(file)) .andExpect(status().isCreated()); objectCheck(itemService.find(context, item.getID()), "addBitstream"); - } - /** - * Create Clarin License Label object for testing purposes. - */ - private ClarinLicenseLabel createClarinLicenseLabel(String label, boolean extended, String title) - throws SQLException, AuthorizeException { - ClarinLicenseLabel clarinLicenseLabel = ClarinLicenseLabelBuilder.createClarinLicenseLabel(context).build(); - clarinLicenseLabel.setLabel(label); - clarinLicenseLabel.setExtended(extended); - clarinLicenseLabel.setTitle(title); - - clarinLicenseLabelService.update(context, clarinLicenseLabel); - return clarinLicenseLabel; - } - - private ClarinLicense createClarinLicense(String name, String definition) - throws SQLException, AuthorizeException { - ClarinLicense clarinLicense = ClarinLicenseBuilder.createClarinLicense(context).build(); - clarinLicense.setDefinition(definition); - clarinLicense.setName(name); - - // add ClarinLicenseLabels to the ClarinLicense - HashSet clarinLicenseLabels = new HashSet<>(); - ClarinLicenseLabel clarinLicenseLabel = createClarinLicenseLabel("lbl", false, "Test Title"); - clarinLicenseLabels.add(clarinLicenseLabel); - clarinLicense.setLicenseLabels(clarinLicenseLabels); - - clarinLicenseService.update(context, clarinLicense); - return clarinLicense; - } - - private ClarinLicenseResourceMapping createResourceMapping(ClarinLicense license, Bitstream bitstream) throws SQLException, AuthorizeException { - ClarinLicenseResourceMapping resourceMapping = ClarinLicenseResourceMappingBuilder.createClarinLicenseResourceMapping(context).build(); - resourceMapping.setLicense(license); - resourceMapping.setBitstream(bitstream); - return resourceMapping; - } - - @Test - public void updateLicenseTest() throws Exception { - Item item = createItem(); - Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); - ClarinLicense clarinLicense1 = createClarinLicense("Test 1", "Test Def"); - ClarinLicenseResourceMapping resourceMapping = createResourceMapping(clarinLicense1, bitstream); - ClarinLicense clarinLicense2 = createClarinLicense("Test 2", "Test Def"); - - String token = getAuthToken(admin.getEmail(), password); - getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") - .param("licenseID", clarinLicense2.getID().toString())) - .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "updateLicense"); - } - - @Test - public void addLicenseTest() throws Exception { - Item item = createItem(); - ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); - String token = getAuthToken(admin.getEmail(), password); - getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") - .param("licenseID", clarinLicense.getID().toString())) - .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "addLicense"); - } - - @Test - public void removeLicenseTest() throws Exception { - Item item = createItem(); - Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); - ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); - ClarinLicenseResourceMapping resourceMapping = createResourceMapping(clarinLicense, bitstream); - - String token = getAuthToken(admin.getEmail(), password); - getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles")) - .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeLicense"); - } - - private Collection createCollection() { - context.turnOffAuthorisationSystem(); - Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); - context.restoreAuthSystemState(); - return col; + deleteBundle(bundle.getID()); } @Test public void moveItemColTest() throws Exception { - Item item = createItem(); Collection col = createCollection(); String token = getAuthToken(admin.getEmail(), password); - getClient(token) .perform(put("/api/core/items/" + item.getID() + "/owningCollection/") .contentType(parseMediaType(TEXT_URI_LIST_VALUE)) @@ -489,5 +480,7 @@ public void moveItemColTest() throws Exception { )) .andExpect(status().isOk()); objectCheck(itemService.find(context, item.getID()), "movedItemCol"); + + deleteCollection(col.getID()); } } diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json index 840267f3c3c6..268957768040 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json @@ -1,22 +1,16 @@ { "discoverable": "Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", "nonDiscoverable": "Item was made non-discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", - "mapped": "was mapped to collection", - "addMetadata": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on", - "removedMapped": "was deleted from mapped collection", - "replaceMetadata": "Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "removeMetadata": "Item metadata (dc.title: Public item 1) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "mappedCol": "was mapped to collection", + "addItemMtd": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on", + "replaceItemMtd": "Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "removeItemMtd": "Item metadata (dc.title: Public item 1) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "removeBitstreamMtd": "Item metadata (dc.description) was added by bitstream", - "replaceBitstreamMtd": "metadata (dc.title: test2) was updated by admin user (test@test.edu) on \nNo. of bitstreams: 1", + "replaceBitstreamMtd": "metadata (dc.title: test) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", "removeBitstream": "was deleted bitstream", "addBitstream": "Item was added bitstream to bundle", "updateLicense": "License (Test 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", - "addLicense": "License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", - "removeLicense": "License (Test) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\n", - "removeResPoliciesItem": "were removed by admin user (test@test.edu) on", - "addAccessCondItem": "Access condition (embargo) was added to item", - "removeResPoliciesBitstream": "were removed by admin user (test@test.edu) on", - "addAccessCondBitstream": "Access condition (embargo) was added to bitstream", + "addLicense": "License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "removeLicense": "License (Test) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", "movedItemCol": "Item was moved from collection " -} - +} \ No newline at end of file From e4da4e122b5cbcf99d659b9b3d4a04ff5e3da697 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 19:46:58 +0200 Subject: [PATCH 27/54] delete clarin license mapping --- .../ClarinLicenseResourceMappingBuilder.java | 16 +++++++++++++ .../dspace/app/rest/ProvenanceServiceIT.java | 24 ++++++++++++------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/test/java/org/dspace/builder/ClarinLicenseResourceMappingBuilder.java b/dspace-api/src/test/java/org/dspace/builder/ClarinLicenseResourceMappingBuilder.java index 4a39a44fd4b1..2b07ee8f23d6 100644 --- a/dspace-api/src/test/java/org/dspace/builder/ClarinLicenseResourceMappingBuilder.java +++ b/dspace-api/src/test/java/org/dspace/builder/ClarinLicenseResourceMappingBuilder.java @@ -8,6 +8,7 @@ package org.dspace.builder; import java.sql.SQLException; +import java.util.Objects; import org.dspace.authorize.AuthorizeException; import org.dspace.content.clarin.ClarinLicenseResourceMapping; @@ -37,6 +38,21 @@ private ClarinLicenseResourceMappingBuilder create(final Context context) { return this; } + public static void delete(Integer id) throws Exception { + if (Objects.isNull(id)) { + return; + } + try (Context c = new Context()) { + c.turnOffAuthorisationSystem(); + ClarinLicenseResourceMapping clarinLicense = clarinLicenseResourceMappingService.find(c, id); + + if (clarinLicense != null) { + clarinLicenseResourceMappingService.delete(c, clarinLicense); + } + c.complete(); + } + } + @Override public void cleanup() throws Exception { try (Context c = new Context()) { diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 326c4072a00e..797066e1a73e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -161,8 +161,9 @@ private Bitstream createBitstream(Item item, String bundleName) throws SQLExcept } private void deleteBitstream(Bitstream bitstream) throws SQLException, IOException { - while (!bitstream.getBundles().isEmpty()) { - deleteBundle(bitstream.getBundles().get(0).getID()); + int size = bitstream.getBundles().size(); + for (int i = 0; i < size; i++) { + deleteBundle(bitstream.getBundles().get(i).getID()); } BitstreamBuilder.deleteBitstream(bitstream.getID()); } @@ -204,8 +205,9 @@ private void deleteClarinLicenseLable(Integer id) throws Exception { } private void deleteClarinLicense(ClarinLicense license) throws Exception { - while (!license.getLicenseLabels().isEmpty()) { - deleteClarinLicenseLable(license.getLicenseLabels().get(0).getID()); + int size = license.getLicenseLabels().size(); + for (int i = 0; i < size; i++) { + deleteClarinLicenseLable(license.getLicenseLabels().get(i).getID()); } ClarinLicenseBuilder.deleteClarinLicense(license.getID()); } @@ -230,11 +232,15 @@ private ClarinLicenseResourceMapping createResourceMapping(ClarinLicense license return resourceMapping; } + private void deleteResourceMapping(Integer id) throws Exception { + ClarinLicenseResourceMappingBuilder.delete(id); + } + @Test public void updateLicenseTest() throws Exception { Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); ClarinLicense clarinLicense1 = createClarinLicense("Test 1", "Test Def"); - createResourceMapping(clarinLicense1, bitstream); + ClarinLicenseResourceMapping mapping = createResourceMapping(clarinLicense1, bitstream); ClarinLicense clarinLicense2 = createClarinLicense("Test 2", "Test Def"); String token = getAuthToken(admin.getEmail(), password); @@ -246,6 +252,7 @@ public void updateLicenseTest() throws Exception { deleteBitstream(bitstream); deleteClarinLicense(clarinLicense1); deleteClarinLicense(clarinLicense2); + deleteResourceMapping(mapping.getID()); } @Test @@ -265,7 +272,7 @@ public void addLicenseTest() throws Exception { public void removeLicenseTest() throws Exception { Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); ClarinLicense clarinLicense = createClarinLicense("Test", "Test Def"); - createResourceMapping(clarinLicense, bitstream); + ClarinLicenseResourceMapping mapping = createResourceMapping(clarinLicense, bitstream); String token = getAuthToken(admin.getEmail(), password); getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") @@ -275,10 +282,12 @@ public void removeLicenseTest() throws Exception { deleteBitstream(bitstream); deleteClarinLicense(clarinLicense); + deleteResourceMapping(mapping.getID()); } @Test public void makeDiscoverableTest() throws Exception { + item.setDiscoverable(false); String token = getAuthToken(admin.getEmail(), password); List ops = new ArrayList<>(); ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", true); @@ -297,6 +306,7 @@ public void makeDiscoverableTest() throws Exception { @Test public void makeNonDiscoverableTest() throws Exception { + item.setDiscoverable(true); String token = getAuthToken(admin.getEmail(), password); List ops = new ArrayList<>(); ReplaceOperation replaceOperation = new ReplaceOperation("/discoverable", false); @@ -311,7 +321,6 @@ public void makeNonDiscoverableTest() throws Exception { objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); } - @Test public void addedToMappedCollTest() throws Exception { Collection coll = createCollection(); @@ -348,7 +357,6 @@ public void addItemMetadataTest() throws Exception { public void replaceItemMetadataTest() throws Exception { String adminToken = getAuthToken(admin.getEmail(), password); int index = 0; - // Modify the entityType and verify the response already contains this modification List ops = new ArrayList<>(); ReplaceOperation replaceOperation = new ReplaceOperation("/metadata/dc.title/" + index, "Test"); ops.add(replaceOperation); From 5b6168cec027c43a2b210aadba972c45dcf56352 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 19:57:24 +0200 Subject: [PATCH 28/54] checkstyle violations --- .../bulkaccesscontrol/BulkAccessControl.java | 3 -- .../core/ProvenanceMessageProvider.java | 17 +++++--- .../core/ProvenanceMessageProviderImpl.java | 29 ++++++++------ .../org/dspace/core/ProvenanceService.java | 33 +++++++++------ .../dspace/core/ProvenanceServiceImpl.java | 40 ++++++++++++------- .../dspace/app/rest/ProvenanceServiceIT.java | 7 ++-- 6 files changed, 78 insertions(+), 51 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 4e9ad7fe9935..271541b88392 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -45,17 +45,14 @@ import org.dspace.app.util.DSpaceObjectUtilsImpl; import org.dspace.app.util.service.DSpaceObjectUtils; import org.dspace.authorize.AuthorizeException; -import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.Bitstream; import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; -import org.dspace.content.factory.ClarinServiceFactory; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; -import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.ProvenanceService; diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java index 56c827ce82b7..945cb8688888 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -7,20 +7,25 @@ */ package org.dspace.core; +import java.sql.SQLException; +import java.util.List; + import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.Bitstream; import org.dspace.content.Item; import org.dspace.content.MetadataField; -import java.sql.SQLException; -import java.util.List; - +/** + * Interface for providing provenance messages. + */ public interface ProvenanceMessageProvider { - public String getMessage(Context context, String templateKey, Object... args) throws SQLException, AuthorizeException; - public String getMessage(Context context, String templateKey, Item item, Object... args) throws SQLException, AuthorizeException; + public String getMessage(Context context, String templateKey, Object... args) + throws SQLException, AuthorizeException; + public String getMessage(Context context, String templateKey, Item item, Object... args) + throws SQLException, AuthorizeException; public String getMessage(String templateKey, Object... args); - public String addCollectionsToMessage(Item item) throws SQLException, AuthorizeException; + public String addCollectionsToMessage(Item item); public String getBitstreamMessage(Bitstream bitstream); public String getResourcePoliciesMessage(List resPolicies); public String getMetadata(String oldMtdKey, String oldMtdValue); diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java index cdef2dbddfe9..b381c0b62710 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java @@ -7,6 +7,15 @@ */ package org.dspace.core; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + import com.fasterxml.jackson.databind.ObjectMapper; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; @@ -20,14 +29,6 @@ import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider { private Map messageTemplates; @@ -41,15 +42,19 @@ public ProvenanceMessageProviderImpl() { private void loadMessageTemplates() { ObjectMapper mapper = new ObjectMapper(); - try { - messageTemplates = mapper.readValue(Files.readAllBytes(Paths.get("C:\\workspace\\DSpace\\dspace-api\\src\\main\\java\\org\\dspace\\core\\provenance_messages.json")), Map.class); + try (InputStream inputStream = getClass().getResourceAsStream("provenance_messages.json")) { + if (inputStream == null) { + throw new RuntimeException("Failed to find message templates file"); + } + messageTemplates = mapper.readValue(inputStream, Map.class); } catch (IOException e) { throw new RuntimeException("Failed to load message templates", e); } } @Override - public String getMessage(Context context, String templateKey, Item item, Object... args) throws SQLException, AuthorizeException { + public String getMessage(Context context, String templateKey, Item item, Object... args) + throws SQLException, AuthorizeException { String msg = getMessage(context, templateKey, args); msg = msg + "\n" + installItemService.getBitstreamProvenanceMessage(context, item); return msg; @@ -77,7 +82,7 @@ public String getMessage(Context context, String templateKey, Object... args) { } @Override - public String addCollectionsToMessage(Item item) throws SQLException, AuthorizeException { + public String addCollectionsToMessage(Item item) { String msg = "Item was in collections:\n"; List collsList = item.getCollections(); for (Collection coll : collsList) { diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java index 6f8fa5592678..8727f3b6f38e 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java @@ -7,6 +7,9 @@ */ package org.dspace.core; +import java.sql.SQLException; +import java.util.List; + import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -17,27 +20,33 @@ import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; -import java.sql.SQLException; -import java.util.List; - public interface ProvenanceService { - public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; + public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, + BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; - public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; + public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) + throws SQLException, AuthorizeException; - public String removedReadPolicies(Context context, DSpaceObject dso, String type) throws SQLException, AuthorizeException; + public String removedReadPolicies(Context context, DSpaceObject dso, String type) + throws SQLException, AuthorizeException; public void uploadBitstream(Context context, Bundle bundle) throws SQLException, AuthorizeException; public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException; public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; - public void deletedItemFromMapped(Context context, Item item, Collection collection) throws SQLException, AuthorizeException; + public void deletedItemFromMapped(Context context, Item item, Collection collection) + throws SQLException, AuthorizeException; public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException; - public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException; - public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException; + public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) + throws SQLException, AuthorizeException; + public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) + throws SQLException, AuthorizeException; public void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, int indexInt) throws SQLException, AuthorizeException; - public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) throws SQLException, AuthorizeException; - public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) throws SQLException, AuthorizeException; - public void makeDiscoverable(Context context, Item item, boolean discoverable) throws SQLException, AuthorizeException; + public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) + throws SQLException, AuthorizeException; + public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) + throws SQLException, AuthorizeException; + public void makeDiscoverable(Context context, Item item, boolean discoverable) + throws SQLException, AuthorizeException; } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index 4af5de728c50..279089d4b9ca 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -7,6 +7,11 @@ */ package org.dspace.core; +import java.sql.SQLException; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + import org.apache.commons.collections4.CollectionUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -30,11 +35,6 @@ import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; import org.springframework.beans.factory.annotation.Autowired; -import java.sql.SQLException; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - public class ProvenanceServiceImpl implements ProvenanceService { private static final Logger log = LogManager.getLogger(); @@ -77,7 +77,8 @@ private Item getItem(Context context, Bitstream bitstream) throws SQLException { } @Override - public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) + throws SQLException, AuthorizeException { String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); if (!resPoliciesStr.isEmpty()) { String msg = messageProvider.getMessage(context,"accessCondition", resPoliciesStr, @@ -87,7 +88,8 @@ public void setItemPolicies(Context context, Item item, BulkAccessControlInput a } @Override - public String removedReadPolicies(Context context, DSpaceObject dso, String type) throws SQLException, AuthorizeException { + public String removedReadPolicies(Context context, DSpaceObject dso, String type) + throws SQLException, AuthorizeException { List resPolicies = resourcePolicyService.find(context, dso, type); if (resPolicies.isEmpty()) { return null; @@ -111,7 +113,8 @@ public String removedReadPolicies(Context context, DSpaceObject dso, String type } @Override - public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, + BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); if (!accConditionsStr.isEmpty()) { String msg = messageProvider.getMessage(context,"accessCondition", accConditionsStr, @@ -163,7 +166,8 @@ public void mappedItem(Context context, Item item, Collection collection) throws } @Override - public void deletedItemFromMapped(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { + public void deletedItemFromMapped(Context context, Item item, Collection collection) + throws SQLException, AuthorizeException { String msg = messageProvider.getMessage(context, "deletedItemFromMapped", item.getID(), collection.getID()); addProvenanceMetadata(context, item, msg); @@ -180,7 +184,8 @@ public void deleteBitstream(Context context,Bitstream bitstream) throws SQLExcep } @Override - public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { + public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) + throws SQLException, AuthorizeException { if (Constants.ITEM == dso.getType()) { // Add suitable provenance String msg = messageProvider.getMessage(context, "itemMetadata", @@ -202,13 +207,15 @@ public void addMetadata(Context context, DSpaceObject dso, MetadataField metadat } @Override - public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { + public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) + throws SQLException, AuthorizeException { if (dso.getType() != Constants.BITSTREAM) { return; } String oldMtdKey = null; String oldMtdValue = null; - List mtd = bitstreamService.getMetadata((Bitstream) dso, metadataField.getMetadataSchema().getName(), + List mtd = bitstreamService.getMetadata((Bitstream) dso, + metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); if (!CollectionUtils.isEmpty(mtd)) { oldMtdKey = mtd.get(0).getMetadataField().getElement(); @@ -241,7 +248,8 @@ public void removeMetadataAtIndex(Context context, DSpaceObject dso, List Date: Mon, 7 Oct 2024 19:58:45 +0200 Subject: [PATCH 29/54] checkstyle violations --- .../java/org/dspace/core/ProvenanceMessageProviderImpl.java | 2 -- .../src/main/java/org/dspace/core/ProvenanceServiceImpl.java | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java index b381c0b62710..a44930dbf466 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java @@ -9,8 +9,6 @@ import java.io.IOException; import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Paths; import java.sql.SQLException; import java.util.List; import java.util.Map; diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index 279089d4b9ca..3dcfb4874701 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -150,7 +150,7 @@ public void editLicense(Context context, Item item, boolean newLicense) throws S @Override public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { - String msg = messageProvider.getMessage(context, "moveItem", item, collection.getID()); + String msg = messageProvider.getMessage(context, "moveItem", item, collection.getID()); // Update item in DB // Because a user can move an item without authorization turn off authorization context.turnOffAuthorisationSystem(); From 0e4c9a221d177498514fc8884511b1c250ecf69d Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 20:05:59 +0200 Subject: [PATCH 30/54] checkstyle violations --- .../app/rest/ItemAddBundleController.java | 5 --- ...mOwningCollectionUpdateRestController.java | 4 -- .../rest/MappedCollectionRestController.java | 4 -- .../operation/BitstreamRemoveOperation.java | 10 ----- .../DSpaceObjectMetadataAddOperation.java | 8 ---- .../DSpaceObjectMetadataRemoveOperation.java | 6 --- .../DSpaceObjectMetadataReplaceOperation.java | 10 ----- .../ItemDiscoverableReplaceOperation.java | 8 ---- .../patch/operation/PatchOperation.java | 5 --- .../dspace/app/rest/ProvenanceServiceIT.java | 38 +++++++++---------- 10 files changed, 19 insertions(+), 79 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index c1095d2f1b19..8abded29630b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -31,19 +31,14 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; -import org.dspace.content.DCDate; import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.clarin.ClarinLicense; -import org.dspace.content.clarin.ClarinLicenseResourceMapping; -import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.ProvenanceService; -import org.dspace.eperson.EPerson; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index c9cbb4ea9a10..ca467c91630e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -26,17 +26,13 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Collection; -import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.CollectionService; -import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.ProvenanceService; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.prepost.PostAuthorize; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index 2ba35bbac229..7abc62ae78f7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -25,16 +25,12 @@ import org.dspace.app.rest.utils.Utils; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Collection; -import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.CollectionService; -import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; import org.dspace.core.ProvenanceService; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index 3de199de7319..722067691b72 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -9,26 +9,16 @@ import java.io.IOException; import java.sql.SQLException; -import java.util.List; import java.util.UUID; -import org.apache.commons.collections4.CollectionUtils; -import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.RESTBitstreamNotFoundException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.service.AuthorizeService; import org.dspace.content.Bitstream; -import org.dspace.content.DCDate; -import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.BitstreamService; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; -import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Component; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 67fd804b1622..f716870d08d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -8,25 +8,17 @@ package org.dspace.app.rest.repository.patch.operation; import java.sql.SQLException; -import java.util.List; -import org.apache.commons.collections4.CollectionUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.Bitstream; import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; -import org.dspace.content.service.clarin.ClarinItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index c024edf561f2..8ca5eb66ea43 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -11,24 +11,18 @@ import java.util.Arrays; import java.util.List; -import org.apache.commons.collections4.CollectionUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.Bitstream; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; -import org.dspace.content.service.clarin.ClarinItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 490358eddb65..e11a4fe78678 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -10,28 +10,18 @@ import java.sql.SQLException; import java.util.List; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.Bitstream; -import org.dspace.content.DCDate; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; -import org.dspace.content.service.clarin.ClarinItemService; -import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index e664005e4cf6..46e85abd7452 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -8,21 +8,13 @@ package org.dspace.app.rest.repository.patch.operation; import java.sql.SQLException; -import java.util.List; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.authorize.AuthorizeException; -import org.dspace.content.Collection; -import org.dspace.content.DCDate; import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; import org.dspace.core.Context; -import org.dspace.eperson.EPerson; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index a737eea74c58..b144a2338c29 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -12,15 +12,10 @@ import org.apache.commons.lang3.BooleanUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.patch.Operation; -import org.dspace.authorize.AuthorizeException; -import org.dspace.content.DCDate; -import org.dspace.content.Item; -import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.service.InstallItemService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; import org.dspace.core.ProvenanceService; -import org.dspace.eperson.EPerson; import org.springframework.beans.factory.annotation.Autowired; /** diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 7533c64280e1..2bbf472ce1c7 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -7,6 +7,25 @@ */ package org.dspace.app.rest; +import static java.nio.charset.Charset.defaultCharset; +import static org.apache.commons.io.IOUtils.toInputStream; +import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; +import static org.springframework.http.MediaType.parseMediaType; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.ws.rs.core.MediaType; + import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.dspace.app.rest.model.patch.AddOperation; @@ -47,25 +66,6 @@ import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -import javax.ws.rs.core.MediaType; -import java.io.IOException; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Objects; -import java.util.UUID; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static java.nio.charset.Charset.defaultCharset; -import static org.apache.commons.io.IOUtils.toInputStream; -import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; -import static org.springframework.http.MediaType.parseMediaType; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); private ClarinLicenseLabelService clarinLicenseLabelService = ClarinServiceFactory.getInstance().getClarinLicenseLabelService(); From 556c3d48db3fa32524a8bfe7cd7afe61d869b541 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 20:09:01 +0200 Subject: [PATCH 31/54] checkstyle violations --- .../patch/operation/DSpaceObjectMetadataAddOperation.java | 4 ++-- .../test/java/org/dspace/app/rest/ProvenanceServiceIT.java | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index f716870d08d9..df28817ab0ea 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -75,8 +75,8 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); provenanceService.addMetadata(context, dso, metadataField); } catch (SQLException e) { - throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + - "metadata to dso.", e); + throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + + "metadata to dso.", e); } catch (AuthorizeException e) { throw new DSpaceBadRequestException( "AuthorizeException in DspaceObjectMetadataAddOperation.add " + diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 2bbf472ce1c7..acc1e7d842dd 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -11,7 +11,9 @@ import static org.apache.commons.io.IOUtils.toInputStream; import static org.springframework.data.rest.webmvc.RestMediaTypes.TEXT_URI_LIST_VALUE; import static org.springframework.http.MediaType.parseMediaType; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; From e7caf0db8b0530e19f1ff4e9c16b3fffea6eda1a Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 20:10:23 +0200 Subject: [PATCH 32/54] checkstyle violations --- .../java/org/dspace/app/rest/ProvenanceServiceIT.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index acc1e7d842dd..0584ea2f03e1 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -70,7 +70,8 @@ public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private ClarinLicenseLabelService clarinLicenseLabelService = ClarinServiceFactory.getInstance().getClarinLicenseLabelService(); + private ClarinLicenseLabelService clarinLicenseLabelService = + ClarinServiceFactory.getInstance().getClarinLicenseLabelService(); private ClarinLicenseService clarinLicenseService = ClarinServiceFactory.getInstance().getClarinLicenseService(); private Collection collection; @@ -152,7 +153,8 @@ private Bundle createBundle(Item item, String bundleName) throws SQLException, A return bundle; } - private Bitstream createBitstream(Item item, String bundleName) throws SQLException, AuthorizeException, IOException { + private Bitstream createBitstream(Item item, String bundleName) + throws SQLException, AuthorizeException, IOException { context.turnOffAuthorisationSystem(); Bundle bundle = createBundle(item, Objects.isNull(bundleName) ? "test" : bundleName); Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, @@ -466,7 +468,8 @@ public void addBitstreamToItemTest() throws Exception { String token = getAuthToken(admin.getEmail(), password); String input = "Hello, World!"; context.turnOffAuthorisationSystem(); - MockMultipartFile file = new MockMultipartFile("file", "hello.txt", org.springframework.http.MediaType.TEXT_PLAIN_VALUE, + MockMultipartFile file = new MockMultipartFile("file", "hello.txt", + org.springframework.http.MediaType.TEXT_PLAIN_VALUE, input.getBytes()); context.restoreAuthSystemState(); getClient(token) From 9b7fb5c86c71b9235675fb6626310f00c2c8129b Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 20:59:40 +0200 Subject: [PATCH 33/54] added json to resources --- .../{java => resources}/org/dspace/core/provenance_messages.json | 0 .../patch/operation/ItemDiscoverableReplaceOperation.java | 1 - 2 files changed, 1 deletion(-) rename dspace-api/src/main/{java => resources}/org/dspace/core/provenance_messages.json (100%) diff --git a/dspace-api/src/main/java/org/dspace/core/provenance_messages.json b/dspace-api/src/main/resources/org/dspace/core/provenance_messages.json similarity index 100% rename from dspace-api/src/main/java/org/dspace/core/provenance_messages.json rename to dspace-api/src/main/resources/org/dspace/core/provenance_messages.json diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index 46e85abd7452..57b406451884 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -46,7 +46,6 @@ public R perform(Context context, R object, Operation operation) { item.setDiscoverable(discoverable); try { provenanceService.makeDiscoverable(context, item, discoverable); - //tu } catch (SQLException ex) { throw new RuntimeException("SQLException occurred when item making " + (discoverable ? "" : "non-") + "discoverable.", ex); From eba6bbdbbaeb3c60fbe8bac864cb7b56c0ec8358 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 22:29:20 +0200 Subject: [PATCH 34/54] modified provenance patch messages --- .../rest/test/item-metadata-patch-suite.json | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json index 1966f304ad00..9c3f6a534a8d 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json @@ -23,7 +23,7 @@ ], "expect": { "dc.description.provenance" : [ - { "value" : "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} + { "value" : "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language" : "en", "authority" : null, "confidence" : -1, "place" : 0} ], "dc.title": [ { "value": "title 1", "language": null, "authority": null, "confidence": -1, "place": 0} @@ -41,9 +41,9 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":1} ], "dc.title": [ @@ -65,11 +65,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -90,11 +90,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -120,11 +120,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -145,11 +145,11 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":2} ], "dc.title": [ @@ -174,15 +174,15 @@ ], "expect": { "dc.description.provenance":[ - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":0}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":1}, - {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":2}, - {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":3}, - {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":4} ], "dc.title": [ @@ -202,15 +202,15 @@ "expect": { "dc.description.provenance": [ { - "value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + "value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language": "en", "authority": null, "confidence": -1, "place": 0}, - {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language": "en", "authority": null, "confidence": -1, "place": 1}, - {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language": "en", "authority": null, "confidence": -1, "place": 2}, - {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", "language": "en", "authority": null, "confidence": -1, "place": 3}, - {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", + {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", "language": "en", "authority": null, "confidence": -1, "place": 4} ] } From a0d5d5588e254250c719a622d2b17214db02bdaf Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 22:36:24 +0200 Subject: [PATCH 35/54] messages bags --- .../dspace/core/ProvenanceServiceImpl.java | 37 +++++++++++-------- .../org/dspace/core/provenance_messages.json | 6 +-- .../dspace/app/rest/ProvenanceServiceIT.java | 2 +- ...-patch-suite.json => provenance-test.json} | 0 4 files changed, 26 insertions(+), 19 deletions(-) rename dspace-server-webapp/src/test/resources/org/dspace/app/rest/{provenance-patch-suite.json => provenance-test.json} (100%) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index 3dcfb4874701..d63dcc576c45 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -123,23 +123,32 @@ public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item } } - @Override - public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { - String oldLicense = null; - List bundles = item.getBundles(Constants.LICENSE_BUNDLE_NAME); + // Method to find license in the bundles + private String findLicenseInBundles(Item item, String bundleName, String currentLicense, Context context) + throws SQLException { + List bundles = item.getBundles(bundleName); for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); for (Bitstream bundleBitstream : bitstreamList) { - if (Objects.isNull(oldLicense)) { + if (Objects.isNull(currentLicense)) { List mappings = - this.clarinResourceMappingService.findByBitstreamUUID( - context, bundleBitstream.getID()); + this.clarinResourceMappingService.findByBitstreamUUID(context, bundleBitstream.getID()); if (!mappings.isEmpty()) { - oldLicense = mappings.get(0).getLicense().getName(); + return mappings.get(0).getLicense().getName(); } } } } + return currentLicense; + } + + @Override + public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { + String oldLicense = null; + oldLicense = findLicenseInBundles(item, Constants.LICENSE_BUNDLE_NAME, oldLicense, context); + if (oldLicense == null) { + oldLicense = findLicenseInBundles(item, Constants.CONTENT_BUNDLE_NAME, oldLicense, context); + } String msg = messageProvider.getMessage(context, "editLicense", item, Objects.isNull(oldLicense) ? "empty" : oldLicense, @@ -160,16 +169,14 @@ public void moveItem(Context context, Item item, Collection collection) throws S @Override public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { - String msg = messageProvider.getMessage(context, "mappedItem", - item.getID(), collection.getID()); + String msg = messageProvider.getMessage(context, "mappedItem", collection.getID()); addProvenanceMetadata(context, item, msg); } @Override public void deletedItemFromMapped(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { - String msg = messageProvider.getMessage(context, "deletedItemFromMapped", - item.getID(), collection.getID()); + String msg = messageProvider.getMessage(context, "deletedItemFromMapped", collection.getID()); addProvenanceMetadata(context, item, msg); } @@ -212,13 +219,13 @@ public void removeMetadata(Context context, DSpaceObject dso, MetadataField meta if (dso.getType() != Constants.BITSTREAM) { return; } - String oldMtdKey = null; + MetadataField oldMtdKey = null; String oldMtdValue = null; List mtd = bitstreamService.getMetadata((Bitstream) dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); if (!CollectionUtils.isEmpty(mtd)) { - oldMtdKey = mtd.get(0).getMetadataField().getElement(); + oldMtdKey = mtd.get(0).getMetadataField(); oldMtdValue = mtd.get(0).getValue(); } // Add suitable provenance @@ -226,7 +233,7 @@ public void removeMetadata(Context context, DSpaceObject dso, MetadataField meta Item item = getItem(context, bitstream); if (!Objects.isNull(item)) { String msg = messageProvider.getMessage(context, "bitstreamMetadata", item, - messageProvider.getMetadata(oldMtdKey, oldMtdValue), + messageProvider.getMetadata(messageProvider.getMetadataField(oldMtdKey), oldMtdValue), "deleted from", messageProvider.getBitstreamMessage(bitstream)); addProvenanceMetadata(context, item, msg); } diff --git a/dspace-api/src/main/resources/org/dspace/core/provenance_messages.json b/dspace-api/src/main/resources/org/dspace/core/provenance_messages.json index 877ce7032d23..c4158c677383 100644 --- a/dspace-api/src/main/resources/org/dspace/core/provenance_messages.json +++ b/dspace-api/src/main/resources/org/dspace/core/provenance_messages.json @@ -1,11 +1,11 @@ { "accessCondition": "Access condition (%s) was added to %s (%s)", - "resourcePoliciesRemoved": "Resource policies (%s) of (%s) (%s) were removed", + "resourcePoliciesRemoved": "Resource policies (%s) of %s (%s) were removed", "bundleAdded": "Item was added bitstream to bundle (%s)", "editLicense": "License (%s) was %s", "moveItem": "Item was moved from collection (%s) to different collection", - "mappedItem": "Item (%s) was mapped to collection (%s)", - "deletedItemFromMapped": "Item (%s) was deleted from mapped collection (%s)", + "mappedItem": "Item was mapped to collection (%s)", + "deletedItemFromMapped": "Item was deleted from mapped collection (%s)", "editBitstream": "Item (%s) was deleted bitstream (%s)", "itemMetadata": "Item metadata (%s) was %s", "bitstreamMetadata": "Item metadata (%s) was %s bitstream (%s)", diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 0584ea2f03e1..1477e4fc0fc9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -92,7 +92,7 @@ public void setUp() throws Exception { .withTitle("Public item 1") .build(); context.restoreAuthSystemState(); - suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-patch-suite.json")); + suite = objectMapper.readTree(getClass().getResourceAsStream("provenance-test.json")); } @After diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-test.json similarity index 100% rename from dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-patch-suite.json rename to dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-test.json From 5282d63063a814f71ddcc1483f5ebec5a1358222 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 23:11:32 +0200 Subject: [PATCH 36/54] refactoring based on git comparison --- .../bulkaccesscontrol/BulkAccessControl.java | 3 +- .../core/ProvenanceMessageProviderImpl.java | 6 +-- .../dspace/core/ProvenanceServiceImpl.java | 54 ++++++++----------- .../app/rest/ItemAddBundleController.java | 1 + .../rest/MappedCollectionRestController.java | 6 --- .../operation/BitstreamRemoveOperation.java | 1 - .../DSpaceObjectMetadataAddOperation.java | 3 -- .../DSpaceObjectMetadataRemoveOperation.java | 3 -- .../dspace/app/rest/ItemRestRepositoryIT.java | 3 +- .../rest/test/item-metadata-patch-suite.json | 8 +-- 10 files changed, 32 insertions(+), 56 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 271541b88392..909a69faf748 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -450,7 +450,6 @@ private void updateItemPolicies(Item item, BulkAccessControlInput accessControl) logInfo(acItem.getAccessConditions(), acItem.getMode(), item); } - /** /** * create the new resource policies of item. * then, call {@link ItemService#adjustItemPolicies( @@ -463,6 +462,7 @@ private void updateItemPolicies(Item item, BulkAccessControlInput accessControl) */ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + accessControl .getItem() .getAccessConditions() @@ -583,6 +583,7 @@ private void removeReadPolicies(DSpaceObject dso, String type) { */ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + accessControl.getBitstream() .getAccessConditions() .forEach(accessCondition -> createResourcePolicy(bitstream, accessCondition, diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java index a44930dbf466..3194209e1273 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java @@ -28,19 +28,17 @@ import org.springframework.beans.factory.annotation.Autowired; public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider { + private static final String PROVENANCE_MSG_JSON = "provenance_messages.json"; private Map messageTemplates; - - @Autowired private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - @Autowired public ProvenanceMessageProviderImpl() { loadMessageTemplates(); } private void loadMessageTemplates() { ObjectMapper mapper = new ObjectMapper(); - try (InputStream inputStream = getClass().getResourceAsStream("provenance_messages.json")) { + try (InputStream inputStream = getClass().getResourceAsStream(PROVENANCE_MSG_JSON)) { if (inputStream == null) { throw new RuntimeException("Failed to find message templates file"); } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index d63dcc576c45..af372f79fdbc 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -36,7 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired; public class ProvenanceServiceImpl implements ProvenanceService { - private static final Logger log = LogManager.getLogger(); + private static final Logger log = LogManager.getLogger(ProvenanceServiceImpl.class); @Autowired private ItemService itemService; @@ -49,16 +49,13 @@ public class ProvenanceServiceImpl implements ProvenanceService { @Autowired private BitstreamService bitstreamService; - private ProvenanceMessageProvider messageProvider = new ProvenanceMessageProviderImpl(); - - + private final ProvenanceMessageProvider messageProvider = new ProvenanceMessageProviderImpl(); private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", msg.toString()); - itemService.update(context, item); // Update item in DB - //context.commit(); + "description", "provenance", "en", msg); + itemService.update(context, item); } private String extractAccessConditions(List accessConditions) { @@ -76,6 +73,24 @@ private Item getItem(Context context, Bitstream bitstream) throws SQLException { return items.get(0); } + private String findLicenseInBundles(Item item, String bundleName, String currentLicense, Context context) + throws SQLException { + List bundles = item.getBundles(bundleName); + for (Bundle clarinBundle : bundles) { + List bitstreamList = clarinBundle.getBitstreams(); + for (Bitstream bundleBitstream : bitstreamList) { + if (Objects.isNull(currentLicense)) { + List mappings = + this.clarinResourceMappingService.findByBitstreamUUID(context, bundleBitstream.getID()); + if (!mappings.isEmpty()) { + return mappings.get(0).getLicense().getName(); + } + } + } + } + return currentLicense; + } + @Override public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { @@ -123,25 +138,6 @@ public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item } } - // Method to find license in the bundles - private String findLicenseInBundles(Item item, String bundleName, String currentLicense, Context context) - throws SQLException { - List bundles = item.getBundles(bundleName); - for (Bundle clarinBundle : bundles) { - List bitstreamList = clarinBundle.getBitstreams(); - for (Bitstream bundleBitstream : bitstreamList) { - if (Objects.isNull(currentLicense)) { - List mappings = - this.clarinResourceMappingService.findByBitstreamUUID(context, bundleBitstream.getID()); - if (!mappings.isEmpty()) { - return mappings.get(0).getLicense().getName(); - } - } - } - } - return currentLicense; - } - @Override public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { String oldLicense = null; @@ -194,14 +190,12 @@ public void deleteBitstream(Context context,Bitstream bitstream) throws SQLExcep public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { if (Constants.ITEM == dso.getType()) { - // Add suitable provenance String msg = messageProvider.getMessage(context, "itemMetadata", messageProvider.getMetadataField(metadataField), "added"); addProvenanceMetadata(context, (Item) dso, msg); } if (dso.getType() == Constants.BITSTREAM) { - // Add suitable provenance Bitstream bitstream = (Bitstream) dso; Item item = getItem(context, bitstream); if (!Objects.isNull(item)) { @@ -228,7 +222,6 @@ public void removeMetadata(Context context, DSpaceObject dso, MetadataField meta oldMtdKey = mtd.get(0).getMetadataField(); oldMtdValue = mtd.get(0).getValue(); } - // Add suitable provenance Bitstream bitstream = (Bitstream) dso; Item item = getItem(context, bitstream); if (!Objects.isNull(item)) { @@ -248,7 +241,6 @@ public void removeMetadataAtIndex(Context context, DSpaceObject dso, List { @Autowired BitstreamService bitstreamService; - @Autowired AuthorizeService authorizeService; public static final String OPERATION_PATH_BITSTREAM_REMOVE = "/bitstreams/"; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index df28817ab0ea..40136115712c 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -9,8 +9,6 @@ import java.sql.SQLException; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; @@ -36,7 +34,6 @@ */ @Component public class DSpaceObjectMetadataAddOperation extends PatchOperation { - private static final Logger log = LogManager.getLogger(); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 8ca5eb66ea43..d4d3a83d0644 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -11,8 +11,6 @@ import java.util.Arrays; import java.util.List; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; @@ -43,7 +41,6 @@ */ @Component public class DSpaceObjectMetadataRemoveOperation extends PatchOperation { - private static final Logger log = LogManager.getLogger(); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index 7db55b1fa39c..8f139a03f5d2 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -2439,8 +2439,7 @@ private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Ex context.restoreAuthSystemState(); String token = getAuthToken(asUser.getEmail(), password); - new MetadataPatchSuite("item-metadata-patch-suite.json") - .runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); + new MetadataPatchSuite().runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); } /** diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json index 9c3f6a534a8d..fdbe61278546 100644 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/test/item-metadata-patch-suite.json @@ -180,9 +180,9 @@ "language":"en","authority":null,"confidence":-1,"place":1}, {"value":"Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language":"en","authority":null,"confidence":-1,"place":2}, - {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", + {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":3}, - {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", + {"value":"Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language":"en","authority":null,"confidence":-1,"place":4} ], "dc.title": [ @@ -208,9 +208,9 @@ "language": "en", "authority": null, "confidence": -1, "place": 1}, {"value": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on ", "language": "en", "authority": null, "confidence": -1, "place": 2}, - {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", + {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 3}, - {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on ", + {"value": "Item metadata (dc.title: title A) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", "language": "en", "authority": null, "confidence": -1, "place": 4} ] } From 828769fe9a30f138e60faecaef8d65b0ccdc8895 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Mon, 7 Oct 2024 23:23:58 +0200 Subject: [PATCH 37/54] checkstyle violations --- .../main/java/org/dspace/core/ProvenanceMessageProviderImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java index 3194209e1273..b20e52c2f15d 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java @@ -25,7 +25,6 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.InstallItemService; import org.dspace.eperson.EPerson; -import org.springframework.beans.factory.annotation.Autowired; public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider { private static final String PROVENANCE_MSG_JSON = "provenance_messages.json"; From a1b95e6c43e585a6edd3683c9ac1eaf3efc91b8d Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 8 Oct 2024 08:12:13 +0200 Subject: [PATCH 38/54] used correct json --- .../src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index 8f139a03f5d2..1af4d735e625 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -2439,7 +2439,7 @@ private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Ex context.restoreAuthSystemState(); String token = getAuthToken(asUser.getEmail(), password); - new MetadataPatchSuite().runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); + new MetadataPatchSuite("item-metadata-patch-suite.json").runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); } /** From 8621bcdb63e1861717f3570273e9e23c876ea401 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Tue, 8 Oct 2024 08:12:44 +0200 Subject: [PATCH 39/54] checkstyle violations --- .../test/java/org/dspace/app/rest/ItemRestRepositoryIT.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java index 1af4d735e625..4e6337d33fef 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ItemRestRepositoryIT.java @@ -2439,7 +2439,8 @@ private void runPatchMetadataTests(EPerson asUser, int expectedStatus) throws Ex context.restoreAuthSystemState(); String token = getAuthToken(asUser.getEmail(), password); - new MetadataPatchSuite("item-metadata-patch-suite.json").runWith(getClient(token), "/api/core/items/" + item.getID(), expectedStatus); + new MetadataPatchSuite("item-metadata-patch-suite.json").runWith(getClient(token), + "/api/core/items/" + item.getID(), expectedStatus); } /** From 2fdc96e9a6647821933d03f95bd9edb76d1fb7c0 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 10 Oct 2024 11:38:57 +0200 Subject: [PATCH 40/54] log exception, replace ! by non conds, added doc comments --- .../core/ProvenanceMessageProvider.java | 2 ++ .../core/ProvenanceMessageProviderImpl.java | 19 ++++++++++++-- .../org/dspace/core/ProvenanceService.java | 6 +++++ .../dspace/core/ProvenanceServiceImpl.java | 25 ++++++++++++------- .../rest/BundleUploadBitstreamController.java | 13 +++++++--- .../DSpaceObjectMetadataAddOperation.java | 17 +++++++++---- .../DSpaceObjectMetadataRemoveOperation.java | 18 ++++++++----- .../DSpaceObjectMetadataReplaceOperation.java | 18 ++++++++----- .../ItemDiscoverableReplaceOperation.java | 16 +++++++++--- 9 files changed, 98 insertions(+), 36 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java index 945cb8688888..ad4e48c38e15 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -18,6 +18,8 @@ /** * Interface for providing provenance messages. + * + * @author Michaela Paurikova (dspace at dataquest.sk) */ public interface ProvenanceMessageProvider { public String getMessage(Context context, String templateKey, Object... args) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java index b20e52c2f15d..0828b40731b2 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java @@ -25,9 +25,19 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.InstallItemService; import org.dspace.eperson.EPerson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +/** + * The ProvenanceMessageProviderImpl class implements the ProvenanceMessageProvider interface, + * providing methods to generate provenance messages for DSpace items. It loads message templates + * from a JSON file and formats messages based on the context, including user details and timestamps. + * + * @author Michaela Paurikova (dspace at dataquest.sk) + */ public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider { private static final String PROVENANCE_MSG_JSON = "provenance_messages.json"; + private static final Logger log = LoggerFactory.getLogger(ProvenanceMessageProviderImpl.class); private Map messageTemplates; private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); @@ -37,13 +47,18 @@ public ProvenanceMessageProviderImpl() { private void loadMessageTemplates() { ObjectMapper mapper = new ObjectMapper(); + String msg; try (InputStream inputStream = getClass().getResourceAsStream(PROVENANCE_MSG_JSON)) { if (inputStream == null) { - throw new RuntimeException("Failed to find message templates file"); + msg = "Failed to find message templates file."; + log.error(msg); + throw new RuntimeException(msg); } messageTemplates = mapper.readValue(inputStream, Map.class); } catch (IOException e) { - throw new RuntimeException("Failed to load message templates", e); + msg = "Failed to load message templates."; + log.error(msg); + throw new RuntimeException(msg, e); } } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java index 8727f3b6f38e..20fb1e4c1187 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java @@ -20,6 +20,12 @@ import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; +/** + * The ProvenanceService interface defines methods for creating provenance metadata + * for items based on the actions performed. + * + * @author Michaela Paurikova (dspace at dataquest.sk) + */ public interface ProvenanceService { public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException; diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index af372f79fdbc..aa604c3f5f84 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -13,6 +13,7 @@ import java.util.stream.Collectors; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dspace.app.bulkaccesscontrol.model.AccessCondition; @@ -35,6 +36,12 @@ import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; import org.springframework.beans.factory.annotation.Autowired; +/** + * ProvenanceServiceImpl is responsible for creating provenance metadata for items based on the actions performed. + * It implements the ProvenanceService interface. + * + * @author Michaela Paurikova (dspace at dataquest.sk) + */ public class ProvenanceServiceImpl implements ProvenanceService { private static final Logger log = LogManager.getLogger(ProvenanceServiceImpl.class); @@ -82,7 +89,7 @@ private String findLicenseInBundles(Item item, String bundleName, String current if (Objects.isNull(currentLicense)) { List mappings = this.clarinResourceMappingService.findByBitstreamUUID(context, bundleBitstream.getID()); - if (!mappings.isEmpty()) { + if (CollectionUtils.isNotEmpty(mappings)) { return mappings.get(0).getLicense().getName(); } } @@ -95,7 +102,7 @@ private String findLicenseInBundles(Item item, String bundleName, String current public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); - if (!resPoliciesStr.isEmpty()) { + if (StringUtils.isNotBlank(resPoliciesStr)) { String msg = messageProvider.getMessage(context,"accessCondition", resPoliciesStr, "item", item.getID()); addProvenanceMetadata(context, item, msg); @@ -118,7 +125,7 @@ public String removedReadPolicies(Context context, DSpaceObject dso, String type } else if (dso.getType() == Constants.BITSTREAM) { Bitstream bitstream = (Bitstream) dso; Item item = getItem(context, bitstream); - if (!Objects.isNull(item)) { + if (Objects.nonNull(item)) { String msg = messageProvider.getMessage(context,"resourcePoliciesRemoved", resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "bitstream", bitstream.getID()); addProvenanceMetadata(context, item, msg); @@ -131,7 +138,7 @@ public String removedReadPolicies(Context context, DSpaceObject dso, String type public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); - if (!accConditionsStr.isEmpty()) { + if (StringUtils.isNotBlank(accConditionsStr)) { String msg = messageProvider.getMessage(context,"accessCondition", accConditionsStr, "bitstream", bitstream.getID()); addProvenanceMetadata(context, item, msg); @@ -179,7 +186,7 @@ public void deletedItemFromMapped(Context context, Item item, Collection collect @Override public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException { Item item = getItem(context, bitstream); - if (!Objects.isNull(item)) { + if (Objects.nonNull(item)) { String msg = messageProvider.getMessage(context, "editBitstream", item, item.getID(), messageProvider.getBitstreamMessage(bitstream)); addProvenanceMetadata(context, item, msg); @@ -198,7 +205,7 @@ public void addMetadata(Context context, DSpaceObject dso, MetadataField metadat if (dso.getType() == Constants.BITSTREAM) { Bitstream bitstream = (Bitstream) dso; Item item = getItem(context, bitstream); - if (!Objects.isNull(item)) { + if (Objects.nonNull(item)) { String msg = messageProvider.getMessage(context, "bitstreamMetadata", item, messageProvider.getMetadataField(metadataField), "added by", messageProvider.getBitstreamMessage(bitstream)); @@ -218,13 +225,13 @@ public void removeMetadata(Context context, DSpaceObject dso, MetadataField meta List mtd = bitstreamService.getMetadata((Bitstream) dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); - if (!CollectionUtils.isEmpty(mtd)) { + if (CollectionUtils.isNotEmpty(mtd)) { oldMtdKey = mtd.get(0).getMetadataField(); oldMtdValue = mtd.get(0).getValue(); } Bitstream bitstream = (Bitstream) dso; Item item = getItem(context, bitstream); - if (!Objects.isNull(item)) { + if (Objects.nonNull(item)) { String msg = messageProvider.getMessage(context, "bitstreamMetadata", item, messageProvider.getMetadata(messageProvider.getMetadataField(oldMtdKey), oldMtdValue), "deleted from", messageProvider.getBitstreamMessage(bitstream)); @@ -267,7 +274,7 @@ public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataFie Bitstream bitstream = (Bitstream) dso; Item item = getItem(context, bitstream); - if (!Objects.isNull(item)) { + if (Objects.nonNull(item)) { String msg = messageProvider.getMessage(context, "itemReplaceSingleMetadata", item, messageProvider.getBitstreamMessage(bitstream), messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), oldMtdVal)); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index 749cd788a4c3..3b3486319f46 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -108,6 +108,7 @@ public ResponseEntity> uploadBitstream( throw new ResourceNotFoundException("The given uuid did not resolve to a Bundle on the server: " + uuid); } InputStream fileInputStream = null; + String msg; try { fileInputStream = uploadfile.getInputStream(); } catch (IOException e) { @@ -118,11 +119,15 @@ public ResponseEntity> uploadBitstream( try { provenanceService.uploadBitstream(context, bundle); } catch (SQLException ex) { - throw new RuntimeException("SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + - "adding new provenance metadata.", ex); + msg = "SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + + "adding new provenance metadata."; + log.error(msg, ex); + throw new RuntimeException(msg, ex); } catch (AuthorizeException ex) { - throw new RuntimeException("AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + - "when adding new provenance metadata.", ex); + msg = "AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + + "when adding new provenance metadata."; + log.error(msg, ex); + throw new RuntimeException(msg, ex); } BitstreamRest bitstreamRest = bundleRestRepository.uploadBitstream( diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 40136115712c..29e5d5acf0f0 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -18,6 +18,8 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -35,6 +37,7 @@ @Component public class DSpaceObjectMetadataAddOperation extends PatchOperation { + private static final Logger log = LoggerFactory.getLogger(DSpaceObjectMetadataAddOperation.class); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; @@ -63,6 +66,7 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi MetadataValueRest metadataValue, String index) { metadataPatchUtils.checkMetadataFieldNotNull(metadataField); int indexInt = 0; + String msg; if (index != null && index.equals("-")) { indexInt = -1; } @@ -72,12 +76,15 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); provenanceService.addMetadata(context, dso, metadataField); } catch (SQLException e) { - throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataAddOperation.add trying to add " + - "metadata to dso.", e); + msg = "SQLException in DspaceObjectMetadataAddOperation.add trying to add " + + "metadata to dso."; + log.error(msg, e); + throw new DSpaceBadRequestException(msg, e); } catch (AuthorizeException e) { - throw new DSpaceBadRequestException( - "AuthorizeException in DspaceObjectMetadataAddOperation.add " + - "trying to add metadata to dso.", e); + msg = "AuthorizeException in DspaceObjectMetadataAddOperation.add " + + "trying to add metadata to dso."; + log.error(msg, e); + throw new DSpaceBadRequestException(msg, e); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index d4d3a83d0644..2efbbaa42cb9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -22,6 +22,8 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -42,6 +44,7 @@ @Component public class DSpaceObjectMetadataRemoveOperation extends PatchOperation { + private static final Logger log = LoggerFactory.getLogger(DSpaceObjectMetadataRemoveOperation.class); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; @@ -67,6 +70,7 @@ public R perform(Context context, R resource, Operation operation) throws SQLExc private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoService, MetadataField metadataField, String index) { metadataPatchUtils.checkMetadataFieldNotNull(metadataField); + String msg; try { if (index == null) { provenanceService.removeMetadata(context, dso, metadataField); @@ -95,13 +99,15 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe } catch (ArrayIndexOutOfBoundsException e) { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } catch (SQLException ex) { - throw new DSpaceBadRequestException( - "SQLException in DspaceObjectMetadataRemoveOperation.remove " + - "trying to remove metadata from dso.", ex); + msg = "SQLException in DspaceObjectMetadataRemoveOperation.remove " + + "trying to remove metadata from dso."; + log.error(msg, ex); + throw new DSpaceBadRequestException(msg, ex); } catch (AuthorizeException ex) { - throw new DSpaceBadRequestException( - "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + - "trying to replace metadata from dso.", ex); + msg = "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + + "trying to replace metadata from dso."; + log.error(msg, ex); + throw new DSpaceBadRequestException(msg, ex); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index e11a4fe78678..689f946bebf8 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -22,6 +22,8 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -39,6 +41,7 @@ */ @Component public class DSpaceObjectMetadataReplaceOperation extends PatchOperation { + private static final Logger log = LoggerFactory.getLogger(DSpaceObjectMetadataReplaceOperation.class); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; @@ -194,6 +197,7 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, DSpaceObjectService dsoService, MetadataField metadataField, String index, String propertyOfMd, String valueMdProperty) { + String msg; try { List metadataValues = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), @@ -225,13 +229,15 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D throw new IllegalArgumentException("Not all numbers are valid numbers. " + "(Index and confidence should be nr)", e); } catch (SQLException e) { - throw new DSpaceBadRequestException( - "SQLException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + - "trying to replace metadata from dso.", e); + msg = "SQLException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + + "trying to replace metadata from dso."; + log.error(msg, e); + throw new DSpaceBadRequestException(msg, e); } catch (AuthorizeException e) { - throw new DSpaceBadRequestException( - "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + - "trying to replace metadata from dso.", e); + msg = "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + + "trying to replace metadata from dso."; + log.error(msg, e); + throw new DSpaceBadRequestException(msg, e); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index 57b406451884..9b243374e6ff 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -15,6 +15,8 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Item; import org.dspace.core.Context; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** @@ -33,6 +35,7 @@ public class ItemDiscoverableReplaceOperation extends PatchOperation { * Path in json body of patch that uses this operation */ private static final String OPERATION_PATH_DISCOVERABLE = "/discoverable"; + private static final Logger log = LoggerFactory.getLogger(ItemDiscoverableReplaceOperation.class); @Override public R perform(Context context, R object, Operation operation) { @@ -44,14 +47,19 @@ public R perform(Context context, R object, Operation operation) { throw new UnprocessableEntityException("A template item cannot be discoverable."); } item.setDiscoverable(discoverable); + String msg; try { provenanceService.makeDiscoverable(context, item, discoverable); } catch (SQLException ex) { - throw new RuntimeException("SQLException occurred when item making " + (discoverable ? "" : "non-") - + "discoverable.", ex); + msg = "SQLException occurred when item making " + (discoverable ? "" : "non-") + + "discoverable."; + log.error(msg, ex); + throw new RuntimeException(msg, ex); } catch (AuthorizeException ex) { - throw new RuntimeException("AuthorizeException occurred when item making " - + (discoverable ? "" : "non-") + "discoverable.", ex); + msg = "AuthorizeException occurred when item making " + + (discoverable ? "" : "non-") + "discoverable."; + log.error(msg, ex); + throw new RuntimeException(msg, ex); } return object; } else { From b026ca0528d709939bd2504d446d795a71a67857 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Thu, 17 Oct 2024 12:53:33 +0200 Subject: [PATCH 41/54] added logs for replacing mtd --- .../DSpaceObjectMetadataReplaceOperation.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 689f946bebf8..39c65551a18f 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -152,6 +152,7 @@ private void replaceMetadataFieldMetadata(Context context, DSpaceObject dso, DSp private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpaceObjectService dsoService, MetadataField metadataField, MetadataValueRest metadataValue, String index) { + String msg; try { List metadataValues = dsoService.getMetadata(dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), @@ -175,13 +176,15 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac } catch (NumberFormatException e) { throw new IllegalArgumentException("This index (" + index + ") is not valid number.", e); } catch (SQLException e) { - throw new DSpaceBadRequestException( - "SQLException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + - "trying to replace metadata from dso.", e); + msg = "SQLException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + + "trying to replace metadata from dso."; + log.error(msg, e); + throw new DSpaceBadRequestException(msg, e); } catch (AuthorizeException e) { - throw new DSpaceBadRequestException( - "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + - "trying to replace metadata from dso.", e); + msg = "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + + "trying to replace metadata from dso."; + log.error(msg, e); + throw new DSpaceBadRequestException(msg, e); } } From 64d7eae5c4f9c7eb27de361df603c0a55ad4f0b2 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Wed, 20 Nov 2024 10:30:05 +0100 Subject: [PATCH 42/54] removed unused services --- .../rest/repository/patch/operation/PatchOperation.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index b144a2338c29..8d4123b20131 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -12,8 +12,6 @@ import org.apache.commons.lang3.BooleanUtils; import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.patch.Operation; -import org.dspace.content.service.InstallItemService; -import org.dspace.content.service.ItemService; import org.dspace.core.Context; import org.dspace.core.ProvenanceService; import org.springframework.beans.factory.annotation.Autowired; @@ -30,12 +28,6 @@ public abstract class PatchOperation { public static final String OPERATION_MOVE = "move"; public static final String OPERATION_REMOVE = "remove"; - @Autowired - InstallItemService installItemService; - - @Autowired - ItemService itemService; - @Autowired ProvenanceService provenanceService; From 49cae228c7bdecdb0c3540cc1c1ad0d5b02f61b1 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Fri, 22 Nov 2024 11:44:50 +0100 Subject: [PATCH 43/54] make object from provenance service --- .../bulkaccesscontrol/BulkAccessControl.java | 12 ++-- ...rviceImpl.java => ProvenanceProvider.java} | 41 ++++--------- .../org/dspace/core/ProvenanceService.java | 58 ------------------- .../core/factory/CoreServiceFactory.java | 3 - .../core/factory/CoreServiceFactoryImpl.java | 9 --- .../rest/BundleUploadBitstreamController.java | 7 +-- .../app/rest/ItemAddBundleController.java | 7 +-- ...mOwningCollectionUpdateRestController.java | 7 +-- .../rest/MappedCollectionRestController.java | 9 ++- .../operation/BitstreamRemoveOperation.java | 2 +- .../DSpaceObjectMetadataAddOperation.java | 2 +- .../DSpaceObjectMetadataRemoveOperation.java | 4 +- .../DSpaceObjectMetadataReplaceOperation.java | 4 +- .../ItemDiscoverableReplaceOperation.java | 2 +- .../patch/operation/PatchOperation.java | 6 +- ...rviceIT.java => ProvenanceProviderIT.java} | 2 +- dspace/config/spring/api/core-services.xml | 1 - 17 files changed, 39 insertions(+), 137 deletions(-) rename dspace-api/src/main/java/org/dspace/core/{ProvenanceServiceImpl.java => ProvenanceProvider.java} (93%) delete mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceService.java rename dspace-server-webapp/src/test/java/org/dspace/app/rest/{ProvenanceServiceIT.java => ProvenanceProviderIT.java} (99%) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 909a69faf748..f58c8f8755ef 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -55,8 +55,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceService; -import org.dspace.core.factory.CoreServiceFactory; +import org.dspace.core.ProvenanceProvider; import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.SearchService; import org.dspace.discovery.SearchServiceException; @@ -113,7 +112,7 @@ public class BulkAccessControl extends DSpaceRunnable resPolicies = resourcePolicyService.find(context, dso, type); @@ -134,7 +129,6 @@ public String removedReadPolicies(Context context, DSpaceObject dso, String type return resPoliciesStr; } - @Override public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); @@ -145,7 +139,6 @@ public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item } } - @Override public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { String oldLicense = null; oldLicense = findLicenseInBundles(item, Constants.LICENSE_BUNDLE_NAME, oldLicense, context); @@ -159,8 +152,6 @@ public void editLicense(Context context, Item item, boolean newLicense) throws S addProvenanceMetadata(context, item, msg); } - - @Override public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { String msg = messageProvider.getMessage(context, "moveItem", item, collection.getID()); // Update item in DB @@ -170,20 +161,17 @@ public void moveItem(Context context, Item item, Collection collection) throws S context.restoreAuthSystemState(); } - @Override public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { String msg = messageProvider.getMessage(context, "mappedItem", collection.getID()); addProvenanceMetadata(context, item, msg); } - @Override public void deletedItemFromMapped(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { String msg = messageProvider.getMessage(context, "deletedItemFromMapped", collection.getID()); addProvenanceMetadata(context, item, msg); } - @Override public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException { Item item = getItem(context, bitstream); if (Objects.nonNull(item)) { @@ -193,7 +181,6 @@ public void deleteBitstream(Context context,Bitstream bitstream) throws SQLExcep } } - @Override public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { if (Constants.ITEM == dso.getType()) { @@ -214,7 +201,6 @@ public void addMetadata(Context context, DSpaceObject dso, MetadataField metadat } } - @Override public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) throws SQLException, AuthorizeException { if (dso.getType() != Constants.BITSTREAM) { @@ -239,7 +225,6 @@ public void removeMetadata(Context context, DSpaceObject dso, MetadataField meta } } - @Override public void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, int indexInt) throws SQLException, AuthorizeException { if (dso.getType() != Constants.ITEM) { @@ -253,7 +238,6 @@ public void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, - int indexInt) throws SQLException, AuthorizeException; - public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) - throws SQLException, AuthorizeException; - public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) - throws SQLException, AuthorizeException; - public void makeDiscoverable(Context context, Item item, boolean discoverable) - throws SQLException, AuthorizeException; -} diff --git a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java index 4b9621faf478..e7260fc2b4f4 100644 --- a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java +++ b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactory.java @@ -7,7 +7,6 @@ */ package org.dspace.core.factory; -import org.dspace.core.ProvenanceService; import org.dspace.core.service.LicenseService; import org.dspace.core.service.NewsService; import org.dspace.core.service.PluginService; @@ -30,8 +29,6 @@ public abstract class CoreServiceFactory { public abstract ClientInfoService getClientInfoService(); - public abstract ProvenanceService getProvenanceService(); - public static CoreServiceFactory getInstance() { return DSpaceServicesFactory.getInstance().getServiceManager() .getServiceByName("coreServiceFactory", CoreServiceFactory.class); diff --git a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java index 6af8209a2ecf..7db3ad24d78b 100644 --- a/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/core/factory/CoreServiceFactoryImpl.java @@ -7,7 +7,6 @@ */ package org.dspace.core.factory; -import org.dspace.core.ProvenanceService; import org.dspace.core.service.LicenseService; import org.dspace.core.service.NewsService; import org.dspace.core.service.PluginService; @@ -34,9 +33,6 @@ public class CoreServiceFactoryImpl extends CoreServiceFactory { @Autowired(required = true) private ClientInfoService clientInfoService; - @Autowired(required = true) - private ProvenanceService provenanceService; - @Override public LicenseService getLicenseService() { return licenseService; @@ -55,9 +51,4 @@ public PluginService getPluginService() { public ClientInfoService getClientInfoService() { return clientInfoService; } - - @Override - public ProvenanceService getProvenanceService() { - return provenanceService; - } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index 3b3486319f46..bbdd11561d52 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -29,7 +29,7 @@ import org.dspace.content.Bundle; import org.dspace.content.service.BundleService; import org.dspace.core.Context; -import org.dspace.core.ProvenanceService; +import org.dspace.core.ProvenanceProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; @@ -79,8 +79,7 @@ public class BundleUploadBitstreamController { @Autowired private ConverterService converter; - @Autowired - private ProvenanceService provenanceService; + private ProvenanceProvider provenanceProvider = new ProvenanceProvider(); /** * Method to upload a Bitstream to a Bundle with the given UUID in the URL. This will create a Bitstream with the @@ -117,7 +116,7 @@ public ResponseEntity> uploadBitstream( throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e); } try { - provenanceService.uploadBitstream(context, bundle); + provenanceProvider.uploadBitstream(context, bundle); } catch (SQLException ex) { msg = "SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + "adding new provenance metadata."; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 6e515452bb99..4656936e0c89 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -38,7 +38,7 @@ import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceService; +import org.dspace.core.ProvenanceProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -99,8 +99,7 @@ public class ItemAddBundleController { @Autowired ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; - @Autowired - ProvenanceService provenanceService; + ProvenanceProvider provenanceProvider = new ProvenanceProvider(); /** * Method to add a Bundle to an Item with the given UUID in the URL. This will create a Bundle with the @@ -169,7 +168,7 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, log.warn("Cannot find clarin license with id: " + licenseId + ". The old license will be detached, " + "but the new one will not be attached."); } - provenanceService.editLicense(context, item, !Objects.isNull(clarinLicense)); + provenanceProvider.editLicense(context, item, !Objects.isNull(clarinLicense)); List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index ca467c91630e..247adec9c36d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -32,7 +32,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceService; +import org.dspace.core.ProvenanceProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.prepost.PostAuthorize; @@ -66,8 +66,7 @@ public class ItemOwningCollectionUpdateRestController { @Autowired Utils utils; - @Autowired - ProvenanceService provenanceService; + ProvenanceProvider provenanceProvider = new ProvenanceProvider(); /** * This method will update the owning collection of the item that correspond to the provided item uuid, effectively @@ -129,7 +128,7 @@ private Collection moveItem(final Context context, final Item item, final Collec final boolean inheritPolicies) throws SQLException, IOException, AuthorizeException { itemService.move(context, item, currentCollection, targetCollection, inheritPolicies); - provenanceService.moveItem(context, item, currentCollection); + provenanceProvider.moveItem(context, item, currentCollection); // Necessary because Controller does not pass through general RestResourceController, and as such does not do // its commit in DSpaceRestRepository.createAndReturn() or similar context.commit(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index b7f8ea8f5977..cbdc46444719 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -30,7 +30,7 @@ import org.dspace.content.service.CollectionService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; -import org.dspace.core.ProvenanceService; +import org.dspace.core.ProvenanceProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; @@ -58,8 +58,7 @@ public class MappedCollectionRestController { @Autowired Utils utils; - @Autowired - ProvenanceService provenanceService; + ProvenanceProvider provenanceProvider = new ProvenanceProvider(); /** * This method will add an Item to a Collection. The Collection object is encapsulated in the request due to the @@ -108,7 +107,7 @@ public void createCollectionToItemRelation(@PathVariable UUID uuid, collectionService.addItem(context, collectionToMapTo, item); collectionService.update(context, collectionToMapTo); - provenanceService.mappedItem(context, item, collectionToMapTo); + provenanceProvider.mappedItem(context, item, collectionToMapTo); itemService.update(context, item); } else { throw new UnprocessableEntityException("Not a valid collection or item uuid."); @@ -155,7 +154,7 @@ public void deleteCollectionToItemRelation(@PathVariable UUID uuid, @PathVariabl if (collection.getID() != owningCollectionUuid && item.getCollections().contains(collection)) { collectionService.removeItem(context, collection, item); collectionService.update(context, collection); - provenanceService.deletedItemFromMapped(context,item, collection); + provenanceProvider.deletedItemFromMapped(context,item, collection); itemService.update(context, item); context.commit(); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index e134bbe7308c..0826ad16adcb 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -54,7 +54,7 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio } authorizeBitstreamRemoveAction(context, bitstreamToDelete, Constants.DELETE); try { - provenanceService.deleteBitstream(context, bitstreamToDelete); + provenanceProvider.deleteBitstream(context, bitstreamToDelete); bitstreamService.delete(context, bitstreamToDelete); } catch (AuthorizeException | IOException e) { throw new RuntimeException(e.getMessage(), e); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 29e5d5acf0f0..6982044d555b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -74,7 +74,7 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi dsoService.addAndShiftRightMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), metadataValue.getLanguage(), metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); - provenanceService.addMetadata(context, dso, metadataField); + provenanceProvider.addMetadata(context, dso, metadataField); } catch (SQLException e) { msg = "SQLException in DspaceObjectMetadataAddOperation.add trying to add " + "metadata to dso."; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 2efbbaa42cb9..5f5f54785d41 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -73,7 +73,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe String msg; try { if (index == null) { - provenanceService.removeMetadata(context, dso, metadataField); + provenanceProvider.removeMetadata(context, dso, metadataField); // remove all metadata of this type dsoService.clearMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); @@ -85,7 +85,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { - provenanceService.removeMetadataAtIndex(context, dso, metadataValues, indexInt); + provenanceProvider.removeMetadataAtIndex(context, dso, metadataValues, indexInt); // remove that metadata dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 39c65551a18f..2f7c4fdffcef 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -168,7 +168,7 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac existingMdv.setLanguage(metadataValue.getLanguage()); existingMdv.setValue(metadataValue.getValue()); dsoService.setMetadataModified(dso); - provenanceService.replaceMetadata(context, dso, metadataField, oldMtdVal); + provenanceProvider.replaceMetadata(context, dso, metadataField, oldMtdVal); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); @@ -224,7 +224,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D existingMdv.setValue(valueMdProperty); } dsoService.setMetadataModified(dso); - provenanceService.replaceMetadataSingle(context, dso, metadataField, oldMtdVal); + provenanceProvider.replaceMetadataSingle(context, dso, metadataField, oldMtdVal); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index 9b243374e6ff..ad901d03a927 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -49,7 +49,7 @@ public R perform(Context context, R object, Operation operation) { item.setDiscoverable(discoverable); String msg; try { - provenanceService.makeDiscoverable(context, item, discoverable); + provenanceProvider.makeDiscoverable(context, item, discoverable); } catch (SQLException ex) { msg = "SQLException occurred when item making " + (discoverable ? "" : "non-") + "discoverable."; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index 8d4123b20131..0fe89aef74d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -13,8 +13,7 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.core.Context; -import org.dspace.core.ProvenanceService; -import org.springframework.beans.factory.annotation.Autowired; +import org.dspace.core.ProvenanceProvider; /** * Base class for all resource patch operations. @@ -28,8 +27,7 @@ public abstract class PatchOperation { public static final String OPERATION_MOVE = "move"; public static final String OPERATION_REMOVE = "remove"; - @Autowired - ProvenanceService provenanceService; + ProvenanceProvider provenanceProvider = new ProvenanceProvider(); /** * Updates the rest model by applying the patch operation. diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceProviderIT.java similarity index 99% rename from dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java rename to dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceProviderIT.java index 1477e4fc0fc9..3bc826400fee 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceProviderIT.java @@ -68,7 +68,7 @@ import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { +public class ProvenanceProviderIT extends AbstractControllerIntegrationTest { private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); private ClarinLicenseLabelService clarinLicenseLabelService = ClarinServiceFactory.getInstance().getClarinLicenseLabelService(); diff --git a/dspace/config/spring/api/core-services.xml b/dspace/config/spring/api/core-services.xml index e1480cb9e981..305d41f64ee5 100644 --- a/dspace/config/spring/api/core-services.xml +++ b/dspace/config/spring/api/core-services.xml @@ -82,7 +82,6 @@ - From eb2315e50929d6ed6f2d43ce982e1ccdefcb3dd2 Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Fri, 22 Nov 2024 11:55:56 +0100 Subject: [PATCH 44/54] removed interface prom provenance msg provider --- .../core/ProvenanceMessageProvider.java | 116 +++++++++++++-- .../core/ProvenanceMessageProviderImpl.java | 137 ------------------ .../org/dspace/core/ProvenanceProvider.java | 3 +- 3 files changed, 106 insertions(+), 150 deletions(-) delete mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java index ad4e48c38e15..e5d109b8bcf4 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -7,29 +7,123 @@ */ package org.dspace.core; +import java.io.IOException; +import java.io.InputStream; import java.sql.SQLException; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import com.fasterxml.jackson.databind.ObjectMapper; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.Bitstream; +import org.dspace.content.Collection; +import org.dspace.content.DCDate; import org.dspace.content.Item; import org.dspace.content.MetadataField; +import org.dspace.content.factory.ContentServiceFactory; +import org.dspace.content.service.InstallItemService; +import org.dspace.eperson.EPerson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** - * Interface for providing provenance messages. + * The ProvenanceMessageProviderImpl class implements the ProvenanceMessageProvider interface, + * providing methods to generate provenance messages for DSpace items. It loads message templates + * from a JSON file and formats messages based on the context, including user details and timestamps. * * @author Michaela Paurikova (dspace at dataquest.sk) */ -public interface ProvenanceMessageProvider { - public String getMessage(Context context, String templateKey, Object... args) - throws SQLException, AuthorizeException; +public class ProvenanceMessageProvider { + private static final String PROVENANCE_MSG_JSON = "provenance_messages.json"; + private static final Logger log = LoggerFactory.getLogger(ProvenanceMessageProvider.class); + private Map messageTemplates; + private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); + + public ProvenanceMessageProvider() { + loadMessageTemplates(); + } + + private void loadMessageTemplates() { + ObjectMapper mapper = new ObjectMapper(); + String msg; + try (InputStream inputStream = getClass().getResourceAsStream(PROVENANCE_MSG_JSON)) { + if (inputStream == null) { + msg = "Failed to find message templates file."; + log.error(msg); + throw new RuntimeException(msg); + } + messageTemplates = mapper.readValue(inputStream, Map.class); + } catch (IOException e) { + msg = "Failed to load message templates."; + log.error(msg); + throw new RuntimeException(msg, e); + } + } + public String getMessage(Context context, String templateKey, Item item, Object... args) - throws SQLException, AuthorizeException; - public String getMessage(String templateKey, Object... args); - public String addCollectionsToMessage(Item item); - public String getBitstreamMessage(Bitstream bitstream); - public String getResourcePoliciesMessage(List resPolicies); - public String getMetadata(String oldMtdKey, String oldMtdValue); - public String getMetadataField(MetadataField metadataField); + throws SQLException, AuthorizeException { + String msg = getMessage(context, templateKey, args); + msg = msg + "\n" + installItemService.getBitstreamProvenanceMessage(context, item); + return msg; + } + + public String getMessage(String templateKey, Object... args) { + String template = messageTemplates.get(templateKey); + if (template == null) { + throw new IllegalArgumentException("No message template found for key: " + templateKey); + } + return String.format(template, args); + } + + public String getMessage(Context context, String templateKey, Object... args) { + EPerson currentUser = context.getCurrentUser(); + String timestamp = DCDate.getCurrent().toString(); + String details = getMessage(templateKey, args); + return String.format("%s by %s (%s) on %s", + details, + currentUser.getFullName(), + currentUser.getEmail(), + timestamp); + } + + public String addCollectionsToMessage(Item item) { + String msg = "Item was in collections:\n"; + List collsList = item.getCollections(); + for (Collection coll : collsList) { + msg = msg + coll.getName() + " (ID: " + coll.getID() + ")\n"; + } + return msg; + } + + public String getBitstreamMessage(Bitstream bitstream) { + // values of deleted bitstream + String msg = bitstream.getName() + ": " + + bitstream.getSizeBytes() + " bytes, checksum: " + + bitstream.getChecksum() + " (" + + bitstream.getChecksumAlgorithm() + ")\n"; + return msg; + } + + public String getResourcePoliciesMessage(List resPolicies) { + return resPolicies.stream() + .filter(rp -> rp.getAction() == Constants.READ) + .map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]", + rp.getRpName(), rp.getRpType(), rp.getAction(), + rp.getEPerson() != null ? rp.getEPerson().getEmail() : null, + rp.getGroup() != null ? rp.getGroup().getName() : null, + rp.getStartDate() != null ? rp.getStartDate().toString() : null, + rp.getEndDate() != null ? rp.getEndDate().toString() : null)) + .collect(Collectors.joining(";")); + } + + public String getMetadata(String oldMtdKey, String oldMtdValue) { + return oldMtdKey + ": " + oldMtdValue; + } + + public String getMetadataField(MetadataField metadataField) { + return metadataField.toString() + .replace('_', '.'); + } } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java deleted file mode 100644 index 0828b40731b2..000000000000 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProviderImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.core; - -import java.io.IOException; -import java.io.InputStream; -import java.sql.SQLException; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.databind.ObjectMapper; -import org.dspace.authorize.AuthorizeException; -import org.dspace.authorize.ResourcePolicy; -import org.dspace.content.Bitstream; -import org.dspace.content.Collection; -import org.dspace.content.DCDate; -import org.dspace.content.Item; -import org.dspace.content.MetadataField; -import org.dspace.content.factory.ContentServiceFactory; -import org.dspace.content.service.InstallItemService; -import org.dspace.eperson.EPerson; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The ProvenanceMessageProviderImpl class implements the ProvenanceMessageProvider interface, - * providing methods to generate provenance messages for DSpace items. It loads message templates - * from a JSON file and formats messages based on the context, including user details and timestamps. - * - * @author Michaela Paurikova (dspace at dataquest.sk) - */ -public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider { - private static final String PROVENANCE_MSG_JSON = "provenance_messages.json"; - private static final Logger log = LoggerFactory.getLogger(ProvenanceMessageProviderImpl.class); - private Map messageTemplates; - private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - - public ProvenanceMessageProviderImpl() { - loadMessageTemplates(); - } - - private void loadMessageTemplates() { - ObjectMapper mapper = new ObjectMapper(); - String msg; - try (InputStream inputStream = getClass().getResourceAsStream(PROVENANCE_MSG_JSON)) { - if (inputStream == null) { - msg = "Failed to find message templates file."; - log.error(msg); - throw new RuntimeException(msg); - } - messageTemplates = mapper.readValue(inputStream, Map.class); - } catch (IOException e) { - msg = "Failed to load message templates."; - log.error(msg); - throw new RuntimeException(msg, e); - } - } - - @Override - public String getMessage(Context context, String templateKey, Item item, Object... args) - throws SQLException, AuthorizeException { - String msg = getMessage(context, templateKey, args); - msg = msg + "\n" + installItemService.getBitstreamProvenanceMessage(context, item); - return msg; - } - - @Override - public String getMessage(String templateKey, Object... args) { - String template = messageTemplates.get(templateKey); - if (template == null) { - throw new IllegalArgumentException("No message template found for key: " + templateKey); - } - return String.format(template, args); - } - - @Override - public String getMessage(Context context, String templateKey, Object... args) { - EPerson currentUser = context.getCurrentUser(); - String timestamp = DCDate.getCurrent().toString(); - String details = getMessage(templateKey, args); - return String.format("%s by %s (%s) on %s", - details, - currentUser.getFullName(), - currentUser.getEmail(), - timestamp); - } - - @Override - public String addCollectionsToMessage(Item item) { - String msg = "Item was in collections:\n"; - List collsList = item.getCollections(); - for (Collection coll : collsList) { - msg = msg + coll.getName() + " (ID: " + coll.getID() + ")\n"; - } - return msg; - } - - @Override - public String getBitstreamMessage(Bitstream bitstream) { - // values of deleted bitstream - String msg = bitstream.getName() + ": " + - bitstream.getSizeBytes() + " bytes, checksum: " + - bitstream.getChecksum() + " (" + - bitstream.getChecksumAlgorithm() + ")\n"; - return msg; - } - - @Override - public String getResourcePoliciesMessage(List resPolicies) { - return resPolicies.stream() - .filter(rp -> rp.getAction() == Constants.READ) - .map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]", - rp.getRpName(), rp.getRpType(), rp.getAction(), - rp.getEPerson() != null ? rp.getEPerson().getEmail() : null, - rp.getGroup() != null ? rp.getGroup().getName() : null, - rp.getStartDate() != null ? rp.getStartDate().toString() : null, - rp.getEndDate() != null ? rp.getEndDate().toString() : null)) - .collect(Collectors.joining(";")); - } - - @Override - public String getMetadata(String oldMtdKey, String oldMtdValue) { - return oldMtdKey + ": " + oldMtdValue; - } - - @Override - public String getMetadataField(MetadataField metadataField) { - return metadataField.toString() - .replace('_', '.'); - } -} diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index 330b66261f0f..b92cbd62d3bf 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -37,7 +37,6 @@ import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; -import org.springframework.beans.factory.annotation.Autowired; /** * Provenance is responsible for creating provenance metadata for items based on the actions performed. @@ -53,7 +52,7 @@ public class ProvenanceProvider { private ClarinLicenseResourceMappingService clarinResourceMappingService = ClarinServiceFactory.getInstance().getClarinLicenseResourceMappingService(); private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); - private final ProvenanceMessageProvider messageProvider = new ProvenanceMessageProviderImpl(); + private final ProvenanceMessageProvider messageProvider = new ProvenanceMessageProvider(); private void addProvenanceMetadata(Context context, Item item, String msg) throws SQLException, AuthorizeException { From 876a7f26235973799952e104d0f789411733107a Mon Sep 17 00:00:00 2001 From: Paurikova2 Date: Fri, 22 Nov 2024 13:25:48 +0100 Subject: [PATCH 45/54] checkstyle --- .../java/org/dspace/core/ProvenanceMessageProvider.java | 4 ++-- .../main/java/org/dspace/core/ProvenanceProvider.java | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java index e5d109b8bcf4..f5f368fd0aa8 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -29,8 +29,8 @@ import org.slf4j.LoggerFactory; /** - * The ProvenanceMessageProviderImpl class implements the ProvenanceMessageProvider interface, - * providing methods to generate provenance messages for DSpace items. It loads message templates + * The ProvenanceMessageProvider providing methods to generate provenance messages for DSpace items. + * It loads message templates * from a JSON file and formats messages based on the context, including user details and timestamps. * * @author Michaela Paurikova (dspace at dataquest.sk) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index b92cbd62d3bf..f41dc57a136d 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -39,7 +39,7 @@ import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; /** - * Provenance is responsible for creating provenance metadata for items based on the actions performed. + * ProvenanceProviderrest is responsible for creating provenance metadata for items based on the actions performed. * * @author Michaela Paurikova (dspace at dataquest.sk) */ @@ -47,9 +47,12 @@ public class ProvenanceProvider { private static final Logger log = LogManager.getLogger(ProvenanceProvider.class); private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private ResourcePolicyService resourcePolicyService = AuthorizeServiceFactory.getInstance().getResourcePolicyService(); + private ResourcePolicyService resourcePolicyService = + AuthorizeServiceFactory.getInstance().getResourcePolicyService(); + private ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); - private ClarinLicenseResourceMappingService clarinResourceMappingService = ClarinServiceFactory.getInstance().getClarinLicenseResourceMappingService(); + private ClarinLicenseResourceMappingService clarinResourceMappingService = + ClarinServiceFactory.getInstance().getClarinLicenseResourceMappingService(); private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); private final ProvenanceMessageProvider messageProvider = new ProvenanceMessageProvider(); From 130d78f6414c8a3f473ed4558b2abb4878e1c23e Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 12 Dec 2024 14:38:34 +0100 Subject: [PATCH 46/54] Refactored method `removeReadPolicies` - add provenance after removing policy --- .../dspace/app/bulkaccesscontrol/BulkAccessControl.java | 8 ++++---- .../src/main/java/org/dspace/core/ProvenanceProvider.java | 6 ++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index f58c8f8755ef..deeb451ff648 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -45,6 +45,7 @@ import org.dspace.app.util.DSpaceObjectUtilsImpl; import org.dspace.app.util.service.DSpaceObjectUtils; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.factory.AuthorizeServiceFactory; import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.Bitstream; @@ -557,11 +558,10 @@ private void updateBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessC */ private void removeReadPolicies(DSpaceObject dso, String type) { try { - String resPoliciesStr = provenanceProvider.removedReadPolicies(context, dso, type); - if (Objects.isNull(resPoliciesStr)) { - return; - } + // Get all read policies of the dso before removing them + List resPolicies = resourcePolicyService.find(context, dso, type); resourcePolicyService.removePolicies(context, dso, type, Constants.READ); + provenanceProvider.removeReadPolicies(context, dso, resPolicies); } catch (SQLException | AuthorizeException e) { throw new BulkAccessControlException(e); } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index f41dc57a136d..5472d03c77b3 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -107,11 +107,10 @@ public void setItemPolicies(Context context, Item item, BulkAccessControlInput a } } - public String removedReadPolicies(Context context, DSpaceObject dso, String type) + public void removeReadPolicies(Context context, DSpaceObject dso, List resPolicies) throws SQLException, AuthorizeException { - List resPolicies = resourcePolicyService.find(context, dso, type); if (resPolicies.isEmpty()) { - return null; + return; } String resPoliciesStr = messageProvider.getResourcePoliciesMessage(resPolicies); if (dso.getType() == Constants.ITEM) { @@ -128,7 +127,6 @@ public String removedReadPolicies(Context context, DSpaceObject dso, String type addProvenanceMetadata(context, item, msg); } } - return resPoliciesStr; } public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, From 419aff33970342de186a7481ef5fe1b5cd351c55 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Thu, 12 Dec 2024 17:19:05 +0100 Subject: [PATCH 47/54] The message templates are loaded from the Enum instead of json file. --- .../core/ProvenanceMessageProvider.java | 45 ++++------------ .../core/ProvenanceMessageTemplates.java | 33 ++++++++++++ .../org/dspace/core/ProvenanceProvider.java | 53 +++++++++++-------- .../org/dspace/core/provenance_messages.json | 14 ----- .../app/rest/ProvenanceExpectedMessages.java | 37 +++++++++++++ .../dspace/app/rest/ProvenanceProviderIT.java | 45 ++++++++-------- .../org/dspace/app/rest/provenance-test.json | 16 ------ 7 files changed, 131 insertions(+), 112 deletions(-) create mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java delete mode 100644 dspace-api/src/main/resources/org/dspace/core/provenance_messages.json create mode 100644 dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceExpectedMessages.java delete mode 100644 dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-test.json diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java index f5f368fd0aa8..f1d65a483c91 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -7,14 +7,10 @@ */ package org.dspace.core; -import java.io.IOException; -import java.io.InputStream; import java.sql.SQLException; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; -import com.fasterxml.jackson.databind.ObjectMapper; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.Bitstream; @@ -36,51 +32,28 @@ * @author Michaela Paurikova (dspace at dataquest.sk) */ public class ProvenanceMessageProvider { - private static final String PROVENANCE_MSG_JSON = "provenance_messages.json"; - private static final Logger log = LoggerFactory.getLogger(ProvenanceMessageProvider.class); - private Map messageTemplates; private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - public ProvenanceMessageProvider() { - loadMessageTemplates(); - } - - private void loadMessageTemplates() { - ObjectMapper mapper = new ObjectMapper(); - String msg; - try (InputStream inputStream = getClass().getResourceAsStream(PROVENANCE_MSG_JSON)) { - if (inputStream == null) { - msg = "Failed to find message templates file."; - log.error(msg); - throw new RuntimeException(msg); - } - messageTemplates = mapper.readValue(inputStream, Map.class); - } catch (IOException e) { - msg = "Failed to load message templates."; - log.error(msg); - throw new RuntimeException(msg, e); - } - } + public ProvenanceMessageProvider() {} - public String getMessage(Context context, String templateKey, Item item, Object... args) + public String getMessage(Context context, String messageTemplate, Item item, Object... args) throws SQLException, AuthorizeException { - String msg = getMessage(context, templateKey, args); + String msg = getMessage(context, messageTemplate, args); msg = msg + "\n" + installItemService.getBitstreamProvenanceMessage(context, item); return msg; } - public String getMessage(String templateKey, Object... args) { - String template = messageTemplates.get(templateKey); - if (template == null) { - throw new IllegalArgumentException("No message template found for key: " + templateKey); + public String validateMessageTemplate(String messageTemplate, Object... args) { + if (messageTemplate == null) { + throw new IllegalArgumentException("The message template is null!"); } - return String.format(template, args); + return String.format(messageTemplate, args); } - public String getMessage(Context context, String templateKey, Object... args) { + public String getMessage(Context context, String messageTemplate, Object... args) { EPerson currentUser = context.getCurrentUser(); String timestamp = DCDate.getCurrent().toString(); - String details = getMessage(templateKey, args); + String details = validateMessageTemplate(messageTemplate, args); return String.format("%s by %s (%s) on %s", details, currentUser.getFullName(), diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java new file mode 100644 index 000000000000..410ff7af4ab3 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java @@ -0,0 +1,33 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.core; + +public enum ProvenanceMessageTemplates { + ACCESS_CONDITION("Access condition (%s) was added to %s (%s)"), + RESOURCE_POLICIES_REMOVED("Resource policies (%s) of %s (%s) were removed"), + BUNDLE_ADDED("Item was added bitstream to bundle (%s)"), + EDIT_LICENSE("License (%s) was %s"), + MOVE_ITEM("Item was moved from collection (%s) to different collection"), + MAPPED_ITEM("Item was mapped to collection (%s)"), + DELETED_ITEM_FROM_MAPPED("Item was deleted from mapped collection (%s)"), + EDIT_BITSTREAM("Item (%s) was deleted bitstream (%s)"), + ITEM_METADATA("Item metadata (%s) was %s"), + BITSTREAM_METADATA("Item metadata (%s) was %s bitstream (%s)"), + ITEM_REPLACE_SINGLE_METADATA("Item bitstream (%s) metadata (%s) was updated"), + DISCOVERABLE("Item was made %sdiscoverable"); + + private final String template; + + ProvenanceMessageTemplates(String template) { + this.template = template; + } + + public String getTemplate() { + return template; + } +} diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index 5472d03c77b3..9180cafb9fda 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -101,8 +101,8 @@ public void setItemPolicies(Context context, Item item, BulkAccessControlInput a throws SQLException, AuthorizeException { String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); if (StringUtils.isNotBlank(resPoliciesStr)) { - String msg = messageProvider.getMessage(context,"accessCondition", resPoliciesStr, - "item", item.getID()); + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ACCESS_CONDITION.getTemplate(), + resPoliciesStr, "item", item.getID()); addProvenanceMetadata(context, item, msg); } } @@ -115,14 +115,16 @@ public void removeReadPolicies(Context context, DSpaceObject dso, List metadata = obj.getMetadata(); boolean contain = false; for (MetadataValue value : metadata) { if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { continue; } - if (provenanceMetadataModified(value.getValue()).contains(expectedSubStr)) { + if (provenanceMetadataModified(value.getValue()).contains(expectedMessage)) { contain = true; break; } } if (!contain) { - Assert.fail("Metadata provenance do not contain expected data: " + expectedSubStr); + Assert.fail("Metadata provenance do not contain expected data: " + expectedMessage); } } @@ -252,7 +246,7 @@ public void updateLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", clarinLicense2.getID().toString())) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "updateLicense"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.UPDATE_LICENSE.getTemplate()); deleteBitstream(bitstream); deleteClarinLicense(clarinLicense1); @@ -268,7 +262,7 @@ public void addLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", clarinLicense.getID().toString())) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "addLicense"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.ADD_LICENSE.getTemplate()); deleteClarinLicense(clarinLicense); } @@ -283,7 +277,7 @@ public void removeLicenseTest() throws Exception { getClient(token).perform(put("/api/core/items/" + item.getID() + "/bundles") .param("licenseID", "-1")) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeLicense"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.REMOVE_LICENSE.getTemplate()); deleteBitstream(bitstream); deleteClarinLicense(clarinLicense); @@ -306,7 +300,7 @@ public void makeDiscoverableTest() throws Exception { .andExpect(jsonPath("$.uuid", Matchers.is(item.getID().toString()))) .andExpect(jsonPath("$.discoverable", Matchers.is(true))); - objectCheck(itemService.find(context, item.getID()), "discoverable"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.DISCOVERABLE.getTemplate()); } @Test @@ -323,7 +317,7 @@ public void makeNonDiscoverableTest() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "nonDiscoverable"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.NON_DISCOVERABLE.getTemplate()); } @Test @@ -338,7 +332,7 @@ public void addedToMappedCollTest() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + coll.getID() + "\n" ) ); - objectCheck(itemService.find(context, item.getID()), "mappedCol"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.MAPPED_COL.getTemplate()); deleteCollection(coll.getID()); } @@ -355,7 +349,7 @@ public void addItemMetadataTest() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "addItemMtd"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.ADD_ITEM_MTD.getTemplate()); } @Test @@ -371,7 +365,7 @@ public void replaceItemMetadataTest() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "replaceItemMtd"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.REPLACE_ITEM_MTD.getTemplate()); } @Test @@ -387,7 +381,7 @@ public void removeItemMetadataTest() throws Exception { .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeItemMtd"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.REMOVE_ITEM_MTD.getTemplate()); } @Test @@ -403,7 +397,8 @@ public void removeBitstreamMetadataTest() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + objectCheck(itemService.find(context, item.getID()), + ProvenanceExpectedMessages.REMOVE_BITSTREAM_MTD.getTemplate()); deleteBitstream(bitstream); } @@ -421,7 +416,8 @@ public void addBitstreamMetadataTest() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "removeBitstreamMtd"); + objectCheck(itemService.find(context, item.getID()), + ProvenanceExpectedMessages.REMOVE_BITSTREAM_MTD.getTemplate()); } @Test @@ -439,7 +435,8 @@ public void updateMetadataBitstreamTest() throws Exception { .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "replaceBitstreamMtd"); + objectCheck(itemService.find(context, item.getID()), + ProvenanceExpectedMessages.REPLACE_BITSTREAM_MTD.getTemplate()); deleteBitstream(bitstream); } @@ -456,7 +453,7 @@ public void removeBitstreamFromItemTest() throws Exception { getClient(adminToken).perform(patch("/api/core/bitstreams") .content(patchBody) .contentType(MediaType.APPLICATION_JSON_PATCH_JSON)); - objectCheck(itemService.find(context, item.getID()), "removeBitstream"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.REMOVE_BITSTREAM.getTemplate()); deleteBitstream(bitstream); } @@ -476,7 +473,7 @@ public void addBitstreamToItemTest() throws Exception { .perform(MockMvcRequestBuilders.multipart("/api/core/bundles/" + bundle.getID() + "/bitstreams") .file(file)) .andExpect(status().isCreated()); - objectCheck(itemService.find(context, item.getID()), "addBitstream"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.ADD_BITSTREAM.getTemplate()); deleteBundle(bundle.getID()); } @@ -493,7 +490,7 @@ public void moveItemColTest() throws Exception { "https://localhost:8080/spring-rest/api/core/collections/" + col.getID() )) .andExpect(status().isOk()); - objectCheck(itemService.find(context, item.getID()), "movedItemCol"); + objectCheck(itemService.find(context, item.getID()), ProvenanceExpectedMessages.MOVED_ITEM_COL.getTemplate()); deleteCollection(col.getID()); } diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-test.json b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-test.json deleted file mode 100644 index 268957768040..000000000000 --- a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/provenance-test.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "discoverable": "Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", - "nonDiscoverable": "Item was made non-discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n", - "mappedCol": "was mapped to collection", - "addItemMtd": "Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on", - "replaceItemMtd": "Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "removeItemMtd": "Item metadata (dc.title: Public item 1) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "removeBitstreamMtd": "Item metadata (dc.description) was added by bitstream", - "replaceBitstreamMtd": "metadata (dc.title: test) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", - "removeBitstream": "was deleted bitstream", - "addBitstream": "Item was added bitstream to bundle", - "updateLicense": "License (Test 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", - "addLicense": "License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0", - "removeLicense": "License (Test) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n", - "movedItemCol": "Item was moved from collection " -} \ No newline at end of file From a0abf729ce14267f5bda248f5a9779b608321443 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Fri, 13 Dec 2024 09:36:57 +0100 Subject: [PATCH 48/54] The `getMessage` methods was overloaded. --- .../core/ProvenanceMessageProvider.java | 22 +++++++++---------- .../org/dspace/core/ProvenanceProvider.java | 12 +++++----- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java index f1d65a483c91..3c2bd4a1bb9b 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java @@ -21,8 +21,6 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.InstallItemService; import org.dspace.eperson.EPerson; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The ProvenanceMessageProvider providing methods to generate provenance messages for DSpace items. @@ -43,13 +41,6 @@ public String getMessage(Context context, String messageTemplate, Item item, Obj return msg; } - public String validateMessageTemplate(String messageTemplate, Object... args) { - if (messageTemplate == null) { - throw new IllegalArgumentException("The message template is null!"); - } - return String.format(messageTemplate, args); - } - public String getMessage(Context context, String messageTemplate, Object... args) { EPerson currentUser = context.getCurrentUser(); String timestamp = DCDate.getCurrent().toString(); @@ -61,7 +52,7 @@ public String getMessage(Context context, String messageTemplate, Object... args timestamp); } - public String addCollectionsToMessage(Item item) { + public String getMessage(Item item) { String msg = "Item was in collections:\n"; List collsList = item.getCollections(); for (Collection coll : collsList) { @@ -70,7 +61,7 @@ public String addCollectionsToMessage(Item item) { return msg; } - public String getBitstreamMessage(Bitstream bitstream) { + public String getMessage(Bitstream bitstream) { // values of deleted bitstream String msg = bitstream.getName() + ": " + bitstream.getSizeBytes() + " bytes, checksum: " + @@ -79,7 +70,7 @@ public String getBitstreamMessage(Bitstream bitstream) { return msg; } - public String getResourcePoliciesMessage(List resPolicies) { + public String getMessage(List resPolicies) { return resPolicies.stream() .filter(rp -> rp.getAction() == Constants.READ) .map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]", @@ -99,4 +90,11 @@ public String getMetadataField(MetadataField metadataField) { return metadataField.toString() .replace('_', '.'); } + + private String validateMessageTemplate(String messageTemplate, Object... args) { + if (messageTemplate == null) { + throw new IllegalArgumentException("The provenance message template is null!"); + } + return String.format(messageTemplate, args); + } } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index 9180cafb9fda..463333ad07bc 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -112,7 +112,7 @@ public void removeReadPolicies(Context context, DSpaceObject dso, List Date: Fri, 13 Dec 2024 10:01:19 +0100 Subject: [PATCH 49/54] Renamed `getItem` to `findItemByBitstream` to clarify the method's purpose. --- .../java/org/dspace/core/ProvenanceProvider.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index 463333ad07bc..bb80443c85f2 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -70,7 +70,7 @@ private String extractAccessConditions(List accessConditions) { .collect(Collectors.joining(";")); } - private Item getItem(Context context, Bitstream bitstream) throws SQLException { + private Item findItemByBitstream(Context context, Bitstream bitstream) throws SQLException { List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); if (items.isEmpty()) { log.warn("Bitstream (" + bitstream.getID() + ") is not assigned to any item."); @@ -121,7 +121,7 @@ public void removeReadPolicies(Context context, DSpaceObject dso, List Date: Fri, 13 Dec 2024 10:07:45 +0100 Subject: [PATCH 50/54] Do not throw exception when adding to provenance --- .../org/dspace/core/ProvenanceProvider.java | 20 ++++++++++++++----- .../rest/BundleUploadBitstreamController.java | 16 +-------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index bb80443c85f2..f62a2d583781 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -280,11 +280,21 @@ public void makeDiscoverable(Context context, Item item, boolean discoverable) addProvenanceMetadata(context, item, msg); } - public void uploadBitstream(Context context, Bundle bundle) throws SQLException, AuthorizeException { + public void uploadBitstream(Context context, Bundle bundle) { Item item = bundle.getItems().get(0); - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.BUNDLE_ADDED.getTemplate(), - item, bundle.getID()); - addProvenanceMetadata(context,item, msg); - itemService.update(context, item); + try { + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.BUNDLE_ADDED.getTemplate(), + item, bundle.getID()); + addProvenanceMetadata(context,item, msg); + itemService.update(context, item); + } catch (SQLException ex) { + String msg = "SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + + "adding new provenance metadata."; + log.error(msg, ex); + } catch (AuthorizeException ex) { + String msg = "AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + + "when adding new provenance metadata."; + log.error(msg, ex); + } } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index bbdd11561d52..e529f1daea08 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -107,7 +107,6 @@ public ResponseEntity> uploadBitstream( throw new ResourceNotFoundException("The given uuid did not resolve to a Bundle on the server: " + uuid); } InputStream fileInputStream = null; - String msg; try { fileInputStream = uploadfile.getInputStream(); } catch (IOException e) { @@ -115,23 +114,10 @@ public ResponseEntity> uploadBitstream( e); throw new UnprocessableEntityException("The InputStream from the file couldn't be read", e); } - try { - provenanceProvider.uploadBitstream(context, bundle); - } catch (SQLException ex) { - msg = "SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + - "adding new provenance metadata."; - log.error(msg, ex); - throw new RuntimeException(msg, ex); - } catch (AuthorizeException ex) { - msg = "AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + - "when adding new provenance metadata."; - log.error(msg, ex); - throw new RuntimeException(msg, ex); - } - BitstreamRest bitstreamRest = bundleRestRepository.uploadBitstream( context, bundle, uploadfile.getOriginalFilename(), fileInputStream, properties); BitstreamResource bitstreamResource = converter.toResource(bitstreamRest); + provenanceProvider.uploadBitstream(context, bundle); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), bitstreamResource); } From 51302fab665c037246901e94ce09fe320132bc5a Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Fri, 13 Dec 2024 10:52:47 +0100 Subject: [PATCH 51/54] The exceptions are caught in the ProvenanceProvider and changed order when calling provenance methods. --- .../bulkaccesscontrol/BulkAccessControl.java | 1 - .../org/dspace/core/ProvenanceProvider.java | 328 ++++++++++-------- .../app/rest/ItemAddBundleController.java | 4 +- .../rest/MappedCollectionRestController.java | 4 +- .../operation/BitstreamRemoveOperation.java | 2 +- .../DSpaceObjectMetadataAddOperation.java | 5 - .../DSpaceObjectMetadataRemoveOperation.java | 9 +- .../DSpaceObjectMetadataReplaceOperation.java | 21 -- .../ItemDiscoverableReplaceOperation.java | 15 +- 9 files changed, 194 insertions(+), 195 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index deeb451ff648..7382a79ba4a7 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -469,7 +469,6 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl) itemAccessConditions.get(accessCondition.getName()))); itemService.adjustItemPolicies(context, item, item.getOwningCollection(), false); - provenanceProvider.setItemPolicies(context, item, accessControl); } diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java index f62a2d583781..08c1ab01bc97 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java @@ -47,9 +47,6 @@ public class ProvenanceProvider { private static final Logger log = LogManager.getLogger(ProvenanceProvider.class); private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private ResourcePolicyService resourcePolicyService = - AuthorizeServiceFactory.getInstance().getResourcePolicyService(); - private ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); private ClarinLicenseResourceMappingService clarinResourceMappingService = ClarinServiceFactory.getInstance().getClarinLicenseResourceMappingService(); @@ -57,46 +54,6 @@ public class ProvenanceProvider { private final ProvenanceMessageProvider messageProvider = new ProvenanceMessageProvider(); - private void addProvenanceMetadata(Context context, Item item, String msg) - throws SQLException, AuthorizeException { - itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), - "description", "provenance", "en", msg); - itemService.update(context, item); - } - - private String extractAccessConditions(List accessConditions) { - return accessConditions.stream() - .map(AccessCondition::getName) - .collect(Collectors.joining(";")); - } - - private Item findItemByBitstream(Context context, Bitstream bitstream) throws SQLException { - List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); - if (items.isEmpty()) { - log.warn("Bitstream (" + bitstream.getID() + ") is not assigned to any item."); - return null; - } - return items.get(0); - } - - private String findLicenseInBundles(Item item, String bundleName, String currentLicense, Context context) - throws SQLException { - List bundles = item.getBundles(bundleName); - for (Bundle clarinBundle : bundles) { - List bitstreamList = clarinBundle.getBitstreams(); - for (Bitstream bundleBitstream : bitstreamList) { - if (Objects.isNull(currentLicense)) { - List mappings = - this.clarinResourceMappingService.findByBitstreamUUID(context, bundleBitstream.getID()); - if (CollectionUtils.isNotEmpty(mappings)) { - return mappings.get(0).getLicense().getName(); - } - } - } - } - return currentLicense; - } - public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); @@ -107,108 +64,140 @@ public void setItemPolicies(Context context, Item item, BulkAccessControlInput a } } - public void removeReadPolicies(Context context, DSpaceObject dso, List resPolicies) - throws SQLException, AuthorizeException { + public void removeReadPolicies(Context context, DSpaceObject dso, List resPolicies) { if (resPolicies.isEmpty()) { return; } String resPoliciesStr = messageProvider.getMessage(resPolicies); - if (dso.getType() == Constants.ITEM) { - Item item = (Item) dso; - String msg = messageProvider.getMessage(context, - ProvenanceMessageTemplates.RESOURCE_POLICIES_REMOVED.getTemplate(), - resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "item", item.getID()); - addProvenanceMetadata(context, item, msg); - } else if (dso.getType() == Constants.BITSTREAM) { - Bitstream bitstream = (Bitstream) dso; - Item item = findItemByBitstream(context, bitstream); - if (Objects.nonNull(item)) { + try { + if (dso.getType() == Constants.ITEM) { + Item item = (Item) dso; String msg = messageProvider.getMessage(context, - ProvenanceMessageTemplates.RESOURCE_POLICIES_REMOVED.getTemplate(), - resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "bitstream", bitstream.getID()); + ProvenanceMessageTemplates.RESOURCE_POLICIES_REMOVED.getTemplate(), + resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "item", item.getID()); addProvenanceMetadata(context, item, msg); + } else if (dso.getType() == Constants.BITSTREAM) { + Bitstream bitstream = (Bitstream) dso; + Item item = findItemByBitstream(context, bitstream); + if (Objects.nonNull(item)) { + String msg = messageProvider.getMessage(context, + ProvenanceMessageTemplates.RESOURCE_POLICIES_REMOVED.getTemplate(), + resPoliciesStr.isEmpty() ? "empty" : resPoliciesStr, "bitstream", bitstream.getID()); + addProvenanceMetadata(context, item, msg); + } } + } catch (SQLException | AuthorizeException e) { + log.error("Unable to remove read policies from the DSpace object.", e); } } public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, - BulkAccessControlInput accessControl) throws SQLException, AuthorizeException { + BulkAccessControlInput accessControl) { String accConditionsStr = extractAccessConditions(accessControl.getBitstream().getAccessConditions()); if (StringUtils.isNotBlank(accConditionsStr)) { String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ACCESS_CONDITION.getTemplate(), accConditionsStr, "bitstream", bitstream.getID()); - addProvenanceMetadata(context, item, msg); + try { + addProvenanceMetadata(context, item, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when setting bitstream policies.", e); + } } } - public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException { + public void editLicense(Context context, Item item, boolean newLicense) { String oldLicense = null; - oldLicense = findLicenseInBundles(item, Constants.LICENSE_BUNDLE_NAME, oldLicense, context); - if (oldLicense == null) { - oldLicense = findLicenseInBundles(item, Constants.CONTENT_BUNDLE_NAME, oldLicense, context); + + try { + oldLicense = findLicenseInBundles(item, Constants.LICENSE_BUNDLE_NAME, oldLicense, context); + if (oldLicense == null) { + oldLicense = findLicenseInBundles(item, Constants.CONTENT_BUNDLE_NAME, oldLicense, context); + } + + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_LICENSE.getTemplate(), item, + Objects.isNull(oldLicense) ? "empty" : oldLicense, + !newLicense ? "removed" : Objects.isNull(oldLicense) ? "added" : "updated"); + addProvenanceMetadata(context, item, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when editing Item's license.", e); } - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_LICENSE.getTemplate(), item, - Objects.isNull(oldLicense) ? "empty" : oldLicense, - !newLicense ? "removed" : Objects.isNull(oldLicense) ? "added" : "updated"); - addProvenanceMetadata(context, item, msg); } - public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.MOVE_ITEM.getTemplate(), - item, collection.getID()); - // Update item in DB - // Because a user can move an item without authorization turn off authorization - context.turnOffAuthorisationSystem(); - addProvenanceMetadata(context, item, msg); - context.restoreAuthSystemState(); + public void moveItem(Context context, Item item, Collection collection) { + try { + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.MOVE_ITEM.getTemplate(), + item, collection.getID()); + // Update item in DB + // Because a user can move an item without authorization turn off authorization + context.turnOffAuthorisationSystem(); + addProvenanceMetadata(context, item, msg); + context.restoreAuthSystemState(); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when moving an item to a different collection.", + e); + } } - public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException { + public void mappedItem(Context context, Item item, Collection collection) { String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.MAPPED_ITEM.getTemplate(), collection.getID()); - addProvenanceMetadata(context, item, msg); + try { + addProvenanceMetadata(context, item, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when mapping an item into a collection.", e); + } } - public void deletedItemFromMapped(Context context, Item item, Collection collection) - throws SQLException, AuthorizeException { + public void deletedItemFromMapped(Context context, Item item, Collection collection) { String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.DELETED_ITEM_FROM_MAPPED.getTemplate(), collection.getID()); - addProvenanceMetadata(context, item, msg); - } - - public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException { - Item item = findItemByBitstream(context, bitstream); - if (Objects.nonNull(item)) { - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_BITSTREAM.getTemplate(), - item, item.getID(), messageProvider.getMessage(bitstream)); + try { addProvenanceMetadata(context, item, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when deleting an item from a mapped collection.", + e); } } - public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) - throws SQLException, AuthorizeException { - if (Constants.ITEM == dso.getType()) { - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ITEM_METADATA.getTemplate(), - messageProvider.getMetadataField(metadataField), "added"); - addProvenanceMetadata(context, (Item) dso, msg); - } - - if (dso.getType() == Constants.BITSTREAM) { - Bitstream bitstream = (Bitstream) dso; + public void deleteBitstream(Context context,Bitstream bitstream) { + try { Item item = findItemByBitstream(context, bitstream); if (Objects.nonNull(item)) { - String msg = messageProvider.getMessage(context, - ProvenanceMessageTemplates.BITSTREAM_METADATA.getTemplate(), item, - messageProvider.getMetadataField(metadataField), "added by", - messageProvider.getMessage(bitstream)); + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_BITSTREAM.getTemplate(), + item, item.getID(), messageProvider.getMessage(bitstream)); addProvenanceMetadata(context, item, msg); } + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when deleting a bitstream.", e); } } - public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) - throws SQLException, AuthorizeException { + public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField) { + try { + if (Constants.ITEM == dso.getType()) { + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ITEM_METADATA.getTemplate(), + messageProvider.getMetadataField(metadataField), "added"); + addProvenanceMetadata(context, (Item) dso, msg); + } + + if (dso.getType() == Constants.BITSTREAM) { + Bitstream bitstream = (Bitstream) dso; + Item item = findItemByBitstream(context, bitstream); + if (Objects.nonNull(item)) { + String msg = messageProvider.getMessage(context, + ProvenanceMessageTemplates.BITSTREAM_METADATA.getTemplate(), item, + messageProvider.getMetadataField(metadataField), "added by", + messageProvider.getMessage(bitstream)); + addProvenanceMetadata(context, item, msg); + } + } + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when adding metadata to a DSpace object.", e); + } + } + + public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField) { if (dso.getType() != Constants.BITSTREAM) { return; } @@ -222,62 +211,83 @@ public void removeMetadata(Context context, DSpaceObject dso, MetadataField meta oldMtdValue = mtd.get(0).getValue(); } Bitstream bitstream = (Bitstream) dso; - Item item = findItemByBitstream(context, bitstream); - if (Objects.nonNull(item)) { - String msg = messageProvider.getMessage(context, - ProvenanceMessageTemplates.BITSTREAM_METADATA.getTemplate(), item, - messageProvider.getMetadata(messageProvider.getMetadataField(oldMtdKey), oldMtdValue), - "deleted from", messageProvider.getMessage(bitstream)); - addProvenanceMetadata(context, item, msg); + try { + Item item = findItemByBitstream(context, bitstream); + if (Objects.nonNull(item)) { + String msg = messageProvider.getMessage(context, + ProvenanceMessageTemplates.BITSTREAM_METADATA.getTemplate(), item, + messageProvider.getMetadata(messageProvider.getMetadataField(oldMtdKey), oldMtdValue), + "deleted from", messageProvider.getMessage(bitstream)); + addProvenanceMetadata(context, item, msg); + } + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when removing metadata from a dso.", e); } + } public void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, - int indexInt) throws SQLException, AuthorizeException { + int indexInt) { if (dso.getType() != Constants.ITEM) { return; } // Remember removed mtd String oldMtdKey = messageProvider.getMetadataField(metadataValues.get(indexInt).getMetadataField()); String oldMtdValue = metadataValues.get(indexInt).getValue(); - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ITEM_METADATA.getTemplate(), - (Item) dso, messageProvider.getMetadata(oldMtdKey, oldMtdValue), "deleted"); - addProvenanceMetadata(context, (Item) dso, msg); + try { + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ITEM_METADATA.getTemplate(), + (Item) dso, messageProvider.getMetadata(oldMtdKey, oldMtdValue), "deleted"); + addProvenanceMetadata(context, (Item) dso, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when removing metadata at a specific index " + + "from a dso", e); + } } - public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) - throws SQLException, AuthorizeException { + public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) { if (dso.getType() != Constants.ITEM) { return; } - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ITEM_METADATA.getTemplate(), - (Item) dso,messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), - oldMtdVal), "updated"); - addProvenanceMetadata(context, (Item) dso, msg); + try { + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ITEM_METADATA.getTemplate(), + (Item) dso,messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), + oldMtdVal), "updated"); + addProvenanceMetadata(context, (Item) dso, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when replacing metadata in a dso.", e); + } + } - public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal) - throws SQLException, AuthorizeException { + public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, + String oldMtdVal) { if (dso.getType() != Constants.BITSTREAM) { return; } Bitstream bitstream = (Bitstream) dso; - Item item = findItemByBitstream(context, bitstream); - if (Objects.nonNull(item)) { - String msg = messageProvider.getMessage(context, - ProvenanceMessageTemplates.ITEM_REPLACE_SINGLE_METADATA.getTemplate(), item, - messageProvider.getMessage(bitstream), - messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), oldMtdVal)); - addProvenanceMetadata(context, item, msg);; + try { + Item item = findItemByBitstream(context, bitstream); + if (Objects.nonNull(item)) { + String msg = messageProvider.getMessage(context, + ProvenanceMessageTemplates.ITEM_REPLACE_SINGLE_METADATA.getTemplate(), item, + messageProvider.getMessage(bitstream), + messageProvider.getMetadata(messageProvider.getMetadataField(metadataField), oldMtdVal)); + addProvenanceMetadata(context, item, msg);; + } + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when replacing metadata in a item.", e); } } - public void makeDiscoverable(Context context, Item item, boolean discoverable) - throws SQLException, AuthorizeException { - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.DISCOVERABLE.getTemplate(), - item, discoverable ? "" : "non-") + messageProvider.getMessage(item); - addProvenanceMetadata(context, item, msg); + public void makeDiscoverable(Context context, Item item, boolean discoverable) { + try { + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.DISCOVERABLE.getTemplate(), + item, discoverable ? "" : "non-") + messageProvider.getMessage(item); + addProvenanceMetadata(context, item, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when making an item discoverable.", e); + } } public void uploadBitstream(Context context, Bundle bundle) { @@ -287,14 +297,48 @@ public void uploadBitstream(Context context, Bundle bundle) { item, bundle.getID()); addProvenanceMetadata(context,item, msg); itemService.update(context, item); - } catch (SQLException ex) { - String msg = "SQLException in BundleUploadBitstreamConverter.uploadBitstream when " + - "adding new provenance metadata."; - log.error(msg, ex); - } catch (AuthorizeException ex) { - String msg = "AuthorizeException in BundleUploadBitstreamConverter.uploadBitstream " + - "when adding new provenance metadata."; - log.error(msg, ex); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when updating an item's bitstream.", e); } } + + private void addProvenanceMetadata(Context context, Item item, String msg) + throws SQLException, AuthorizeException { + itemService.addMetadata(context, item, MetadataSchemaEnum.DC.getName(), + "description", "provenance", "en", msg); + itemService.update(context, item); + } + + private String extractAccessConditions(List accessConditions) { + return accessConditions.stream() + .map(AccessCondition::getName) + .collect(Collectors.joining(";")); + } + + private Item findItemByBitstream(Context context, Bitstream bitstream) throws SQLException { + List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); + if (items.isEmpty()) { + log.warn("Bitstream (" + bitstream.getID() + ") is not assigned to any item."); + return null; + } + return items.get(0); + } + + private String findLicenseInBundles(Item item, String bundleName, String currentLicense, Context context) + throws SQLException { + List bundles = item.getBundles(bundleName); + for (Bundle clarinBundle : bundles) { + List bitstreamList = clarinBundle.getBitstreams(); + for (Bitstream bundleBitstream : bitstreamList) { + if (Objects.isNull(currentLicense)) { + List mappings = + this.clarinResourceMappingService.findByBitstreamUUID(context, bundleBitstream.getID()); + if (CollectionUtils.isNotEmpty(mappings)) { + return mappings.get(0).getLicense().getName(); + } + } + } + } + return currentLicense; + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 4656936e0c89..de17013773f7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -168,7 +168,7 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, log.warn("Cannot find clarin license with id: " + licenseId + ". The old license will be detached, " + "but the new one will not be attached."); } - provenanceProvider.editLicense(context, item, !Objects.isNull(clarinLicense)); + List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); @@ -185,8 +185,8 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, if (Objects.nonNull(clarinLicense)) { clarinLicenseService.addLicenseMetadataToItem(context, clarinLicense, item); } - itemService.update(context, item); + provenanceProvider.editLicense(context, item, !Objects.isNull(clarinLicense)); context.commit(); return converter.toRest(item, utils.obtainProjection()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index cbdc46444719..960e53fde1c4 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -107,8 +107,8 @@ public void createCollectionToItemRelation(@PathVariable UUID uuid, collectionService.addItem(context, collectionToMapTo, item); collectionService.update(context, collectionToMapTo); - provenanceProvider.mappedItem(context, item, collectionToMapTo); itemService.update(context, item); + provenanceProvider.mappedItem(context, item, collectionToMapTo); } else { throw new UnprocessableEntityException("Not a valid collection or item uuid."); } @@ -154,8 +154,8 @@ public void deleteCollectionToItemRelation(@PathVariable UUID uuid, @PathVariabl if (collection.getID() != owningCollectionUuid && item.getCollections().contains(collection)) { collectionService.removeItem(context, collection, item); collectionService.update(context, collection); - provenanceProvider.deletedItemFromMapped(context,item, collection); itemService.update(context, item); + provenanceProvider.deletedItemFromMapped(context,item, collection); context.commit(); } } else { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java index 0826ad16adcb..1a0b4ca16554 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/BitstreamRemoveOperation.java @@ -54,8 +54,8 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio } authorizeBitstreamRemoveAction(context, bitstreamToDelete, Constants.DELETE); try { - provenanceProvider.deleteBitstream(context, bitstreamToDelete); bitstreamService.delete(context, bitstreamToDelete); + provenanceProvider.deleteBitstream(context, bitstreamToDelete); } catch (AuthorizeException | IOException e) { throw new RuntimeException(e.getMessage(), e); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index 6982044d555b..cee0e1113035 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -80,11 +80,6 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi "metadata to dso."; log.error(msg, e); throw new DSpaceBadRequestException(msg, e); - } catch (AuthorizeException e) { - msg = "AuthorizeException in DspaceObjectMetadataAddOperation.add " + - "trying to add metadata to dso."; - log.error(msg, e); - throw new DSpaceBadRequestException(msg, e); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 5f5f54785d41..28b78cf7cd4a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -73,10 +73,10 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe String msg; try { if (index == null) { - provenanceProvider.removeMetadata(context, dso, metadataField); // remove all metadata of this type dsoService.clearMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); + provenanceProvider.removeMetadata(context, dso, metadataField); } else { // remove metadata at index List metadataValues = dsoService.getMetadata(dso, @@ -85,10 +85,10 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe int indexInt = Integer.parseInt(index); if (indexInt >= 0 && metadataValues.size() > indexInt && metadataValues.get(indexInt) != null) { - provenanceProvider.removeMetadataAtIndex(context, dso, metadataValues, indexInt); // remove that metadata dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); + provenanceProvider.removeMetadataAtIndex(context, dso, metadataValues, indexInt); } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + "this type at that index"); @@ -103,11 +103,6 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe "trying to remove metadata from dso."; log.error(msg, ex); throw new DSpaceBadRequestException(msg, ex); - } catch (AuthorizeException ex) { - msg = "AuthorizeException in DspaceObjectMetadataRemoveOperation.remove " + - "trying to replace metadata from dso."; - log.error(msg, ex); - throw new DSpaceBadRequestException(msg, ex); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 2f7c4fdffcef..88ca03b31af2 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -169,22 +169,11 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac existingMdv.setValue(metadataValue.getValue()); dsoService.setMetadataModified(dso); provenanceProvider.replaceMetadata(context, dso, metadataField, oldMtdVal); - } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } } catch (NumberFormatException e) { throw new IllegalArgumentException("This index (" + index + ") is not valid number.", e); - } catch (SQLException e) { - msg = "SQLException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + - "trying to replace metadata from dso."; - log.error(msg, e); - throw new DSpaceBadRequestException(msg, e); - } catch (AuthorizeException e) { - msg = "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSingleMetadataValue " + - "trying to replace metadata from dso."; - log.error(msg, e); - throw new DSpaceBadRequestException(msg, e); } } @@ -231,16 +220,6 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D } catch (NumberFormatException e) { throw new IllegalArgumentException("Not all numbers are valid numbers. " + "(Index and confidence should be nr)", e); - } catch (SQLException e) { - msg = "SQLException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + - "trying to replace metadata from dso."; - log.error(msg, e); - throw new DSpaceBadRequestException(msg, e); - } catch (AuthorizeException e) { - msg = "AuthorizeException in DspaceObjectMetadataReplaceOperation.replaceSinglePropertyOfMdValue " + - "trying to replace metadata from dso."; - log.error(msg, e); - throw new DSpaceBadRequestException(msg, e); } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index ad901d03a927..fcf39effe0d9 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -47,20 +47,7 @@ public R perform(Context context, R object, Operation operation) { throw new UnprocessableEntityException("A template item cannot be discoverable."); } item.setDiscoverable(discoverable); - String msg; - try { - provenanceProvider.makeDiscoverable(context, item, discoverable); - } catch (SQLException ex) { - msg = "SQLException occurred when item making " + (discoverable ? "" : "non-") - + "discoverable."; - log.error(msg, ex); - throw new RuntimeException(msg, ex); - } catch (AuthorizeException ex) { - msg = "AuthorizeException occurred when item making " - + (discoverable ? "" : "non-") + "discoverable."; - log.error(msg, ex); - throw new RuntimeException(msg, ex); - } + provenanceProvider.makeDiscoverable(context, item, discoverable); return object; } else { throw new DSpaceBadRequestException("ItemDiscoverableReplaceOperation does not support this operation"); From 46ab18cfaef6df45213ca051d19c6a3aabe77969 Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Fri, 13 Dec 2024 14:37:48 +0100 Subject: [PATCH 52/54] Renamed ProvenanceProvider to ProvenanceService and refactored it to be used as Spring Service. --- .../bulkaccesscontrol/BulkAccessControl.java | 12 +- ...r.java => ProvenanceMessageFormatter.java} | 4 +- .../core/ProvenanceMessageTemplates.java | 5 + .../org/dspace/core/ProvenanceService.java | 178 ++++++++++++ ...ovider.java => ProvenanceServiceImpl.java} | 57 ++-- .../rest/BundleUploadBitstreamController.java | 5 - .../app/rest/ItemAddBundleController.java | 7 +- ...mOwningCollectionUpdateRestController.java | 7 +- .../rest/MappedCollectionRestController.java | 9 +- .../rest/repository/BundleRestRepository.java | 5 + .../operation/BitstreamRemoveOperation.java | 11 +- .../DSpaceObjectMetadataAddOperation.java | 6 +- .../DSpaceObjectMetadataRemoveOperation.java | 8 +- .../DSpaceObjectMetadataReplaceOperation.java | 8 +- .../ItemDiscoverableReplaceOperation.java | 10 +- .../patch/operation/PatchOperation.java | 3 - .../app/rest/ProvenanceExpectedMessages.java | 29 +- ...oviderIT.java => ProvenanceServiceIT.java} | 266 +++++++++--------- dspace/config/spring/api/core-services.xml | 2 + 19 files changed, 430 insertions(+), 202 deletions(-) rename dspace-api/src/main/java/org/dspace/core/{ProvenanceMessageProvider.java => ProvenanceMessageFormatter.java} (97%) create mode 100644 dspace-api/src/main/java/org/dspace/core/ProvenanceService.java rename dspace-api/src/main/java/org/dspace/core/{ProvenanceProvider.java => ProvenanceServiceImpl.java} (90%) rename dspace-server-webapp/src/test/java/org/dspace/app/rest/{ProvenanceProviderIT.java => ProvenanceServiceIT.java} (97%) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index 7382a79ba4a7..b2a5015666ab 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -56,7 +56,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceProvider; +import org.dspace.core.ProvenanceServiceImpl; import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.SearchService; import org.dspace.discovery.SearchServiceException; @@ -70,6 +70,7 @@ import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.submit.model.AccessConditionOption; import org.dspace.utils.DSpace; +import org.springframework.beans.factory.annotation.Autowired; /** * Implementation of {@link DSpaceRunnable} to perform a bulk access control via json file. @@ -113,7 +114,8 @@ public class BulkAccessControl extends DSpaceRunnable resPolicies = resourcePolicyService.find(context, dso, type); resourcePolicyService.removePolicies(context, dso, type, Constants.READ); - provenanceProvider.removeReadPolicies(context, dso, resPolicies); + provenanceService.removeReadPolicies(context, dso, resPolicies); } catch (SQLException | AuthorizeException e) { throw new BulkAccessControlException(e); } @@ -588,7 +590,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream); mediaFilterService.updatePoliciesOfDerivativeBitstreams(context, item, bitstream); - provenanceProvider.setBitstreamPolicies(context, bitstream, item, accessControl); + provenanceService.setBitstreamPolicies(context, bitstream, item, accessControl); } /** diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageFormatter.java similarity index 97% rename from dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java rename to dspace-api/src/main/java/org/dspace/core/ProvenanceMessageFormatter.java index 3c2bd4a1bb9b..e698ca192dae 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageFormatter.java @@ -29,10 +29,10 @@ * * @author Michaela Paurikova (dspace at dataquest.sk) */ -public class ProvenanceMessageProvider { +public class ProvenanceMessageFormatter { private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService(); - public ProvenanceMessageProvider() {} + public ProvenanceMessageFormatter() {} public String getMessage(Context context, String messageTemplate, Item item, Object... args) throws SQLException, AuthorizeException { diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java index 410ff7af4ab3..c14d3f447591 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceMessageTemplates.java @@ -7,6 +7,11 @@ */ package org.dspace.core; +/** + * The ProvenanceMessageTemplates enum provides message templates for provenance messages. + * + * @author Michaela Paurikova (dspace at dataquest.sk) + */ public enum ProvenanceMessageTemplates { ACCESS_CONDITION("Access condition (%s) was added to %s (%s)"), RESOURCE_POLICIES_REMOVED("Resource policies (%s) of %s (%s) were removed"), diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java new file mode 100644 index 000000000000..23e1be4c9c10 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceService.java @@ -0,0 +1,178 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.core; + +import java.util.List; + +import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.content.Collection; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.MetadataField; +import org.dspace.content.MetadataValue; + +/** + * The ProvenanceService is responsible for creating provenance metadata for items based on the actions performed. + * + * @author Milan Majchrak (dspace at dataquest.sk) + */ +public interface ProvenanceService { + /** + * Add a provenance message to the item when a new access condition is added + * + * @param context DSpace context object + * @param item item to which the access condition is added + * @param accessControl the access control input + */ + void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl); + + /** + * Add a provenance message to the item when a read policy is removed + * + * @param context DSpace context object + * @param dso DSpace object from which the read policy is removed + * @param resPolicies list of resource policies that are removed + */ + void removeReadPolicies(Context context, DSpaceObject dso, List resPolicies); + + /** + * Add a provenance message to the item when a bitstream policy is set + * + * @param context DSpace context object + * @param bitstream bitstream to which the policy is set + * @param item item to which the bitstream belongs + * @param accessControl the access control input + */ + void setBitstreamPolicies(Context context, Bitstream bitstream, Item item, + BulkAccessControlInput accessControl); + + /** + * Add a provenance message to the item when an item's license is edited + * + * @param context DSpace context object + * @param item item to which the license is edited + * @param newLicense true if the license is new, false if it's edited + */ + void editLicense(Context context, Item item, boolean newLicense); + + /** + * Add a provenance message to the item when it's moved to a collection + * + * @param context DSpace context object + * @param item item that is moved + * @param collection collection to which the item is moved + */ + void moveItem(Context context, Item item, Collection collection); + + /** + * Add a provenance message to the item when it's mapped to a collection + * + * @param context DSpace context object + * @param item item that is mapped + * @param collection collection to which the item is mapped + */ + void mappedItem(Context context, Item item, Collection collection); + + /** + * Add a provenance message to the item when it's deleted from a mapped collection + * + * @param context DSpace context object + * @param item item that is deleted from a mapped collection + * @param collection collection from which the item is deleted + */ + void deletedItemFromMapped(Context context, Item item, Collection collection); + + /** + * Add a provenance message to the item when it's bitstream is deleted + * + * @param context DSpace context object + * @param bitstream deleted bitstream + * @param item item from which the bitstream is deleted + */ + void deleteBitstream(Context context, Bitstream bitstream, Item item); + + /** + * Add a provenance message to the item when metadata is added + * + * @param context DSpace context object + * @param dso DSpace object to which the metadata is added + * @param metadataField metadata field that is added + */ + void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField); + + /** + * Add a provenance message to the item when metadata is removed + * + * @param context DSpace context object + * @param dso DSpace object from which the metadata is removed + * @param metadataField metadata field that is removed + */ + void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField); + + /** + * Add a provenance message to the item when metadata is removed at a given index + * + * @param context DSpace context object + * @param dso DSpace object from which the metadata is removed + * @param metadataValues list of metadata values + * @param indexInt index at which the metadata is removed + */ + void removeMetadataAtIndex(Context context, DSpaceObject dso, List metadataValues, + int indexInt); + + /** + * Add a provenance message to the item when metadata is replaced + * + * @param context DSpace context object + * @param dso DSpace object to which the metadata is replaced + * @param metadataField metadata field that is replaced + * @param oldMtdVal old metadata value + */ + void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal); + + /** + * Add a provenance message to the item when metadata is replaced + * + * @param context DSpace context object + * @param dso DSpace object to which the metadata is replaced + * @param metadataField metadata field that is replaced + * @param oldMtdVal old metadata value + */ + void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, + String oldMtdVal); + + /** + * Add a provenance message to the item when metadata is updated + * + * @param context DSpace context object + * @param item item to which the metadata is updated + * @param discoverable true if the item is discoverable, false if it's not + */ + void makeDiscoverable(Context context, Item item, boolean discoverable); + + /** + * Add a provenance message to the item when a bitstream is uploaded + * + * @param context DSpace context object + * @param bundle bundle to which the bitstream is uploaded + */ + void uploadBitstream(Context context, Bundle bundle); + + /** + * Fetch an Item object using a service and return the first Item object from the list. + * Log an error if the list is empty or if there is an SQL error + * + * @param context DSpace context object + * @param bitstream bitstream to which the item is fetched + */ + Item findItemByBitstream(Context context, Bitstream bitstream); + +} diff --git a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java similarity index 90% rename from dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java rename to dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java index 08c1ab01bc97..ace390d2922e 100644 --- a/dspace-api/src/main/java/org/dspace/core/ProvenanceProvider.java +++ b/dspace-api/src/main/java/org/dspace/core/ProvenanceServiceImpl.java @@ -20,8 +20,6 @@ import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.ResourcePolicy; -import org.dspace.authorize.factory.AuthorizeServiceFactory; -import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; @@ -31,36 +29,41 @@ import org.dspace.content.MetadataSchemaEnum; import org.dspace.content.MetadataValue; import org.dspace.content.clarin.ClarinLicenseResourceMapping; -import org.dspace.content.factory.ClarinServiceFactory; -import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.BitstreamService; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinItemService; import org.dspace.content.service.clarin.ClarinLicenseResourceMappingService; +import org.springframework.beans.factory.annotation.Autowired; /** - * ProvenanceProviderrest is responsible for creating provenance metadata for items based on the actions performed. + * ProvenanceServiceImpl is an implementation of ProvenanceService. * * @author Michaela Paurikova (dspace at dataquest.sk) */ -public class ProvenanceProvider { - private static final Logger log = LogManager.getLogger(ProvenanceProvider.class); +public class ProvenanceServiceImpl implements ProvenanceService { + private static final Logger log = LogManager.getLogger(ProvenanceServiceImpl.class); - private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private ClarinItemService clarinItemService = ClarinServiceFactory.getInstance().getClarinItemService(); - private ClarinLicenseResourceMappingService clarinResourceMappingService = - ClarinServiceFactory.getInstance().getClarinLicenseResourceMappingService(); - private BitstreamService bitstreamService = ContentServiceFactory.getInstance().getBitstreamService(); + @Autowired + private ItemService itemService; + @Autowired + private ClarinItemService clarinItemService; + @Autowired + private ClarinLicenseResourceMappingService clarinResourceMappingService; + @Autowired + private BitstreamService bitstreamService; - private final ProvenanceMessageProvider messageProvider = new ProvenanceMessageProvider(); + private final ProvenanceMessageFormatter messageProvider = new ProvenanceMessageFormatter(); - public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) - throws SQLException, AuthorizeException { + public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl) { String resPoliciesStr = extractAccessConditions(accessControl.getItem().getAccessConditions()); if (StringUtils.isNotBlank(resPoliciesStr)) { String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.ACCESS_CONDITION.getTemplate(), resPoliciesStr, "item", item.getID()); - addProvenanceMetadata(context, item, msg); + try { + addProvenanceMetadata(context, item, msg); + } catch (SQLException | AuthorizeException e) { + log.error("Unable to add new provenance metadata when setting item policies.", e); + } } } @@ -114,8 +117,8 @@ public void editLicense(Context context, Item item, boolean newLicense) { oldLicense = findLicenseInBundles(item, Constants.CONTENT_BUNDLE_NAME, oldLicense, context); } - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_LICENSE.getTemplate(), item, - Objects.isNull(oldLicense) ? "empty" : oldLicense, + String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_LICENSE.getTemplate(), + item, Objects.isNull(oldLicense) ? "empty" : oldLicense, !newLicense ? "removed" : Objects.isNull(oldLicense) ? "added" : "updated"); addProvenanceMetadata(context, item, msg); } catch (SQLException | AuthorizeException e) { @@ -160,12 +163,12 @@ public void deletedItemFromMapped(Context context, Item item, Collection collect } } - public void deleteBitstream(Context context,Bitstream bitstream) { + public void deleteBitstream(Context context, Bitstream bitstream, Item item) { try { - Item item = findItemByBitstream(context, bitstream); if (Objects.nonNull(item)) { - String msg = messageProvider.getMessage(context, ProvenanceMessageTemplates.EDIT_BITSTREAM.getTemplate(), - item, item.getID(), messageProvider.getMessage(bitstream)); + String msg = messageProvider.getMessage(context, + ProvenanceMessageTemplates.EDIT_BITSTREAM.getTemplate(), item, item.getID(), + messageProvider.getMessage(bitstream)); addProvenanceMetadata(context, item, msg); } } catch (SQLException | AuthorizeException e) { @@ -315,8 +318,14 @@ private String extractAccessConditions(List accessConditions) { .collect(Collectors.joining(";")); } - private Item findItemByBitstream(Context context, Bitstream bitstream) throws SQLException { - List items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); + public Item findItemByBitstream(Context context, Bitstream bitstream) { + List items = null; + try { + items = clarinItemService.findByBitstreamUUID(context, bitstream.getID()); + } catch (SQLException e) { + log.error("Unable to find item by bitstream (" + bitstream.getID() + " ).", e); + return null; + } if (items.isEmpty()) { log.warn("Bitstream (" + bitstream.getID() + ") is not assigned to any item."); return null; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java index e529f1daea08..44065583fafc 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/BundleUploadBitstreamController.java @@ -25,11 +25,9 @@ import org.dspace.app.rest.repository.BundleRestRepository; import org.dspace.app.rest.utils.ContextUtil; import org.dspace.app.rest.utils.Utils; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bundle; import org.dspace.content.service.BundleService; import org.dspace.core.Context; -import org.dspace.core.ProvenanceProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ControllerUtils; import org.springframework.data.rest.webmvc.ResourceNotFoundException; @@ -79,8 +77,6 @@ public class BundleUploadBitstreamController { @Autowired private ConverterService converter; - private ProvenanceProvider provenanceProvider = new ProvenanceProvider(); - /** * Method to upload a Bitstream to a Bundle with the given UUID in the URL. This will create a Bitstream with the * file provided in the request and attach this to the Item that matches the UUID in the URL. @@ -117,7 +113,6 @@ public ResponseEntity> uploadBitstream( BitstreamRest bitstreamRest = bundleRestRepository.uploadBitstream( context, bundle, uploadfile.getOriginalFilename(), fileInputStream, properties); BitstreamResource bitstreamResource = converter.toResource(bitstreamRest); - provenanceProvider.uploadBitstream(context, bundle); return ControllerUtils.toResponseEntity(HttpStatus.CREATED, new HttpHeaders(), bitstreamResource); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index de17013773f7..c9bf0f719866 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -38,7 +38,7 @@ import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceProvider; +import org.dspace.core.ProvenanceServiceImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -99,7 +99,8 @@ public class ItemAddBundleController { @Autowired ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; - ProvenanceProvider provenanceProvider = new ProvenanceProvider(); + @Autowired + ProvenanceServiceImpl provenanceService; /** * Method to add a Bundle to an Item with the given UUID in the URL. This will create a Bundle with the @@ -186,7 +187,7 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, clarinLicenseService.addLicenseMetadataToItem(context, clarinLicense, item); } itemService.update(context, item); - provenanceProvider.editLicense(context, item, !Objects.isNull(clarinLicense)); + provenanceService.editLicense(context, item, !Objects.isNull(clarinLicense)); context.commit(); return converter.toRest(item, utils.obtainProjection()); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index 247adec9c36d..6108f81b0168 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -32,7 +32,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceProvider; +import org.dspace.core.ProvenanceServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.prepost.PostAuthorize; @@ -66,7 +66,8 @@ public class ItemOwningCollectionUpdateRestController { @Autowired Utils utils; - ProvenanceProvider provenanceProvider = new ProvenanceProvider(); + @Autowired + ProvenanceServiceImpl provenanceService; /** * This method will update the owning collection of the item that correspond to the provided item uuid, effectively @@ -128,7 +129,7 @@ private Collection moveItem(final Context context, final Item item, final Collec final boolean inheritPolicies) throws SQLException, IOException, AuthorizeException { itemService.move(context, item, currentCollection, targetCollection, inheritPolicies); - provenanceProvider.moveItem(context, item, currentCollection); + provenanceService.moveItem(context, item, currentCollection); // Necessary because Controller does not pass through general RestResourceController, and as such does not do // its commit in DSpaceRestRepository.createAndReturn() or similar context.commit(); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index 960e53fde1c4..65966b100ada 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -30,7 +30,7 @@ import org.dspace.content.service.CollectionService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; -import org.dspace.core.ProvenanceProvider; +import org.dspace.core.ProvenanceServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; @@ -58,7 +58,8 @@ public class MappedCollectionRestController { @Autowired Utils utils; - ProvenanceProvider provenanceProvider = new ProvenanceProvider(); + @Autowired + ProvenanceServiceImpl provenanceService; /** * This method will add an Item to a Collection. The Collection object is encapsulated in the request due to the @@ -108,7 +109,7 @@ public void createCollectionToItemRelation(@PathVariable UUID uuid, collectionService.addItem(context, collectionToMapTo, item); collectionService.update(context, collectionToMapTo); itemService.update(context, item); - provenanceProvider.mappedItem(context, item, collectionToMapTo); + provenanceService.mappedItem(context, item, collectionToMapTo); } else { throw new UnprocessableEntityException("Not a valid collection or item uuid."); } @@ -155,7 +156,7 @@ public void deleteCollectionToItemRelation(@PathVariable UUID uuid, @PathVariabl collectionService.removeItem(context, collection, item); collectionService.update(context, collection); itemService.update(context, item); - provenanceProvider.deletedItemFromMapped(context,item, collection); + provenanceService.deletedItemFromMapped(context,item, collection); context.commit(); } } else { diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java index f750743db66e..b9da0dc34dca 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java @@ -35,6 +35,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.ProvenanceServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -69,6 +70,9 @@ public class BundleRestRepository extends DSpaceObjectRestRepository { BitstreamService bitstreamService; @Autowired AuthorizeService authorizeService; + @Autowired + ProvenanceService provenanceService; public static final String OPERATION_PATH_BITSTREAM_REMOVE = "/bitstreams/"; @Override @@ -54,8 +58,13 @@ public Bitstream perform(Context context, Bitstream resource, Operation operatio } authorizeBitstreamRemoveAction(context, bitstreamToDelete, Constants.DELETE); try { + // Find the item to which the bitstream belongs before deleting the bitstream, + // because after deletion, the item will no longer be connected to the bitstream. + Item item = provenanceService.findItemByBitstream(context, bitstreamToDelete); + // Delete the bitstream bitstreamService.delete(context, bitstreamToDelete); - provenanceProvider.deleteBitstream(context, bitstreamToDelete); + // Update the provenance metadata after the bitstream has been successfully deleted + provenanceService.deleteBitstream(context, bitstreamToDelete, item); } catch (AuthorizeException | IOException e) { throw new RuntimeException(e.getMessage(), e); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java index cee0e1113035..8860bc766708 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataAddOperation.java @@ -12,12 +12,12 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.MetadataField; import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -40,6 +40,8 @@ public class DSpaceObjectMetadataAddOperation extends Pa private static final Logger log = LoggerFactory.getLogger(DSpaceObjectMetadataAddOperation.class); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; + @Autowired + ProvenanceService provenanceService; @Override public R perform(Context context, R resource, Operation operation) throws SQLException { @@ -74,7 +76,7 @@ private void add(Context context, DSpaceObject dso, DSpaceObjectService dsoServi dsoService.addAndShiftRightMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), metadataValue.getLanguage(), metadataValue.getValue(), metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt); - provenanceProvider.addMetadata(context, dso, metadataField); + provenanceService.addMetadata(context, dso, metadataField); } catch (SQLException e) { msg = "SQLException in DspaceObjectMetadataAddOperation.add trying to add " + "metadata to dso."; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java index 28b78cf7cd4a..51f332c919c3 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataRemoveOperation.java @@ -14,7 +14,6 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; @@ -22,6 +21,7 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -47,6 +47,8 @@ public class DSpaceObjectMetadataRemoveOperation extends private static final Logger log = LoggerFactory.getLogger(DSpaceObjectMetadataRemoveOperation.class); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; + @Autowired + ProvenanceService provenanceService; @Override public R perform(Context context, R resource, Operation operation) throws SQLException { @@ -76,7 +78,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe // remove all metadata of this type dsoService.clearMetadata(context, dso, metadataField.getMetadataSchema().getName(), metadataField.getElement(), metadataField.getQualifier(), Item.ANY); - provenanceProvider.removeMetadata(context, dso, metadataField); + provenanceService.removeMetadata(context, dso, metadataField); } else { // remove metadata at index List metadataValues = dsoService.getMetadata(dso, @@ -88,7 +90,7 @@ private void remove(Context context, DSpaceObject dso, DSpaceObjectService dsoSe // remove that metadata dsoService.removeMetadataValues(context, dso, Arrays.asList(metadataValues.get(indexInt))); - provenanceProvider.removeMetadataAtIndex(context, dso, metadataValues, indexInt); + provenanceService.removeMetadataAtIndex(context, dso, metadataValues, indexInt); } else { throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " + "this type at that index"); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java index 88ca03b31af2..3d52745e220a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/DSpaceObjectMetadataReplaceOperation.java @@ -14,7 +14,6 @@ import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.Operation; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.MetadataField; @@ -22,6 +21,7 @@ import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.DSpaceObjectService; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -44,6 +44,8 @@ public class DSpaceObjectMetadataReplaceOperation extend private static final Logger log = LoggerFactory.getLogger(DSpaceObjectMetadataReplaceOperation.class); @Autowired DSpaceObjectMetadataPatchUtils metadataPatchUtils; + @Autowired + ProvenanceService provenanceService; @Override public R perform(Context context, R resource, Operation operation) throws SQLException { @@ -168,7 +170,7 @@ private void replaceSingleMetadataValue(Context context, DSpaceObject dso, DSpac existingMdv.setLanguage(metadataValue.getLanguage()); existingMdv.setValue(metadataValue.getValue()); dsoService.setMetadataModified(dso); - provenanceProvider.replaceMetadata(context, dso, metadataField, oldMtdVal); + provenanceService.replaceMetadata(context, dso, metadataField, oldMtdVal); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } @@ -213,7 +215,7 @@ private void replaceSinglePropertyOfMdValue(Context context, DSpaceObject dso, D existingMdv.setValue(valueMdProperty); } dsoService.setMetadataModified(dso); - provenanceProvider.replaceMetadataSingle(context, dso, metadataField, oldMtdVal); + provenanceService.replaceMetadataSingle(context, dso, metadataField, oldMtdVal); } else { throw new UnprocessableEntityException("There is no metadata of this type at that index"); } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java index fcf39effe0d9..2dbf8d966238 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/ItemDiscoverableReplaceOperation.java @@ -7,16 +7,15 @@ */ package org.dspace.app.rest.repository.patch.operation; -import java.sql.SQLException; - import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.patch.Operation; -import org.dspace.authorize.AuthorizeException; import org.dspace.content.Item; import org.dspace.core.Context; +import org.dspace.core.ProvenanceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** @@ -37,6 +36,9 @@ public class ItemDiscoverableReplaceOperation extends PatchOperation { private static final String OPERATION_PATH_DISCOVERABLE = "/discoverable"; private static final Logger log = LoggerFactory.getLogger(ItemDiscoverableReplaceOperation.class); + @Autowired + ProvenanceService provenanceService; + @Override public R perform(Context context, R object, Operation operation) { checkOperationValue(operation.getValue()); @@ -47,7 +49,7 @@ public R perform(Context context, R object, Operation operation) { throw new UnprocessableEntityException("A template item cannot be discoverable."); } item.setDiscoverable(discoverable); - provenanceProvider.makeDiscoverable(context, item, discoverable); + provenanceService.makeDiscoverable(context, item, discoverable); return object; } else { throw new DSpaceBadRequestException("ItemDiscoverableReplaceOperation does not support this operation"); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java index 0fe89aef74d9..0842746f329d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/patch/operation/PatchOperation.java @@ -13,7 +13,6 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.patch.Operation; import org.dspace.core.Context; -import org.dspace.core.ProvenanceProvider; /** * Base class for all resource patch operations. @@ -27,8 +26,6 @@ public abstract class PatchOperation { public static final String OPERATION_MOVE = "move"; public static final String OPERATION_REMOVE = "remove"; - ProvenanceProvider provenanceProvider = new ProvenanceProvider(); - /** * Updates the rest model by applying the patch operation. * diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceExpectedMessages.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceExpectedMessages.java index 94c14b5ad974..d95412a20bfd 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceExpectedMessages.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceExpectedMessages.java @@ -7,20 +7,33 @@ */ package org.dspace.app.rest; +/** + * The ProvenanceExpectedMessages enum provides message templates for provenance messages. + * + * @author Michaela Paurikova (dspace at dataquest.sk) + */ public enum ProvenanceExpectedMessages { - DISCOVERABLE("Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n"), - NON_DISCOVERABLE("Item was made non-discoverable by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0\nItem was in collections:\n"), + DISCOVERABLE("Item was made discoverable by first (admin) last (admin) (admin@email.com) on \nNo. " + + "of bitstreams: 0\nItem was in collections:\n"), + NON_DISCOVERABLE("Item was made non-discoverable by first (admin) last (admin) (admin@email.com) on " + + "\nNo. of bitstreams: 0\nItem was in collections:\n"), MAPPED_COL("was mapped to collection"), ADD_ITEM_MTD("Item metadata (dc.title) was added by first (admin) last (admin) (admin@email.com) on"), - REPLACE_ITEM_MTD("Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0"), - REMOVE_ITEM_MTD("Item metadata (dc.title: Public item 1) was deleted by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0"), + REPLACE_ITEM_MTD("Item metadata (dc.title: Public item 1) was updated by first (admin) last (admin) " + + "(admin@email.com) on \nNo. of bitstreams: 0"), + REMOVE_ITEM_MTD("Item metadata (dc.title: Public item 1) was deleted by first (admin) last (admin) " + + "(admin@email.com) on \nNo. of bitstreams: 0"), REMOVE_BITSTREAM_MTD("Item metadata (dc.description) was added by bitstream"), - REPLACE_BITSTREAM_MTD("metadata (dc.title: test) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n"), + REPLACE_BITSTREAM_MTD("metadata (dc.title: test) was updated by first (admin) last (admin) " + + "(admin@email.com) on \nNo. of bitstreams: 1\n"), REMOVE_BITSTREAM("was deleted bitstream"), ADD_BITSTREAM("Item was added bitstream to bundle"), - UPDATE_LICENSE("License (Test 1) was updated by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n"), - ADD_LICENSE("License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 0"), - REMOVE_LICENSE("License (Test) was removed by first (admin) last (admin) (admin@email.com) on \nNo. of bitstreams: 1\n"), + UPDATE_LICENSE("License (Test 1) was updated by first (admin) last (admin) (admin@email.com) " + + "on \nNo. of bitstreams: 1\n"), + ADD_LICENSE("License (empty) was added by first (admin) last (admin) (admin@email.com) on \nNo." + + " of bitstreams: 0"), + REMOVE_LICENSE("License (Test) was removed by first (admin) last (admin) (admin@email.com) on " + + "\nNo. of bitstreams: 1\n"), MOVED_ITEM_COL("Item was moved from collection "); private final String template; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceProviderIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java similarity index 97% rename from dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceProviderIT.java rename to dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java index 51cef4d416d8..d9aa3768e250 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceProviderIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ProvenanceServiceIT.java @@ -51,8 +51,6 @@ import org.dspace.content.clarin.ClarinLicense; import org.dspace.content.clarin.ClarinLicenseLabel; import org.dspace.content.clarin.ClarinLicenseResourceMapping; -import org.dspace.content.factory.ClarinServiceFactory; -import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.service.ItemService; import org.dspace.content.service.clarin.ClarinLicenseLabelService; import org.dspace.content.service.clarin.ClarinLicenseService; @@ -63,14 +61,17 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; -public class ProvenanceProviderIT extends AbstractControllerIntegrationTest { - private ItemService itemService = ContentServiceFactory.getInstance().getItemService(); - private ClarinLicenseLabelService clarinLicenseLabelService = - ClarinServiceFactory.getInstance().getClarinLicenseLabelService(); - private ClarinLicenseService clarinLicenseService = ClarinServiceFactory.getInstance().getClarinLicenseService(); +public class ProvenanceServiceIT extends AbstractControllerIntegrationTest { + @Autowired + private ItemService itemService; + @Autowired + private ClarinLicenseLabelService clarinLicenseLabelService; + @Autowired + private ClarinLicenseService clarinLicenseService; private Collection collection; private Item item; @@ -110,131 +111,6 @@ public void destroy() throws Exception { super.destroy(); } - private String provenanceMetadataModified(String metadata) { - // Regex to match the date pattern - String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; - Pattern pattern = Pattern.compile(datePattern); - Matcher matcher = pattern.matcher(metadata); - String rspModifiedProvenance = metadata; - while (matcher.find()) { - String dateString = matcher.group(0); - rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); - } - return rspModifiedProvenance; - } - - private void objectCheck(DSpaceObject obj, String expectedMessage) throws Exception { - List metadata = obj.getMetadata(); - boolean contain = false; - for (MetadataValue value : metadata) { - if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { - continue; - } - if (provenanceMetadataModified(value.getValue()).contains(expectedMessage)) { - contain = true; - break; - } - } - if (!contain) { - Assert.fail("Metadata provenance do not contain expected data: " + expectedMessage); - } - } - - private Bundle createBundle(Item item, String bundleName) throws SQLException, AuthorizeException { - context.turnOffAuthorisationSystem(); - Bundle bundle = BundleBuilder.createBundle(context, item).withName(bundleName).build(); - context.restoreAuthSystemState(); - return bundle; - } - - private Bitstream createBitstream(Item item, String bundleName) - throws SQLException, AuthorizeException, IOException { - context.turnOffAuthorisationSystem(); - Bundle bundle = createBundle(item, Objects.isNull(bundleName) ? "test" : bundleName); - Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, - toInputStream("Test Content", defaultCharset())).build(); - context.restoreAuthSystemState(); - return bitstream; - } - - private void deleteBitstream(Bitstream bitstream) throws SQLException, IOException { - int size = bitstream.getBundles().size(); - for (int i = 0; i < size; i++) { - deleteBundle(bitstream.getBundles().get(i).getID()); - } - BitstreamBuilder.deleteBitstream(bitstream.getID()); - } - - - private void deleteBundle(UUID uuid) throws SQLException, IOException { - BundleBuilder.deleteBundle(uuid); - } - - private ClarinLicenseLabel createClarinLicenseLabel(String label, boolean extended, String title) - throws SQLException, AuthorizeException { - context.turnOffAuthorisationSystem(); - ClarinLicenseLabel clarinLicenseLabel = ClarinLicenseLabelBuilder.createClarinLicenseLabel(context).build(); - clarinLicenseLabel.setLabel(label); - clarinLicenseLabel.setExtended(extended); - clarinLicenseLabel.setTitle(title); - clarinLicenseLabelService.update(context, clarinLicenseLabel); - context.restoreAuthSystemState(); - return clarinLicenseLabel; - } - - private ClarinLicense createClarinLicense(String name, String definition) - throws SQLException, AuthorizeException { - context.turnOffAuthorisationSystem(); - ClarinLicense clarinLicense = ClarinLicenseBuilder.createClarinLicense(context).build(); - clarinLicense.setDefinition(definition); - clarinLicense.setName(name); - HashSet clarinLicenseLabels = new HashSet<>(); - ClarinLicenseLabel clarinLicenseLabel = createClarinLicenseLabel("lbl", false, "Test Title"); - clarinLicenseLabels.add(clarinLicenseLabel); - clarinLicense.setLicenseLabels(clarinLicenseLabels); - clarinLicenseService.update(context, clarinLicense); - context.restoreAuthSystemState(); - return clarinLicense; - } - - private void deleteClarinLicenseLable(Integer id) throws Exception { - ClarinLicenseLabelBuilder.deleteClarinLicenseLabel(id); - } - - private void deleteClarinLicense(ClarinLicense license) throws Exception { - int size = license.getLicenseLabels().size(); - for (int i = 0; i < size; i++) { - deleteClarinLicenseLable(license.getLicenseLabels().get(i).getID()); - } - ClarinLicenseBuilder.deleteClarinLicense(license.getID()); - } - - private Collection createCollection() { - context.turnOffAuthorisationSystem(); - Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); - context.restoreAuthSystemState(); - return col; - } - - private void deleteCollection(UUID uuid) throws SearchServiceException, SQLException, IOException { - CollectionBuilder.deleteCollection(uuid); - } - - private ClarinLicenseResourceMapping createResourceMapping(ClarinLicense license, Bitstream bitstream) - throws SQLException, AuthorizeException { - context.turnOffAuthorisationSystem(); - ClarinLicenseResourceMapping resourceMapping = - ClarinLicenseResourceMappingBuilder.createClarinLicenseResourceMapping(context).build(); - context.restoreAuthSystemState(); - resourceMapping.setLicense(license); - resourceMapping.setBitstream(bitstream); - return resourceMapping; - } - - private void deleteResourceMapping(Integer id) throws Exception { - ClarinLicenseResourceMappingBuilder.delete(id); - } - @Test public void updateLicenseTest() throws Exception { Bitstream bitstream = createBitstream(item, Constants.LICENSE_BUNDLE_NAME); @@ -494,4 +370,130 @@ public void moveItemColTest() throws Exception { deleteCollection(col.getID()); } + + + private String provenanceMetadataModified(String metadata) { + // Regex to match the date pattern + String datePattern = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z"; + Pattern pattern = Pattern.compile(datePattern); + Matcher matcher = pattern.matcher(metadata); + String rspModifiedProvenance = metadata; + while (matcher.find()) { + String dateString = matcher.group(0); + rspModifiedProvenance = rspModifiedProvenance.replaceAll(dateString, ""); + } + return rspModifiedProvenance; + } + + private void objectCheck(DSpaceObject obj, String expectedMessage) throws Exception { + List metadata = obj.getMetadata(); + boolean contain = false; + for (MetadataValue value : metadata) { + if (!Objects.equals(value.getMetadataField().toString(), "dc_description_provenance")) { + continue; + } + if (provenanceMetadataModified(value.getValue()).contains(expectedMessage)) { + contain = true; + break; + } + } + if (!contain) { + Assert.fail("Metadata provenance do not contain expected data: " + expectedMessage); + } + } + + private Bundle createBundle(Item item, String bundleName) throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + Bundle bundle = BundleBuilder.createBundle(context, item).withName(bundleName).build(); + context.restoreAuthSystemState(); + return bundle; + } + + private Bitstream createBitstream(Item item, String bundleName) + throws SQLException, AuthorizeException, IOException { + context.turnOffAuthorisationSystem(); + Bundle bundle = createBundle(item, Objects.isNull(bundleName) ? "test" : bundleName); + Bitstream bitstream = BitstreamBuilder.createBitstream(context, bundle, + toInputStream("Test Content", defaultCharset())).build(); + context.restoreAuthSystemState(); + return bitstream; + } + + private void deleteBitstream(Bitstream bitstream) throws SQLException, IOException { + int size = bitstream.getBundles().size(); + for (int i = 0; i < size; i++) { + deleteBundle(bitstream.getBundles().get(i).getID()); + } + BitstreamBuilder.deleteBitstream(bitstream.getID()); + } + + + private void deleteBundle(UUID uuid) throws SQLException, IOException { + BundleBuilder.deleteBundle(uuid); + } + + private ClarinLicenseLabel createClarinLicenseLabel(String label, boolean extended, String title) + throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + ClarinLicenseLabel clarinLicenseLabel = ClarinLicenseLabelBuilder.createClarinLicenseLabel(context).build(); + clarinLicenseLabel.setLabel(label); + clarinLicenseLabel.setExtended(extended); + clarinLicenseLabel.setTitle(title); + clarinLicenseLabelService.update(context, clarinLicenseLabel); + context.restoreAuthSystemState(); + return clarinLicenseLabel; + } + + private ClarinLicense createClarinLicense(String name, String definition) + throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + ClarinLicense clarinLicense = ClarinLicenseBuilder.createClarinLicense(context).build(); + clarinLicense.setDefinition(definition); + clarinLicense.setName(name); + HashSet clarinLicenseLabels = new HashSet<>(); + ClarinLicenseLabel clarinLicenseLabel = createClarinLicenseLabel("lbl", false, "Test Title"); + clarinLicenseLabels.add(clarinLicenseLabel); + clarinLicense.setLicenseLabels(clarinLicenseLabels); + clarinLicenseService.update(context, clarinLicense); + context.restoreAuthSystemState(); + return clarinLicense; + } + + private void deleteClarinLicenseLable(Integer id) throws Exception { + ClarinLicenseLabelBuilder.deleteClarinLicenseLabel(id); + } + + private void deleteClarinLicense(ClarinLicense license) throws Exception { + int size = license.getLicenseLabels().size(); + for (int i = 0; i < size; i++) { + deleteClarinLicenseLable(license.getLicenseLabels().get(i).getID()); + } + ClarinLicenseBuilder.deleteClarinLicense(license.getID()); + } + + private Collection createCollection() { + context.turnOffAuthorisationSystem(); + Collection col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection 1").build(); + context.restoreAuthSystemState(); + return col; + } + + private void deleteCollection(UUID uuid) throws SearchServiceException, SQLException, IOException { + CollectionBuilder.deleteCollection(uuid); + } + + private ClarinLicenseResourceMapping createResourceMapping(ClarinLicense license, Bitstream bitstream) + throws SQLException, AuthorizeException { + context.turnOffAuthorisationSystem(); + ClarinLicenseResourceMapping resourceMapping = + ClarinLicenseResourceMappingBuilder.createClarinLicenseResourceMapping(context).build(); + context.restoreAuthSystemState(); + resourceMapping.setLicense(license); + resourceMapping.setBitstream(bitstream); + return resourceMapping; + } + + private void deleteResourceMapping(Integer id) throws Exception { + ClarinLicenseResourceMappingBuilder.delete(id); + } } diff --git a/dspace/config/spring/api/core-services.xml b/dspace/config/spring/api/core-services.xml index 305d41f64ee5..f6ad5b1e5938 100644 --- a/dspace/config/spring/api/core-services.xml +++ b/dspace/config/spring/api/core-services.xml @@ -179,5 +179,7 @@ + + From 5f63dcd4aeaee9fffcc5c3510f1a000a1182f9fa Mon Sep 17 00:00:00 2001 From: milanmajchrak Date: Mon, 16 Dec 2024 07:56:01 +0100 Subject: [PATCH 53/54] The ProvenanceService wasn't initialized in the BundleAccessControl --- .../dspace/app/bulkaccesscontrol/BulkAccessControl.java | 6 ++---- .../dspace/content/factory/ContentServiceFactory.java | 9 +++++++++ .../content/factory/ContentServiceFactoryImpl.java | 9 +++++++++ .../org/dspace/app/rest/ItemAddBundleController.java | 4 ++-- .../rest/ItemOwningCollectionUpdateRestController.java | 4 ++-- .../dspace/app/rest/MappedCollectionRestController.java | 4 ++-- .../dspace/app/rest/repository/BundleRestRepository.java | 4 ++-- 7 files changed, 28 insertions(+), 12 deletions(-) diff --git a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java index b2a5015666ab..aaf652f2da11 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkaccesscontrol/BulkAccessControl.java @@ -56,7 +56,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceServiceImpl; +import org.dspace.core.ProvenanceService; import org.dspace.discovery.DiscoverQuery; import org.dspace.discovery.SearchService; import org.dspace.discovery.SearchServiceException; @@ -70,7 +70,6 @@ import org.dspace.services.factory.DSpaceServicesFactory; import org.dspace.submit.model.AccessConditionOption; import org.dspace.utils.DSpace; -import org.springframework.beans.factory.annotation.Autowired; /** * Implementation of {@link DSpaceRunnable} to perform a bulk access control via json file. @@ -114,8 +113,7 @@ public class BulkAccessControl extends DSpaceRunnable> getDSpaceObjectServices() { return dSpaceObjectServices; @@ -173,6 +177,11 @@ public PreviewContentService getPreviewContentService() { return previewContentService; } + @Override + public ProvenanceService getProvenanceService() { + return provenanceService; + } + @Override public RelationshipTypeService getRelationshipTypeService() { return relationshipTypeService; diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index c9bf0f719866..89a2ad104ebf 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -38,7 +38,7 @@ import org.dspace.content.service.clarin.ClarinLicenseService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceServiceImpl; +import org.dspace.core.ProvenanceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -100,7 +100,7 @@ public class ItemAddBundleController { ClarinLicenseResourceMappingService clarinLicenseResourceMappingService; @Autowired - ProvenanceServiceImpl provenanceService; + ProvenanceService provenanceService; /** * Method to add a Bundle to an Item with the given UUID in the URL. This will create a Bundle with the diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java index 6108f81b0168..ca467c91630e 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemOwningCollectionUpdateRestController.java @@ -32,7 +32,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceServiceImpl; +import org.dspace.core.ProvenanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.security.access.prepost.PostAuthorize; @@ -67,7 +67,7 @@ public class ItemOwningCollectionUpdateRestController { Utils utils; @Autowired - ProvenanceServiceImpl provenanceService; + ProvenanceService provenanceService; /** * This method will update the owning collection of the item that correspond to the provided item uuid, effectively diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java index 65966b100ada..09581f5e2998 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/MappedCollectionRestController.java @@ -30,7 +30,7 @@ import org.dspace.content.service.CollectionService; import org.dspace.content.service.ItemService; import org.dspace.core.Context; -import org.dspace.core.ProvenanceServiceImpl; +import org.dspace.core.ProvenanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PathVariable; @@ -59,7 +59,7 @@ public class MappedCollectionRestController { Utils utils; @Autowired - ProvenanceServiceImpl provenanceService; + ProvenanceService provenanceService; /** * This method will add an Item to a Collection. The Collection object is encapsulated in the request due to the diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java index b9da0dc34dca..7f800ea81813 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/BundleRestRepository.java @@ -35,7 +35,7 @@ import org.dspace.content.service.ItemService; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.core.ProvenanceServiceImpl; +import org.dspace.core.ProvenanceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -71,7 +71,7 @@ public class BundleRestRepository extends DSpaceObjectRestRepository Date: Mon, 16 Dec 2024 08:55:42 +0100 Subject: [PATCH 54/54] Removal of unwanted changes --- .../main/java/org/dspace/app/rest/ItemAddBundleController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java index 89a2ad104ebf..249cf916be56 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/ItemAddBundleController.java @@ -169,7 +169,6 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, log.warn("Cannot find clarin license with id: " + licenseId + ". The old license will be detached, " + "but the new one will not be attached."); } - List bundles = item.getBundles(Constants.CONTENT_BUNDLE_NAME); for (Bundle clarinBundle : bundles) { List bitstreamList = clarinBundle.getBitstreams(); @@ -186,6 +185,7 @@ public ItemRest updateLicenseForBundle(@PathVariable UUID uuid, if (Objects.nonNull(clarinLicense)) { clarinLicenseService.addLicenseMetadataToItem(context, clarinLicense, item); } + itemService.update(context, item); provenanceService.editLicense(context, item, !Objects.isNull(clarinLicense)); context.commit();