[DS-4389] Refactored new ResourcePolicy Patch system to work like the improved patch system (ResourcePolicy from DS-4398)

This commit is contained in:
Marie Verdonck
2020-02-14 18:56:01 +01:00
parent 7c7422e4cf
commit 1bee20c732
28 changed files with 2036 additions and 1657 deletions

View File

@@ -8,7 +8,6 @@
package org.dspace.app.rest.repository; package org.dspace.app.rest.repository;
import java.io.IOException; import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@@ -24,13 +23,11 @@ import org.dspace.app.rest.exception.RESTAuthorizationException;
import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException; import org.dspace.app.rest.exception.RepositoryMethodNotImplementedException;
import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.model.patch.Patch; import org.dspace.app.rest.model.patch.Patch;
import org.dspace.app.rest.projection.Projection; import org.dspace.app.rest.projection.Projection;
import org.dspace.app.rest.repository.patch.factories.ResourcePolicyOperationFactory; import org.dspace.app.rest.repository.patch.ResourcePatch;
import org.dspace.app.rest.utils.DSpaceObjectUtils; import org.dspace.app.rest.utils.DSpaceObjectUtils;
import org.dspace.app.rest.utils.Utils; import org.dspace.app.rest.utils.Utils;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.ResourcePolicyService; import org.dspace.authorize.service.ResourcePolicyService;
@@ -59,9 +56,6 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
@Autowired @Autowired
ResourcePolicyService resourcePolicyService; ResourcePolicyService resourcePolicyService;
@Autowired
ResourcePolicyOperationFactory resourcePolicyOperationPatchFactory;
@Autowired @Autowired
Utils utils; Utils utils;
@@ -74,6 +68,9 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
@Autowired @Autowired
DSpaceObjectUtils dspaceObjectUtils; DSpaceObjectUtils dspaceObjectUtils;
@Autowired
ResourcePatch<ResourcePolicy> resourcePatch;
@Override @Override
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'READ')") @PreAuthorize("hasPermission(#id, 'resourcepolicy', 'READ')")
@@ -103,7 +100,7 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
/** /**
* Find the resource policies matching the uuid of the resource object and/or the specified action * Find the resource policies matching the uuid of the resource object and/or the specified action
* *
* @param resourceUuid * @param resourceUuid
* mandatory, the uuid of the resource object of the policy * mandatory, the uuid of the resource object of the policy
* @param action * @param action
@@ -142,7 +139,7 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
/** /**
* Find the resource policies matching uuid of the eperson and/or the one specified resource object * Find the resource policies matching uuid of the eperson and/or the one specified resource object
* *
* @param epersonUuid * @param epersonUuid
* mandatory, the uuid of the eperson that benefit of the policy * mandatory, the uuid of the eperson that benefit of the policy
* @param resourceUuid * @param resourceUuid
@@ -186,14 +183,14 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
/** /**
* Find the resource policies matching uuid of the group and/or the ones specified resource object * Find the resource policies matching uuid of the group and/or the ones specified resource object
* *
* @param groupUuid * @param groupUuid
* mandatory, the uuid of the group that benefit of the policy * mandatory, the uuid of the group that benefit of the policy
* @param resourceUuid * @param resourceUuid
* optional, limit the returned policies to the ones related to the specified resource * optional, limit the returned policies to the ones related to the specified resource
* @param pageable * @param pageable
* contains the pagination information * contains the pagination information
* *
* @return It returns the list of explicit matching resource policies, no inherited or broader resource policies * @return It returns the list of explicit matching resource policies, no inherited or broader resource policies
* will be included in the list nor policies derived by groups' membership * will be included in the list nor policies derived by groups' membership
*/ */
@@ -321,27 +318,9 @@ public class ResourcePolicyRestRepository extends DSpaceRestRepository<ResourceP
@Override @Override
@PreAuthorize("hasPermission(#id, 'resourcepolicy', 'ADMIN')") @PreAuthorize("hasPermission(#id, 'resourcepolicy', 'ADMIN')")
protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, Integer id, protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, Integer id,
Patch patch) Patch patch) throws RepositoryMethodNotImplementedException, SQLException, AuthorizeException {
throws RepositoryMethodNotImplementedException, SQLException, AuthorizeException, DCInputsReaderException { ResourcePolicy resourcePolicy = resourcePolicyService.find(context, id);
ResourcePolicyRest rest = findOne(context,id); resourcePatch.patch(obtainContext(), resourcePolicy, patch.getOperations());
if (rest == null) { resourcePolicyService.update(context, resourcePolicy);
throw new ResourceNotFoundException(
ResourcePolicyRest.CATEGORY + "." + ResourcePolicyRest.NAME + " with id: " + id + " not found");
}
for (Operation op : patch.getOperations()) {
rest = resourcePolicyOperationPatchFactory.getOperationForPath(op.getPath()).perform(rest, op);
}
ResourcePolicy resourcePolicy = null;
try {
resourcePolicy = resourcePolicyService.find(context, id);
resourcePolicy.setStartDate(rest.getStartDate());
resourcePolicy.setEndDate(rest.getEndDate());
resourcePolicy.setRpDescription(rest.getDescription());
resourcePolicy.setRpName(rest.getName());
resourcePolicyService.update(context, resourcePolicy);
} catch (SQLException e) {
throw new RuntimeException("Unable to patch ResourcePolicy with id = " + id, e);
}
} }
} }

