D4CRIS-416 first implementation of the contract (missing bitstream move operation and replace operation on attribute at accessConditions level)

This commit is contained in:
Luigi Andrea Pascarelli
2017-12-13 20:11:41 +01:00
parent d521163760
commit 151d45d0d0
20 changed files with 323 additions and 169 deletions

View File

@@ -160,6 +160,12 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
String element = tokens[1]; String element = tokens[1];
String qualifier = tokens[2]; String qualifier = tokens[2];
List<MetadataValue> values = getMetadata(dso, schema, element, qualifier);
return values;
}
private List<MetadataValue> getMetadata(T dso, String schema, String element, String qualifier) {
List<MetadataValue> values; List<MetadataValue> values;
if (Item.ANY.equals(qualifier)) if (Item.ANY.equals(qualifier))
{ {
@@ -173,7 +179,6 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
{ {
values = getMetadata(dso, schema, element, qualifier, Item.ANY); values = getMetadata(dso, schema, element, qualifier, Item.ANY);
} }
return values; return values;
} }
@@ -624,7 +629,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
@Override @Override
public void addAndShiftRightMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, String value, String authority, int confidence, int index) throws SQLException { public void addAndShiftRightMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, String value, String authority, int confidence, int index) throws SQLException {
List<MetadataValue> list = getMetadata(dso, schema, element, qualifier, lang); List<MetadataValue> list = getMetadata(dso, schema, element, qualifier);
clearMetadata(context, dso, schema, element, qualifier, Item.ANY); clearMetadata(context, dso, schema, element, qualifier, Item.ANY);
@@ -654,7 +659,7 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
throw new IllegalArgumentException("The \"from\" location MUST be different from \"to\" location"); throw new IllegalArgumentException("The \"from\" location MUST be different from \"to\" location");
} }
List<MetadataValue> list = getMetadata(dso, schema, element, qualifier, Item.ANY); List<MetadataValue> list = getMetadata(dso, schema, element, qualifier);
if(from>=list.size()) { if(from>=list.size()) {
throw new IllegalArgumentException("The \"from\" location MUST exist for the operation to be successful. Idx:" + from); throw new IllegalArgumentException("The \"from\" location MUST exist for the operation to be successful. Idx:" + from);
@@ -693,4 +698,25 @@ public abstract class DSpaceObjectServiceImpl<T extends DSpaceObject> implements
addMetadata(context, dso, schema, element, qualifier, moved.getLanguage(), moved.getValue(), moved.getAuthority(), moved.getConfidence()); addMetadata(context, dso, schema, element, qualifier, moved.getLanguage(), moved.getValue(), moved.getAuthority(), moved.getConfidence());
} }
} }
@Override
public void replaceMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, String value, String authority, int confidence, int index) throws SQLException {
List<MetadataValue> list = getMetadata(dso, schema, element, qualifier);
clearMetadata(context, dso, schema, element, qualifier, Item.ANY);
int idx = 0;
for(MetadataValue rr : list) {
if(idx==index) {
addMetadata(context, dso, schema, element, qualifier,
lang, value, authority, confidence);
}
else {
addMetadata(context, dso, schema, element, qualifier,
rr.getLanguage(), rr.getValue(), rr.getAuthority(), rr.getConfidence());
}
idx++;
}
}
} }

View File

@@ -402,5 +402,7 @@ public interface DSpaceObjectService<T extends DSpaceObject> {
void addAndShiftRightMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, String value, String authority, int confidence, int index) throws SQLException; void addAndShiftRightMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, String value, String authority, int confidence, int index) throws SQLException;
void replaceMetadata(Context context, T dso, String schema, String element, String qualifier, String lang, String value, String authority, int confidence, int index) throws SQLException;
void moveMetadata(Context context, T dso, String schema, String element, String qualifier, int from, int to) throws SQLException; void moveMetadata(Context context, T dso, String schema, String element, String qualifier, int from, int to) throws SQLException;
} }

View File

@@ -24,6 +24,8 @@ public class DataLicense implements SectionData {
@JsonProperty(access = Access.READ_ONLY) @JsonProperty(access = Access.READ_ONLY)
private String acceptanceDate; private String acceptanceDate;
private boolean granted = false;
public String getAcceptanceDate() { public String getAcceptanceDate() {
return acceptanceDate; return acceptanceDate;
} }
@@ -40,6 +42,14 @@ public class DataLicense implements SectionData {
this.url = url; this.url = url;
} }
public boolean isGranted() {
return granted;
}
public void setGranted(boolean granted) {
this.granted = granted;
}
} }

View File

