resource-registry/src/main/java/org/gcube/informationsystem/resourceregistry/instances/base/relations/BaseRelationManagement.java

220 lines
8.1 KiB
Java

package org.gcube.informationsystem.resourceregistry.instances.base.relations;
import java.util.UUID;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.entities.BaseEntity;
import org.gcube.informationsystem.base.reference.relations.BaseRelation;
import org.gcube.informationsystem.model.reference.relations.Relation;
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.instances.base.ERManagement;
import org.gcube.informationsystem.resourceregistry.instances.base.entities.BaseEntityManagement;
import org.gcube.informationsystem.resourceregistry.instances.model.entity.FacetManagement;
import org.gcube.informationsystem.resourceregistry.security.SecurityContext;
import org.gcube.informationsystem.resourceregistry.utils.Utility;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientBaseGraph;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public abstract class BaseRelationManagement<R extends BaseRelation<S, T>, SEM extends BaseEntityManagement<S>, TEM extends BaseEntityManagement<T>, S extends BaseEntity, T extends BaseEntity>
extends ERManagement<R,Edge> {
protected final Class<S> sourceEntityClass;
protected final Class<T> targetEntityClass;
protected SEM sourceEntityManagement;
protected TEM targetEntityManagement;
protected BaseRelationManagement(AccessType accessType, Class<S> sourceEntityClass, Class<T> targetEntityClass) {
super(accessType);
this.ignoreKeys.add(Relation.HEADER_PROPERTY);
this.ignoreKeys.add(Relation.SOURCE_PROPERTY);
this.ignoreKeys.add(Relation.TARGET_PROPERTY);
this.ignoreKeys.add(OrientBaseGraph.CONNECTION_OUT.toLowerCase());
this.ignoreKeys.add(OrientBaseGraph.CONNECTION_IN.toLowerCase());
this.ignoreKeys.add(OrientBaseGraph.CONNECTION_OUT.toUpperCase());
this.ignoreKeys.add(OrientBaseGraph.CONNECTION_IN.toUpperCase());
this.sourceEntityClass = sourceEntityClass;
this.targetEntityClass = targetEntityClass;
this.sourceEntityManagement = null;
this.targetEntityManagement = null;
}
protected BaseRelationManagement(AccessType accessType, Class<S> sourceEntityClass, Class<T> targetEntityClass, SecurityContext workingContext, OrientGraph orientGraph) {
this(accessType, sourceEntityClass, targetEntityClass);
this.orientGraph = orientGraph;
setWorkingContext(workingContext);
}
public SEM getSourceEntityManagement() throws ResourceRegistryException {
if(sourceEntityManagement == null) {
Vertex source = getElement().getVertex(Direction.OUT);
sourceEntityManagement = newSourceEntityManagement();
sourceEntityManagement.setElement(source);
}
sourceEntityManagement.setReload(reload);
return sourceEntityManagement;
}
public TEM getTargetEntityManagement() throws ResourceRegistryException {
if(targetEntityManagement == null) {
Vertex target = getElement().getVertex(Direction.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
public String serialize() throws ResourceRegistryException {
return serializeAsJson().toString();
}
@Override
public JsonNode serializeAsJson() throws ResourceRegistryException {
return serializeAsJson(true, true);
}
public JsonNode serializeAsJson(boolean includeSource, boolean includeTarget) throws ResourceRegistryException {
JsonNode relation = serializeSelfOnly();
try {
if(includeSource) {
BaseEntityManagement<S> sourceEntityManagement = getSourceEntityManagement();
((ObjectNode) relation).replace(Relation.SOURCE_PROPERTY, sourceEntityManagement.serializeSelfOnly());
}
if(includeTarget) {
BaseEntityManagement<T> targetEntityManagement = getTargetEntityManagement();
((ObjectNode) relation).replace(Relation.TARGET_PROPERTY, targetEntityManagement.serializeAsJson());
}
} 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;
}
@Override
protected Edge 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 " + elementType + ". No target definition found");
}
try {
targetEntityManagement.setJsonNode(jsonNode.get(Relation.TARGET_PROPERTY));
} catch(SchemaException e) {
StringBuilder errorMessage = new StringBuilder();
errorMessage.append("A ");
errorMessage.append(elementType);
errorMessage.append(" can be only created beetween ");
errorMessage.append(sourceEntityManagement.getAccessType().getName());
errorMessage.append(" and ");
errorMessage.append(targetEntityManagement.getAccessType().getName());
throw new ResourceRegistryException(errorMessage.toString(), e);
}
try {
targetEntityManagement.getElement();
} catch(Exception e) {
targetEntityManagement.internalCreate();
}
}
logger.trace("Creating {} beetween {} -> {}", elementType, getSourceEntityManagement().serialize(),
getTargetEntityManagement().serialize());
Vertex source = (Vertex) getSourceEntityManagement().getElement();
Vertex target = (Vertex) getTargetEntityManagement().getElement();
element = orientGraph.addEdge(null, source, target, elementType);
ERManagement.updateProperties(oClass, element, jsonNode, ignoreKeys, ignoreStartWithKeys);
return element;
}
protected abstract SEM newSourceEntityManagement() throws ResourceRegistryException;
protected abstract TEM newTargetEntityManagement() throws ResourceRegistryException;
@Override
protected Edge reallyUpdate() throws ResourceRegistryException {
logger.debug("Trying to update {} : {}", elementType, jsonNode);
Edge edge = getElement();
ERManagement.updateProperties(oClass, edge, jsonNode, ignoreKeys, ignoreStartWithKeys);
if(accessType.compareTo(AccessType.CONSISTS_OF) == 0) {
JsonNode target = jsonNode.get(Relation.TARGET_PROPERTY);
if(target != null) {
FacetManagement fm = new FacetManagement(getWorkingContext(), orientGraph);
fm.setJsonNode(target);
fm.internalUpdate();
}
}
logger.info("{} {} successfully updated", elementType, jsonNode);
return edge;
}
@Override
protected boolean reallyDelete() throws RelationNotFoundException, ResourceRegistryException {
logger.debug("Going to remove {} with UUID {}. Related {}s will be detached.", accessType.getName(), uuid,
targetEntityClass.getSimpleName());
getElement().remove();
return true;
}
}