View File

@@ -14,7 +14,6 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.exception.UnprocessableEntityException; import org.dspace.app.rest.exception.UnprocessableEntityException;
import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation; import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.content.DSpaceObject;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -23,7 +22,7 @@ import org.springframework.stereotype.Component;
* The base class for resource PATCH operations. * The base class for resource PATCH operations.
*/ */
@Component @Component
public class ResourcePatch<M extends DSpaceObject> { public class ResourcePatch<M extends Object> {
@Autowired @Autowired
private List<PatchOperation> patchOperations; private List<PatchOperation> patchOperations;
@@ -48,15 +47,15 @@ public class ResourcePatch<M extends DSpaceObject> {
* Checks with all possible patch operations whether they support this operation * Checks with all possible patch operations whether they support this operation
* (based on instanceof dso and operation.path) * (based on instanceof dso and operation.path)
* @param context Context of patch operation * @param context Context of patch operation
* @param dso the dso resource to patch * @param object the resource to patch
* @param operation the patch operation * @param operation the patch operation
* @throws DSpaceBadRequestException * @throws DSpaceBadRequestException
*/ */
protected void performPatchOperation(Context context, M dso, Operation operation) protected void performPatchOperation(Context context, M object, Operation operation)
throws DSpaceBadRequestException, SQLException { throws DSpaceBadRequestException, SQLException {
for (PatchOperation patchOperation: patchOperations) { for (PatchOperation patchOperation: patchOperations) {
if (patchOperation.supports(dso, operation)) { if (patchOperation.supports(object, operation)) {
patchOperation.perform(context, dso, operation); patchOperation.perform(context,object, operation);
return; return;
} }
} }

View File

@@ -1,67 +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.app.rest.repository.patch.factories;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePatchOperation;
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePolicyDescriptionOperations;
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePolicyEndDateOperations;
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePolicyNameOperations;
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePolicyStartDateOperations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Provides factory methods for obtaining instances of ResourcePolicy patch operations.
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyOperationFactory {
@Autowired
ResourcePolicyStartDateOperations resourcePolicyStartDateOperations;
@Autowired
ResourcePolicyEndDateOperations resourcePolicyEndDateOperations;
@Autowired
ResourcePolicyNameOperations resourcePolicyNameOperations;
@Autowired
ResourcePolicyDescriptionOperations resourcePolicyDescriptionOperations;
private static final String OPERATION_PATH_STARTDATE = "/startDate";
private static final String OPERATION_PATH_ENDDATE = "/endDate";
private static final String OPERATION_PATH_DESCRIPTION = "/description";
private static final String OPERATION_PATH_NAME = "/name";
/**
* Returns the patch instance for the operation (based on the operation path).
*
* @param path the operation path
* @return the patch operation implementation
* @throws DSpaceBadRequestException
*/
public ResourcePatchOperation<ResourcePolicyRest> getOperationForPath(String path) {
switch (path) {
case OPERATION_PATH_STARTDATE:
return resourcePolicyStartDateOperations;
case OPERATION_PATH_ENDDATE:
return resourcePolicyEndDateOperations;
case OPERATION_PATH_DESCRIPTION:
return resourcePolicyDescriptionOperations;
case OPERATION_PATH_NAME:
return resourcePolicyNameOperations;
default:
throw new DSpaceBadRequestException("Missing patch operation for: " + path);
}
}
}

View File

@@ -1,107 +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.app.rest.repository.patch.factories.impl;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.model.patch.Operation;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy name patches.
*
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /description", "value": "my description"]'
* </code>
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyDescriptionOperations implements ResourcePatchOperation<ResourcePolicyRest> {
@Override
public ResourcePolicyRest perform(ResourcePolicyRest resource, Operation operation)
throws DSpaceBadRequestException {
switch (operation.getOp()) {
case "replace":
checkOperationValue(operation.getValue());
checkModelForExistingValue(resource, operation);
return replace(resource, operation);
case "add":
checkOperationValue(operation.getValue());
checkModelForNotExistingValue(resource, operation);
return add(resource, operation);
case "remove":
checkModelForExistingValue(resource, operation);
return delete(resource, operation);
default:
throw new DSpaceBadRequestException("Unsupported operation " + operation.getOp());
}
}
public ResourcePolicyRest replace(ResourcePolicyRest resourcePolicy, Operation operation) {
String newDescription = (String) operation.getValue();
resourcePolicy.setDescription(newDescription);
return resourcePolicy;
}
public ResourcePolicyRest add(ResourcePolicyRest resourcePolicy, Operation operation) {
String description = (String) operation.getValue();
resourcePolicy.setDescription(description);
return resourcePolicy;
}
public ResourcePolicyRest delete(ResourcePolicyRest resourcePolicy, Operation operation) {
resourcePolicy.setDescription(null);
return resourcePolicy;
}
/**
* Throws PatchBadRequestException for missing operation value.
*
* @param value
* the value to test
*/
void checkOperationValue(Object value) {
if (value == null || value.equals("")) {
throw new DSpaceBadRequestException("No value provided for the operation.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /description path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getDescription() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp() + " a non-existent value.");
}
}
/**
* Throws PatchBadRequestException if a value is already set in the /description path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForNotExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getDescription() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
}

View File

@@ -1,147 +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.app.rest.repository.patch.factories.impl;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.model.patch.Operation;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy endDate patches.
*
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /endDate", "value": "YYYY-MM-DD"]'
* </code>
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyEndDateOperations implements ResourcePatchOperation<ResourcePolicyRest> {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public ResourcePolicyRest perform(ResourcePolicyRest resource, Operation operation)
throws DSpaceBadRequestException {
switch (operation.getOp()) {
case "replace":
checkOperationValue(operation.getValue());
checkModelForExistingValue(resource, operation);
checkModelForConsistentValue(resource, operation);
return replace(resource, operation);
case "add":
checkOperationValue(operation.getValue());
checkModelForNotExistingValue(resource, operation);
checkModelForConsistentValue(resource, operation);
return add(resource, operation);
case "remove":
checkModelForExistingValue(resource, operation);
return delete(resource, operation);
default:
throw new DSpaceBadRequestException("Unsupported operation " + operation.getOp());
}
}
ResourcePolicyRest add(ResourcePolicyRest resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
resourcePolicy.setEndDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid endDate value", e);
}
return resourcePolicy;
}
ResourcePolicyRest delete(ResourcePolicyRest resourcePolicy, Operation operation) {
resourcePolicy.setEndDate(null);
return resourcePolicy;
}
ResourcePolicyRest replace(ResourcePolicyRest resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
resourcePolicy.setEndDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid endDate value", e);
}
return resourcePolicy;
}
/**
* Throws PatchBadRequestException for missing operation value.
*
* @param value
* the value to test
*/
void checkOperationValue(Object value) {
if (value == null) {
throw new DSpaceBadRequestException("No value provided for the operation.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /endDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getEndDate() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp() + " a non-existent value.");
}
}
/**
* Throws PatchBadRequestException if a value is already set in the /endDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForNotExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getEndDate() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
/**
* Throws PatchBadRequestException if the value for endDate is not consistent with the startDate value, if present
* (smaller than).
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForConsistentValue(ResourcePolicyRest resource, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
if (resource.getEndDate() != null && resource.getStartDate().after(date)) {
throw new DSpaceBadRequestException("Attempting to set an invalid endDate smaller than the startDate.");
}
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid endDate value", e);
}
}
}

View File

@@ -1,107 +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.app.rest.repository.patch.factories.impl;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.model.patch.Operation;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy name patches.
*
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /name", "value": "New Name"]'
* </code>
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyNameOperations implements ResourcePatchOperation<ResourcePolicyRest> {
@Override
public ResourcePolicyRest perform(ResourcePolicyRest resource, Operation operation)
throws DSpaceBadRequestException {
switch (operation.getOp()) {
case "replace":
checkOperationValue(operation.getValue());
checkModelForExistingValue(resource, operation);
return replace(resource, operation);
case "add":
checkOperationValue(operation.getValue());
checkModelForNotExistingValue(resource, operation);
return add(resource, operation);
case "remove":
checkModelForExistingValue(resource, operation);
return delete(resource, operation);
default:
throw new DSpaceBadRequestException("Unsupported operation " + operation.getOp());
}
}
public ResourcePolicyRest replace(ResourcePolicyRest resourcePolicy, Operation operation) {
String newName = (String) operation.getValue();
resourcePolicy.setName(newName);
return resourcePolicy;
}
public ResourcePolicyRest add(ResourcePolicyRest resourcePolicy, Operation operation) {
String name = (String) operation.getValue();
resourcePolicy.setName(name);
return resourcePolicy;
}
public ResourcePolicyRest delete(ResourcePolicyRest resourcePolicy, Operation operation) {
resourcePolicy.setName(null);
return resourcePolicy;
}
/**
* Throws PatchBadRequestException for missing operation value.
*
* @param value
* the value to test
*/
void checkOperationValue(Object value) {
if (value == null || value.equals("")) {
throw new DSpaceBadRequestException("No value provided for the operation.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /name path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getName() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp() + " a non-existent value.");
}
}
/**
* Throws PatchBadRequestException if a value is already set in the /name path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForNotExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getName() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
}

View File

@@ -1,161 +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.app.rest.repository.patch.factories.impl;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.app.rest.model.patch.Operation;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy startDate patches.
*
* Examples:
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /startDate", "value": "YYYY-MM-DD"]'
* </code>
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "add", "path": "
* /startDate", "value": "YYYY-MM-DD"]'
* </code>
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "delete", "path": "
* /startDate"]'
* </code>
*
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyStartDateOperations implements ResourcePatchOperation<ResourcePolicyRest> {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public ResourcePolicyRest perform(ResourcePolicyRest resource, Operation operation)
throws DSpaceBadRequestException {
switch (operation.getOp()) {
case "replace":
checkOperationValue(operation.getValue());
checkModelForExistingValue(resource, operation);
checkModelForConsistentValue(resource, operation);
return replace(resource, operation);
case "add":
checkOperationValue(operation.getValue());
checkModelForNotExistingValue(resource, operation);
checkModelForConsistentValue(resource, operation);
return add(resource, operation);
case "remove":
checkModelForExistingValue(resource, operation);
return delete(resource, operation);
default:
throw new DSpaceBadRequestException("Unsupported operation " + operation.getOp());
}
}
ResourcePolicyRest add(ResourcePolicyRest resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
resourcePolicy.setStartDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid startDate value", e);
}
return resourcePolicy;
}
ResourcePolicyRest delete(ResourcePolicyRest resourcePolicy, Operation operation) {
resourcePolicy.setStartDate(null);
return resourcePolicy;
}
ResourcePolicyRest replace(ResourcePolicyRest resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
resourcePolicy.setStartDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid startDate value", e);
}
return resourcePolicy;
}
/**
* Throws PatchBadRequestException for missing operation value.
*
* @param value
* the value to test
*/
void checkOperationValue(Object value) {
if (value == null) {
throw new DSpaceBadRequestException("No value provided for the operation.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /startDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getStartDate() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp() + " a non-existent value.");
}
}
/**
* Throws PatchBadRequestException if a value is already set in the /startDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForNotExistingValue(ResourcePolicyRest resource, Operation operation) {
if (resource.getStartDate() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
/**
* Throws PatchBadRequestException if the value for startDate is not consistent with the endDate value, if present
* (greater than).
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
void checkModelForConsistentValue(ResourcePolicyRest resource, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
if (resource.getEndDate() != null && resource.getEndDate().before(date)) {
throw new DSpaceBadRequestException("Attempting to set an invalid startDate greater than the endDate.");
}
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid startDate value", e);
}
}
}

View File

@@ -77,8 +77,8 @@ public class DSpaceObjectMetadataAddOperation<R extends DSpaceObject> extends Pa
@Override @Override
public boolean supports(Object objectToMatch, Operation operation) { public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.METADATA_PATH) return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.METADATA_PATH)) || operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD) && operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD)
&& objectToMatch instanceof DSpaceObject); && objectToMatch instanceof DSpaceObject);
} }

View File

@@ -94,8 +94,8 @@ public class DSpaceObjectMetadataCopyOperation<R extends DSpaceObject> extends P
@Override @Override
public boolean supports(Object objectToMatch, Operation operation) { public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.METADATA_PATH) return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.METADATA_PATH)) || operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_COPY) && operation.getOp().trim().equalsIgnoreCase(OPERATION_COPY)
&& objectToMatch instanceof DSpaceObject); && objectToMatch instanceof DSpaceObject);
} }

View File

@@ -76,8 +76,8 @@ public class DSpaceObjectMetadataMoveOperation<R extends DSpaceObject> extends P
@Override @Override
public boolean supports(Object objectToMatch, Operation operation) { public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.METADATA_PATH) return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.METADATA_PATH)) || operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_MOVE) && operation.getOp().trim().equalsIgnoreCase(OPERATION_MOVE)
&& objectToMatch instanceof DSpaceObject); && objectToMatch instanceof DSpaceObject);
} }

View File

@@ -37,9 +37,9 @@ public final class DSpaceObjectMetadataPatchUtils {
private MetadataFieldService metadataFieldService; private MetadataFieldService metadataFieldService;
/** /**
* Path in json body of patch that uses this operation * Path in json body of patch that uses these metadata operations
*/ */
protected static final String METADATA_PATH = "/metadata"; protected static final String OPERATION_METADATA_PATH = "/metadata";
private DSpaceObjectMetadataPatchUtils() { private DSpaceObjectMetadataPatchUtils() {
} }
@@ -84,9 +84,9 @@ public final class DSpaceObjectMetadataPatchUtils {
* @return The mdField (schema.element.qualifier) patch is being performed on * @return The mdField (schema.element.qualifier) patch is being performed on
*/ */
protected String extractMdFieldStringFromOperation(Operation operation) { protected String extractMdFieldStringFromOperation(Operation operation) {
String mdElement = StringUtils.substringBetween(operation.getPath(), METADATA_PATH + "/", "/"); String mdElement = StringUtils.substringBetween(operation.getPath(), OPERATION_METADATA_PATH + "/", "/");
if (mdElement == null) { if (mdElement == null) {
mdElement = StringUtils.substringAfter(operation.getPath(), METADATA_PATH + "/"); mdElement = StringUtils.substringAfter(operation.getPath(), OPERATION_METADATA_PATH + "/");
if (mdElement == null) { if (mdElement == null) {
throw new DSpaceBadRequestException("No metadata field string found in path: " + operation.getPath()); throw new DSpaceBadRequestException("No metadata field string found in path: " + operation.getPath());
} }

View File

@@ -99,8 +99,8 @@ public class DSpaceObjectMetadataRemoveOperation<R extends DSpaceObject> extends
@Override @Override
public boolean supports(Object objectToMatch, Operation operation) { public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.METADATA_PATH) return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.METADATA_PATH)) || operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE) && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE)
&& objectToMatch instanceof DSpaceObject); && objectToMatch instanceof DSpaceObject);
} }

View File

@@ -214,8 +214,8 @@ public class DSpaceObjectMetadataReplaceOperation<R extends DSpaceObject> extend
@Override @Override
public boolean supports(Object objectToMatch, Operation operation) { public boolean supports(Object objectToMatch, Operation operation) {
return ((operation.getPath().startsWith(metadataPatchUtils.METADATA_PATH) return ((operation.getPath().startsWith(metadataPatchUtils.OPERATION_METADATA_PATH)
|| operation.getPath().equals(metadataPatchUtils.METADATA_PATH)) || operation.getPath().equals(metadataPatchUtils.OPERATION_METADATA_PATH))
&& operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE) && operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE)
&& objectToMatch instanceof DSpaceObject); && objectToMatch instanceof DSpaceObject);
} }

View File

@@ -40,12 +40,16 @@ public abstract class PatchOperation<M> {
/** /**
* Throws PatchBadRequestException for missing operation value. * Throws PatchBadRequestException for missing operation value.
* *
* @param value the value to test * @param value
* the value to test
*/ */
void checkOperationValue(Object value) { public void checkOperationValue(Object value) {
if (value == null) { if (value == null) {
throw new DSpaceBadRequestException("No value provided for the operation."); throw new DSpaceBadRequestException("No value provided for the operation.");
} }
if (value instanceof String && (((String) value).trim().isBlank())) {
throw new DSpaceBadRequestException("Value can't be empty or just spaces.");
}
} }
/** /**

View File

@@ -0,0 +1,78 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy description ADD patch.
*
* Example:
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "add", "path": "
* /description", "value": "YYYY-MM-DD"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyDescriptionAddOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
this.checkResourcePolicyForNonExistingDescriptionValue(resourcePolicy);
this.add(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual add description of resourcePolicy operation
*
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void add(ResourcePolicy resourcePolicy, Operation operation) {
String description = (String) operation.getValue();
resourcePolicy.setRpDescription(description);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_DESCRIPTION));
}
/**
* Throws PatchBadRequestException if a value is already set in the /description path.
*
* @param resource the resource to update
*/
void checkResourcePolicyForNonExistingDescriptionValue(ResourcePolicy resource) {
if (resource.getRpDescription() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
}

View File

@@ -0,0 +1,63 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy description DELETE patch.
*
* Example:
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "remove", "path": "
* /description"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyDescriptionRemoveOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingDescriptionValue(resourcePolicy, operation);
this.delete(resourcePolicy);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual delete description of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
*/
private void delete(ResourcePolicy resourcePolicy) {
resourcePolicy.setRpDescription(null);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_DESCRIPTION));
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy description REPLACE patch.
*
* Example:
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /description", "value": "my description"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyDescriptionReplaceOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingDescriptionValue(resourcePolicy, operation);
this.replace(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual replace description of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void replace(ResourcePolicy resourcePolicy, Operation operation) {
String newDescription = (String) operation.getValue();
resourcePolicy.setRpDescription(newDescription);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_DESCRIPTION));
}
}

View File

@@ -0,0 +1,75 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import java.text.ParseException;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy startDate ADD patch.
*
* Example:
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "add", "path": "
* /endDate", "value": "YYYY-MM-DD"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyEndDateAddOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingEndDateValue(resourcePolicy, operation);
resourcePolicyUtils.checkResourcePolicyForConsistentEndDateValue(resourcePolicy, operation);
this.add(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual add endDate of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void add(ResourcePolicy resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = resourcePolicyUtils.simpleDateFormat.parse(dateS);
resourcePolicy.setEndDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid endDate value", e);
}
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_ENDDATE));
}
}

View File

@@ -0,0 +1,63 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy endDate DELETE patch.
*
* Example:
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "remove", "path": "
* /endDate"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyEndDateRemoveOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingEndDateValue(resourcePolicy, operation);
this.delete(resourcePolicy);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual delete endDate of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
*/
private void delete(ResourcePolicy resourcePolicy) {
resourcePolicy.setEndDate(null);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_ENDDATE));
}
}

