mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-18 07:23:08 +00:00
66075: Feedback improvements 2:
DspaceObjectMetadataOperation - JsonPatchConverter removed - SQL exceptions thrown as is, others to DSpaceBadRequestException - DspaceObjectMetadataOperation.remove() > UnprocessableEntityException with exceptionalities > Already parsed value used in second parse PatchOperation - M no longer extends DSO - supports in child classes with R objectToMatch ItemWithdrawReplaceOperation - one try-catch block with relevant exception handling
This commit is contained in:
@@ -16,7 +16,6 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.dspace.app.rest.converter.JsonPatchConverter;
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
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.CopyOperation;
|
import org.dspace.app.rest.model.patch.CopyOperation;
|
||||||
@@ -36,32 +35,32 @@ import org.springframework.stereotype.Component;
|
|||||||
* Options (can be done on other dso than Item also):
|
* Options (can be done on other dso than Item also):
|
||||||
* - ADD metadata (with schema.identifier.qualifier) value of a dso (here: Item)
|
* - ADD metadata (with schema.identifier.qualifier) value of a dso (here: Item)
|
||||||
* <code>
|
* <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/items/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "add", "path": "
|
* Content-Type: application/json" -d '[{ "op": "add", "path": "
|
||||||
* /metadata/schema.identifier.qualifier(/0|-)}", "value": "metadataValue"]'
|
* /metadata/schema.identifier.qualifier(/0|-)}", "value": "metadataValue"]'
|
||||||
* </code>
|
* </code>
|
||||||
* - REMOVE metadata
|
* - REMOVE metadata
|
||||||
* <code>
|
* <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/items/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "remove",
|
* Content-Type: application/json" -d '[{ "op": "remove",
|
||||||
* "path": "/metadata/schema.identifier.qualifier(/0|-)}"]'
|
* "path": "/metadata/schema.identifier.qualifier(/0|-)}"]'
|
||||||
* </code>
|
* </code>
|
||||||
* - REPLACE metadata
|
* - REPLACE metadata
|
||||||
* <code>
|
* <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/items/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
|
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
|
||||||
* /metadata/schema.identifier.qualifier}", "value": "metadataValue"]'
|
* /metadata/schema.identifier.qualifier}", "value": "metadataValue"]'
|
||||||
* </code>
|
* </code>
|
||||||
* - ORDERING metadata
|
* - ORDERING metadata
|
||||||
* <code>
|
* <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/items/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "move",
|
* Content-Type: application/json" -d '[{ "op": "move",
|
||||||
* "from": "/metadata/schema.identifier.qualifier/index"
|
* "from": "/metadata/schema.identifier.qualifier/index"
|
||||||
* "path": "/metadata/schema.identifier.qualifier/newIndex"}]'
|
* "path": "/metadata/schema.identifier.qualifier/newIndex"}]'
|
||||||
* </code>
|
* </code>
|
||||||
* - COPY metadata
|
* - COPY metadata
|
||||||
* <code>
|
* <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/items/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "copy",
|
* Content-Type: application/json" -d '[{ "op": "copy",
|
||||||
* "from": "/metadata/schema.identifier.qualifier/indexToCopyFrom"
|
* "from": "/metadata/schema.identifier.qualifier/indexToCopyFrom"
|
||||||
* "path": "/metadata/schema.identifier.qualifier/-"}]'
|
* "path": "/metadata/schema.identifier.qualifier/-"}]'
|
||||||
@@ -80,7 +79,6 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
private static final String METADATA_PATH = "/metadata";
|
private static final String METADATA_PATH = "/metadata";
|
||||||
|
|
||||||
private ObjectMapper objectMapper = new ObjectMapper();
|
private ObjectMapper objectMapper = new ObjectMapper();
|
||||||
private JsonPatchConverter jsonPatchConverter = new JsonPatchConverter(objectMapper);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the patch operation for metadata operations.
|
* Implements the patch operation for metadata operations.
|
||||||
@@ -160,8 +158,8 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("IOException in DspaceObjectMetadataOperation.performPatchOperation trying " +
|
throw new DSpaceBadRequestException("IOException in DspaceObjectMetadataOperation.performPatchOperation" +
|
||||||
"to map json from operation.value to MetadataValue class.", e);
|
" trying to map json from operation.value to MetadataValue class.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +186,8 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
metadataValue.getLanguage(), metadataValue.getValue(),
|
metadataValue.getLanguage(), metadataValue.getValue(),
|
||||||
metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt);
|
metadataValue.getAuthority(), metadataValue.getConfidence(), indexInt);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("SQLException in DspaceObjectMetadataOperation.add trying to add metadata to dso.", e);
|
throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataOperation.add trying to add " +
|
||||||
|
"metadata to dso.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,17 +221,18 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
&& metadataValues.get(indexInt) != null) {
|
&& metadataValues.get(indexInt) != null) {
|
||||||
//remove that metadata
|
//remove that metadata
|
||||||
dsoService.removeMetadataValues(context, dso,
|
dsoService.removeMetadataValues(context, dso,
|
||||||
Arrays.asList(metadataValues.get(Integer.parseInt(index))));
|
Arrays.asList(metadataValues.get(indexInt)));
|
||||||
} else {
|
} else {
|
||||||
throw new UnprocessableEntityException("There is no metadata of this type at that index");
|
throw new UnprocessableEntityException("UnprocessableEntityException - There is no metadata of " +
|
||||||
|
"this type at that index");
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new IllegalArgumentException("This index (" + index + ") is not valid nr", e);
|
throw new IllegalArgumentException("This index (" + index + ") is not valid nr", e);
|
||||||
} catch (ArrayIndexOutOfBoundsException e) {
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
throw new UnprocessableEntityException("There is no metadata of this type at that index");
|
throw new UnprocessableEntityException("There is no metadata of this type at that index");
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("SQLException in DspaceObjectMetadataOperation.remove trying to remove " +
|
throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataOperation.remove trying to " +
|
||||||
"metadata from dso.", e);
|
"remove metadata from dso.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,8 +261,8 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
try {
|
try {
|
||||||
dsoService.clearMetadata(context, dso, Item.ANY, Item.ANY, Item.ANY, Item.ANY);
|
dsoService.clearMetadata(context, dso, Item.ANY, Item.ANY, Item.ANY, Item.ANY);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("SQLException in DspaceObjectMetadataOperation.replace trying to remove" +
|
throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataOperation.replace trying to " +
|
||||||
"and replace metadata from dso.", e);
|
"remove and replace metadata from dso.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// replace all metadata for existing key
|
// replace all metadata for existing key
|
||||||
@@ -271,8 +271,8 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
dsoService.clearMetadata(context, dso, schema, element, qualifier, Item.ANY);
|
dsoService.clearMetadata(context, dso, schema, element, qualifier, Item.ANY);
|
||||||
this.add(context, dso, dsoService, schema, element, qualifier, metadataValue, null);
|
this.add(context, dso, dsoService, schema, element, qualifier, metadataValue, null);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("SQLException in DspaceObjectMetadataOperation.replace trying to remove " +
|
throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataOperation.replace trying to " +
|
||||||
"and replace metadata from dso.", e);
|
"remove and replace metadata from dso.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// replace single existing metadata value
|
// replace single existing metadata value
|
||||||
@@ -344,7 +344,8 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
dsoService.moveMetadata(context, dso, schema, element, qualifier,
|
dsoService.moveMetadata(context, dso, schema, element, qualifier,
|
||||||
Integer.parseInt(indexFrom), Integer.parseInt(indexTo));
|
Integer.parseInt(indexFrom), Integer.parseInt(indexTo));
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
log.error("SQLException in DspaceObjectMetadataOperation.move trying to move metadata in dso.", e);
|
throw new DSpaceBadRequestException("SQLException in DspaceObjectMetadataOperation.move trying to move " +
|
||||||
|
"metadata in dso.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,7 +379,8 @@ public class DspaceObjectMetadataOperation<R extends DSpaceObject> extends Patch
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return ((path.startsWith(METADATA_PATH) || path.equals(METADATA_PATH)) && R instanceof DSpaceObject);
|
return ((path.startsWith(METADATA_PATH) || path.equals(METADATA_PATH))
|
||||||
|
&& objectToMatch instanceof DSpaceObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -24,7 +23,7 @@ import org.springframework.stereotype.Component;
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class EPersonCertificateReplaceOperation extends PatchOperation<EPerson> {
|
public class EPersonCertificateReplaceOperation<R> extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -32,26 +31,20 @@ public class EPersonCertificateReplaceOperation extends PatchOperation<EPerson>
|
|||||||
private static final String OPERATION_PATH_CERTIFICATE = "/certificate";
|
private static final String OPERATION_PATH_CERTIFICATE = "/certificate";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EPerson perform(Context context, EPerson eperson, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(eperson);
|
|
||||||
Boolean requireCert = getBooleanOperationValue(operation.getValue());
|
Boolean requireCert = getBooleanOperationValue(operation.getValue());
|
||||||
|
if (supports(object, operation.getPath())) {
|
||||||
|
EPerson eperson = (EPerson) object;
|
||||||
eperson.setRequireCertificate(requireCert);
|
eperson.setRequireCertificate(requireCert);
|
||||||
return eperson;
|
return object;
|
||||||
|
} else {
|
||||||
}
|
throw new DSpaceBadRequestException("EPersonCertificateReplaceOperation does not support this operation.");
|
||||||
|
|
||||||
void checkModelForExistingValue(EPerson resource) {
|
|
||||||
// TODO: many (all?) boolean values on the rest model should never be null.
|
|
||||||
// So perhaps the error to throw in this case is different...IllegalStateException?
|
|
||||||
// Or perhaps do nothing (no check is required).
|
|
||||||
if ((Object) resource.getRequireCertificate() == null) {
|
|
||||||
throw new DSpaceBadRequestException("Attempting to replace a non-existent value.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (R instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_CERTIFICATE));
|
return (objectToMatch instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_CERTIFICATE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -24,7 +23,7 @@ import org.springframework.stereotype.Component;
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class EPersonEmailReplaceOperation extends PatchOperation<EPerson> {
|
public class EPersonEmailReplaceOperation<R> extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -32,21 +31,19 @@ public class EPersonEmailReplaceOperation extends PatchOperation<EPerson> {
|
|||||||
private static final String OPERATION_PATH_EMAIL = "/email";
|
private static final String OPERATION_PATH_EMAIL = "/email";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EPerson perform(Context context, EPerson eperson, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(eperson);
|
if (supports(object, operation.getPath())) {
|
||||||
|
EPerson eperson = (EPerson) object;
|
||||||
eperson.setEmail((String) operation.getValue());
|
eperson.setEmail((String) operation.getValue());
|
||||||
return eperson;
|
return object;
|
||||||
}
|
} else {
|
||||||
|
throw new DSpaceBadRequestException("EPersonEmailReplaceOperation does not support this operation");
|
||||||
void checkModelForExistingValue(EPerson resource) {
|
|
||||||
if (resource.getEmail() == null) {
|
|
||||||
throw new DSpaceBadRequestException("Attempting to replace a non-existent value.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (R instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_EMAIL));
|
return (objectToMatch instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_EMAIL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -24,7 +23,7 @@ import org.springframework.stereotype.Component;
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class EPersonLoginReplaceOperation extends PatchOperation<EPerson> {
|
public class EPersonLoginReplaceOperation<R>extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -32,22 +31,20 @@ public class EPersonLoginReplaceOperation extends PatchOperation<EPerson> {
|
|||||||
private static final String OPERATION_PATH_PASSWORD = "/canLogin";
|
private static final String OPERATION_PATH_PASSWORD = "/canLogin";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EPerson perform(Context context, EPerson eperson, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(eperson);
|
|
||||||
Boolean canLogin = getBooleanOperationValue(operation.getValue());
|
Boolean canLogin = getBooleanOperationValue(operation.getValue());
|
||||||
|
if (supports(object, operation.getPath())) {
|
||||||
|
EPerson eperson = (EPerson) object;
|
||||||
eperson.setCanLogIn(canLogin);
|
eperson.setCanLogIn(canLogin);
|
||||||
return eperson;
|
return object;
|
||||||
}
|
} else {
|
||||||
|
throw new DSpaceBadRequestException("EPersonLoginReplaceOperation does not support this operation");
|
||||||
void checkModelForExistingValue(EPerson resource) {
|
|
||||||
if ((Object) resource.canLogIn() == null) {
|
|
||||||
throw new DSpaceBadRequestException("Attempting to replace a non-existent value.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (R instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_PASSWORD));
|
return (objectToMatch instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_PASSWORD));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -24,7 +23,7 @@ import org.springframework.stereotype.Component;
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class EPersonNetidReplaceOperation extends PatchOperation<EPerson> {
|
public class EPersonNetidReplaceOperation<R> extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -32,21 +31,19 @@ public class EPersonNetidReplaceOperation extends PatchOperation<EPerson> {
|
|||||||
private static final String OPERATION_PATH_NETID = "/netid";
|
private static final String OPERATION_PATH_NETID = "/netid";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EPerson perform(Context context, EPerson eperson, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(eperson);
|
if (supports(object, operation.getPath())) {
|
||||||
|
EPerson eperson = (EPerson) object;
|
||||||
eperson.setNetid((String) operation.getValue());
|
eperson.setNetid((String) operation.getValue());
|
||||||
return eperson;
|
return object;
|
||||||
}
|
} else {
|
||||||
|
throw new DSpaceBadRequestException("EPersonNetidReplaceOperation does not support this operation");
|
||||||
void checkModelForExistingValue(EPerson resource) {
|
|
||||||
if (resource.getNetid() == null) {
|
|
||||||
throw new DSpaceBadRequestException("Attempting to replace a non-existent value.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (R instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_NETID));
|
return (objectToMatch instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PATH_NETID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,8 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest.repository.patch.factories.impl;
|
package org.dspace.app.rest.repository.patch.factories.impl;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.dspace.eperson.EPerson;
|
import org.dspace.eperson.EPerson;
|
||||||
import org.dspace.eperson.factory.EPersonServiceFactory;
|
import org.dspace.eperson.factory.EPersonServiceFactory;
|
||||||
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Component;
|
|||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class EPersonPasswordReplaceOperation extends PatchOperation<EPerson> {
|
public class EPersonPasswordReplaceOperation<R> extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -34,25 +34,19 @@ public class EPersonPasswordReplaceOperation extends PatchOperation<EPerson> {
|
|||||||
protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
protected EPersonService ePersonService = EPersonServiceFactory.getInstance().getEPersonService();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EPerson perform(Context context, EPerson eperson, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(eperson);
|
if (supports(object, operation.getPath())) {
|
||||||
|
EPerson eperson = (EPerson) object;
|
||||||
ePersonService.setPassword(eperson, (String) operation.getValue());
|
ePersonService.setPassword(eperson, (String) operation.getValue());
|
||||||
return eperson;
|
return object;
|
||||||
|
} else {
|
||||||
|
throw new DSpaceBadRequestException("EPersonPasswordReplaceOperation does not support this operation");
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkModelForExistingValue(EPerson resource) {
|
|
||||||
/*
|
|
||||||
* FIXME: the password field in eperson rest model is always null because
|
|
||||||
* the value is not set in the rest converter.
|
|
||||||
* We would normally throw an exception here since replace
|
|
||||||
* operations are not allowed on non-existent values, but that
|
|
||||||
* would prevent the password update from ever taking place.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (R instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PASSWORD_CHANGE));
|
return (objectToMatch instanceof EPerson && path.trim().equalsIgnoreCase(OPERATION_PASSWORD_CHANGE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,6 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -18,13 +17,13 @@ import org.springframework.stereotype.Component;
|
|||||||
* This is the implementation for Item resource patches.
|
* This is the implementation for Item resource patches.
|
||||||
*
|
*
|
||||||
* Example: <code>
|
* Example: <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/item/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
|
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
|
||||||
* /discoverable", "value": true|false]'
|
* /discoverable", "value": true|false]'
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ItemDiscoverableReplaceOperation extends PatchOperation<Item> {
|
public class ItemDiscoverableReplaceOperation<R> extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -32,24 +31,21 @@ public class ItemDiscoverableReplaceOperation extends PatchOperation<Item> {
|
|||||||
private static final String OPERATION_PATH_DISCOVERABLE = "/discoverable";
|
private static final String OPERATION_PATH_DISCOVERABLE = "/discoverable";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item perform(Context context, Item item, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(item);
|
|
||||||
Boolean discoverable = getBooleanOperationValue(operation.getValue());
|
Boolean discoverable = getBooleanOperationValue(operation.getValue());
|
||||||
|
if (supports(object, operation.getPath())) {
|
||||||
|
Item item = (Item) object;
|
||||||
item.setDiscoverable(discoverable);
|
item.setDiscoverable(discoverable);
|
||||||
return item;
|
return object;
|
||||||
|
} else {
|
||||||
}
|
throw new DSpaceBadRequestException("ItemDiscoverableReplaceOperation does not support this operation");
|
||||||
|
|
||||||
void checkModelForExistingValue(Item resource) {
|
|
||||||
if ((Object) resource.isDiscoverable() == null) {
|
|
||||||
throw new DSpaceBadRequestException("Attempting to replace a non-existent value.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject R, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (R instanceof Item && path.trim().equalsIgnoreCase(OPERATION_PATH_DISCOVERABLE));
|
return (objectToMatch instanceof Item && path.trim().equalsIgnoreCase(OPERATION_PATH_DISCOVERABLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -10,10 +10,10 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
|
import org.dspace.app.rest.exception.RESTAuthorizationException;
|
||||||
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.authorize.AuthorizeException;
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.content.Item;
|
import org.dspace.content.Item;
|
||||||
import org.dspace.content.factory.ContentServiceFactory;
|
import org.dspace.content.factory.ContentServiceFactory;
|
||||||
import org.dspace.content.service.ItemService;
|
import org.dspace.content.service.ItemService;
|
||||||
@@ -24,13 +24,13 @@ import org.springframework.stereotype.Component;
|
|||||||
* This is the implementation for Item resource patches.
|
* This is the implementation for Item resource patches.
|
||||||
* <p>
|
* <p>
|
||||||
* Example: <code>
|
* Example: <code>
|
||||||
* curl -X PATCH http://${dspace.url}/api/item/<:id-item> -H "
|
* curl -X PATCH http://${dspace.url}/api/core/items/<:id-item> -H "
|
||||||
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
|
* Content-Type: application/json" -d '[{ "op": "replace", "path": "
|
||||||
* /withdrawn", "value": true|false]'
|
* /withdrawn", "value": true|false]'
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class ItemWithdrawReplaceOperation extends PatchOperation<Item> {
|
public class ItemWithdrawReplaceOperation<R> extends PatchOperation<R> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path in json body of patch that uses this operation
|
* Path in json body of patch that uses this operation
|
||||||
@@ -39,13 +39,15 @@ public class ItemWithdrawReplaceOperation extends PatchOperation<Item> {
|
|||||||
private static final ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
private static final ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item perform(Context context, Item item, Operation operation) {
|
public R perform(Context context, R object, Operation operation) {
|
||||||
checkOperationValue(operation.getValue());
|
checkOperationValue(operation.getValue());
|
||||||
checkModelForExistingValue(item);
|
|
||||||
|
|
||||||
Boolean withdraw = getBooleanOperationValue(operation.getValue());
|
Boolean withdraw = getBooleanOperationValue(operation.getValue());
|
||||||
|
|
||||||
|
if (supports(object, operation.getPath())) {
|
||||||
|
Item item = (Item) object;
|
||||||
// This is a request to withdraw the item.
|
// This is a request to withdraw the item.
|
||||||
|
try {
|
||||||
if (withdraw) {
|
if (withdraw) {
|
||||||
// The item is currently not withdrawn and also not archived. Is this a possible situation?
|
// The item is currently not withdrawn and also not archived. Is this a possible situation?
|
||||||
if (!item.isWithdrawn() && !item.isArchived()) {
|
if (!item.isWithdrawn() && !item.isArchived()) {
|
||||||
@@ -54,49 +56,34 @@ public class ItemWithdrawReplaceOperation extends PatchOperation<Item> {
|
|||||||
// Item is already withdrawn. No-op, 200 response.
|
// Item is already withdrawn. No-op, 200 response.
|
||||||
// (The operation is not idempotent since it results in a provenance note in the record.)
|
// (The operation is not idempotent since it results in a provenance note in the record.)
|
||||||
if (item.isWithdrawn()) {
|
if (item.isWithdrawn()) {
|
||||||
return item;
|
return object;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
itemService.withdraw(context, item);
|
itemService.withdraw(context, item);
|
||||||
} catch (SQLException e) {
|
return object;
|
||||||
// TODO
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (AuthorizeException e) {
|
|
||||||
// TODO
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// No need to reinstate item if it has not previously been not withdrawn.
|
// No need to reinstate item if it has not previously been not withdrawn.
|
||||||
// No-op, 200 response. (The operation is not idempotent since it results
|
// No-op, 200 response. (The operation is not idempotent since it results
|
||||||
// in a provenance note in the record.)
|
// in a provenance note in the record.)
|
||||||
if (!item.isWithdrawn()) {
|
if (!item.isWithdrawn()) {
|
||||||
return item;
|
return object;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
itemService.reinstate(context, item);
|
itemService.reinstate(context, item);
|
||||||
} catch (SQLException e) {
|
return object;
|
||||||
// TODO
|
}
|
||||||
e.printStackTrace();
|
|
||||||
} catch (AuthorizeException e) {
|
} catch (AuthorizeException e) {
|
||||||
// TODO
|
throw new RESTAuthorizationException("Unauthorized user for item withdrawal/reinstation");
|
||||||
e.printStackTrace();
|
} catch (SQLException e) {
|
||||||
|
throw new DSpaceBadRequestException("SQL exception during item withdrawal/reinstation");
|
||||||
}
|
}
|
||||||
return item;
|
} else {
|
||||||
}
|
throw new DSpaceBadRequestException("ItemWithdrawReplaceOperation does not support this operation");
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkModelForExistingValue(Item resource) {
|
|
||||||
if ((Object) resource.isWithdrawn() == null) {
|
|
||||||
throw new DSpaceBadRequestException("Attempting to replace a non-existent value.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(DSpaceObject dso, String path) {
|
public boolean supports(R objectToMatch, String path) {
|
||||||
return (dso instanceof Item && path.trim().equalsIgnoreCase(OPERATION_PATH_WITHDRAW));
|
return (objectToMatch instanceof Item && path.trim().equalsIgnoreCase(OPERATION_PATH_WITHDRAW));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -10,13 +10,12 @@ package org.dspace.app.rest.repository.patch.factories.impl;
|
|||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all resource patch operations.
|
* Base class for all resource patch operations.
|
||||||
*/
|
*/
|
||||||
public abstract class PatchOperation<M extends DSpaceObject>
|
public abstract class PatchOperation<M>
|
||||||
implements ResourcePatchOperation<M> {
|
implements ResourcePatchOperation<M> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,10 +64,11 @@ public abstract class PatchOperation<M extends DSpaceObject>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether or not this Patch Operation can do this patch (RestModel and path gets checked)
|
* Determines whether or not this Patch Operation can do this patch (RestModel and path gets checked)
|
||||||
* @param M dso, whose class must be instance of dso for which this PatchOperation was created
|
* @param objectToMatch Object whose class must be instance of type object
|
||||||
|
* for which this PatchOperation was created
|
||||||
* @param path Path given to the patch body, should match this type of Patch Operation
|
* @param path Path given to the patch body, should match this type of Patch Operation
|
||||||
* @return True if this PatchOperation class can do the patch for this given dso type and Path
|
* @return True if this PatchOperation class can do the patch for this given dso type and Path
|
||||||
*/
|
*/
|
||||||
public abstract boolean supports(DSpaceObject M, String path);
|
public abstract boolean supports(M objectToMatch, String path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,18 +7,19 @@
|
|||||||
*/
|
*/
|
||||||
package org.dspace.app.rest.repository.patch.factories.impl;
|
package org.dspace.app.rest.repository.patch.factories.impl;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
import org.dspace.app.rest.model.patch.Operation;
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
import org.dspace.content.DSpaceObject;
|
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The patch interface used by repository classes.
|
* The patch interface used by repository classes.
|
||||||
* @param <M>
|
* @param <M>
|
||||||
*/
|
*/
|
||||||
public interface ResourcePatchOperation<M extends DSpaceObject> {
|
public interface ResourcePatchOperation<M> {
|
||||||
|
|
||||||
M perform(Context context, M resource, Operation operation)
|
M perform(Context context, M resource, Operation operation)
|
||||||
throws DSpaceBadRequestException;
|
throws DSpaceBadRequestException, SQLException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user