mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-17 06:53:09 +00:00
64640: Move PATCH request for bitstreams in bundles
This commit is contained in:
@@ -268,6 +268,30 @@ public class BundleServiceImpl extends DSpaceObjectServiceImpl<Bundle> implement
|
|||||||
return authorizeService.getPolicies(context, bundle);
|
return authorizeService.getPolicies(context, bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveBitstream(Context context, Bundle bundle, int from, int to)
|
||||||
|
throws AuthorizeException, SQLException {
|
||||||
|
List<Bitstream> bitstreams = bundle.getBitstreams();
|
||||||
|
if (bitstreams.size() < 1 || from >= bitstreams.size() || to >= bitstreams.size() || from < 0 || to < 0) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalid 'from' and 'to' arguments supplied for moving a bitstream within bundle " +
|
||||||
|
bundle.getID() + ". from: " + from + "; to: " + to
|
||||||
|
);
|
||||||
|
}
|
||||||
|
List<UUID> bitstreamIds = new LinkedList<>();
|
||||||
|
for (Bitstream bitstream : bitstreams) {
|
||||||
|
bitstreamIds.add(bitstream.getID());
|
||||||
|
}
|
||||||
|
if (from < to) {
|
||||||
|
bitstreamIds.add(to + 1, bitstreamIds.get(from));
|
||||||
|
bitstreamIds.remove(from);
|
||||||
|
} else {
|
||||||
|
bitstreamIds.add(to, bitstreamIds.get(from));
|
||||||
|
bitstreamIds.remove(from + 1);
|
||||||
|
}
|
||||||
|
setOrder(context, bundle, bitstreamIds.toArray(new UUID[bitstreamIds.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOrder(Context context, Bundle bundle, UUID[] bitstreamIds) throws AuthorizeException, SQLException {
|
public void setOrder(Context context, Bundle bundle, UUID[] bitstreamIds) throws AuthorizeException, SQLException {
|
||||||
authorizeService.authorizeAction(context, bundle, Constants.WRITE);
|
authorizeService.authorizeAction(context, bundle, Constants.WRITE);
|
||||||
|
@@ -109,6 +109,18 @@ public interface BundleService extends DSpaceObjectService<Bundle>, DSpaceObject
|
|||||||
|
|
||||||
public List<ResourcePolicy> getBundlePolicies(Context context, Bundle bundle) throws SQLException;
|
public List<ResourcePolicy> getBundlePolicies(Context context, Bundle bundle) throws SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves a bitstream within a bundle from one place to another, shifting all other bitstreams in the process
|
||||||
|
*
|
||||||
|
* @param context DSpace Context
|
||||||
|
* @param bundle The bitstream bundle
|
||||||
|
* @param from The index of the bitstream to move
|
||||||
|
* @param to The index to move the bitstream to
|
||||||
|
* @throws AuthorizeException when an SQL error has occurred (querying DSpace)
|
||||||
|
* @throws SQLException If the user can't make the changes
|
||||||
|
*/
|
||||||
|
public void moveBitstream(Context context, Bundle bundle, int from, int to) throws AuthorizeException, SQLException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes bitstream order according to the array
|
* Changes bitstream order according to the array
|
||||||
*
|
*
|
||||||
|
@@ -10,11 +10,16 @@ package org.dspace.app.rest.repository;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.dspace.app.rest.converter.BundleConverter;
|
import org.dspace.app.rest.converter.BundleConverter;
|
||||||
import org.dspace.app.rest.model.BundleRest;
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
import org.dspace.app.rest.model.hateoas.BundleResource;
|
import org.dspace.app.rest.model.hateoas.BundleResource;
|
||||||
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
||||||
|
import org.dspace.app.rest.model.patch.Patch;
|
||||||
|
import org.dspace.app.rest.repository.patch.BundlePatch;
|
||||||
import org.dspace.app.rest.repository.patch.DSpaceObjectPatch;
|
import org.dspace.app.rest.repository.patch.DSpaceObjectPatch;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
import org.dspace.content.Bundle;
|
import org.dspace.content.Bundle;
|
||||||
import org.dspace.content.service.BundleService;
|
import org.dspace.content.service.BundleService;
|
||||||
import org.dspace.core.Context;
|
import org.dspace.core.Context;
|
||||||
@@ -36,9 +41,13 @@ public class BundleRestRepository extends DSpaceObjectRestRepository<Bundle, Bun
|
|||||||
@Autowired
|
@Autowired
|
||||||
private BundleService bundleService;
|
private BundleService bundleService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BundlePatch bundlePatch;
|
||||||
|
|
||||||
public BundleRestRepository(BundleService dsoService,
|
public BundleRestRepository(BundleService dsoService,
|
||||||
BundleConverter dsoConverter) {
|
BundleConverter dsoConverter,
|
||||||
super(dsoService, dsoConverter, new DSpaceObjectPatch<BundleRest>() {});
|
BundlePatch dsoPatch) {
|
||||||
|
super(dsoService, dsoConverter, dsoPatch);
|
||||||
this.bundleService = dsoService;
|
this.bundleService = dsoService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +69,13 @@ public class BundleRestRepository extends DSpaceObjectRestRepository<Bundle, Bun
|
|||||||
throw new RuntimeException("Method not allowed!");
|
throw new RuntimeException("Method not allowed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@PreAuthorize("hasPermission(#uuid, 'BUNDLE', 'WRITE')")
|
||||||
|
protected void patch(Context context, HttpServletRequest request, String apiCategory, String model, UUID uuid,
|
||||||
|
Patch patch) throws AuthorizeException, SQLException {
|
||||||
|
patchDSpaceObject(apiCategory, model, uuid, patch);
|
||||||
|
}
|
||||||
|
|
||||||
public Class<BundleRest> getDomainClass() {
|
public Class<BundleRest> getDomainClass() {
|
||||||
return BundleRest.class;
|
return BundleRest.class;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
package org.dspace.app.rest.repository.patch;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
|
import org.dspace.app.rest.repository.patch.factories.BundleOperationFactory;
|
||||||
|
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePatchOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by kristof on 24/09/2019
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BundlePatch extends DSpaceObjectPatch<BundleRest> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
BundleOperationFactory patchFactory;
|
||||||
|
|
||||||
|
protected BundleRest move(BundleRest restModel, Operation operation) {
|
||||||
|
ResourcePatchOperation<BundleRest> patchOperation = patchFactory.getMoveOperation();
|
||||||
|
return patchOperation.perform(restModel, operation);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
package org.dspace.app.rest.repository.patch.factories;
|
||||||
|
|
||||||
|
import org.dspace.app.rest.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.repository.patch.factories.impl.BundleMoveOperation;
|
||||||
|
import org.dspace.app.rest.repository.patch.factories.impl.ResourcePatchOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by kristof on 24/09/2019
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BundleOperationFactory {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
BundleMoveOperation bundleMoveOperation;
|
||||||
|
|
||||||
|
public ResourcePatchOperation<BundleRest> getMoveOperation() {
|
||||||
|
return bundleMoveOperation;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,68 @@
|
|||||||
|
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.model.BundleRest;
|
||||||
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
|
import org.dspace.app.rest.utils.ContextUtil;
|
||||||
|
import org.dspace.authorize.AuthorizeException;
|
||||||
|
import org.dspace.content.Bundle;
|
||||||
|
import org.dspace.content.service.BundleService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.services.RequestService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by kristof on 24/09/2019
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BundleMoveOperation extends MovePatchOperation<BundleRest, Integer> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
BundleService bundleService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RequestService requestService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BundleRest move(BundleRest resource, Operation operation) {
|
||||||
|
Context context = ContextUtil.obtainContext(requestService.getCurrentRequest().getServletRequest());
|
||||||
|
try {
|
||||||
|
Bundle bundle = bundleService.findByIdOrLegacyId(context, resource.getId());
|
||||||
|
int totalAmount = bundle.getBitstreams().size();
|
||||||
|
|
||||||
|
if(totalAmount < 1) {
|
||||||
|
throw new DSpaceBadRequestException(createMoveExceptionMessage(bundle, from, to, "No sub-communities found."));
|
||||||
|
}
|
||||||
|
if(from >= totalAmount) {
|
||||||
|
throw new DSpaceBadRequestException(createMoveExceptionMessage(bundle, from, to, "\"from\" location out of bounds. Latest available position: " + (totalAmount-1)));
|
||||||
|
}
|
||||||
|
if(to >= totalAmount) {
|
||||||
|
throw new DSpaceBadRequestException(createMoveExceptionMessage(bundle, from, to, "\"to\" location out of bounds. Latest available position: " + (totalAmount-1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
bundleService.moveBitstream(context, bundle, from, to);
|
||||||
|
} catch (SQLException | AuthorizeException e) {
|
||||||
|
throw new DSpaceBadRequestException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<Integer[]> getArrayClassForEvaluation() {
|
||||||
|
return Integer[].class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<Integer> getClassForEvaluation() {
|
||||||
|
return Integer.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createMoveExceptionMessage(Bundle bundle, int from, int to, String message) {
|
||||||
|
return "Failed moving bitstreams of bundle with id " + bundle.getID() + " from location " + from + " to " + to + ": " + message;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,57 @@
|
|||||||
|
package org.dspace.app.rest.repository.patch.factories.impl;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||||
|
import org.dspace.app.rest.model.RestModel;
|
||||||
|
import org.dspace.app.rest.model.patch.MoveOperation;
|
||||||
|
import org.dspace.app.rest.model.patch.Operation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by kristof on 24/09/2019
|
||||||
|
*/
|
||||||
|
public abstract class MovePatchOperation<R extends RestModel, T> extends PatchOperation<R, T> {
|
||||||
|
|
||||||
|
protected int from;
|
||||||
|
protected int to;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public R perform(R resource, Operation operation) {
|
||||||
|
checkMoveOperation(operation);
|
||||||
|
return move(resource, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract R move(R resource, Operation operation);
|
||||||
|
|
||||||
|
private void checkMoveOperation(Operation operation) {
|
||||||
|
if(!(operation instanceof MoveOperation)) {
|
||||||
|
throw new DSpaceBadRequestException("Expected a MoveOperation, but received " + operation.getClass().getName() + " instead.");
|
||||||
|
}
|
||||||
|
from = getLocationFromPath(((MoveOperation)operation).getFrom());
|
||||||
|
to = getLocationFromPath(operation.getPath());
|
||||||
|
if(from == to) {
|
||||||
|
throw new DSpaceBadRequestException("The \"from\" location must be different from the \"to\" location.");
|
||||||
|
}
|
||||||
|
if(from < 0) {
|
||||||
|
throw new DSpaceBadRequestException("A negative \"from\" location was provided: " + from);
|
||||||
|
}
|
||||||
|
if(to < 0) {
|
||||||
|
throw new DSpaceBadRequestException("A negative \"to\" location was provided: " + to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getLocationFromPath(String path) {
|
||||||
|
String[] parts = StringUtils.split(path, "/");
|
||||||
|
String locationStr;
|
||||||
|
if(parts.length > 1) {
|
||||||
|
if(StringUtils.equals(parts[parts.length-1], "href")) {
|
||||||
|
locationStr = parts[parts.length-2];
|
||||||
|
} else {
|
||||||
|
locationStr = parts[parts.length-1];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
locationStr = parts[0];
|
||||||
|
}
|
||||||
|
return Integer.parseInt(locationStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user