View File

@@ -0,0 +1,75 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import java.text.ParseException;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy endDate REPLACE patch.
*
* Example:
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /endDate", "value": "YYYY-MM-DD"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyEndDateReplaceOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingEndDateValue(resourcePolicy, operation);
resourcePolicyUtils.checkResourcePolicyForConsistentEndDateValue(resourcePolicy, operation);
this.replace(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual replace endDate of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void replace(ResourcePolicy resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = resourcePolicyUtils.simpleDateFormat.parse(dateS);
resourcePolicy.setEndDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid endDate value", e);
}
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_ENDDATE));
}
}

View File

@@ -0,0 +1,76 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy name ADD patch.
*
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "add", "path": "
* /name", "value": "New Name"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyNameAddOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
this.checkModelForNotExistingValue(resourcePolicy);
this.add(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual add name of resourcePolicy operation
*
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
public void add(ResourcePolicy resourcePolicy, Operation operation) {
String name = (String) operation.getValue();
resourcePolicy.setRpName(name);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_NAME));
}
/**
* Throws PatchBadRequestException if a value is already set in the /name path.
*
* @param resource the resource to update
*/
private void checkModelForNotExistingValue(ResourcePolicy resource) {
if (resource.getRpName() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
}

View File

@@ -0,0 +1,62 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy name DELETE patch.
*
* Example:
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "remove", "path": "
* /name"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyNameRemoveOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingNameValue(resourcePolicy, operation);
this.delete(resourcePolicy);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual delete name of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
*/
private void delete(ResourcePolicy resourcePolicy) {
resourcePolicy.setRpName(null);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_NAME));
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy name REPLACE patch.
*
* Example:
* Example: <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /name", "value": "New Name"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyNameReplaceOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingNameValue(resourcePolicy, operation);
this.replace(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual replace name of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void replace(ResourcePolicy resourcePolicy, Operation operation) {
String newName = (String) operation.getValue();
resourcePolicy.setRpName(newName);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_NAME));
}
}

