You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
resource-registry/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/relations/RelationElementManagement.java

231 lines
8.9 KiB
Java

package org.gcube.informationsystem.resourceregistry.instances.base.relations;
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;
import org.gcube.informationsystem.base.reference.entities.EntityElement;
import org.gcube.informationsystem.model.reference.relations.Relation;
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.relation.RelationNotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaViolationException;
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
import org.gcube.informationsystem.resourceregistry.instances.base.entities.EntityElementManagement;
import org.gcube.informationsystem.resourceregistry.utils.Utility;
import org.gcube.informationsystem.types.reference.entities.EntityType;
import org.gcube.informationsystem.types.reference.relations.RelationType;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.record.ODirection;
import com.orientechnologies.orient.core.record.OEdge;
import com.orientechnologies.orient.core.record.OVertex;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public abstract class RelationElementManagement<SEM extends EntityElementManagement<? extends EntityElement, SET>, TEM extends EntityElementManagement<? extends EntityElement, TET>, SET extends EntityType, TET extends EntityType>
extends ElementManagement<OEdge, RelationType<SET, TET>> {
public final static String IN = "in";
public final static String OUT = "out";
protected final Class<? extends EntityElement> sourceEntityClass;
protected final Class<? extends EntityElement> targetEntityClass;
protected SEM sourceEntityManagement;
protected TEM targetEntityManagement;
protected boolean includeSource;
protected boolean includeTarget;
protected RelationElementManagement(AccessType accessType, Class<? extends EntityElement> sourceEntityClass, Class<? extends EntityElement> targetEntityClass) {
super(accessType);
this.ignoreKeys.add(Relation.HEADER_PROPERTY);
this.ignoreKeys.add(Relation.SOURCE_PROPERTY);
this.ignoreKeys.add(Relation.TARGET_PROPERTY);
this.ignoreKeys.add(IN.toLowerCase());
this.ignoreKeys.add(OUT.toLowerCase());
this.ignoreKeys.add(IN.toUpperCase());
this.ignoreKeys.add(OUT.toUpperCase());
this.sourceEntityClass = sourceEntityClass;
this.targetEntityClass = targetEntityClass;
this.sourceEntityManagement = null;
this.targetEntityManagement = null;
this.includeSource = true;
this.includeTarget = true;
}
public void includeSource(boolean includeSource) {
this.includeSource = includeSource;
}
public void includeTarget(boolean includeTarget) {
this.includeTarget = includeTarget;
}
protected RelationElementManagement(AccessType accessType, Class<? extends EntityElement> sourceEntityClass, Class<? extends EntityElement> targetEntityClass, SecurityContext workingContext, ODatabaseDocument orientGraph) {
this(accessType, sourceEntityClass, targetEntityClass);
this.oDatabaseDocument = orientGraph;
setWorkingContext(workingContext);
}
public SEM getSourceEntityManagement() throws ResourceRegistryException {
if(sourceEntityManagement == null) {
OVertex source = getElement().getVertex(ODirection.OUT);
sourceEntityManagement = newSourceEntityManagement();
sourceEntityManagement.setElement(source);
}
sourceEntityManagement.setReload(reload);
return sourceEntityManagement;
}
public TEM getTargetEntityManagement() throws ResourceRegistryException {
if(targetEntityManagement == null) {
OVertex target = getElement().getVertex(ODirection.IN);
targetEntityManagement = newTargetEntityManagement();
targetEntityManagement.setElement(target);
}
targetEntityManagement.setReload(reload);
return targetEntityManagement;
}
public void setSourceEntityManagement(SEM sourceEntityManagement) {
this.sourceEntityManagement = sourceEntityManagement;
}
public void setTargetEntityManagement(TEM targetEntityManagement) {
this.targetEntityManagement = targetEntityManagement;
}
@Override
protected JsonNode createCompleteJsonNode() throws ResourceRegistryException {
JsonNode relation = serializeSelfAsJsonNode();
try {
if(includeSource) {
EntityElementManagement<? extends EntityElement, ? extends EntityType> sourceEntityManagement = getSourceEntityManagement();
((ObjectNode) relation).replace(Relation.SOURCE_PROPERTY, sourceEntityManagement.serializeSelfAsJsonNode());
}
if(includeTarget) {
EntityElementManagement<? extends EntityElement, ? extends EntityType> targetEntityManagement = getTargetEntityManagement();
((ObjectNode) relation).replace(Relation.TARGET_PROPERTY, targetEntityManagement.serializeAsJsonNode());
}
} catch(ResourceRegistryException e) {
logger.error("Unable to correctly serialize {}. {}", element, Utility.SHOULD_NOT_OCCUR_ERROR_MESSAGE, e);
throw e;
} catch(Exception e) {
logger.error("Unable to correctly serialize {}. {}", element, Utility.SHOULD_NOT_OCCUR_ERROR_MESSAGE, e);
throw new ResourceRegistryException(e);
}
return relation;
}
protected abstract void checksourceAndTargetEntityCompliancy() throws NotFoundException, AvailableInAnotherContextException, SchemaViolationException, ResourceRegistryException;
@Override
protected OEdge reallyCreate() throws ResourceRegistryException {
if(sourceEntityManagement == null) {
if(!jsonNode.has(Relation.SOURCE_PROPERTY)) {
throw new ResourceRegistryException("Error while creating relation. No source definition found");
}
UUID sourceUUID = org.gcube.informationsystem.utils.Utility
.getUUIDFromJsonNode(jsonNode.get(Relation.SOURCE_PROPERTY));
sourceEntityManagement = newSourceEntityManagement();
sourceEntityManagement.setUUID(sourceUUID);
}
if(targetEntityManagement == null) {
targetEntityManagement = newTargetEntityManagement();
if(!jsonNode.has(Relation.TARGET_PROPERTY)) {
throw new ResourceRegistryException(
"Error while creating " + typeName + ". No target definition found");
}
try {
targetEntityManagement.setJsonNode(jsonNode.get(Relation.TARGET_PROPERTY));
} catch(SchemaException e) {
StringBuilder errorMessage = new StringBuilder();
errorMessage.append("A ");
errorMessage.append(typeName);
errorMessage.append(" can be only created beetween ");
errorMessage.append(sourceEntityManagement.getAccessType().getName());
errorMessage.append(" and ");
errorMessage.append(targetEntityManagement.getAccessType().getName());
throw new SchemaViolationException(errorMessage.toString(), e);
}
try {
targetEntityManagement.getElement();
} catch(Exception e) {
targetEntityManagement.internalCreate();
}
}
OVertex source = (OVertex) getSourceEntityManagement().getElement();
OVertex target = (OVertex) getTargetEntityManagement().getElement();
checksourceAndTargetEntityCompliancy();
logger.trace("Going to create {} beetween {} -> {}", typeName, source.toString(), target.toString());
element = oDatabaseDocument.newEdge(source, target, typeName);
updateProperties(oClass, element, jsonNode, ignoreKeys, ignoreStartWithKeys);
return element;
}
protected abstract SEM newSourceEntityManagement() throws ResourceRegistryException;
protected abstract TEM newTargetEntityManagement() throws ResourceRegistryException;
@Override
protected OEdge reallyUpdate() throws ResourceRegistryException {
logger.debug("Trying to update {} : {}", typeName, jsonNode);
OEdge edge = getElement();
updateProperties(oClass, edge, jsonNode, ignoreKeys, ignoreStartWithKeys);
if(accessType.compareTo(AccessType.CONSISTS_OF) == 0) {
JsonNode target = jsonNode.get(Relation.TARGET_PROPERTY);
if(target != null) {
targetEntityManagement = newTargetEntityManagement();
targetEntityManagement.setJsonNode(target);
targetEntityManagement.internalUpdate();
}
}
logger.info("{} {} successfully updated", typeName, jsonNode);
return edge;
}
@Override
protected void reallyDelete() throws RelationNotFoundException, ResourceRegistryException {
logger.debug("Going to remove {} with UUID {}. Related {}s will be detached.", accessType.getName(), uuid,
targetEntityClass.getSimpleName());
affectedInstances.put(uuid, serializeAsAffectedInstance());
getElement().delete();
}
}