diff --git a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java index 4c9e7a2ac8..59beec72a6 100644 --- a/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/content/ItemServiceImpl.java @@ -1363,7 +1363,7 @@ prevent the generation of resource policy entry values with null dspace_object a * Supports moving metadata by adding the metadata value or updating the place of the relationship */ @Override - public void moveSingleMetadataValue(Context context, Item dso, int place, MetadataValue rr) { + protected void moveSingleMetadataValue(Context context, Item dso, int place, MetadataValue rr) { if (rr instanceof RelationshipMetadataValue) { try { //Retrieve the applicable relationship diff --git a/dspace-api/src/main/java/org/dspace/content/service/DSpaceObjectService.java b/dspace-api/src/main/java/org/dspace/content/service/DSpaceObjectService.java index dd7141d4d3..606f5bb7c0 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/DSpaceObjectService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/DSpaceObjectService.java @@ -368,7 +368,7 @@ public interface DSpaceObjectService { String lang, String value) throws SQLException; /** - * Add a single metadata field at the given place position. + * Add a single metadata value at the given place position. * * @param context DSpace context * @param dso DSpaceObject diff --git a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java index d9083ee83f..2a38488f7a 100644 --- a/dspace-api/src/main/java/org/dspace/content/service/ItemService.java +++ b/dspace-api/src/main/java/org/dspace/content/service/ItemService.java @@ -741,13 +741,4 @@ public interface ItemService public List getMetadata(Item item, String schema, String element, String qualifier, String lang, boolean enableVirtualMetadata); - /** - * - * @param context DSpace context object - * @param item Item - * @param place new metadata position - * @param rr MetadataValue to move - */ - public void moveSingleMetadataValue(Context context, Item item, int place, MetadataValue rr); - } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java index b8e7dda1a3..805a8d1fa1 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/submit/factory/impl/ItemMetadataValueAddPatchOperation.java @@ -14,6 +14,8 @@ import java.util.Map; import java.util.Optional; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.Logger; +import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.patch.LateObjectEvaluator; import org.dspace.authorize.AuthorizeException; @@ -76,6 +78,12 @@ import org.springframework.util.Assert; */ public class ItemMetadataValueAddPatchOperation extends MetadataValueAddPatchOperation { + /** + * log4j category + */ + private static final Logger log = + org.apache.logging.log4j.LogManager.getLogger(ItemMetadataValueAddPatchOperation.class); + @Autowired ItemService itemService; @@ -154,20 +162,21 @@ public class ItemMetadataValueAddPatchOperation extends MetadataValueAddPatchOpe // if a virtual value is present in the list, it must be present in preExistentRelationships too. // (with this operator virtual value can only be moved or deleted). - // a not present virtual value will be discarded int idx = 0; for (MetadataValueRest ll : list) { if (StringUtils.startsWith(ll.getAuthority(), Constants.VIRTUAL_AUTHORITY_PREFIX)) { - Optional preExistentMvr = preExistentMetadata.stream().filter(mvr -> + Optional preExistentMv = preExistentMetadata.stream().filter(mvr -> StringUtils.equals(ll.getAuthority(), mvr.getAuthority())).findFirst(); - if (!preExistentMvr.isPresent()) { - idx++; - continue; + if (!preExistentMv.isPresent()) { + throw new UnprocessableEntityException( + "Relationship with authority=" + ll.getAuthority() + " not found"); } - this.itemService.moveSingleMetadataValue(context, source, idx, preExistentMvr.get()); + final RelationshipMetadataValue rmv = (RelationshipMetadataValue) preExistentMv.get(); + final Relationship rel = preExistentRelationships.get(rmv.getRelationshipId()); + this.updateRelationshipPlace(context, source, idx, rel); } else { getDSpaceObjectService() @@ -201,6 +210,22 @@ public class ItemMetadataValueAddPatchOperation extends MetadataValueAddPatchOpe return relId; } + private void updateRelationshipPlace(Context context, Item dso, int place, Relationship rs) { + + try { + if (rs.getLeftItem() == dso) { + rs.setLeftPlace(place); + } else { + rs.setRightPlace(place); + } + relationshipService.update(context, rs); + } catch (Exception e) { + //should not occur, otherwise metadata can't be updated either + log.error("An error occurred while moving " + rs.getID() + " for item " + dso.getID(), e); + } + + } + @Override protected ItemService getDSpaceObjectService() { return itemService; diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java index f28a397495..7c57e98f1c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/PatchMetadataIT.java @@ -1191,6 +1191,36 @@ public class PatchMetadataIT extends AbstractEntityIntegrationTest { } + /** + * This test will overwrite all authors (dc.contributor.author) of a workspace publication's "traditionalpageone" + * section using a PATCH add with an array composed by only a not existent virtual metadata. + */ + @Test + public void patchAddAllAuthorsOnTraditionalPageNotExistentRelationTest() throws Exception { + + initPersonPublicationWorkspace(); + + List ops = new ArrayList(); + List value = new ArrayList(); + + MetadataValueRest mrv = new MetadataValueRest(); + value.add(mrv); + mrv.setValue("Dumbar, John"); + mrv.setAuthority("virtual::" + Integer.MAX_VALUE); + + AddOperation add = new AddOperation("/sections/traditionalpageone/dc.contributor.author", value); + ops.add(add); + String patchBody = getPatchContent(ops); + + String token = getAuthToken(admin.getEmail(), password); + + getClient(token).perform(patch("/api/submission/workspaceitems/" + publicationItem.getID()) + .content(patchBody) + .contentType(javax.ws.rs.core.MediaType.APPLICATION_JSON_PATCH_JSON)) + .andExpect(status().isUnprocessableEntity()); + + } + /** * This method moves an author (dc.contributor.author) within a workspace publication's "traditionalpageone" * section from position "from" to "path" using a PATCH request and verifies the order of the authors within the