View File

@@ -0,0 +1,86 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import java.text.ParseException;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy startDate ADD patch.
*
* Example:
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "add", "path": "
* /startDate", "value": "YYYY-MM-DD"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyStartDateAddOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
this.checkResourcePolicyForNotExistingStartDateValue(resourcePolicy);
resourcePolicyUtils.checkResourcePolicyForConsistentStartDateValue(resourcePolicy, operation);
this.add(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual add startDate of resourcePolicy operation
*
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void add(ResourcePolicy resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = resourcePolicyUtils.simpleDateFormat.parse(dateS);
resourcePolicy.setStartDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid startDate value", e);
}
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_ADD)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_STARTDATE));
}
/**
* Throws PatchBadRequestException if a value is already set in the /startDate path.
*
* @param resource the resource to update
*/
void checkResourcePolicyForNotExistingStartDateValue(ResourcePolicy resource) {
if (resource.getStartDate() != null) {
throw new DSpaceBadRequestException("Attempting to add a value to an already existing path.");
}
}
}

View File

@@ -0,0 +1,63 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy startDate DELETE patch.
*
* Example:
*
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "remove", "path": "
* /startDate"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyStartDateRemoveOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingStartDateValue(resourcePolicy, operation);
this.delete(resourcePolicy);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual delete startDate of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
*/
private void delete(ResourcePolicy resourcePolicy) {
resourcePolicy.setStartDate(null);
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REMOVE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_STARTDATE));
}
}