@@ -32,9 +32,12 @@ public interface AbstractRestProcessingStep {
public static final String COLLECTION_STEP_OPERATION_ENTRY = "collection"; public static final String COLLECTION_STEP_OPERATION_ENTRY = "collection";
public static final String UPLOAD_STEP_METADATA_OPERATION_ENTRY = "bitstreammetadata"; public static final String UPLOAD_STEP_METADATA_OPERATION_ENTRY = "bitstreammetadata";
public static final String UPLOAD_STEP_REMOVE_OPERATION_ENTRY = "bitstreamremove"; public static final String UPLOAD_STEP_REMOVE_OPERATION_ENTRY = "bitstreamremove";
public static final String UPLOAD_STEP_MOVE_OPERATION_ENTRY = "bitstreammove";
public static final String UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY = "accessConditions"; public static final String UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY = "accessConditions";
public static final String LICENSE_STEP_OPERATION_ENTRY = "granted"; public static final String LICENSE_STEP_OPERATION_ENTRY = "granted";
public static final String UPLOAD_STEP_METADATA_PATH = "metadata";
public <T extends Serializable> T getData(SubmissionService submissionService, WorkspaceItem obj, SubmissionStepConfig config) throws Exception; public <T extends Serializable> T getData(SubmissionService submissionService, WorkspaceItem obj, SubmissionStepConfig config) throws Exception;
default public List<ErrorRest> validate(SubmissionService submissionService, WorkspaceItem obj, SubmissionStepConfig config) throws Exception default public List<ErrorRest> validate(SubmissionService submissionService, WorkspaceItem obj, SubmissionStepConfig config) throws Exception

View File

@@ -42,31 +42,33 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
@Override @Override
void add(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) throws Exception { void add(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) throws Exception {
//"path": "/sections/upload/files/0/metadata/dc.title/2"
//"abspath": "/files/0/metadata/dc.title/2"
String[] split = getAbsolutePath(path).split("/"); String[] split = getAbsolutePath(path).split("/");
Item item = source.getItem(); Item item = source.getItem();
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);; List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);;
for(Bundle bb : bundle) { for(Bundle bb : bundle) {
int idx = 0; int idx = 0;
for(Bitstream b : bb.getBitstreams()) { for(Bitstream b : bb.getBitstreams()) {
if(idx==Integer.parseInt(split[0])) { if(idx==Integer.parseInt(split[1])) {
if (split.length == 2) { if (split.length == 4) {
List<MetadataValueRest> list = evaluateArrayObject((LateObjectEvaluator) value); List<MetadataValueRest> list = evaluateArrayObject((LateObjectEvaluator) value);
replaceValue(context, b, split[2], list); replaceValue(context, b, split[3], list);
} else { } else {
// call with "-" or "index-based" we should receive only single // call with "-" or "index-based" we should receive only single
// object member // object member
MetadataValueRest object = evaluateSingleObject((LateObjectEvaluator) value); MetadataValueRest object = evaluateSingleObject((LateObjectEvaluator) value);
// check if is not empty // check if is not empty
List<MetadataValue> metadataByMetadataString = itemService.getMetadataByMetadataString(source.getItem(), List<MetadataValue> metadataByMetadataString = bitstreamService.getMetadataByMetadataString(b,
split[0]); split[3]);
Assert.notEmpty(metadataByMetadataString); Assert.notEmpty(metadataByMetadataString);
if (split.length > 2) { if (split.length > 4) {
String controlChar = split[3]; String controlChar = split[4];
switch (controlChar) { switch (controlChar) {
case "-": case "-":
addValue(context, b, split[2], object, -1); addValue(context, b, split[3], object, -1);
break; break;
default: default:
// index based // index based
@@ -76,7 +78,7 @@ public class BitstreamMetadataValueAddPatchOperation extends MetadataValueAddPat
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The specified index MUST NOT be greater than the number of elements in the array"); "The specified index MUST NOT be greater than the number of elements in the array");
} }
addValue(context, b, split[2], object, index); addValue(context, b, split[3], object, index);
break; break;
} }

View File

@@ -39,22 +39,24 @@ public class BitstreamMetadataValueMovePatchOperation extends MetadataValueMoveP
@Override @Override
void move(Context context, Request currentRequest, WorkspaceItem source, String path, String from) void move(Context context, Request currentRequest, WorkspaceItem source, String path, String from)
throws Exception { throws Exception {
//"path": "/sections/upload/files/0/metadata/dc.title/2"
//"abspath": "/files/0/metadata/dc.title/2"
String[] splitTo = getAbsolutePath(path).split("/"); String[] splitTo = getAbsolutePath(path).split("/");
Item item = source.getItem(); Item item = source.getItem();
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME); List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
for (Bundle bb : bundle) { for (Bundle bb : bundle) {
int idx = 0; int idx = 0;
for (Bitstream b : bb.getBitstreams()) { for (Bitstream b : bb.getBitstreams()) {
if (idx == Integer.parseInt(splitTo[0])) { if (idx == Integer.parseInt(splitTo[1])) {
String evalFrom = getAbsolutePath(from); String evalFrom = getAbsolutePath(from);
String[] splitFrom = evalFrom.split("/"); String[] splitFrom = evalFrom.split("/");
String metadata = splitFrom[0]; String metadata = splitFrom[3];
if (splitTo.length > 1) { if (splitTo.length > 4) {
String stringTo = splitTo[1]; String stringTo = splitTo[4];
if (splitFrom.length > 1) { if (splitFrom.length > 4) {
String stringFrom = splitFrom[1]; String stringFrom = splitFrom[4];
int intTo = Integer.parseInt(stringTo); int intTo = Integer.parseInt(stringTo);
int intFrom = Integer.parseInt(stringFrom); int intFrom = Integer.parseInt(stringFrom);

View File

@@ -38,19 +38,21 @@ public class BitstreamMetadataValueRemovePatchOperation extends MetadataValueRem
@Override @Override
void remove(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) throws Exception { void remove(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) throws Exception {
//"path": "/sections/upload/files/0/metadata/dc.title/2"
//"abspath": "/files/0/metadata/dc.title/2"
String[] split = getAbsolutePath(path).split("/"); String[] split = getAbsolutePath(path).split("/");
Item item = source.getItem(); Item item = source.getItem();
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);; List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);;
for(Bundle bb : bundle) { for(Bundle bb : bundle) {
int idx = 0; int idx = 0;
for(Bitstream b : bb.getBitstreams()) { for(Bitstream b : bb.getBitstreams()) {
if(idx==Integer.parseInt(split[0])) { if(idx==Integer.parseInt(split[1])) {
if (split.length == 2) { if (split.length == 4) {
deleteValue(context, b, split[2], -1); deleteValue(context, b, split[3], -1);
} else { } else {
Integer toDelete = Integer.parseInt(split[3]); Integer toDelete = Integer.parseInt(split[4]);
deleteValue(context, b, split[2], toDelete); deleteValue(context, b, split[3], toDelete);
} }
} }
idx++; idx++;

View File

@@ -47,13 +47,15 @@ public class BitstreamMetadataValueReplacePatchOperation extends MetadataValueRe
@Override @Override
void replace(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void replace(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
//"path": "/sections/upload/files/0/metadata/dc.title/2"
//"abspath": "/files/0/metadata/dc.title/2"
String[] split = getAbsolutePath(path).split("/"); String[] split = getAbsolutePath(path).split("/");
Item item = source.getItem(); Item item = source.getItem();
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME); List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
for (Bundle bb : bundle) { for (Bundle bb : bundle) {
int idx = 0; int idx = 0;
for (Bitstream b : bb.getBitstreams()) { for (Bitstream b : bb.getBitstreams()) {
if (idx == Integer.parseInt(split[0])) { if (idx == Integer.parseInt(split[1])) {
replace(context, b, split, value); replace(context, b, split, value);
} }
idx++; idx++;
@@ -62,45 +64,19 @@ public class BitstreamMetadataValueReplacePatchOperation extends MetadataValueRe
} }
private void replace(Context context, Bitstream b, String[] split, Object value) throws SQLException, IllegalArgumentException, IllegalAccessException { private void replace(Context context, Bitstream b, String[] split, Object value) throws SQLException, IllegalArgumentException, IllegalAccessException {
List<MetadataValue> metadataByMetadataString = bitstreamService.getMetadataByMetadataString(b, split[0]); String mdString = split[3];
List<MetadataValue> metadataByMetadataString = bitstreamService.getMetadataByMetadataString(b, mdString);
Assert.notEmpty(metadataByMetadataString); Assert.notEmpty(metadataByMetadataString);
int index = Integer.parseInt(split[2]); int index = Integer.parseInt(split[4]);
// if split size is one so we have a call to initialize or replace // if split size is one so we have a call to initialize or replace
if (split.length == 1) { if (split.length == 5) {
MetadataValueRest obj = evaluateSingleObject((LateObjectEvaluator) value); MetadataValueRest obj = evaluateSingleObject((LateObjectEvaluator) value);
replaceValue(context, b, split[1], metadataByMetadataString, obj, index); replaceValue(context, b, mdString, metadataByMetadataString, obj, index);
} else { } else {
if (split.length == 2) { //"path": "/sections/upload/files/0/metadata/dc.title/2/language"
String namedField = split[3]; if (split.length > 5) {
// check field setDeclaredField(context, b, value, mdString, split[5], metadataByMetadataString, index);
String raw = evaluateString((LateObjectEvaluator) value);
for (Field field : MetadataValueRest.class.getDeclaredFields()) {
if (!field.getDeclaredAnnotation(JsonProperty.class).access().equals(Access.READ_ONLY)) {
if (field.getName().equals(namedField)) {
int idx = 0;
MetadataValueRest obj = new MetadataValueRest();
for (MetadataValue mv : metadataByMetadataString) {
if (idx == index) {
obj.setAuthority(mv.getAuthority());
obj.setConfidence(mv.getConfidence());
obj.setLanguage(mv.getLanguage());
obj.setValue(mv.getValue());
if (field.getType().isAssignableFrom(Integer.class)) {
obj.setConfidence(Integer.parseInt(raw));
} else {
field.set(mv, raw);
}
break;
}
idx++;
}
replaceValue(context, b, split[1], metadataByMetadataString, obj, index);
}
}
}
} }
} }
} }

View File

@@ -0,0 +1,55 @@
/**
* 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.submit.factory.impl;
import java.util.List;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Item;
import org.dspace.content.WorkspaceItem;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.BundleService;
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.services.model.Request;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Submission "move" operation for ordering the Bitstream
*
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
*
*/
public class BitstreamMovePatchOperation extends MovePatchOperation<String>{
@Autowired
ItemService itemService;
@Autowired
BundleService bundleService;
@Override
protected Class<String[]> getArrayClassForEvaluation() {
return String[].class;
}
@Override
protected Class<String> getClassForEvaluation() {
return String.class;
}
@Override
void move(Context context, Request currentRequest, WorkspaceItem source, String path, String from)
throws Exception {
// TODO Auto-generated method stub
}
}

View File

@@ -39,13 +39,17 @@ public class BitstreamRemovePatchOperation extends RemovePatchOperation<String>{
void remove(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void remove(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
String absPath = getAbsolutePath(path);
String[] split = absPath.split("/");
int index = Integer.parseInt(split[1]);
Item item = source.getItem(); Item item = source.getItem();
List<Bundle> bbb = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME); List<Bundle> bbb = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
Bitstream bitstream = null; Bitstream bitstream = null;
external : for(Bundle bb : bbb) { external : for(Bundle bb : bbb) {
int idx = 0; int idx = 0;
for(Bitstream b : bb.getBitstreams()) { for(Bitstream b : bb.getBitstreams()) {
if(idx==Integer.parseInt(getAbsolutePath(path))) { if(idx==index) {
bitstream = b; bitstream = b;
break external; break external;
} }

View File

@@ -8,6 +8,7 @@
package org.dspace.app.rest.submit.factory.impl; package org.dspace.app.rest.submit.factory.impl;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.List; import java.util.List;
import org.dspace.app.rest.model.MetadataValueRest; import org.dspace.app.rest.model.MetadataValueRest;
@@ -70,42 +71,7 @@ public class ItemMetadataValueReplacePatchOperation extends MetadataValueReplace
replaceValue(context, source.getItem(), split[0], metadataByMetadataString, obj, index); replaceValue(context, source.getItem(), split[0], metadataByMetadataString, obj, index);
} else { } else {
if (split.length == 3) { if (split.length == 3) {
String namedField = split[2]; setDeclaredField(context, source.getItem(), value, split[0], split[2], metadataByMetadataString, index);
// check field
String raw = (String)value;
for (Field field : MetadataValueRest.class.getDeclaredFields()) {
JsonProperty jsonP = field.getDeclaredAnnotation(JsonProperty.class);
if (jsonP!=null && jsonP.access().equals(Access.READ_ONLY)) {
continue;
}
else {
if (field.getName().equals(namedField)) {
int idx = 0;
MetadataValueRest obj = new MetadataValueRest();
for (MetadataValue mv : metadataByMetadataString) {
if (idx == index) {
obj.setAuthority(mv.getAuthority());
obj.setConfidence(mv.getConfidence());
obj.setLanguage(mv.getLanguage());
obj.setValue(mv.getValue());
if (field.getType().isAssignableFrom(Integer.class)) {
obj.setConfidence(Integer.parseInt(raw));
} else {
boolean accessible = field.isAccessible();
field.setAccessible(true);
field.set(obj, raw);
field.setAccessible(accessible);
}
break;
}
idx++;
}
replaceValue(context, source.getItem(), split[0], metadataByMetadataString, obj, index);
}
}
}
} }
} }
} }

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.app.rest.submit.factory.impl; package org.dspace.app.rest.submit.factory.impl;
import org.apache.commons.lang.BooleanUtils;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.LicenseUtils; import org.dspace.content.LicenseUtils;
import org.dspace.content.WorkspaceItem; import org.dspace.content.WorkspaceItem;
@@ -19,15 +20,14 @@ import org.springframework.beans.factory.annotation.Autowired;
/** /**
* Submission "add" PATCH operation * Submission "add" PATCH operation
* *
* To accept a license the timestamp of the acceptance the client must send a * To accept/reject the license.
* JSON Patch ADD operation as follow.
* *
* Example: <code> * Example: <code>
* curl -X PATCH http://${dspace.url}/dspace-spring-rest/api/submission/workspaceitems/31599 -H "Content-Type: application/json" -d '[{ "op": "add", "path": "/sections/license/granted", "value":"true"}]' * curl -X PATCH http://${dspace.url}/dspace-spring-rest/api/submission/workspaceitems/31599 -H "Content-Type: application/json" -d '[{ "op": "add", "path": "/sections/license/granted", "value":"true"}]'
* </code> * </code>
* *
* Please note that according to the JSON Patch specification RFC6902 a * Please note that according to the JSON Patch specification RFC6902 a
* subsequent add operation on the acceptanceDate will have the effect to * subsequent add operation on the "granted" path will have the effect to
* replace the previous granted license with a new one. * replace the previous granted license with a new one.
* *
* *
@@ -52,6 +52,13 @@ public class LicenseAddPatchOperation extends AddPatchOperation<String> {
@Override @Override
void add(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void add(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
Boolean grant = BooleanUtils.toBooleanObject((String)value);
if(grant==null) {
throw new IllegalArgumentException("Value is not a valid boolean expression (permitted value: on/off, true/false and yes/no");
}
Item item = source.getItem(); Item item = source.getItem();
EPerson submitter = context.getCurrentUser(); EPerson submitter = context.getCurrentUser();
@@ -59,10 +66,12 @@ public class LicenseAddPatchOperation extends AddPatchOperation<String> {
// accepted it previously) // accepted it previously)
itemService.removeDSpaceLicense(context, item); itemService.removeDSpaceLicense(context, item);
if(grant) {
String license = LicenseUtils.getLicenseText(context.getCurrentLocale(), source.getCollection(), item, String license = LicenseUtils.getLicenseText(context.getCurrentLocale(), source.getCollection(), item,
submitter); submitter);
LicenseUtils.grantLicense(context, item, license, null); LicenseUtils.grantLicense(context, item, license, null);
} }
}
} }

View File

@@ -7,9 +7,7 @@
*/ */
package org.dspace.app.rest.submit.factory.impl; package org.dspace.app.rest.submit.factory.impl;
import java.util.List; import org.apache.commons.lang.BooleanUtils;
import org.dspace.content.Bundle;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.LicenseUtils; import org.dspace.content.LicenseUtils;
import org.dspace.content.WorkspaceItem; import org.dspace.content.WorkspaceItem;
@@ -18,18 +16,11 @@ import org.dspace.core.Context;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.services.model.Request; import org.dspace.services.model.Request;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
/** /**
* Submission "replace" patch operation * Submission "replace" patch operation
* *
* The replace operation allows to replace existent information with new one. * {@link LicenseAddPatchOperation}
* Attempt to use the replace operation without a previous accepted license must
* return an error.
*
* Example: <code>
* curl -X PATCH http://${dspace.url}/dspace-spring-rest/api/submission/workspaceitems/31599 -H "Content-Type: application/json" -d '[{ "op": "replace", "path": "/sections/license/granted", "value":"true"}]'
* </code>
* *
* @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it) * @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it)
* *
@@ -42,21 +33,27 @@ public class LicenseReplacePatchOperation extends ReplacePatchOperation<String>
@Override @Override
void replace(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void replace(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
Item item = source.getItem();
List<Bundle> bunds = itemService.getBundles(item, "LICENSE");
Assert.notEmpty(bunds);
Boolean grant = BooleanUtils.toBooleanObject((String)value);
if(grant==null) {
throw new IllegalArgumentException("Value is not a valid boolean expression (permitted value: on/off, true/false and yes/no");
}
Item item = source.getItem();
EPerson submitter = context.getCurrentUser(); EPerson submitter = context.getCurrentUser();
// remove any existing DSpace license (just in case the user // remove any existing DSpace license (just in case the user
// accepted it previously) // accepted it previously)
itemService.removeDSpaceLicense(context, item); itemService.removeDSpaceLicense(context, item);
if(grant) {
String license = LicenseUtils.getLicenseText(context.getCurrentLocale(), source.getCollection(), item, String license = LicenseUtils.getLicenseText(context.getCurrentLocale(), source.getCollection(), item,
submitter); submitter);
LicenseUtils.grantLicense(context, item, license, null); LicenseUtils.grantLicense(context, item, license, null);
} }
}
@Override @Override
protected Class<String[]> getArrayClassForEvaluation() { protected Class<String[]> getArrayClassForEvaluation() {

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.app.rest.submit.factory.impl; package org.dspace.app.rest.submit.factory.impl;
import java.lang.reflect.Field;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -18,6 +19,9 @@ import org.dspace.content.service.DSpaceObjectService;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.Utils; import org.dspace.core.Utils;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonProperty.Access;
/** /**
* Submission "replace" common PATCH operation. * Submission "replace" common PATCH operation.
* *
@@ -39,21 +43,49 @@ public abstract class MetadataValueReplacePatchOperation<DSO extends DSpaceObjec
protected void replaceValue(Context context, DSO source, String target, List<MetadataValue> list, MetadataValueRest object, int index) protected void replaceValue(Context context, DSO source, String target, List<MetadataValue> list, MetadataValueRest object, int index)
throws SQLException { throws SQLException {
String[] metadata = Utils.tokenize(target); String[] metadata = Utils.tokenize(target);
List<MetadataValue> values = new ArrayList<MetadataValue>(); getDSpaceObjectService().replaceMetadata(context, source, metadata[0], metadata[1], metadata[2],
int idx = 0;
for (MetadataValue ll : list) {
if(idx==index) {
values.add(ll);
}
idx++;
}
getDSpaceObjectService().removeMetadataValues(context, source, values);
getDSpaceObjectService().addAndShiftRightMetadata(context, source, metadata[0], metadata[1], metadata[2],
object.getLanguage(), object.getValue(), object.getAuthority(), object.getConfidence(), index); object.getLanguage(), object.getValue(), object.getAuthority(), object.getConfidence(), index);
} }
protected void setDeclaredField(Context context, DSO source, Object value, String metadata, String namedField,
List<MetadataValue> metadataByMetadataString, int index) throws IllegalAccessException, SQLException {
// check field
String raw = (String)value;
for (Field field : MetadataValueRest.class.getDeclaredFields()) {
JsonProperty jsonP = field.getDeclaredAnnotation(JsonProperty.class);
if (jsonP!=null && jsonP.access().equals(Access.READ_ONLY)) {
continue;
}
else {
if (field.getName().equals(namedField)) {
int idx = 0;
MetadataValueRest obj = new MetadataValueRest();
for (MetadataValue mv : metadataByMetadataString) {
if (idx == index) {
obj.setAuthority(mv.getAuthority());
obj.setConfidence(mv.getConfidence());
obj.setLanguage(mv.getLanguage());
obj.setValue(mv.getValue());
if (field.getType().isAssignableFrom(Integer.class)) {
obj.setConfidence(Integer.parseInt(raw));
} else {
boolean accessible = field.isAccessible();
field.setAccessible(true);
field.set(obj, raw);
field.setAccessible(accessible);
}
break;
}
idx++;
}
replaceValue(context, source, metadata, metadataByMetadataString, obj, index);
}
}
}
}
protected abstract DSpaceObjectService<DSO> getDSpaceObjectService(); protected abstract DSpaceObjectService<DSO> getDSpaceObjectService();
} }

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.app.rest.submit.factory.impl; package org.dspace.app.rest.submit.factory.impl;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@@ -54,6 +55,7 @@ public class ResourcePolicyAddPatchOperation extends AddPatchOperation<ResourceP
@Override @Override
void add(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void add(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
//"path": "/sections/upload/files/0/accessConditions"
String[] split = getAbsolutePath(path).split("/"); String[] split = getAbsolutePath(path).split("/");
Item item = source.getItem(); Item item = source.getItem();
@@ -62,8 +64,16 @@ public class ResourcePolicyAddPatchOperation extends AddPatchOperation<ResourceP
for (Bundle bb : bundle) { for (Bundle bb : bundle) {
int idx = 0; int idx = 0;
for (Bitstream b : bb.getBitstreams()) { for (Bitstream b : bb.getBitstreams()) {
if (idx == Integer.parseInt(split[0])) { if (idx == Integer.parseInt(split[1])) {
List<ResourcePolicyRest> newAccessConditions = evaluateArrayObject((LateObjectEvaluator) value);
List<ResourcePolicyRest> newAccessConditions = new ArrayList<ResourcePolicyRest>();
if (split.length == 3) {
newAccessConditions = evaluateArrayObject((LateObjectEvaluator) value);
} else if (split.length == 4) {
// contains "-", call index-based accessConditions it make not sense
newAccessConditions.add(evaluateSingleObject((LateObjectEvaluator)value));
}
for (ResourcePolicyRest newAccessCondition : newAccessConditions) { for (ResourcePolicyRest newAccessCondition : newAccessConditions) {
String name = newAccessCondition.getName(); String name = newAccessCondition.getName();
String description = newAccessCondition.getDescription(); String description = newAccessCondition.getDescription();

View File

@@ -20,6 +20,7 @@ import org.dspace.content.Item;
import org.dspace.content.MetadataValue; import org.dspace.content.MetadataValue;
import org.dspace.content.WorkspaceItem; import org.dspace.content.WorkspaceItem;
import org.dspace.content.factory.ContentServiceFactory; import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.BitstreamService;
import org.dspace.content.service.ItemService; import org.dspace.content.service.ItemService;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
@@ -40,43 +41,50 @@ public class ResourcePolicyRemovePatchOperation extends RemovePatchOperation<Res
@Autowired @Autowired
ResourcePolicyService resourcePolicyService; ResourcePolicyService resourcePolicyService;
@Autowired
BitstreamService bitstreamService;
@Override @Override
void remove(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void remove(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
// "path" : "/sections/upload/files/0/accessConditions/0"
// "abspath" : "/files/0/accessConditions/0"
String[] split = getAbsolutePath(path).split("/"); String[] split = getAbsolutePath(path).split("/");
String bitstreamIdx = split[0]; String bitstreamIdx = split[1];
String rpIdx = split[2];
Item item = source.getItem(); Item item = source.getItem();
List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME); List<Bundle> bundle = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME);
Bitstream bitstream = null;
ResourcePolicy dpolicy = null;
for (Bundle bb : bundle) { for (Bundle bb : bundle) {
int idx = 0; int idx = 0;
for (Bitstream b : bb.getBitstreams()) { for (Bitstream b : bb.getBitstreams()) {
if (idx == Integer.parseInt(bitstreamIdx)) { if (idx == Integer.parseInt(bitstreamIdx)) {
List<ResourcePolicy> policies = resourcePolicyService.find(context, b, ResourcePolicy.TYPE_CUSTOM); if (split.length == 3) {
resourcePolicyService.removePolicies(context, b,
ResourcePolicy.TYPE_CUSTOM);
} else {
String rpIdx = split[3];
List<ResourcePolicy> policies = resourcePolicyService.find(context, b,
ResourcePolicy.TYPE_CUSTOM);
int index = 0; int index = 0;
for(ResourcePolicy policy : policies) { for (ResourcePolicy policy : policies) {
Integer toDelete = Integer.parseInt(rpIdx); Integer toDelete = Integer.parseInt(rpIdx);
if(index == toDelete) { if (index == toDelete) {
dpolicy = policy;
b.getResourcePolicies().remove(policy); b.getResourcePolicies().remove(policy);
bitstream = b;
break; break;
} }
index++; index++;
} }
} }
}
idx++; idx++;
} }
} }
if(bitstream != null) {
if(dpolicy!=null) { bitstreamService.update(context, bitstream);
resourcePolicyService.delete(context, dpolicy);
} }
} }
@Override @Override

View File

@@ -13,6 +13,7 @@ import java.util.List;
import org.dspace.app.rest.model.ResourcePolicyRest; import org.dspace.app.rest.model.ResourcePolicyRest;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.authorize.service.AuthorizeService; import org.dspace.authorize.service.AuthorizeService;
import org.dspace.authorize.service.ResourcePolicyService;
import org.dspace.content.Bitstream; import org.dspace.content.Bitstream;
import org.dspace.content.Bundle; import org.dspace.content.Bundle;
import org.dspace.content.Item; import org.dspace.content.Item;
@@ -45,6 +46,8 @@ public class ResourcePolicyReplacePatchOperation extends ReplacePatchOperation<R
@Autowired @Autowired
AuthorizeService authorizeService; AuthorizeService authorizeService;
@Autowired
ResourcePolicyService resourcePolicyService;
@Autowired @Autowired
GroupService groupService; GroupService groupService;
@@ -54,6 +57,8 @@ public class ResourcePolicyReplacePatchOperation extends ReplacePatchOperation<R
@Override @Override
void replace(Context context, Request currentRequest, WorkspaceItem source, String path, Object value) void replace(Context context, Request currentRequest, WorkspaceItem source, String path, Object value)
throws Exception { throws Exception {
// "path": "/sections/upload/files/0/accessConditions/0"
// "abspath": "/files/0/accessConditions/0"
String[] split = getAbsolutePath(path).split("/"); String[] split = getAbsolutePath(path).split("/");
Item item = source.getItem(); Item item = source.getItem();
@@ -62,21 +67,45 @@ public class ResourcePolicyReplacePatchOperation extends ReplacePatchOperation<R
for (Bundle bb : bundle) { for (Bundle bb : bundle) {
int idx = 0; int idx = 0;
for (Bitstream b : bb.getBitstreams()) { for (Bitstream b : bb.getBitstreams()) {
if (idx == Integer.parseInt(split[0])) { if (idx == Integer.parseInt(split[1])) {
authorizeService.removeAllPolicies(context, b); List<ResourcePolicy> policies = authorizeService.findPoliciesByDSOAndType(context, b,
List<ResourcePolicyRest> newAccessConditions = evaluateArrayObject((LateObjectEvaluator) value); ResourcePolicy.TYPE_CUSTOM);
for (ResourcePolicyRest newAccessCondition : newAccessConditions) { String rpIdx = split[3];
int index = 0;
for (ResourcePolicy policy : policies) {
Integer toReplace = Integer.parseInt(rpIdx);
if (index == toReplace) {
b.getResourcePolicies().remove(policy);
break;
}
index++;
}
if (split.length == 4) {
ResourcePolicyRest newAccessCondition = evaluateSingleObject((LateObjectEvaluator) value);
String name = newAccessCondition.getName(); String name = newAccessCondition.getName();
String description = newAccessCondition.getDescription(); String description = newAccessCondition.getDescription();
//TODO manage error on select group and eperson //TODO manage error on select group and eperson
Group group = groupService.find(context, newAccessCondition.getGroupUUID()); Group group = null;
EPerson eperson = epersonService.find(context, newAccessCondition.getEpersonUUID()); if(newAccessCondition.getGroupUUID()!=null) {
group = groupService.find(context, newAccessCondition.getGroupUUID());
}
EPerson eperson = null;
if(newAccessCondition.getEpersonUUID()!=null) {
eperson = epersonService.find(context, newAccessCondition.getEpersonUUID());
}
Date startDate = newAccessCondition.getStartDate(); Date startDate = newAccessCondition.getStartDate();
Date endDate = newAccessCondition.getEndDate(); Date endDate = newAccessCondition.getEndDate();
authorizeService.createResourcePolicy(context, b, group, eperson, Constants.READ, ResourcePolicy.TYPE_CUSTOM, name, description, startDate, endDate); authorizeService.createResourcePolicy(context, b, group, eperson, Constants.READ,
ResourcePolicy.TYPE_CUSTOM, name, description, startDate, endDate);
// TODO manage duplicate policy // TODO manage duplicate policy
} else {
// "path":
// "/sections/upload/files/0/accessConditions/0/startDate"
// TODO
} }
} }
idx++; idx++;

View File

@@ -40,6 +40,7 @@ public class LicenseStep extends org.dspace.submit.step.LicenseStep implements A
String acceptanceDate = bitstreamService.getMetadata(bitstream, DCTERMS_RIGHTSDATE); String acceptanceDate = bitstreamService.getMetadata(bitstream, DCTERMS_RIGHTSDATE);
result.setAcceptanceDate(acceptanceDate); result.setAcceptanceDate(acceptanceDate);
result.setUrl(configurationService.getProperty("dspace.url")+"/api/"+BitstreamRest.CATEGORY +"/"+ English.plural(BitstreamRest.NAME) + "/" + bitstream.getID() + "/content"); result.setUrl(configurationService.getProperty("dspace.url")+"/api/"+BitstreamRest.CATEGORY +"/"+ English.plural(BitstreamRest.NAME) + "/" + bitstream.getID() + "/content");
result.setGranted(true);
} }
return result; return result;
} }

View File

@@ -53,8 +53,24 @@ public class UploadStep extends org.dspace.submit.step.UploadStep implements Abs
String instance = ""; String instance = "";
if("remove".equals(op.getOp())) { if("remove".equals(op.getOp())) {
if(op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
}
else if(op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) {
instance = UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY;
}
else {
instance = UPLOAD_STEP_REMOVE_OPERATION_ENTRY; instance = UPLOAD_STEP_REMOVE_OPERATION_ENTRY;
} }
}
else if("move".equals(op.getOp())) {
if(op.getPath().contains(UPLOAD_STEP_METADATA_PATH)) {
instance = UPLOAD_STEP_METADATA_OPERATION_ENTRY;
}
else {
instance = UPLOAD_STEP_MOVE_OPERATION_ENTRY;
}
}
else { else {
if(op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) { if(op.getPath().contains(UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY)) {
instance = UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY; instance = UPLOAD_STEP_ACCESSCONDITIONS_OPERATION_ENTRY;

View File

@@ -30,6 +30,10 @@
<bean <bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueMovePatchOperation" /> class="org.dspace.app.rest.submit.factory.impl.BitstreamMetadataValueMovePatchOperation" />
</entry> </entry>
<entry key="bitstreammove">
<bean
class="org.dspace.app.rest.submit.factory.impl.BitstreamMovePatchOperation" />
</entry>
</map> </map>
</entry> </entry>
<entry key="add"> <entry key="add">