From a10323735ddf42c87df61975c8ad72d09b9b627a Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Mon, 25 Jan 2021 17:38:19 +0100 Subject: [PATCH] Implementing #20530 #20531 --- .../contexts/entities/ContextManagement.java | 5 +- .../relations/IsParentOfManagement.java | 7 +- .../instances/base/ElementManagement.java | 121 ++++++++-- .../model/entities/EntityManagement.java | 28 ++- .../model/relations/RelationManagement.java | 53 +++-- .../resourceregistry/rest/SharingManager.java | 223 +++++++++--------- .../EntityTypeDefinitionManagement.java | 6 +- .../PropertyTypeDefinitionManagement.java | 6 +- .../RelationTypeDefinitionManagement.java | 7 +- .../model/entity/FacetManagementTest.java | 20 +- .../instances/multicontext/BasicTest.java | 12 +- 11 files changed, 317 insertions(+), 171 deletions(-) diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java index 55e7cfd..c38de28 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/entities/ContextManagement.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.UUID; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; @@ -432,13 +433,13 @@ public class ContextManagement extends EntityElementManagement { } @Override - protected boolean reallyAddToContext(SecurityContext targetSecurityContext) + protected Map reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/relations/IsParentOfManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/relations/IsParentOfManagement.java index 437714b..6e670f8 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/relations/IsParentOfManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/contexts/relations/IsParentOfManagement.java @@ -1,5 +1,8 @@ package org.gcube.informationsystem.resourceregistry.contexts.relations; +import java.util.Map; +import java.util.UUID; + import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode; import org.gcube.informationsystem.base.reference.AccessType; @@ -101,13 +104,13 @@ public class IsParentOfManagement extends RelationElementManagement reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java index 9f795fb..59c3e33 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/ElementManagement.java @@ -87,6 +87,69 @@ public abstract class ElementManagement { protected El element; protected boolean reload; + /** + * By the default the system execute the the operation of + * context sharing so this variable is initialised as false. + * + * Setting this variable to false the system just simulate + * the operation of context sharing + * i.e. AddToContext, RemoveFromContext. + * + * This option can also be used in conjunction with + * {@link ElementManagement#honourPropagationConstraintsInContextSharing}=false. + * This allow to simulate a sharing operation which requires + * do not honour the propagation constraints. + */ + protected boolean dryRunContextSharing; + + /** + * By the default the system honour the propagation constraints + * so this variable is initialised as true. + * + * To revert a previous operation or for particular a maintenance + * we could request to the service do not honour the propagation + * constraints but under certain conditions and with some limitation + * only. + * These limitation are required to keep the system in a consistent + * state. + * In fact, this directive is only valid for Resources and IsRelatedTo + * relations. We need to take in account that to add an + * IsRelatedTo to a context always the source and target + * Resources must be in such a Context. + * Please also take into account that adding a Resource + * to a context always imply to honour the propagation constraints + * of ConsistsOf relations. In fact, a resource must be characterised + * least by one facet in any context it belongs. Giving that we + * cannot made assumption on which facets must be used. + * A way could be to consider just the facets are mandatory for such a + * Resource Type, but the type could not have mandatory facets + * (even every Resource Type in the gCube Model has one mandatory facet). + * As counterpart, when a Resource is removed from a Context all the facets + * charactering it must be removed. + * + * This option can also be used in conjunction with + * {@link ElementManagement#dryRunContextSharing}=true. + * This allow to simulate a sharing operation which requires + * do not honour the propagation constraints. + */ + protected boolean honourPropagationConstraintsInContextSharing; + + public boolean isDryRunContextSharing() { + return dryRunContextSharing; + } + + public void setDryRunContextSharing(boolean dryRunContextSharing) { + this.dryRunContextSharing = dryRunContextSharing; + } + + public boolean isHonourPropagationConstraintsInContextSharing() { + return honourPropagationConstraintsInContextSharing; + } + + public void setHonourPropagationConstraintsInContextSharing(boolean honourPropagationConstraintsInContextSharing) { + this.honourPropagationConstraintsInContextSharing = honourPropagationConstraintsInContextSharing; + } + public UUID getUUID() { return uuid; } @@ -128,6 +191,19 @@ public abstract class ElementManagement { this.reload = false; + + /* + * By the default the system execute the the operation of + * context sharing so this variable is initialised as false. + */ + this.dryRunContextSharing = false; + + /* + * By the default the system honour the propagation constraints + * so this variable is initialised as true. + */ + this.honourPropagationConstraintsInContextSharing = true; + } public void setUUID(UUID uuid) throws ResourceRegistryException { @@ -327,16 +403,19 @@ public abstract class ElementManagement { return reallyDelete(); } - protected abstract boolean reallyAddToContext(SecurityContext targetSecurityContext) + protected abstract Map reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException; - public boolean internalAddToContext(SecurityContext targetSecurityContext) + public Map internalAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { try { - boolean ret = reallyAddToContext(targetSecurityContext); - HeaderUtility.updateModifiedByAndLastUpdate(element); - element.save(); - return ret && true; + Map affectedInstances = reallyAddToContext(targetSecurityContext); + if(!dryRunContextSharing) { + HeaderUtility.updateModifiedByAndLastUpdate(element); + element.save(); + } + affectedInstances.put(uuid, serializeSelfOnly()); + return affectedInstances; } catch(ResourceRegistryException e) { throw e; } catch(Exception e) { @@ -345,16 +424,19 @@ public abstract class ElementManagement { } } - protected abstract boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected abstract Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException; - public boolean internalRemoveFromContext(SecurityContext targetSecurityContext) + public Map internalRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { try { - boolean ret = reallyRemoveFromContext(targetSecurityContext); - HeaderUtility.updateModifiedByAndLastUpdate(element); - element.save(); - return ret && true; + Map affectedInstances = reallyRemoveFromContext(targetSecurityContext); + if(!dryRunContextSharing) { + HeaderUtility.updateModifiedByAndLastUpdate(element); + element.save(); + } + affectedInstances.put(uuid, serializeSelfOnly()); + return affectedInstances; } catch(ResourceRegistryException e) { throw e; } catch(Exception e) { @@ -681,7 +763,7 @@ public abstract class ElementManagement { } } - public boolean addToContext(UUID contextUUID) + public Map addToContext(UUID contextUUID) throws NotFoundException, ContextException, ResourceRegistryException { logger.info("Going to add {} with UUID {} to Context with UUID {}", accessType.getName(), uuid, contextUUID); ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); @@ -691,12 +773,12 @@ public abstract class ElementManagement { SecurityContext targetSecurityContext = ContextUtility.getInstance().getSecurityContextByUUID(contextUUID); - boolean added = internalAddToContext(targetSecurityContext); + Map affecteElements = internalAddToContext(targetSecurityContext); oDatabaseDocument.commit(); logger.info("{} with UUID {} successfully added to Context with UUID {}", elementType, uuid, contextUUID); - return added; + return affecteElements; } catch(ResourceRegistryException e) { logger.error("Unable to add {} with UUID {} to Context with UUID {}", elementType, uuid, contextUUID); if(oDatabaseDocument != null) { @@ -720,7 +802,7 @@ public abstract class ElementManagement { } } - public boolean removeFromContext(UUID contextUUID) + public Map removeFromContext(UUID contextUUID) throws NotFoundException, ContextException, ResourceRegistryException { logger.debug("Going to remove {} with UUID {} from Context with UUID {}", elementType, uuid, contextUUID); ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal(); @@ -730,13 +812,12 @@ public abstract class ElementManagement { SecurityContext targetSecurityContext = ContextUtility.getInstance().getSecurityContextByUUID(contextUUID); - boolean removed = internalRemoveFromContext(targetSecurityContext); + Map affecteElements = internalRemoveFromContext(targetSecurityContext); oDatabaseDocument.commit(); - logger.info("{} with UUID {} successfully removed from Context with UUID {}", elementType, uuid, - contextUUID); + logger.info("{} with UUID {} successfully removed from Context with UUID {}", elementType, uuid, contextUUID); - return removed; + return affecteElements; } catch(ResourceRegistryException e) { logger.error("Unable to remove {} with UUID {} from Context with UUID {}", elementType, uuid, contextUUID); if(oDatabaseDocument != null) { diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java index 9afa86c..e095d1c 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/entities/EntityManagement.java @@ -191,37 +191,53 @@ public abstract class EntityManagement extends EntityEl } @Override - protected boolean reallyAddToContext(SecurityContext targetSecurityContext) + protected Map reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { + Map affectedInstances = new HashMap<>(); + targetSecurityContext.addElement(getElement(), oDatabaseDocument); + /* + * DO NOT UNCOMMENT + * the instance is added internalAddToContext() function after + * the update of Header metadata i.e. modifiedBy, lastUpdateTime + * affectedInstances.put(uuid, serializeSelfOnly()); + */ Iterable edges = getElement().getEdges(ODirection.OUT); for(OEdge edge : edges) { @SuppressWarnings("rawtypes") RelationManagement relationManagement = getRelationManagement(edge); - relationManagement.internalAddToContext(targetSecurityContext); + affectedInstances.putAll(relationManagement.internalAddToContext(targetSecurityContext)); } - return true; + return affectedInstances; } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { + Map affectedInstances = new HashMap<>(); + Iterable edges = getElement().getEdges(ODirection.OUT); for(OEdge edge : edges) { @SuppressWarnings("rawtypes") RelationManagement relationManagement = getRelationManagement(edge); - relationManagement.internalRemoveFromContext(targetSecurityContext); + affectedInstances.putAll(relationManagement.internalRemoveFromContext(targetSecurityContext)); } targetSecurityContext.removeElement(getElement(), oDatabaseDocument); + /* + * DO NOT UNCOMMENT + * the instance is added internalAddToContext() function after + * the update of Header metadata i.e. modifiedBy, lastUpdateTime + * affectedInstances.put(uuid, serializeSelfOnly()); + */ - return true; + return affectedInstances; } @Override diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/RelationManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/RelationManagement.java index 339e34a..0819374 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/RelationManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/RelationManagement.java @@ -47,11 +47,21 @@ import com.orientechnologies.orient.core.record.impl.ODocument; public abstract class RelationManagement> extends RelationElementManagement{ + /** + * Used in AddToContext. The Relation must add/check also the source entity + */ + public boolean checkContextOfSourceEntity; + + public void setCheckContextOfSourceEntity(boolean checkContextOfSourceEntity) { + this.checkContextOfSourceEntity = checkContextOfSourceEntity; + } + public final PropagationConstraint defaultPropagationConstraint; protected RelationManagement(AccessType accessType, Class targetEntityClass, PropagationConstraint defaultPropagationConstraint) { super(accessType, Resource.class, targetEntityClass); this.defaultPropagationConstraint = defaultPropagationConstraint; + this.checkContextOfSourceEntity = false; } protected RelationManagement(AccessType accessType, Class targetEntityClass, SecurityContext workingContext, ODatabaseDocument orientGraph, @@ -260,10 +270,12 @@ public abstract class RelationManagement reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { getElement(); + Map affectedInstances = new HashMap<>(); + AddConstraint addConstraint = AddConstraint.unpropagate; try { @@ -292,9 +304,15 @@ public abstract class RelationManagement forcedAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { - getElement(); + Map affectedInstances = new HashMap<>(); + /* Adding source to Context */ - getSourceEntityManagement().internalAddToContext(targetSecurityContext); + affectedInstances.putAll(getSourceEntityManagement().internalAddToContext(targetSecurityContext)); /* Adding target to Context */ - getTargetEntityManagement().internalAddToContext(targetSecurityContext); + affectedInstances.putAll(getTargetEntityManagement().internalAddToContext(targetSecurityContext)); targetSecurityContext.addElement(getElement(), oDatabaseDocument); + affectedInstances.put(uuid, serializeSelfOnly()); - return true; + return affectedInstances; } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { getElement(); + Map affectedInstances = new HashMap<>(); + RemoveConstraint removeConstraint = RemoveConstraint.keep; try { @@ -357,10 +379,11 @@ public abstract class RelationManagement 0) { logger.trace( - "{} point to {} which is not orphan ({} exists). Giving {} directive, it will be not remove from .", + "{} point to {} which is not orphan ({} exists). Giving {} directive, it will be not remove from {}.", element, target, edge, removeConstraint, targetSecurityContext); } else { - getTargetEntityManagement().internalRemoveFromContext(targetSecurityContext); + affectedInstances.putAll(getTargetEntityManagement().internalRemoveFromContext(targetSecurityContext)); } break; @@ -400,7 +423,7 @@ public abstract class RelationManagement addToContext(UUID contextUUID) throws NotFoundException, ContextException { logger.debug("Going to add {} with UUID {} to Context with UUID {}", accessType.getName(), uuid, contextUUID); try { @@ -503,7 +526,7 @@ public abstract class RelationManagement added = forcedAddToContext(targetSecurityContext); oDatabaseDocument.commit(); logger.info("{} with UUID {} successfully added to Context with UUID {}", accessType.getName(), uuid, diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java index 539f769..6d09bd8 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/rest/SharingManager.java @@ -1,18 +1,23 @@ package org.gcube.informationsystem.resourceregistry.rest; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; +import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; +import org.gcube.com.fasterxml.jackson.databind.JsonNode; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.common.authorization.library.provider.CalledMethodProvider; +import org.gcube.informationsystem.base.reference.Element; +import org.gcube.informationsystem.base.reference.IdentifiableElement; import org.gcube.informationsystem.context.reference.entities.Context; +import org.gcube.informationsystem.model.reference.properties.Header; import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextNotFoundException; import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException; @@ -21,7 +26,6 @@ import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath; import org.gcube.informationsystem.resourceregistry.api.rest.SharingPath.SharingOperation; import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement; import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility; -import org.gcube.informationsystem.resourceregistry.rest.extrahttpmethods.PATCH; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,6 +37,19 @@ public class SharingManager { private static Logger logger = LoggerFactory.getLogger(SharingManager.class); + protected String serializeAffectedInstaces(ObjectMapper objectMapper, Map affectedInstances) throws ResourceRegistryException { + ArrayNode arrayNode = objectMapper.createArrayNode(); + for(JsonNode jsonNode : affectedInstances.values()) { + arrayNode.add(jsonNode); + } + + try { + return objectMapper.writeValueAsString(arrayNode); + } catch (JsonProcessingException e) { + throw new ResourceRegistryException(e); + } + } + /** * Add/Remove to/from the context identified by CONTEXT_UUID path parameter the list of instances contained in the body of the request. * The the body is the following @@ -55,143 +72,133 @@ public class SharingManager { * where * 67062c11-9c3a-4906-870d-7df6a43408b0/ is the Context UUID * - * The body contains the list of instances to add/remvoe to/from the context identified by CONTEXT_UUID + * The body contains the list of instances to add/remove to/from the context identified by CONTEXT_UUID * */ - @PATCH + @POST @Path("{" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}") - public boolean addRemoveToFromContextNoPropagationConstraint( + public String addRemoveToFromContextNoPropagationConstraint( @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, @QueryParam(SharingPath.OPERATION_QUERY_PARAMETER) SharingOperation operation, + @QueryParam(SharingPath.DRY_RUN_QUERY_PARAMETER) Boolean dryRun, String body) throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { - logger.info("Requested to add to {} with UUID {} the following instances {}", Context.NAME, contextId, body); - - if(operation == SharingOperation.ADD) { - CalledMethodProvider.instance.set("addToContextNoPropagationConstraint"); - }else { - CalledMethodProvider.instance.set("removeFromContextNoPropagationConstraint"); + try { + StringBuffer calledMethod = new StringBuffer(); + if(dryRun==null) { + dryRun = false; + } + + if(dryRun) { + calledMethod.append("dryRun"); + } + + if(operation == SharingOperation.ADD) { + logger.info("Requested {} {} to {} with UUID {}", dryRun? "a dry run for adding": "to add", body, Context.NAME, contextId); + calledMethod.append("AddToContext"); + }else { + logger.info("Requested {} {} from {} with UUID {}", dryRun? "a dry run for removing": "to remove", body, Context.NAME, contextId); + calledMethod.append("RemoveFromContext"); + } + calledMethod.append("NoPropagationConstraint"); + CalledMethodProvider.instance.set(calledMethod.toString()); + + ObjectMapper objectMapper = new ObjectMapper(); + Map affectedInstances = new HashMap<>(); + + ArrayNode arrayNode = (ArrayNode) objectMapper.readTree(body); + for(JsonNode node : arrayNode) { + + String type = node.get(Element.CLASS_PROPERTY).asText(); + String instanceId = node.get(IdentifiableElement.HEADER_PROPERTY).get(Header.UUID_PROPERTY).asText(); + + @SuppressWarnings("rawtypes") + ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); + elementManagement.setUUID(UUID.fromString(instanceId)); + elementManagement.setDryRunContextSharing(dryRun); + + ArrayNode ret = null; + if(operation == SharingOperation.ADD) { + affectedInstances.putAll(elementManagement.addToContext(UUID.fromString(contextId))); + }else { + affectedInstances.putAll(elementManagement.removeFromContext(UUID.fromString(contextId))); + } + } + + return serializeAffectedInstaces(objectMapper, affectedInstances); + }catch (ResourceRegistryException e) { + throw e; + }catch (Exception e) { + throw new ResourceRegistryException(e); } - /* - boolean success = true; - for(any element in body) { - String type = ""; // get type - UUID instanceUUID = UUID.fromString(""); - @SuppressWarnings("rawtypes") - ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); - elementManagement.setUUID(instanceUUID); - // success = success && return elementManagement.addToContextNoPropagationConstraint(UUID.fromString(contextId), body); - } - */ - return true; } /** + * Add/Remove an instance from context. The operation can have a cascade effect due to propagation constraint. * - * Get the list of instances affected by an add/remove to/from context the target instance identified by UUID path parameter + * Return the list of instances affected by an add/remove to/from context the target instance identified by UUID path parameter * - * GET /sharing/contexts/{CONTEXT_UUID}/{TYPE_NAME}/{UUID}?operation=(ADD|REMOVE) + * POST /sharing/contexts/{CONTEXT_UUID}/{TYPE_NAME}/{UUID}?operation=(ADD|REMOVE)&[dryRun=true] * * e.g - * GET /resource-registry/sharing/contexts/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8?operation=ADD - * GET /resource-registry/sharing/contexts/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8?operation=REMOVE + * POST /resource-registry/sharing/contexts/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8?operation=ADD&dryRun=true + * POST /resource-registry/sharing/contexts/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8?operation=REMOVE&dryRun=true * * where * 67062c11-9c3a-4906-870d-7df6a43408b0 is the Context UUID and * 16032d09-3823-444e-a1ff-a67de4f350a8 is the HostingNode UUID * */ - @GET - @Path("{" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}/" - + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}") - public String checkAddRemove( - @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, - @PathParam(AccessPath.TYPE_PATH_PARAM) String type, - @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId, - @QueryParam(SharingPath.OPERATION_QUERY_PARAMETER) SharingOperation operation) - throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { - - logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, instanceId, Context.NAME, contextId); - - if(operation == SharingOperation.ADD) { - CalledMethodProvider.instance.set("dryRunAddToContext"); - }else { - CalledMethodProvider.instance.set("dryRunRemoveFromContext"); - } - - - @SuppressWarnings("rawtypes") - ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); - elementManagement.setUUID(UUID.fromString(instanceId)); - - if(operation == SharingOperation.ADD) { - // elementManagement.dryRunAddToContext(UUID.fromString(contextId)); - }else { - // elementManagement.dryRunRemoveFromContext(UUID.fromString(contextId)); - } - - return ""; - } - - /** - * POST /sharing/contexts/{CONTEXT_UUID}/{TYPE_NAME}/{UUID} - * e.g - * POST /resource-registry/sharing/contexts/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8 - * Where - * 67062c11-9c3a-4906-870d-7df6a43408b0 is the Context UUID and - * 16032d09-3823-444e-a1ff-a67de4f350a8 is the HostingNode UUID - * - */ @POST @Path("{" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}/" + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}") - public boolean add( + public String addRemove( @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, @PathParam(AccessPath.TYPE_PATH_PARAM) String type, - @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId) + @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId, + @QueryParam(SharingPath.OPERATION_QUERY_PARAMETER) SharingOperation operation, + @QueryParam(SharingPath.DRY_RUN_QUERY_PARAMETER) Boolean dryRun) throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { - - logger.info("Requested to add {} with UUID {} to {} with UUID {}", type, instanceId, Context.NAME, contextId); - // setRESTCalledMethod(HTTPMETHOD.PUT, type); - CalledMethodProvider.instance.set("addToContext"); - - @SuppressWarnings("rawtypes") - ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); - elementManagement.setUUID(UUID.fromString(instanceId)); - return elementManagement.addToContext(UUID.fromString(contextId)); - } - - /* - * DELETE /sharing/contexts/{CONTEXT_UUID}/{TYPE_NAME}/{UUID} - * e.g - * DELETE /resource-registry/sharing/contexts/67062c11-9c3a-4906-870d-7df6a43408b0/HostingNode/16032d09-3823-444e-a1ff-a67de4f350a8 - * Where - * 67062c11-9c3a-4906-870d-7df6a43408b0 is the Context UUID and - * 16032d09-3823-444e-a1ff-a67de4f350a8 is the HostingNode UUID - * - * - */ - @DELETE - @Path("{" + SharingPath.CONTEXTS_PATH_PART + "/{" + AccessPath.CONTEXT_UUID_PATH_PARAM + "}/" - + AccessPath.TYPE_PATH_PARAM + "}" + "/{" + AccessPath.UUID_PATH_PARAM + "}") - public Response remove( - @PathParam(AccessPath.CONTEXT_UUID_PATH_PARAM) String contextId, - @PathParam(AccessPath.TYPE_PATH_PARAM) String type, - @PathParam(AccessPath.UUID_PATH_PARAM) String instanceId) - throws ResourceNotFoundException, ContextNotFoundException, ResourceRegistryException { - logger.info("Requested to remove {} with UUID {} to {} with UUID {}", type, instanceId, Context.NAME, - contextId); - CalledMethodProvider.instance.set("removeFromContext"); + StringBuffer calledMethod = new StringBuffer(); + if(dryRun==null) { + dryRun = false; + } + + if(dryRun) { + calledMethod.append("dryRun"); + } + + if(operation == SharingOperation.ADD) { + logger.info("Requested {} {} with UUID {} to {} with UUID {}", dryRun? "a dry run for adding": "to add", type, instanceId, Context.NAME, contextId); + calledMethod.append("AddToContext"); + }else { + logger.info("Requested {} {} with UUID {} from {} with UUID {}", dryRun? "a dry run for removing": "to remove", type, instanceId, Context.NAME, contextId); + calledMethod.append("RemoveFromContext"); + } + + CalledMethodProvider.instance.set(calledMethod.toString()); @SuppressWarnings("rawtypes") ElementManagement elementManagement = ElementManagementUtility.getERManagement(type); elementManagement.setUUID(UUID.fromString(instanceId)); - elementManagement.removeFromContext(UUID.fromString(contextId)); - - return Response.status(Status.NO_CONTENT).build(); + elementManagement.setDryRunContextSharing(dryRun); + + ObjectMapper objectMapper = new ObjectMapper(); + Map affectedInstances = null; + if(operation == SharingOperation.ADD) { + affectedInstances = elementManagement.addToContext(UUID.fromString(contextId)); + }else { + affectedInstances = elementManagement.removeFromContext(UUID.fromString(contextId)); + } + + try { + return serializeAffectedInstaces(objectMapper, affectedInstances); + } catch (Exception e) { + throw new ResourceRegistryException(e); + } } } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/types/entities/EntityTypeDefinitionManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/types/entities/EntityTypeDefinitionManagement.java index e34a7f8..e57418d 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/types/entities/EntityTypeDefinitionManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/types/entities/EntityTypeDefinitionManagement.java @@ -1,6 +1,8 @@ package org.gcube.informationsystem.resourceregistry.types.entities; import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.informationsystem.base.reference.AccessType; @@ -196,13 +198,13 @@ public abstract class EntityTypeDefinitionManagement exten } @Override - protected boolean reallyAddToContext(SecurityContext targetSecurityContext) + protected Map reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/types/properties/PropertyTypeDefinitionManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/types/properties/PropertyTypeDefinitionManagement.java index d5c3ceb..c01e911 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/types/properties/PropertyTypeDefinitionManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/types/properties/PropertyTypeDefinitionManagement.java @@ -1,6 +1,8 @@ package org.gcube.informationsystem.resourceregistry.types.properties; import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.informationsystem.base.reference.AccessType; @@ -188,13 +190,13 @@ public class PropertyTypeDefinitionManagement extends ElementManagement reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } diff --git a/src/main/java/org/gcube/informationsystem/resourceregistry/types/relations/RelationTypeDefinitionManagement.java b/src/main/java/org/gcube/informationsystem/resourceregistry/types/relations/RelationTypeDefinitionManagement.java index 0479b51..b7bf2d9 100644 --- a/src/main/java/org/gcube/informationsystem/resourceregistry/types/relations/RelationTypeDefinitionManagement.java +++ b/src/main/java/org/gcube/informationsystem/resourceregistry/types/relations/RelationTypeDefinitionManagement.java @@ -1,7 +1,10 @@ package org.gcube.informationsystem.resourceregistry.types.relations; import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.informationsystem.base.reference.AccessType; import org.gcube.informationsystem.model.reference.relations.Relation; import org.gcube.informationsystem.resourceregistry.api.exceptions.AlreadyPresentException; @@ -194,13 +197,13 @@ public abstract class RelationTypeDefinitionManagement reallyAddToContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } @Override - protected boolean reallyRemoveFromContext(SecurityContext targetSecurityContext) + protected Map reallyRemoveFromContext(SecurityContext targetSecurityContext) throws ContextException, ResourceRegistryException { throw new UnsupportedOperationException(); } diff --git a/src/test/java/org/gcube/informationsystem/resourceregistry/instances/model/entity/FacetManagementTest.java b/src/test/java/org/gcube/informationsystem/resourceregistry/instances/model/entity/FacetManagementTest.java index 7fa8b88..a937120 100644 --- a/src/test/java/org/gcube/informationsystem/resourceregistry/instances/model/entity/FacetManagementTest.java +++ b/src/test/java/org/gcube/informationsystem/resourceregistry/instances/model/entity/FacetManagementTest.java @@ -1,7 +1,9 @@ package org.gcube.informationsystem.resourceregistry.instances.model.entity; +import java.util.Map; import java.util.UUID; +import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.informationsystem.base.reference.IdentifiableElement; import org.gcube.informationsystem.model.reference.entities.Facet; import org.gcube.informationsystem.resourceregistry.ContextTest; @@ -145,28 +147,30 @@ public class FacetManagementTest extends ContextTest { return deleted; } - protected boolean addToContext(F facet) throws Exception { + protected Map addToContext(F facet) throws Exception { FacetManagement facetManagement = new FacetManagement(); String facetType = Utility.getTypeName(facet); facetManagement.setElementType(facetType); facetManagement.setUUID(facet.getHeader().getUUID()); - boolean added = facetManagement.addToContext(ContextUtility.getCurrentSecurityContext().getUUID()); - Assert.assertTrue(added); + Map affectedInstances = facetManagement.addToContext(ContextUtility.getCurrentSecurityContext().getUUID()); + Assert.assertTrue(affectedInstances.containsKey(facet.getHeader().getUUID())); + Assert.assertTrue(affectedInstances.size()==1); - return added; + return affectedInstances; } - protected boolean removeFromContext(F facet) throws Exception { + protected Map removeFromContext(F facet) throws Exception { FacetManagement facetManagement = new FacetManagement(); String facetType = Utility.getTypeName(facet); facetManagement.setElementType(facetType); facetManagement.setUUID(facet.getHeader().getUUID()); - boolean added = facetManagement.removeFromContext(ContextUtility.getCurrentSecurityContext().getUUID()); - Assert.assertTrue(added); + Map affectedInstances = facetManagement.removeFromContext(ContextUtility.getCurrentSecurityContext().getUUID()); + Assert.assertTrue(affectedInstances.containsKey(facet.getHeader().getUUID())); + Assert.assertTrue(affectedInstances.size()==1); - return added; + return affectedInstances; } interface ActionFunction { diff --git a/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java b/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java index 8057d9e..8c30698 100644 --- a/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java +++ b/src/test/java/org/gcube/informationsystem/resourceregistry/instances/multicontext/BasicTest.java @@ -9,9 +9,12 @@ import java.net.URL; import java.util.Calendar; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; +import org.gcube.com.fasterxml.jackson.databind.JsonNode; +import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode; import org.gcube.common.authorization.client.exceptions.ObjectNotFound; import org.gcube.informationsystem.context.reference.entities.Context; import org.gcube.informationsystem.model.impl.properties.PropagationConstraintImpl; @@ -281,8 +284,9 @@ public class BasicTest extends ContextTest { resourceManagement = new ResourceManagement(); resourceManagement.setUUID(uuid); - boolean addedToContext = resourceManagement.addToContext(ContextUtility.getCurrentSecurityContext().getUUID()); - Assert.assertTrue(addedToContext); + Map affectedInstaces = resourceManagement.addToContext(ContextUtility.getCurrentSecurityContext().getUUID()); + + Assert.assertTrue(affectedInstaces); resourceManagement = new ResourceManagement(); resourceManagement.setUUID(uuid); @@ -439,8 +443,8 @@ public class BasicTest extends ContextTest { resourceManagement = new ResourceManagement(); resourceManagement.setUUID(hnUUID); - boolean removed = resourceManagement.removeFromContext(ContextUtility.getCurrentSecurityContext().getUUID()); - Assert.assertTrue(removed); + Map affectedInstaces = resourceManagement.removeFromContext(ContextUtility.getCurrentSecurityContext().getUUID()); + Assert.assertTrue(affectedInstaces); /* The cascading MUST remove the relation and the target so that * I MUST not be able to read Activates relation and EService