View File

@@ -0,0 +1,74 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import java.text.ParseException;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.app.rest.repository.patch.operation.PatchOperation;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Implementation for ResourcePolicy startDate REPLACE patch.
*
* Example:
* <code>
* curl -X PATCH http://${dspace.server.url}/api/authz/resourcepolicies/<:id-resourcepolicy> -H "
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
* /startDate", "value": "YYYY-MM-DD"]'
* </code>
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyStartDateReplaceOperation<R> extends PatchOperation<R> {
@Autowired
ResourcePolicyUtils resourcePolicyUtils;
@Override
public R perform(Context context, R resource, Operation operation) {
checkOperationValue(operation.getValue());
if (this.supports(resource, operation)) {
ResourcePolicy resourcePolicy = (ResourcePolicy) resource;
resourcePolicyUtils.checkResourcePolicyForExistingStartDateValue(resourcePolicy, operation);
resourcePolicyUtils.checkResourcePolicyForConsistentStartDateValue(resourcePolicy, operation);
this.replace(resourcePolicy, operation);
return resource;
} else {
throw new DSpaceBadRequestException(this.getClass() + " does not support this operation");
}
}
/**
* Performs the actual replace startDate of resourcePolicy operation
* @param resourcePolicy resourcePolicy being patched
* @param operation patch operation
*/
private void replace(ResourcePolicy resourcePolicy, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = resourcePolicyUtils.simpleDateFormat.parse(dateS);
resourcePolicy.setStartDate(date);
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid startDate value", e);
}
}
@Override
public boolean supports(Object objectToMatch, Operation operation) {
return (objectToMatch instanceof ResourcePolicy && operation.getOp().trim().equalsIgnoreCase(OPERATION_REPLACE)
&& operation.getPath().trim().equalsIgnoreCase(resourcePolicyUtils.OPERATION_PATH_STARTDATE));
}
}

