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.
231 lines
8.9 KiB
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();
|
|
}
|
|
|
|
}
|