diff --git a/src/main/java/de/mpg/imeji/j2j/transaction/CRUDTransaction.java b/src/main/java/de/mpg/imeji/j2j/transaction/CRUDTransaction.java index 8320a7140..a71e102fa 100644 --- a/src/main/java/de/mpg/imeji/j2j/transaction/CRUDTransaction.java +++ b/src/main/java/de/mpg/imeji/j2j/transaction/CRUDTransaction.java @@ -3,11 +3,17 @@ import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang3.NotImplementedException; import org.apache.jena.query.Dataset; import org.apache.jena.query.ReadWrite; import de.mpg.imeji.exceptions.ImejiException; +import de.mpg.imeji.exceptions.NotFoundException; +import de.mpg.imeji.exceptions.WorkflowException; import de.mpg.imeji.j2j.controler.ResourceController; +import de.mpg.imeji.logic.model.Properties; +import de.mpg.imeji.logic.model.aspects.CloneURI; +import de.mpg.imeji.logic.workflow.WorkflowValidator; /** * {@link Transaction} for CRUD methods @@ -51,6 +57,7 @@ public CRUDTransaction(List objects, CRUDTransactionType type, String mo protected void execute(Dataset ds) throws ImejiException { final ResourceController rc = new ResourceController(getModel(ds), lazy); for (final Object o : objects) { + checkObjectStatus(rc, o); invokeResourceController(rc, o); } } @@ -59,6 +66,62 @@ public List getResults() { return this.results; } + /** + * For data objects that have a status (i.e. Item or CollectionImeji) check whether the status + * allows proceeding with a create, update or delete operation. + * + * @param object + * @throws NotFoundException + * @throws WorkflowException + */ + private void checkObjectStatus(ResourceController resourceController, Object object) throws NotFoundException, WorkflowException { + + if (object instanceof Properties) { + + if (this.type == CRUDTransactionType.CREATE || this.type == CRUDTransactionType.UPDATE || this.type == CRUDTransactionType.DELETE) { + // check status of database object and not client object + Object databaseObject = getCorrespondingObjectInDatabase(object, resourceController); + WorkflowValidator workflowManager = new WorkflowValidator(); + switch (this.type) { + case CREATE: + workflowManager.isCreateAllowed((Properties) databaseObject); + break; + case DELETE: + workflowManager.isDeleteAllowed((Properties) databaseObject); + break; + case UPDATE: + workflowManager.isUpdateAllowed((Properties) databaseObject); + break; + default: + // error + } + } + } + } + + /** + * Given a data object that has been manipulated by a client, read the corresponding data object + * from database. Useful in order to determine if database object has changed since it was last + * read by the client. + * + * @param clientImejiDataObject + * @param resourceController + * @return + * @throws NotFoundException + */ + private Object getCorrespondingObjectInDatabase(Object clientImejiDataObject, ResourceController resourceController) + throws NotFoundException { + + if (clientImejiDataObject instanceof CloneURI) { + Object currentObjectInJena = resourceController.read(((CloneURI) clientImejiDataObject).cloneURI()); + return currentObjectInJena; + } else { + throw new NotImplementedException("Could not process update request, interface CloneURI not implemented but should be in class " + + clientImejiDataObject.getClass()); + } + } + + /** * Make the CRUD operation for one {@link Object} thanks to the {@link ResourceController} @@ -88,6 +151,7 @@ private void invokeResourceController(ResourceController rc, Object o) throws Im } } + @Override protected ReadWrite getLockType() { switch (type) { diff --git a/src/main/java/de/mpg/imeji/logic/db/writer/WriterFacade.java b/src/main/java/de/mpg/imeji/logic/db/writer/WriterFacade.java index c9904f17c..58c360443 100644 --- a/src/main/java/de/mpg/imeji/logic/db/writer/WriterFacade.java +++ b/src/main/java/de/mpg/imeji/logic/db/writer/WriterFacade.java @@ -24,7 +24,6 @@ import de.mpg.imeji.exceptions.SearchIndexBulkFailureException; import de.mpg.imeji.exceptions.SearchIndexFailureException; import de.mpg.imeji.exceptions.UnprocessableError; -import de.mpg.imeji.exceptions.WorkflowException; import de.mpg.imeji.logic.config.Imeji; import de.mpg.imeji.logic.db.indexretry.RetryIndex; import de.mpg.imeji.logic.db.indexretry.model.RetryBaseRequest; @@ -34,7 +33,6 @@ import de.mpg.imeji.logic.model.CollectionImeji; import de.mpg.imeji.logic.model.ContentVO; import de.mpg.imeji.logic.model.Item; -import de.mpg.imeji.logic.model.Properties; import de.mpg.imeji.logic.model.Subscription; import de.mpg.imeji.logic.model.User; import de.mpg.imeji.logic.model.UserGroup; @@ -48,7 +46,6 @@ import de.mpg.imeji.logic.util.ObjectsHelper; import de.mpg.imeji.logic.validation.ValidatorFactory; import de.mpg.imeji.logic.validation.impl.Validator; -import de.mpg.imeji.logic.workflow.WorkflowValidator; /** * Facade implementing Writer {@link Authorization} @@ -62,7 +59,6 @@ public class WriterFacade { private static final Logger LOGGER = LogManager.getLogger(WriterFacade.class); private final Writer writer; private final SearchIndexer indexer; - private final WorkflowValidator workflowManager = new WorkflowValidator(); private final ExecutorService executor = Executors.newCachedThreadPool(); /** @@ -114,7 +110,6 @@ public List create(List objects, User user) throws ImejiExceptio if (objects.isEmpty()) { return objects; } - checkWorkflow(objects, "create"); checkSecurity(objects, user, true); validate(objects, Validator.Method.CREATE); List createdObjects = writeAndIndex(new CreateTask(objects, user), new IndexTask()); @@ -132,7 +127,6 @@ public void delete(List objects, User user) throws ImejiException { if (objects.isEmpty()) { return; } - checkWorkflow(objects, "delete"); checkSecurity(objects, user, false); validate(objects, Validator.Method.DELETE); writeAndIndex(new DeleteTask(objects, user), new DeleteIndexTask()); @@ -149,7 +143,6 @@ public List update(List objects, final User user, boolean doChec if (objects.isEmpty()) { return objects; } - checkWorkflow(objects, "update"); if (doCheckSecurity) { checkSecurity(objects, user, false); } @@ -192,7 +185,6 @@ public Object changeElement(ChangeMember changeMember, User user) throws ImejiEx } List imejiDataObjectList = Arrays.asList(changeMember.getImejiDataObject()); - checkWorkflow(imejiDataObjectList, "update"); checkSecurity(imejiDataObjectList, user, true); Object valueToSet = changeMember.getValue(); validate(valueToSet, Validator.Method.UPDATE); @@ -216,7 +208,6 @@ public List editElements(List changeElements, User user) t List imejiDataObjectList = changeElements.stream().map(dataObject -> dataObject.getImejiDataObject()).collect(Collectors.toList()); - checkWorkflow(imejiDataObjectList, "update"); checkSecurity(imejiDataObjectList, user, true); for (ChangeMember changeMember : changeElements) { Object valueToSet = changeMember.getValue(); @@ -317,7 +308,6 @@ private List writeToDatabase(Callable> databaseTask) throws throw new ImejiException(execExept.getMessage()); } } - return objectsInDatabase; } @@ -428,25 +418,6 @@ private void validate(Object object, Validator.Method method) throws Unprocessab validator.validate(object, method); } - private void checkWorkflow(List objects, String operation) throws WorkflowException { - - for (final Object o : objects) { - if (o instanceof Properties) { - switch (operation) { - case "create": - workflowManager.isCreateAllowed((Properties) o); - break; - case "delete": - workflowManager.isDeleteAllowed((Properties) o); - break; - case "update": - workflowManager.isUpdateAllowed((Properties) o); - break; - } - } - } - } - /** * Check {@link Security} for WRITE operations *