View File

@@ -0,0 +1,144 @@
/**
* 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.repository.patch.operation.resourcePolicy;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.dspace.app.rest.exception.DSpaceBadRequestException;
import org.dspace.app.rest.model.patch.Operation;
import org.dspace.authorize.ResourcePolicy;
import org.springframework.stereotype.Component;
/**
* Util class for shared methods between the ResourcePolicy patches.
*
* @author Maria Verdonck (Atmire) on 14/02/2020
* @author Andrea Bollini (andrea.bollini at 4science.it)
*/
@Component
public class ResourcePolicyUtils {
public static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
/**
* Paths in json body of patched that use these resourcePolicy operations
*/
public static final String OPERATION_PATH_STARTDATE = "/startDate";
public static final String OPERATION_PATH_ENDDATE = "/endDate";
public static final String OPERATION_PATH_DESCRIPTION = "/description";
public static final String OPERATION_PATH_NAME = "/name";
/**
* Throws PatchBadRequestException for missing value in the /startDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
public void checkResourcePolicyForExistingStartDateValue(ResourcePolicy resource, Operation operation) {
if (resource.getStartDate() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp()
+ " a non-existent start date value.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /endDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
public void checkResourcePolicyForExistingEndDateValue(ResourcePolicy resource, Operation operation) {
if (resource.getEndDate() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp()
+ " a non-existent end date value.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /startDate path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
public void checkResourcePolicyForExistingNameValue(ResourcePolicy resource, Operation operation) {
if (resource.getRpName() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp() + " a non-existent name value.");
}
}
/**
* Throws PatchBadRequestException for missing value in the /description path.
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
public void checkResourcePolicyForExistingDescriptionValue(ResourcePolicy resource, Operation operation) {
if (resource.getRpDescription() == null) {
throw new DSpaceBadRequestException("Attempting to " + operation.getOp()
+ " a non-existent description value.");
}
}
/**
* Throws PatchBadRequestException if the value for startDate is not consistent with the endDate value, if present
* (greater than).
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
public void checkResourcePolicyForConsistentStartDateValue(ResourcePolicy resource, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
if (resource.getEndDate() != null && resource.getEndDate().before(date)) {
throw new DSpaceBadRequestException("Attempting to set an invalid startDate greater than the endDate.");
}
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid startDate value", e);
}
}
/**
* Throws PatchBadRequestException if the value for endDate is not consistent with the startDate value, if present
* (smaller than).
*
* @param resource
* the resource to update
* @param operation
* the operation to apply
*
*/
public void checkResourcePolicyForConsistentEndDateValue(ResourcePolicy resource, Operation operation) {
String dateS = (String) operation.getValue();
try {
Date date = simpleDateFormat.parse(dateS);
if (resource.getEndDate() != null && resource.getStartDate().after(date)) {
throw new DSpaceBadRequestException("Attempting to set an invalid endDate smaller than the startDate.");
}
} catch (ParseException e) {
throw new DSpaceBadRequestException("Invalid endDate value", e);
}
}
}