resource-registry/src/main/java/org/gcube/informationsystem/resourceregistry/instances/model/relations/RelationManagement.java

824 lines
32 KiB
Java
Raw Normal View History

2019-11-06 12:14:27 +01:00
package org.gcube.informationsystem.resourceregistry.instances.model.relations;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
2020-07-07 17:15:22 +02:00
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.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.relations.RelationElement;
2021-10-25 11:40:47 +02:00
import org.gcube.informationsystem.contexts.reference.entities.Context;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.AddConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.DeleteConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.model.reference.relations.Relation;
2021-02-05 17:50:16 +01:00
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.contexts.ContextException;
2021-10-25 11:00:54 +02:00
import org.gcube.informationsystem.resourceregistry.api.exceptions.relations.RelationNotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaViolationException;
2020-01-27 17:07:37 +01:00
import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility;
2023-05-10 17:21:00 +02:00
import org.gcube.informationsystem.resourceregistry.contexts.ServerContextCache;
2020-01-27 17:07:37 +01:00
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext;
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagementUtility;
import org.gcube.informationsystem.resourceregistry.instances.base.relations.RelationElementManagement;
2021-02-05 17:50:16 +01:00
import org.gcube.informationsystem.resourceregistry.instances.model.ERManagement;
import org.gcube.informationsystem.resourceregistry.instances.model.Operation;
import org.gcube.informationsystem.resourceregistry.instances.model.entities.EntityManagement;
import org.gcube.informationsystem.resourceregistry.instances.model.entities.FacetManagement;
import org.gcube.informationsystem.resourceregistry.instances.model.entities.ResourceManagement;
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
2023-05-11 18:35:56 +02:00
import org.gcube.informationsystem.resourceregistry.utils.DBUtility;
2023-04-18 17:52:07 +02:00
import org.gcube.informationsystem.resourceregistry.utils.MetadataUtility;
2023-05-10 17:21:00 +02:00
import org.gcube.informationsystem.resourceregistry.utils.PropagationConstraintOrient;
2023-02-07 16:27:10 +01:00
import org.gcube.informationsystem.serialization.ElementMapper;
2021-02-22 16:36:19 +01:00
import org.gcube.informationsystem.types.reference.entities.EntityType;
import org.gcube.informationsystem.types.reference.entities.ResourceType;
import org.gcube.informationsystem.types.reference.relations.RelationType;
2023-05-11 18:35:56 +02:00
import com.arcadedb.database.Document;
import com.arcadedb.database.MutableDocument;
import com.arcadedb.graph.Edge;
import com.arcadedb.graph.Vertex;
import com.arcadedb.graph.Vertex.DIRECTION;
import com.arcadedb.remote.RemoteDatabase;
import com.arcadedb.schema.Type;
/**
* @author Luca Frosini (ISTI - CNR)
*/
2021-02-22 16:36:19 +01:00
public abstract class RelationManagement<T extends EntityManagement<? extends Entity, TET>, TET extends EntityType>
extends RelationElementManagement<ResourceManagement, T, ResourceType, TET> implements ERManagement {
2021-03-05 10:46:59 +01:00
/**
* The source context of an addToContex
*/
protected SecurityContext sourceSecurityContext;
/**
* The target context of an addToContex/RemoveFromContext
*/
protected SecurityContext targetSecurityContext;
2021-02-05 17:50:16 +01:00
/**
* 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
2021-06-24 12:27:41 +02:00
* {@link ElementManagement#dryRun}=true.
2021-02-05 17:50:16 +01:00
* This allow to simulate a sharing operation which requires
* do not honour the propagation constraints.
*/
protected boolean honourPropagationConstraintsInContextSharing;
2021-03-05 10:46:59 +01:00
@Override
public void setSourceSecurityContext(SecurityContext sourceSecurityContext) {
this.sourceSecurityContext = sourceSecurityContext;
}
@Override
public SecurityContext getSourceSecurityContext() {
return sourceSecurityContext;
}
@Override
public void setTargetSecurityContext(SecurityContext targetSecurityContext) {
this.targetSecurityContext = targetSecurityContext;
}
2021-03-05 10:46:59 +01:00
@Override
public SecurityContext getTargetSecurityContext() {
return sourceSecurityContext;
}
@Override
2021-02-05 17:50:16 +01:00
public boolean isHonourPropagationConstraintsInContextSharing() {
return honourPropagationConstraintsInContextSharing;
2021-01-25 17:38:19 +01:00
}
@Override
2021-02-05 17:50:16 +01:00
public void setHonourPropagationConstraintsInContextSharing(boolean honourPropagationConstraintsInContextSharing) {
this.honourPropagationConstraintsInContextSharing = honourPropagationConstraintsInContextSharing;
}
public final PropagationConstraint defaultPropagationConstraint;
2021-03-05 10:46:59 +01:00
public boolean isAvailableOnContext(SecurityContext securityContext) {
try {
return securityContext.isElementInContext(element);
} catch (ResourceRegistryException e) {
return false;
}
}
2019-11-08 12:29:32 +01:00
protected RelationManagement(AccessType accessType, Class<? extends Entity> targetEntityClass, PropagationConstraint defaultPropagationConstraint) {
super(accessType, Resource.class, targetEntityClass);
this.defaultPropagationConstraint = defaultPropagationConstraint;
2021-02-05 17:50:16 +01:00
/*
* By the default the system honour the propagation constraints
* so this variable is initialised as true.
*/
this.honourPropagationConstraintsInContextSharing = true;
2021-09-16 17:23:13 +02:00
this.skipped = false;
}
protected PropagationConstraint propagationConstraint;
2022-06-08 16:06:56 +02:00
/* The instance is added to the context even is not in source context */
protected boolean forceAddToContext;
/* Indicate that AddToContext skipped the instance because it was not the source context */
2021-09-16 17:23:13 +02:00
protected boolean skipped;
2021-02-05 17:50:16 +01:00
@Override
2023-05-11 18:35:56 +02:00
public Edge getElement() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
2021-02-05 17:50:16 +01:00
try {
element = super.getElement();
} catch(NotFoundException e) {
try {
retrieveElementFromAnyContext();
2021-03-05 10:46:59 +01:00
throw getSpecificAvailableInAnotherContextException(typeName == null ? accessType.getName()
2021-02-18 09:42:51 +01:00
: typeName + " with UUID " + uuid + " is available in another "
2021-02-05 17:50:16 +01:00
+ Context.class.getSimpleName());
} catch(AvailableInAnotherContextException e1) {
throw e1;
} catch(Exception e1) {
throw e;
}
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
throw new ResourceRegistryException(e);
}
return element;
}
/*
* Needed for ResourceManagement.serializeAsJson() function to check that
* sourceEntityManagement is the same of the instance is creating this
* RelationManagement.
*/
public ResourceManagement giveMeSourceEntityManagementAsIs() throws ResourceRegistryException {
return sourceEntityManagement;
}
protected Map<String,JsonNode> fullSerialize(Map<String,JsonNode> visitedSourceResources)
throws ResourceRegistryException {
2023-05-11 18:35:56 +02:00
Vertex source = getElement().getVertex(DIRECTION.OUT);
String id = source.getIdentity().toString();
JsonNode sourceResource = visitedSourceResources.get(id);
ResourceManagement resourceManagement = null;
if(sourceResource == null) {
resourceManagement = (ResourceManagement) ElementManagementUtility.getEntityManagement(getWorkingContext(),
2023-05-11 18:35:56 +02:00
database, source);
if(this instanceof IsRelatedToManagement) {
2021-02-16 18:43:47 +01:00
sourceResource = resourceManagement.createCompleteJsonNode();
} else if(this instanceof ConsistsOfManagement) {
if(includeSource) {
sourceResource = resourceManagement.serializeSelfAsJsonNode();
}
} else {
String error = String.format("{%s is not a %s nor a %s. %s", this,
IsRelatedToManagement.class.getSimpleName(), ConsistsOfManagement.class.getSimpleName(),
2023-05-11 18:35:56 +02:00
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
throw new ResourceRegistryException(error);
}
}
if(this instanceof IsRelatedToManagement) {
2021-02-17 11:29:43 +01:00
sourceResource = ResourceManagement.addIsRelatedTo(sourceResource, serializeAsJsonNode());
} else if(this instanceof ConsistsOfManagement) {
2021-02-17 11:29:43 +01:00
sourceResource = ResourceManagement.addConsistsOf(sourceResource, serializeAsJsonNode());
} else {
String error = String.format("{%s is not a %s nor a %s. %s", this,
IsRelatedToManagement.class.getSimpleName(), ConsistsOfManagement.class.getSimpleName(),
2023-05-11 18:35:56 +02:00
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
throw new ResourceRegistryException(error);
}
visitedSourceResources.put(id, sourceResource);
return visitedSourceResources;
}
2023-05-11 18:35:56 +02:00
protected PropagationConstraintOrient getPropagationConstraint(Document document)
throws ResourceRegistryException {
PropagationConstraintOrient propagationConstraintOrient = new PropagationConstraintOrient();
PropagationConstraint propagationConstraint = null;
2023-05-11 18:35:56 +02:00
if(document == null) {
propagationConstraint = defaultPropagationConstraint;
2023-05-11 18:35:56 +02:00
} else if(document instanceof PropagationConstraintOrient) {
propagationConstraint = (PropagationConstraint) document;
} else {
try {
2023-05-11 18:35:56 +02:00
propagationConstraint = ElementMapper.unmarshal(PropagationConstraint.class, DBUtility.toJsonString(document));
} catch(Exception e) {
logger.warn("Unable to recreate {}. {}", PropagationConstraint.NAME,
2023-05-11 18:35:56 +02:00
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
}
}
AddConstraint addConstraint = propagationConstraint.getAddConstraint();
if(addConstraint == null) {
addConstraint = defaultPropagationConstraint.getAddConstraint();
2021-09-17 10:35:57 +02:00
logger.debug("Unable to get {}. Default value ({}) will be used", AddConstraint.class.getSimpleName(),
addConstraint);
}
propagationConstraintOrient.setAddConstraint(addConstraint);
RemoveConstraint removeConstraint = propagationConstraint.getRemoveConstraint();
if(removeConstraint == null) {
removeConstraint = defaultPropagationConstraint.getRemoveConstraint();
2021-09-17 10:35:57 +02:00
logger.debug("Unable to get {}. Default value ({}) will be used", RemoveConstraint.class.getSimpleName(),
removeConstraint);
}else {
if (this instanceof ConsistsOfManagement && removeConstraint == RemoveConstraint.keep) {
removeConstraint = defaultPropagationConstraint.getRemoveConstraint();
logger.warn("A {} cannot use {}.{}. Default value ({}) will be used", ConsistsOf.NAME,
RemoveConstraint.class.getSimpleName(), RemoveConstraint.keep, removeConstraint);
}
}
propagationConstraintOrient.setRemoveConstraint(removeConstraint);
DeleteConstraint deleteConstraint = propagationConstraint.getDeleteConstraint();
if(deleteConstraint == null) {
deleteConstraint = defaultPropagationConstraint.getDeleteConstraint();
logger.debug("Unable to get {}. Default value ({}) will be used", DeleteConstraint.class.getSimpleName(),
deleteConstraint);
}else {
if (this instanceof ConsistsOfManagement && deleteConstraint == DeleteConstraint.keep) {
deleteConstraint = defaultPropagationConstraint.getDeleteConstraint();
logger.warn("A {} cannot use {}.{}. Default value ({}) will be used", ConsistsOf.NAME,
DeleteConstraint.class.getSimpleName(), DeleteConstraint.keep, deleteConstraint);
}
}
propagationConstraintOrient.setDeleteConstraint(deleteConstraint);
return propagationConstraintOrient;
}
protected void checkPropagationConstraint() throws ResourceRegistryException {
2023-05-11 18:35:56 +02:00
Object object = getElement().get(Relation.PROPAGATION_CONSTRAINT_PROPERTY);
PropagationConstraintOrient pc = getPropagationConstraint((Document) object);
((MutableDocument) getElement()).set(Relation.PROPAGATION_CONSTRAINT_PROPERTY, pc, Type.EMBEDDED);
}
@Override
2023-05-11 18:35:56 +02:00
protected Edge reallyCreate() throws ResourceRegistryException {
element = super.reallyCreate();
checkPropagationConstraint();
2021-09-17 10:35:57 +02:00
logger.trace("{} successfully created", typeName);
return element;
}
@Override
protected ResourceManagement newSourceEntityManagement() throws ResourceRegistryException {
2021-02-10 15:45:48 +01:00
ResourceManagement resourceManagement = new ResourceManagement();
resourceManagement.setWorkingContext(getWorkingContext());
2023-05-11 18:35:56 +02:00
resourceManagement.setDatabase(database);
2021-02-10 15:45:48 +01:00
return resourceManagement;
}
protected String getEntityTypeNotValidErrroMessage(String entityPosition, String requiredType, String effectiveType) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("The ");
stringBuffer.append(entityPosition);
stringBuffer.append(" instance of the relation ");
stringBuffer.append(typeName);
stringBuffer.append(" is of type ");
stringBuffer.append(effectiveType);
stringBuffer.append(" which is not a specialisation of ");
stringBuffer.append(requiredType);
stringBuffer.append(".");
return stringBuffer.toString();
}
@Override
protected void checksourceAndTargetEntityCompliancy() throws NotFoundException, AvailableInAnotherContextException, SchemaViolationException, ResourceRegistryException {
String sourceType = sourceEntityManagement.getTypeName();
String targetType = targetEntityManagement.getTypeName();
RelationType<ResourceType, TET> relationType = getCachedType().getType();
ResourceType resourceType = relationType.getSource();
TET tet = relationType.getTarget();
String requiredSourceType = resourceType.getName();
String requiredTargetType = tet.getName();
TypesCache typesCache = TypesCache.getInstance();
if(!typeSatified(typesCache, requiredSourceType, sourceType)) {
String message = getEntityTypeNotValidErrroMessage(RelationElement.SOURCE_PROPERTY, requiredSourceType, sourceType);
throw new SchemaViolationException(message);
}
if(!typeSatified(typesCache, requiredTargetType, targetType)) {
String message = getEntityTypeNotValidErrroMessage(RelationElement.TARGET_PROPERTY, requiredTargetType, targetType);
throw new SchemaViolationException(message);
}
}
@Override
2023-05-11 18:35:56 +02:00
protected Edge reallyUpdate() throws ResourceRegistryException {
2021-09-17 10:35:57 +02:00
logger.trace("Trying to update {} with UUID {}", typeName, uuid);
logger.trace("Trying to update {} : {}", typeName, jsonNode);
2023-05-11 18:35:56 +02:00
Edge edge = getElement();
updateProperties(documentType, edge, jsonNode, ignoreKeys, ignoreStartWithKeys);
if(accessType.compareTo(AccessType.CONSISTS_OF) == 0) {
JsonNode target = jsonNode.get(Relation.TARGET_PROPERTY);
if(target != null) {
2021-02-10 15:45:48 +01:00
FacetManagement facetManagement = new FacetManagement();
facetManagement.setWorkingContext(getWorkingContext());
2023-05-11 18:35:56 +02:00
facetManagement.setDatabase(database);
2021-02-10 15:45:48 +01:00
facetManagement.setJsonNode(target);
facetManagement.internalUpdate();
}
}
2021-09-17 10:35:57 +02:00
logger.info("{} with UUID {} successfully updated", typeName, uuid);
logger.trace("{} {} successfully updated", typeName, jsonNode);
return edge;
}
2021-03-06 10:53:45 +01:00
protected void reallyAddToContext()
2021-02-05 17:50:16 +01:00
throws ContextException, ResourceRegistryException {
2022-06-08 16:06:56 +02:00
if(!forceAddToContext && !sourceSecurityContext.isElementInContext(getElement())) {
// The element in not in the source security context. It will be skipped
2021-09-16 17:23:13 +02:00
skipped = true;
return;
}
2021-02-05 17:50:16 +01:00
if(honourPropagationConstraintsInContextSharing) {
AddConstraint addConstraint = AddConstraint.unpropagate;
try {
2023-05-11 18:35:56 +02:00
propagationConstraint = DBUtility.getPropertyDocument(PropagationConstraint.class, element,
2021-02-05 17:50:16 +01:00
Relation.PROPAGATION_CONSTRAINT_PROPERTY);
if(propagationConstraint.getAddConstraint() != null) {
addConstraint = propagationConstraint.getAddConstraint();
} else {
String error = String.format("%s.%s in %s is null. %s", Relation.PROPAGATION_CONSTRAINT_PROPERTY,
2023-05-11 18:35:56 +02:00
PropagationConstraint.ADD_PROPERTY, DBUtility.getAsStringForException(element),
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
2021-02-05 17:50:16 +01:00
logger.error(error);
throw new ResourceRegistryException(error);
}
} catch(Exception e) {
String error = String.format("Error while getting %s from %s while performing AddToContext. %s",
2023-05-11 18:35:56 +02:00
Relation.PROPAGATION_CONSTRAINT_PROPERTY, DBUtility.getAsStringForException(element),
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
2021-02-05 17:50:16 +01:00
logger.warn(error);
throw new ResourceRegistryException(error, e);
}
switch(addConstraint) {
case propagate:
/*
* The relation must be added only in the case the target vertex must be added.
* Otherwise we have a relation which point to an entity outside of the context.
*/
2021-03-05 14:41:02 +01:00
getTargetEntityManagement().setDryRun(dryRun);
2021-02-05 17:50:16 +01:00
targetEntityManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing);
targetEntityManagement.setSourceSecurityContext(sourceSecurityContext);
targetEntityManagement.setTargetSecurityContext(targetSecurityContext);
2021-03-05 14:41:02 +01:00
targetEntityManagement.internalAddToContext();
affectedInstances.putAll(targetEntityManagement.getAffectedInstances());
2021-02-05 17:50:16 +01:00
2023-05-11 18:35:56 +02:00
targetSecurityContext.addElement(getElement(), database);
2021-02-05 17:50:16 +01:00
/*
* DO NOT UNCOMMENT
* // affectedInstances.put(uuid, serializeSelfOnly());
* the relation instance is added in internalAddToContext() function after
2023-04-19 11:36:49 +02:00
* the update of Metadata i.e. modifiedBy, lastUpdateTime
2021-02-05 17:50:16 +01:00
*/
break;
case unpropagate:
break;
default:
break;
}
}else {
2023-05-11 18:35:56 +02:00
targetSecurityContext.addElement(getElement(), database);
2021-02-05 17:50:16 +01:00
/*
* DO NOT UNCOMMENT
* // affectedInstances.put(uuid, serializeSelfOnly());
* the relation instance is added in internalAddToContext() function after
2023-04-19 11:36:49 +02:00
* the update of Metadata i.e. modifiedBy, lastUpdateTime
2021-02-05 17:50:16 +01:00
*/
}
}
@Override
2021-03-05 14:41:02 +01:00
public void internalAddToContext()
throws ContextException, ResourceRegistryException {
try {
2021-03-04 11:45:27 +01:00
operation = Operation.ADD_TO_CONTEXT;
reallyAddToContext();
2021-09-16 17:23:13 +02:00
if(!skipped && propagationConstraint.getAddConstraint()==PropagationConstraint.AddConstraint.propagate) {
2023-04-18 17:52:07 +02:00
MetadataUtility.updateModifiedByAndLastUpdate(element);
2023-05-11 18:35:56 +02:00
// element.save();
2021-03-06 10:53:45 +01:00
affectedInstances.put(uuid, serializeAsAffectedInstance());
}
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
throw new ResourceRegistryException(
2021-02-18 09:42:51 +01:00
"Error Adding " + typeName + " to " + targetSecurityContext.toString(), e.getCause());
}
}
2021-03-06 10:53:45 +01:00
public void forcedAddToContext()
throws ContextException, ResourceRegistryException {
2021-03-04 11:45:27 +01:00
setOperation(Operation.ADD_TO_CONTEXT);
/* Adding source to Context */
2021-03-05 14:41:02 +01:00
getSourceEntityManagement().setDryRun(dryRun);
sourceEntityManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing);
sourceEntityManagement.setTargetSecurityContext(targetSecurityContext);
sourceEntityManagement.internalAddToContext();
affectedInstances.putAll(sourceEntityManagement.getAffectedInstances());
/* Adding target to Context */
2021-03-05 14:41:02 +01:00
getTargetEntityManagement().setDryRun(dryRun);
targetEntityManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing);
targetEntityManagement.setTargetSecurityContext(targetSecurityContext);
2021-03-05 14:41:02 +01:00
targetEntityManagement.internalAddToContext();
affectedInstances.putAll(targetEntityManagement.getAffectedInstances());
2023-05-11 18:35:56 +02:00
targetSecurityContext.addElement(getElement(), database);
2021-03-06 10:53:45 +01:00
affectedInstances.put(uuid, serializeAsAffectedInstance());
}
@Override
2021-09-17 10:35:57 +02:00
public void addToContext(UUID contextUUID) throws SchemaViolationException, NotFoundException, ContextException, ResourceRegistryException {
2023-05-10 17:21:00 +02:00
String contextFullName = ServerContextCache.getInstance().getContextFullNameByUUID(contextUUID);
2021-09-17 10:35:57 +02:00
logger.debug("Going to add {} with UUID {} to Context with UUID {} (i.e {})", accessType.getName(), uuid, contextUUID, contextFullName);
2023-05-11 18:35:56 +02:00
RemoteDatabase current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
2021-02-05 17:50:16 +01:00
try {
workingContext = ContextUtility.getAdminSecurityContext();
2023-05-11 18:35:56 +02:00
database = workingContext.getRemoteDatabase(PermissionMode.WRITER);
2021-03-04 11:45:27 +01:00
setAsEntryPoint();
2021-02-05 17:50:16 +01:00
sourceSecurityContext = ContextUtility.getCurrentSecurityContext();
targetSecurityContext = ContextUtility.getInstance().getSecurityContextByUUID(contextUUID);
2021-02-05 17:50:16 +01:00
forcedAddToContext();
2021-02-05 17:50:16 +01:00
sanityCheck();
if(!dryRun) {
2023-05-11 18:35:56 +02:00
database.commit();
}else {
2023-05-11 18:35:56 +02:00
database.rollback();
}
2021-09-17 10:35:57 +02:00
logger.info("{} with UUID {} successfully added to Context with UUID {} (i.e {})", accessType.getName(), uuid, contextUUID, contextFullName);
2021-02-05 17:50:16 +01:00
} catch(Exception e) {
2021-09-17 10:35:57 +02:00
logger.error("Unable to add {} with UUID {} to Context with UUID {} (i.e. {})", accessType.getName(), uuid,
contextUUID, contextFullName, e);
2023-05-11 18:35:56 +02:00
if(database != null) {
database.rollback();
2021-02-05 17:50:16 +01:00
}
throw new ContextException(e);
} finally {
2023-05-11 18:35:56 +02:00
if(database != null) {
database.close();
2021-02-05 17:50:16 +01:00
}
2023-05-11 18:35:56 +02:00
// if(current!=null) {
// current.activateOnCurrentThread();
// }
2021-02-05 17:50:16 +01:00
}
}
protected Map<UUID,JsonNode> reallyRemoveFromContext()
throws ContextException, ResourceRegistryException {
if(!targetSecurityContext.isElementInContext(getElement())) {
// The element in not in the source security context. It will be skipped
return affectedInstances;
}
getSourceEntityManagement().getElement();
RemoveConstraint removeConstraint = RemoveConstraint.keep;
try {
2023-05-11 18:35:56 +02:00
propagationConstraint = DBUtility.getPropertyDocument(PropagationConstraint.class, element,
Relation.PROPAGATION_CONSTRAINT_PROPERTY);
if(propagationConstraint.getRemoveConstraint() != null) {
removeConstraint = propagationConstraint.getRemoveConstraint();
} else {
String error = String.format("%s.%s in %s is null. %s", Relation.PROPAGATION_CONSTRAINT_PROPERTY,
2023-05-11 18:35:56 +02:00
PropagationConstraint.REMOVE_PROPERTY, DBUtility.getAsStringForException(element),
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
logger.error(error);
throw new ResourceRegistryException(error);
}
} catch(Exception e) {
String error = String.format("Error while getting %s from %s while performing RemoveFromContext. %s",
2023-05-11 18:35:56 +02:00
Relation.PROPAGATION_CONSTRAINT_PROPERTY, DBUtility.getAsStringForException(element),
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
logger.error(error);
throw new ResourceRegistryException(error, e);
}
/*
* In any removeConstraint value the relation MUST be removed from context to
* avoid to have edge having a source outside of the context.
*/
2023-05-11 18:35:56 +02:00
targetSecurityContext.removeElement(getElement(), database);
2021-03-06 10:53:45 +01:00
affectedInstances.put(uuid, serializeAsAffectedInstance());
T targetEntityManagement = getTargetEntityManagement();
targetEntityManagement.setDryRun(dryRun);
targetEntityManagement.setHonourPropagationConstraintsInContextSharing(honourPropagationConstraintsInContextSharing);
// Not needed targetEntityManagement.setSourceSecurityContext(sourceSecurityContext);
targetEntityManagement.setTargetSecurityContext(targetSecurityContext);
2021-03-09 12:26:49 +01:00
if(targetEntityManagement instanceof ResourceManagement) {
((ResourceManagement) targetEntityManagement).setSanityCheckNotRequired();
}
switch(removeConstraint) {
case cascade:
2021-03-05 14:41:02 +01:00
targetEntityManagement.internalRemoveFromContext();
affectedInstances.putAll(targetEntityManagement.getAffectedInstances());
break;
case cascadeWhenOrphan:
2023-05-11 18:35:56 +02:00
Vertex target = (Vertex) targetEntityManagement.getElement();
2023-05-11 18:35:56 +02:00
Iterable<Edge> iterable = target.getEdges(DIRECTION.IN);
Iterator<Edge> iterator = iterable.iterator();
int count = 0;
2023-05-11 18:35:56 +02:00
Edge edge = null;
while(iterator.hasNext()) {
2023-05-11 18:35:56 +02:00
edge = (Edge) iterator.next();
Edge thisEdge = (Edge) getElement();
if(edge.compareTo(thisEdge) != 0) {
if(thisEdge.getVertex(DIRECTION.OUT).compareTo(edge.getVertex(DIRECTION.OUT)) != 0) {
count++;
break;
}
/*
* else{ ContextUtility.removeFromActualContext(orientGraph, edge); }
*/
}
}
if(count > 0) {
logger.trace(
2021-01-25 17:38:19 +01:00
"{} point to {} which is not orphan ({} exists). Giving {} directive, it will be not remove from {}.",
element, target, edge, removeConstraint, targetSecurityContext);
} else {
2021-03-05 14:41:02 +01:00
targetEntityManagement.internalRemoveFromContext();
affectedInstances.putAll(targetEntityManagement.getAffectedInstances());
}
break;
case keep:
break;
default:
break;
}
2021-01-25 17:38:19 +01:00
return affectedInstances;
}
@Override
2021-03-05 14:41:02 +01:00
public void internalRemoveFromContext()
2021-02-05 17:50:16 +01:00
throws ContextException, ResourceRegistryException {
try {
2021-03-04 11:45:27 +01:00
setOperation(Operation.REMOVE_FROM_CONTEXT);
reallyRemoveFromContext();
2023-04-18 17:52:07 +02:00
MetadataUtility.updateModifiedByAndLastUpdate(element);
2023-05-11 18:35:56 +02:00
// element.save();
2021-03-06 10:53:45 +01:00
affectedInstances.put(uuid, serializeAsAffectedInstance());
2021-02-05 17:50:16 +01:00
} catch(ResourceRegistryException e) {
throw e;
} catch(Exception e) {
throw new ResourceRegistryException(
2021-02-18 09:42:51 +01:00
"Error Removing " + typeName + " from " + targetSecurityContext.toString(), e.getCause());
2021-02-05 17:50:16 +01:00
}
}
@Override
2021-03-05 14:41:02 +01:00
public void removeFromContext(UUID contextUUID)
2021-02-05 17:50:16 +01:00
throws NotFoundException, ContextException, ResourceRegistryException {
2021-02-18 09:42:51 +01:00
logger.debug("Going to remove {} with UUID {} from Context with UUID {}", typeName, uuid, contextUUID);
2023-05-11 18:35:56 +02:00
RemoteDatabase current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
2021-02-05 17:50:16 +01:00
try {
workingContext = ContextUtility.getAdminSecurityContext();
2023-05-11 18:35:56 +02:00
database = workingContext.getRemoteDatabase(PermissionMode.WRITER);
database.begin();
2021-03-04 11:45:27 +01:00
setAsEntryPoint();
2021-02-05 17:50:16 +01:00
// Not needed sourceSecurityContext = ContextUtility.getCurrentSecurityContext();
targetSecurityContext = ContextUtility.getInstance().getSecurityContextByUUID(contextUUID);
2021-02-05 17:50:16 +01:00
internalRemoveFromContext();
2021-02-05 17:50:16 +01:00
sanityCheck();
if(!dryRun) {
2023-05-11 18:35:56 +02:00
database.commit();
}else {
2023-05-11 18:35:56 +02:00
database.rollback();
}
2021-02-18 09:42:51 +01:00
logger.info("{} with UUID {} successfully removed from Context with UUID {}", typeName, uuid, contextUUID);
2021-02-05 17:50:16 +01:00
} catch(ResourceRegistryException e) {
2021-02-18 09:42:51 +01:00
logger.error("Unable to remove {} with UUID {} from Context with UUID {}", typeName, uuid, contextUUID);
2023-05-11 18:35:56 +02:00
if(database != null) {
database.rollback();
2021-02-05 17:50:16 +01:00
}
throw e;
} catch(Exception e) {
2021-02-18 09:42:51 +01:00
logger.error("Unable to remove {} with UUID {} from Context with UUID {}", typeName, uuid, contextUUID,
2021-02-05 17:50:16 +01:00
e);
2023-05-11 18:35:56 +02:00
if(database != null) {
database.rollback();
2021-02-05 17:50:16 +01:00
}
throw new ContextException(e);
} finally {
2023-05-11 18:35:56 +02:00
if(database != null) {
database.close();
2021-02-05 17:50:16 +01:00
}
2023-05-11 18:35:56 +02:00
// if(current!=null) {
// current.activateOnCurrentThread();
// }
2021-02-05 17:50:16 +01:00
}
}
@Override
protected void reallyDelete() throws RelationNotFoundException, ResourceRegistryException {
logger.debug("Going to remove {} with UUID {}. Related {}s will be detached.", accessType.getName(), uuid,
targetEntityClass.getSimpleName());
getElement();
getSourceEntityManagement().getElement();
DeleteConstraint deleteConstraint = DeleteConstraint.keep;
try {
2023-05-11 18:35:56 +02:00
PropagationConstraint propagationConstraint = DBUtility.getPropertyDocument(PropagationConstraint.class,
element, Relation.PROPAGATION_CONSTRAINT_PROPERTY);
if(propagationConstraint.getDeleteConstraint() != null) {
deleteConstraint = propagationConstraint.getDeleteConstraint();
} else {
String error = String.format("%s.%s in %s is null. %s", Relation.PROPAGATION_CONSTRAINT_PROPERTY,
2023-05-11 18:35:56 +02:00
PropagationConstraint.DELETE_PROPERTY, DBUtility.getAsStringForException(element),
DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
deleteConstraint = DeleteConstraint.values()[propagationConstraint.getRemoveConstraint().ordinal()];
2023-04-26 21:44:03 +02:00
throw new ResourceRegistryException(error);
}
} catch(Exception e) {
logger.warn("Error while getting {} from {}. Assuming {}. {}", Relation.PROPAGATION_CONSTRAINT_PROPERTY,
2023-05-11 18:35:56 +02:00
DBUtility.getAsStringForException(element), deleteConstraint, DBUtility.SHOULD_NOT_OCCUR_ERROR_MESSAGE);
}
// pre-loading target entity because after deleting the relation we will not be able to get it
T t = getTargetEntityManagement();
2021-03-05 17:22:01 +01:00
if(targetEntityManagement instanceof ResourceManagement) {
((ResourceManagement) targetEntityManagement).setSanityCheckNotRequired();
}
2021-03-06 10:53:45 +01:00
affectedInstances.put(uuid, serializeAsAffectedInstance());
element.delete();
switch(deleteConstraint) {
case cascade:
t.internalDelete();
break;
case cascadeWhenOrphan:
2023-05-11 18:35:56 +02:00
Vertex target = t.getElement();
Iterable<Edge> iterable = target.getEdges(DIRECTION.IN);
Iterator<Edge> iterator = iterable.iterator();
if(iterator.hasNext()) {
logger.trace("{} point to {} which is not orphan. Giving {} directive, it will be keep.", element,
target, deleteConstraint);
} else {
getTargetEntityManagement().internalDelete();
}
break;
case keep:
break;
default:
break;
}
affectedInstances.putAll(t.getAffectedInstances());
}
2023-05-11 18:35:56 +02:00
protected Collection<JsonNode> serializeEdges(Iterable<Document> edges, boolean postFilterPolymorphic)
throws ResourceRegistryException {
// Map<String,JsonNode> visitedSourceResources = new HashMap<>();
List<JsonNode> serilizedEdges = new ArrayList<>();
2023-05-11 18:35:56 +02:00
for(Document d : edges) {
Edge edge = (Edge) d;
2023-05-11 18:35:56 +02:00
if(postFilterPolymorphic && getDocumentType().isSubTypeOf(typeName)) {
continue;
}
RelationManagement<?, ?> relationManagement = ElementManagementUtility.getRelationManagement(getWorkingContext(),
2023-05-11 18:35:56 +02:00
database, edge);
// visitedSourceResources = relationManagement.fullSerialize(visitedSourceResources);
serilizedEdges.add(relationManagement.serializeAsJsonNode());
}
return serilizedEdges;
}
protected String serializeJsonNodeCollectionAsString(Collection<JsonNode> collection) throws ResourceRegistryException {
try {
ObjectMapper objectMapper = new ObjectMapper();
ArrayNode arrayNode = objectMapper.valueToTree(collection);
return objectMapper.writeValueAsString(arrayNode);
} catch(Exception e) {
throw new ResourceRegistryException(e);
}
}
@Override
public String reallyGetAll(boolean polymorphic) throws ResourceRegistryException {
2023-05-11 18:35:56 +02:00
Iterable<Document> edges = database.browseClass(typeName, polymorphic);
Collection<JsonNode> collection = serializeEdges(edges, false);
return serializeJsonNodeCollectionAsString(collection);
}
2022-06-08 16:06:56 +02:00
@Override
public void setForceAddToContext(Boolean forceAddToContext) {
this.forceAddToContext = forceAddToContext;
}
}