2019-11-04 18:01:20 +01:00
|
|
|
package org.gcube.informationsystem.resourceregistry.instances.base;
|
2016-12-19 14:59:27 +01:00
|
|
|
|
|
|
|
import java.io.IOException;
|
2017-01-18 14:57:20 +01:00
|
|
|
import java.text.DateFormat;
|
2019-11-04 18:01:20 +01:00
|
|
|
import java.util.ArrayList;
|
2017-01-18 14:57:20 +01:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.Date;
|
2016-12-19 14:59:27 +01:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashSet;
|
|
|
|
import java.util.Iterator;
|
2019-11-04 18:01:20 +01:00
|
|
|
import java.util.List;
|
2016-12-19 14:59:27 +01:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map.Entry;
|
|
|
|
import java.util.Set;
|
2016-12-30 17:31:12 +01:00
|
|
|
import java.util.UUID;
|
2016-12-19 14:59:27 +01:00
|
|
|
|
2017-06-28 16:29:01 +02:00
|
|
|
import javax.activation.UnsupportedDataTypeException;
|
|
|
|
|
2020-07-07 17:15:22 +02:00
|
|
|
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.com.fasterxml.jackson.databind.node.JsonNodeType;
|
|
|
|
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
|
|
|
import org.gcube.com.fasterxml.jackson.databind.node.TextNode;
|
2020-03-16 14:51:13 +01:00
|
|
|
import org.gcube.common.authorization.library.provider.CalledMethodProvider;
|
2019-10-25 17:45:59 +02:00
|
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
2020-01-30 11:04:16 +01:00
|
|
|
import org.gcube.informationsystem.base.reference.Element;
|
2020-02-03 10:52:09 +01:00
|
|
|
import org.gcube.informationsystem.base.reference.IdentifiableElement;
|
2020-01-20 10:29:56 +01:00
|
|
|
import org.gcube.informationsystem.model.reference.properties.Header;
|
2018-06-04 15:31:13 +02:00
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.AlreadyPresentException;
|
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.AvailableInAnotherContextException;
|
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.NotFoundException;
|
2016-12-19 14:59:27 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
2016-12-30 17:31:12 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.context.ContextException;
|
2017-03-27 15:04:44 +02:00
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
|
2021-02-18 18:22:39 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaViolationException;
|
2020-01-27 17:07:37 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility;
|
2020-11-03 16:30:24 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.contexts.security.AdminSecurityContext;
|
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;
|
2020-01-30 11:53:15 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.instances.base.properties.PropertyElementManagement;
|
2021-03-02 10:25:58 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.instances.model.Operation;
|
2021-02-11 14:35:54 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.types.CachedType;
|
2021-02-08 16:26:58 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
|
2017-01-18 14:57:20 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.utils.HeaderOrient;
|
2016-12-30 17:31:12 +01:00
|
|
|
import org.gcube.informationsystem.resourceregistry.utils.HeaderUtility;
|
|
|
|
import org.gcube.informationsystem.resourceregistry.utils.Utility;
|
2021-02-22 12:38:12 +01:00
|
|
|
import org.gcube.informationsystem.types.reference.Type;
|
2021-02-23 17:31:46 +01:00
|
|
|
import org.gcube.informationsystem.types.reference.entities.ResourceType;
|
2021-02-22 12:38:12 +01:00
|
|
|
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
2016-12-19 14:59:27 +01:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
|
2017-01-11 12:06:50 +01:00
|
|
|
import com.orientechnologies.orient.core.metadata.schema.OClass;
|
2017-01-18 14:57:20 +01:00
|
|
|
import com.orientechnologies.orient.core.metadata.schema.OProperty;
|
|
|
|
import com.orientechnologies.orient.core.metadata.schema.OType;
|
2019-11-05 18:36:44 +01:00
|
|
|
import com.orientechnologies.orient.core.record.OElement;
|
2017-01-18 14:57:20 +01:00
|
|
|
import com.orientechnologies.orient.core.record.impl.ODocument;
|
|
|
|
import com.orientechnologies.orient.core.util.ODateHelper;
|
2016-12-19 14:59:27 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Luca Frosini (ISTI - CNR)
|
|
|
|
*/
|
2021-02-22 16:36:19 +01:00
|
|
|
public abstract class ElementManagement<El extends OElement, T extends Type> {
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-15 19:31:49 +01:00
|
|
|
protected Logger logger = LoggerFactory.getLogger(this.getClass());
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
public final static String DELETED = "deleted";
|
|
|
|
|
2021-01-29 16:13:33 +01:00
|
|
|
public final static String AT = "@";
|
|
|
|
public final static String UNDERSCORE = "_";
|
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
protected final Set<String> ignoreKeys;
|
|
|
|
protected final Set<String> ignoreStartWithKeys;
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-03-29 16:53:37 +02:00
|
|
|
protected Class<El> elementClass;
|
2017-11-17 11:42:37 +01:00
|
|
|
protected final AccessType accessType;
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
protected ODatabaseDocument oDatabaseDocument;
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
protected UUID uuid;
|
|
|
|
protected JsonNode jsonNode;
|
2017-03-29 16:53:37 +02:00
|
|
|
protected OClass oClass;
|
2021-02-18 09:42:51 +01:00
|
|
|
protected String typeName;
|
2021-02-17 15:52:09 +01:00
|
|
|
|
|
|
|
protected JsonNode self;
|
|
|
|
protected JsonNode complete;
|
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
protected CachedType<T> cachedType;
|
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
protected El element;
|
2017-11-21 18:18:11 +01:00
|
|
|
protected boolean reload;
|
2017-11-15 19:31:49 +01:00
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
/**
|
|
|
|
* Some operation, e.g. delete has a cascade impact which is not know a priori by the client.
|
|
|
|
* Setting this variable to false the system just simulate the operation so an interested client
|
|
|
|
* could know the impact in advance.
|
|
|
|
*
|
|
|
|
* By the default the system execute effectively the requested operation.
|
|
|
|
* So this variable is initialised as false.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
protected boolean dryRun;
|
|
|
|
|
2021-03-01 16:42:34 +01:00
|
|
|
/**
|
2021-03-05 10:46:59 +01:00
|
|
|
* An operation can affects multiple instances (e.g. create, update)
|
2021-03-01 16:42:34 +01:00
|
|
|
* We need to know if the instance is the entry point of the operation
|
|
|
|
* or if it is just a subordinated operation.
|
2021-03-05 17:22:01 +01:00
|
|
|
* This is required for example in delete to trigger sanity check
|
|
|
|
* in the Resource when the action is performed directly on the Facet.
|
|
|
|
* Resource sanity check is not required to be triggered by the Facet
|
2021-03-01 16:42:34 +01:00
|
|
|
* because the entry point of the action already take care
|
2021-03-05 17:22:01 +01:00
|
|
|
* of triggering this action (e.g. the delete was invoked on the Resource and
|
2021-03-01 16:42:34 +01:00
|
|
|
* each describing Facets must not trigger multiple time the sanityCheck).
|
|
|
|
*/
|
|
|
|
protected boolean entryPoint;
|
|
|
|
|
2021-03-02 10:25:58 +01:00
|
|
|
/**
|
|
|
|
* It is assigned only in the entry point
|
|
|
|
*/
|
|
|
|
protected Operation operation;
|
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
/**
|
|
|
|
* A Delete operation has a cascade impact we could want to know the impact
|
|
|
|
* Instances affected by a delete
|
|
|
|
*/
|
|
|
|
protected final Map<UUID,JsonNode> affectedInstances;
|
|
|
|
|
2021-03-01 16:42:34 +01:00
|
|
|
protected ElementManagement(AccessType accessType) {
|
|
|
|
this.accessType = accessType;
|
|
|
|
|
|
|
|
this.ignoreKeys = new HashSet<String>();
|
|
|
|
|
|
|
|
this.ignoreStartWithKeys = new HashSet<String>();
|
|
|
|
|
|
|
|
this.ignoreStartWithKeys.add(ElementManagement.AT);
|
|
|
|
this.ignoreStartWithKeys.add(ElementManagement.UNDERSCORE);
|
|
|
|
|
|
|
|
this.reload = false;
|
|
|
|
|
|
|
|
this.entryPoint = false;
|
2021-03-02 10:25:58 +01:00
|
|
|
this.operation = null;
|
2021-03-05 11:59:24 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* By the default the system execute the operation
|
|
|
|
* which has a cascade impact so this variable is initialised as false.
|
|
|
|
*/
|
|
|
|
this.dryRun = false;
|
|
|
|
|
|
|
|
this.affectedInstances = new HashMap<>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Map<UUID,JsonNode> getAffectedInstances() {
|
|
|
|
return affectedInstances;
|
2021-03-02 10:25:58 +01:00
|
|
|
}
|
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
public boolean isDryRun() {
|
|
|
|
return dryRun;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setDryRun(boolean dryRun) {
|
|
|
|
this.dryRun = dryRun;
|
|
|
|
}
|
|
|
|
|
2021-03-04 11:45:27 +01:00
|
|
|
protected void setAsEntryPoint() {
|
2021-03-03 17:18:36 +01:00
|
|
|
this.entryPoint = true;
|
2021-03-04 11:45:27 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setOperation(Operation operation) {
|
2021-03-02 10:25:58 +01:00
|
|
|
this.operation = operation;
|
2021-03-01 16:42:34 +01:00
|
|
|
}
|
|
|
|
|
2021-03-04 10:24:21 +01:00
|
|
|
protected void cleanCachedSerialization() {
|
2021-02-17 15:52:09 +01:00
|
|
|
this.self = null;
|
|
|
|
this.complete = null;
|
|
|
|
}
|
|
|
|
|
2018-06-04 15:34:20 +02:00
|
|
|
public UUID getUUID() {
|
|
|
|
return uuid;
|
|
|
|
}
|
2021-03-01 16:42:34 +01:00
|
|
|
|
2017-11-21 18:18:11 +01:00
|
|
|
public boolean isReload() {
|
|
|
|
return reload;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-21 18:18:11 +01:00
|
|
|
public void setReload(boolean reload) {
|
|
|
|
this.reload = reload;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-17 11:42:37 +01:00
|
|
|
public AccessType getAccessType() {
|
|
|
|
return accessType;
|
|
|
|
}
|
|
|
|
|
2017-11-28 17:34:43 +01:00
|
|
|
protected SecurityContext workingContext;
|
|
|
|
|
|
|
|
protected SecurityContext getWorkingContext() throws ResourceRegistryException {
|
|
|
|
if(workingContext == null) {
|
|
|
|
workingContext = ContextUtility.getCurrentSecurityContext();
|
|
|
|
}
|
|
|
|
return workingContext;
|
2017-11-15 19:31:49 +01:00
|
|
|
}
|
2017-11-28 17:34:43 +01:00
|
|
|
|
|
|
|
public void setWorkingContext(SecurityContext workingContext) {
|
|
|
|
this.workingContext = workingContext;
|
2017-11-15 19:31:49 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
public void setUUID(UUID uuid) throws ResourceRegistryException {
|
|
|
|
this.uuid = uuid;
|
2017-11-30 18:06:08 +01:00
|
|
|
if(jsonNode != null) {
|
2016-12-30 17:31:12 +01:00
|
|
|
checkUUIDMatch();
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
public void setJsonNode(JsonNode jsonNode) throws ResourceRegistryException {
|
2016-12-30 17:31:12 +01:00
|
|
|
this.jsonNode = jsonNode;
|
2019-02-13 12:33:29 +01:00
|
|
|
checkJsonNode();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-11 14:35:54 +01:00
|
|
|
public void setJson(String json) throws ResourceRegistryException {
|
2016-12-30 17:31:12 +01:00
|
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
|
|
try {
|
2021-02-11 14:35:54 +01:00
|
|
|
this.jsonNode = mapper.readTree(json);
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(IOException e) {
|
2016-12-30 17:31:12 +01:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
}
|
2019-02-13 12:33:29 +01:00
|
|
|
checkJsonNode();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-23 14:44:37 +01:00
|
|
|
public void setODatabaseDocument(ODatabaseDocument oDatabaseDocument) {
|
2021-02-10 15:45:48 +01:00
|
|
|
this.oDatabaseDocument = oDatabaseDocument;
|
|
|
|
}
|
|
|
|
|
2019-11-08 12:29:32 +01:00
|
|
|
public void setOClass(OClass oClass) {
|
|
|
|
this.oClass = oClass;
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:31:49 +01:00
|
|
|
protected OClass getOClass() throws SchemaException, ResourceRegistryException {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(oClass == null) {
|
|
|
|
if(element != null) {
|
2021-02-23 12:27:42 +01:00
|
|
|
try {
|
|
|
|
oClass = ElementManagementUtility.getOClass(element);
|
2021-03-03 17:18:36 +01:00
|
|
|
if(typeName==null) {
|
|
|
|
typeName = oClass.getName();
|
|
|
|
}
|
2021-02-23 12:27:42 +01:00
|
|
|
getCachedType().setOClass(oClass);
|
|
|
|
}catch (ResourceRegistryException e) {
|
|
|
|
try {
|
|
|
|
oClass = getCachedType().getOClass();
|
2021-03-03 17:18:36 +01:00
|
|
|
if(typeName==null) {
|
|
|
|
typeName = oClass.getName();
|
|
|
|
}
|
2021-02-23 12:27:42 +01:00
|
|
|
}catch (Exception e1) {
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
2017-11-28 17:34:43 +01:00
|
|
|
} else {
|
2021-03-03 17:18:36 +01:00
|
|
|
if(typeName==null) {
|
|
|
|
throw new SchemaException("Unknown type name. Please set it first.");
|
|
|
|
}
|
2021-02-22 16:36:19 +01:00
|
|
|
oClass = getCachedType().getOClass();
|
2021-02-11 14:35:54 +01:00
|
|
|
AccessType gotAccessType = cachedType.getAccessType();
|
2021-02-10 15:45:48 +01:00
|
|
|
if(accessType!=gotAccessType) {
|
2021-02-18 09:42:51 +01:00
|
|
|
throw new SchemaException(typeName + " is not a " + accessType.getName());
|
2021-02-10 15:45:48 +01:00
|
|
|
}
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return oClass;
|
2017-03-27 15:04:44 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
protected CachedType<T> getCachedType(){
|
|
|
|
if(cachedType==null) {
|
|
|
|
TypesCache typesCache = TypesCache.getInstance();
|
|
|
|
cachedType = (CachedType<T>) typesCache.getCachedType(typeName);
|
|
|
|
}
|
|
|
|
return cachedType;
|
|
|
|
}
|
|
|
|
|
2020-01-20 10:29:56 +01:00
|
|
|
public void setElementType(String elementType) throws ResourceRegistryException {
|
2021-02-18 09:42:51 +01:00
|
|
|
if(this.typeName == null) {
|
2020-01-20 10:29:56 +01:00
|
|
|
if(elementType == null || elementType.compareTo("") == 0) {
|
|
|
|
elementType = accessType.getName();
|
2018-06-12 16:43:47 +02:00
|
|
|
}
|
2021-02-18 09:42:51 +01:00
|
|
|
this.typeName = elementType;
|
2018-06-12 18:09:36 +02:00
|
|
|
} else {
|
2020-01-20 10:29:56 +01:00
|
|
|
if(elementType.compareTo(elementType) != 0) {
|
2018-06-12 18:09:36 +02:00
|
|
|
throw new ResourceRegistryException(
|
2020-01-20 10:29:56 +01:00
|
|
|
"Provided type " + elementType + " does not match with the one already known " + this.accessType);
|
2018-06-12 16:43:47 +02:00
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2018-06-12 16:43:47 +02:00
|
|
|
|
2017-11-30 18:06:08 +01:00
|
|
|
if(jsonNode != null) {
|
2016-12-30 17:31:12 +01:00
|
|
|
checkERMatch();
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-23 11:33:57 +01:00
|
|
|
public String getTypeName() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
|
|
|
|
if(typeName==null) {
|
|
|
|
if(element!=null) {
|
|
|
|
typeName = element.getProperty(Element.CLASS_PROPERTY);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(typeName==null && jsonNode!=null) {
|
|
|
|
this.typeName = getClassProperty(jsonNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(typeName==null) {
|
|
|
|
typeName = getOClass().getName();
|
|
|
|
}
|
|
|
|
}
|
2021-02-18 09:42:51 +01:00
|
|
|
return typeName;
|
2018-06-08 18:18:48 +02:00
|
|
|
}
|
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
protected void checkJsonNode() throws ResourceRegistryException {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(uuid == null) {
|
2016-12-30 17:31:12 +01:00
|
|
|
try {
|
2019-02-13 12:33:29 +01:00
|
|
|
uuid = org.gcube.informationsystem.utils.Utility.getUUIDFromJsonNode(jsonNode);
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-11-28 17:34:43 +01:00
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
} else {
|
|
|
|
checkUUIDMatch();
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-18 09:42:51 +01:00
|
|
|
if(this.typeName == null) {
|
|
|
|
this.typeName = getClassProperty(jsonNode);
|
2017-03-29 16:14:03 +02:00
|
|
|
getOClass();
|
2016-12-30 17:31:12 +01:00
|
|
|
} else {
|
|
|
|
checkERMatch();
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
protected void checkERMatch() throws ResourceRegistryException {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(jsonNode != null) {
|
2017-01-13 17:06:57 +01:00
|
|
|
String type = getClassProperty(jsonNode);
|
2021-02-18 09:42:51 +01:00
|
|
|
if(type != null && type.compareTo(typeName) != 0) {
|
2018-06-06 19:26:19 +02:00
|
|
|
String error = String.format("Requested type does not match with json representation %s!=%s",
|
2021-02-18 09:42:51 +01:00
|
|
|
typeName, type);
|
2017-01-13 17:06:57 +01:00
|
|
|
logger.trace(error);
|
|
|
|
throw new ResourceRegistryException(error);
|
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2017-03-29 16:14:03 +02:00
|
|
|
getOClass();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
protected void checkUUIDMatch() throws ResourceRegistryException {
|
|
|
|
Header header = null;
|
|
|
|
try {
|
|
|
|
header = HeaderUtility.getHeader(jsonNode, false);
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2016-12-30 17:31:12 +01:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(header != null) {
|
2016-12-30 17:31:12 +01:00
|
|
|
UUID resourceUUID = header.getUUID();
|
2017-11-30 18:06:08 +01:00
|
|
|
if(resourceUUID.compareTo(uuid) != 0) {
|
2017-11-28 17:34:43 +01:00
|
|
|
String error = String.format(
|
|
|
|
"UUID provided in header (%s) differs from the one (%s) used to identify the %s instance",
|
2021-02-18 09:42:51 +01:00
|
|
|
resourceUUID.toString(), uuid.toString(), typeName);
|
2016-12-30 17:31:12 +01:00
|
|
|
throw new ResourceRegistryException(error);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
|
|
|
|
private JsonNode createSelfJsonNode() throws ResourceRegistryException {
|
2017-01-17 16:53:24 +01:00
|
|
|
try {
|
2021-02-16 18:43:47 +01:00
|
|
|
|
|
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
ObjectNode objectNode = objectMapper.createObjectNode();
|
|
|
|
OElement element = getElement();
|
|
|
|
Set<String> keys = element.getPropertyNames();
|
|
|
|
for(String key : keys) {
|
|
|
|
Object object = element.getProperty(key);
|
2021-08-05 19:44:11 +02:00
|
|
|
if(object == null) {
|
|
|
|
objectNode.replace(key, null);
|
|
|
|
continue;
|
|
|
|
}
|
2021-02-16 18:43:47 +01:00
|
|
|
JsonNode jsonNode = getPropertyForJson(key, object);
|
|
|
|
if(jsonNode != null) {
|
|
|
|
objectNode.replace(key, jsonNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
objectNode.put(Element.CLASS_PROPERTY, getTypeName());
|
2021-02-16 18:43:47 +01:00
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
Collection<String> superClasses = getCachedType().getSuperTypes();
|
2021-02-16 18:43:47 +01:00
|
|
|
ArrayNode arrayNode = objectMapper.valueToTree(superClasses);
|
|
|
|
|
|
|
|
objectNode.replace(Element.SUPERCLASSES_PROPERTY, arrayNode);
|
|
|
|
|
|
|
|
return objectNode;
|
|
|
|
} catch(ResourceRegistryException e) {
|
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2021-02-16 18:43:47 +01:00
|
|
|
throw new ResourceRegistryException("Error while serializing " + getElement().toString(), e);
|
2017-01-17 16:53:24 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-06 10:53:45 +01:00
|
|
|
public JsonNode serializeAsAffectedInstance() throws ResourceRegistryException {
|
|
|
|
return serializeSelfAsJsonNode();
|
|
|
|
}
|
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
public JsonNode serializeSelfAsJsonNode() throws ResourceRegistryException {
|
2021-02-16 18:43:47 +01:00
|
|
|
try {
|
2021-03-05 15:26:19 +01:00
|
|
|
if(self==null || reload) {
|
2021-02-17 15:52:09 +01:00
|
|
|
self = createSelfJsonNode();
|
|
|
|
}
|
|
|
|
return self.deepCopy();
|
2021-02-16 18:43:47 +01:00
|
|
|
} catch(Exception e) {
|
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
}
|
2021-02-05 17:50:16 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
protected abstract JsonNode createCompleteJsonNode() throws ResourceRegistryException;
|
2021-02-16 18:43:47 +01:00
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
public JsonNode serializeAsJsonNode() throws ResourceRegistryException {
|
2021-02-16 18:43:47 +01:00
|
|
|
try {
|
2021-03-05 15:26:19 +01:00
|
|
|
if(complete==null || reload) {
|
2021-02-17 15:52:09 +01:00
|
|
|
complete = createCompleteJsonNode();
|
|
|
|
}
|
|
|
|
return complete;
|
2021-02-16 18:43:47 +01:00
|
|
|
} catch(Exception e) {
|
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
protected abstract El reallyCreate() throws AlreadyPresentException, ResourceRegistryException;
|
2017-11-28 17:34:43 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
public El internalCreate() throws AlreadyPresentException, ResourceRegistryException {
|
2017-10-26 17:09:07 +02:00
|
|
|
try {
|
2021-03-04 11:45:27 +01:00
|
|
|
setOperation(Operation.CREATE);
|
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
reallyCreate();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
Header entityHeader = HeaderUtility.getHeader(jsonNode, true);
|
2017-11-30 18:06:08 +01:00
|
|
|
if(entityHeader != null) {
|
2020-02-03 10:52:09 +01:00
|
|
|
element.setProperty(IdentifiableElement.HEADER_PROPERTY, entityHeader);
|
2017-10-26 17:09:07 +02:00
|
|
|
} else {
|
|
|
|
entityHeader = HeaderUtility.addHeader(element, null);
|
2021-03-04 10:39:18 +01:00
|
|
|
uuid = entityHeader.getUUID();
|
2017-10-26 17:09:07 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
getWorkingContext().addElement(element, oDatabaseDocument);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
element.save();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-03 17:18:36 +01:00
|
|
|
sanityCheck();
|
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
return element;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-10-26 17:09:07 +02:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2021-02-18 09:42:51 +01:00
|
|
|
throw new ResourceRegistryException("Error Creating " + typeName + " with " + jsonNode, e);
|
2017-10-26 17:09:07 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
protected abstract El reallyUpdate() throws NotFoundException, ResourceRegistryException;
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
public El internalUpdate() throws NotFoundException, ResourceRegistryException {
|
2017-10-26 17:09:07 +02:00
|
|
|
try {
|
2021-03-04 11:45:27 +01:00
|
|
|
setOperation(Operation.UPDATE);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
reallyUpdate();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-13 12:41:41 +01:00
|
|
|
HeaderUtility.updateModifiedByAndLastUpdate(element);
|
2021-02-22 11:15:15 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
element.save();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-03 17:18:36 +01:00
|
|
|
sanityCheck();
|
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
return element;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-10-26 17:09:07 +02:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2021-02-18 09:42:51 +01:00
|
|
|
throw new ResourceRegistryException("Error Updating " + typeName + " with " + jsonNode, e);
|
2017-10-26 17:09:07 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
public El internalCreateOrUdate() throws ResourceRegistryException {
|
2017-07-06 17:45:22 +02:00
|
|
|
try {
|
2017-10-26 17:09:07 +02:00
|
|
|
return internalUpdate();
|
2018-06-04 15:31:13 +02:00
|
|
|
} catch(NotFoundException e) {
|
2017-10-26 17:09:07 +02:00
|
|
|
return internalCreate();
|
2017-07-06 17:45:22 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
protected abstract void reallyDelete() throws NotFoundException, ResourceRegistryException;
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
public void internalDelete() throws NotFoundException, ResourceRegistryException {
|
2021-03-04 11:45:27 +01:00
|
|
|
setOperation(Operation.DELETE);
|
2021-03-05 11:59:24 +01:00
|
|
|
reallyDelete();
|
|
|
|
sanityCheck();
|
2017-10-26 17:09:07 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
public void setElement(El element) throws ResourceRegistryException {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(element == null) {
|
2017-11-28 17:34:43 +01:00
|
|
|
throw new ResourceRegistryException("Trying to set null " + elementClass.getSimpleName() + " in " + this);
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
this.element = element;
|
|
|
|
this.uuid = HeaderUtility.getHeader(element).getUUID();
|
2019-11-05 18:36:44 +01:00
|
|
|
OClass oClass = getOClass();
|
2021-02-18 09:42:51 +01:00
|
|
|
this.typeName = oClass.getName();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 10:46:59 +01:00
|
|
|
protected abstract NotFoundException getSpecificNotFoundException(NotFoundException e);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 10:46:59 +01:00
|
|
|
protected abstract AlreadyPresentException getSpecificAlreadyPresentException(String message);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
public El getElement() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(element == null) {
|
2017-04-04 15:03:25 +02:00
|
|
|
try {
|
|
|
|
element = retrieveElement();
|
2018-06-04 15:31:13 +02:00
|
|
|
} catch(NotFoundException e) {
|
2021-02-05 17:50:16 +01:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-04-04 15:03:25 +02:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-04-04 15:03:25 +02:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-28 17:34:43 +01:00
|
|
|
} else {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(reload) {
|
2019-11-05 18:36:44 +01:00
|
|
|
element.reload();
|
2017-11-21 18:18:11 +01:00
|
|
|
}
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
2017-04-04 15:03:25 +02:00
|
|
|
return element;
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
public El retrieveElement() throws NotFoundException, ResourceRegistryException {
|
2016-12-30 17:31:12 +01:00
|
|
|
try {
|
2017-11-30 18:06:08 +01:00
|
|
|
if(uuid == null) {
|
2018-06-04 15:31:13 +02:00
|
|
|
throw new NotFoundException("null UUID does not allow to retrieve the Element");
|
2017-07-06 17:45:22 +02:00
|
|
|
}
|
2021-02-18 09:42:51 +01:00
|
|
|
return Utility.getElementByUUID(oDatabaseDocument, typeName == null ? accessType.getName() : typeName, uuid,
|
2017-11-28 17:34:43 +01:00
|
|
|
elementClass);
|
2018-06-04 15:31:13 +02:00
|
|
|
} catch(NotFoundException e) {
|
2021-03-05 10:46:59 +01:00
|
|
|
throw getSpecificNotFoundException(e);
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-03-29 16:14:03 +02:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-03-29 16:14:03 +02:00
|
|
|
throw new ResourceRegistryException(e);
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
public El retrieveElementFromAnyContext() throws NotFoundException, ResourceRegistryException {
|
2017-11-28 17:34:43 +01:00
|
|
|
try {
|
2021-02-18 09:42:51 +01:00
|
|
|
return Utility.getElementByUUIDAsAdmin(typeName == null ? accessType.getName() : typeName, uuid,
|
2018-06-12 18:09:36 +02:00
|
|
|
elementClass);
|
2018-06-04 15:31:13 +02:00
|
|
|
} catch(NotFoundException e) {
|
2021-03-05 10:46:59 +01:00
|
|
|
throw getSpecificNotFoundException(e);
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-04-04 15:03:25 +02:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-04-04 15:03:25 +02:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
}
|
2017-11-28 17:34:43 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-28 17:34:43 +01:00
|
|
|
public abstract String reallyGetAll(boolean polymorphic) throws ResourceRegistryException;
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-01-11 12:06:50 +01:00
|
|
|
public String all(boolean polymorphic) throws ResourceRegistryException {
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2017-01-11 12:06:50 +01:00
|
|
|
try {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.READER);
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
|
|
|
setOperation(Operation.QUERY);
|
2017-01-11 12:06:50 +01:00
|
|
|
return reallyGetAll(polymorphic);
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-01-11 12:06:50 +01:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-01-11 12:06:50 +01:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2017-01-11 12:06:50 +01:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2017-01-11 12:06:50 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-12 18:09:36 +02:00
|
|
|
public boolean exists() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2017-03-28 16:02:23 +02:00
|
|
|
try {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.READER);
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
|
|
|
setOperation(Operation.EXISTS);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-04-04 15:03:25 +02:00
|
|
|
getElement();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-04-04 15:03:25 +02:00
|
|
|
return true;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to find {} with UUID {}", accessType.getName(), uuid);
|
2017-03-28 16:02:23 +02:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to find {} with UUID {}", accessType.getName(), uuid, e);
|
2017-03-28 16:02:23 +02:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2017-03-28 16:02:23 +02:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2017-03-28 16:02:23 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
public String createOrUpdate()
|
|
|
|
throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2018-06-12 18:09:36 +02:00
|
|
|
try {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.WRITER);
|
|
|
|
oDatabaseDocument.begin();
|
2018-06-12 18:09:36 +02:00
|
|
|
boolean update = false;
|
|
|
|
try {
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
2018-06-12 18:09:36 +02:00
|
|
|
getElement();
|
|
|
|
update = true;
|
2021-02-22 11:15:15 +01:00
|
|
|
internalUpdate();
|
2019-02-13 12:33:29 +01:00
|
|
|
} catch(NotFoundException e) {
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
2020-03-16 14:51:13 +01:00
|
|
|
String calledMethod = CalledMethodProvider.instance.get();
|
|
|
|
calledMethod = calledMethod.replace("update", "create");
|
|
|
|
CalledMethodProvider.instance.set(calledMethod);
|
2021-02-22 11:15:15 +01:00
|
|
|
internalCreate();
|
2018-06-12 18:09:36 +02:00
|
|
|
}
|
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument.commit();
|
2018-06-12 18:09:36 +02:00
|
|
|
|
|
|
|
if(update) {
|
|
|
|
setReload(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO Notify to subscriptionNotification
|
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
return serializeAsJsonNode().toString();
|
2018-06-12 18:09:36 +02:00
|
|
|
|
|
|
|
} catch(ResourceRegistryException e) {
|
|
|
|
logger.error("Unable to update {} with UUID {}", accessType.getName(), uuid);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2018-06-12 18:09:36 +02:00
|
|
|
}
|
|
|
|
throw e;
|
|
|
|
} catch(Exception e) {
|
|
|
|
logger.error("Unable to update {} with UUID {}", accessType.getName(), uuid, e);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2018-06-12 18:09:36 +02:00
|
|
|
}
|
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2018-06-12 18:09:36 +02:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2018-06-12 18:09:36 +02:00
|
|
|
}
|
2018-06-12 17:55:46 +02:00
|
|
|
}
|
|
|
|
|
2018-06-12 18:09:36 +02:00
|
|
|
public String create() throws AlreadyPresentException, ResourceRegistryException {
|
2021-03-04 11:45:27 +01:00
|
|
|
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2017-05-03 11:21:45 +02:00
|
|
|
try {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.WRITER);
|
|
|
|
oDatabaseDocument.begin();
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-22 11:15:15 +01:00
|
|
|
internalCreate();
|
2021-02-18 18:22:39 +01:00
|
|
|
|
2021-02-19 15:31:26 +01:00
|
|
|
oDatabaseDocument.commit();
|
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
// TODO Notify to subscriptionNotification
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
return serializeAsJsonNode().toString();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
} catch(ResourceRegistryException e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to create {}", accessType.getName());
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2017-05-03 11:21:45 +02:00
|
|
|
}
|
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to create {}", accessType.getName(), e);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2017-05-03 11:21:45 +02:00
|
|
|
}
|
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2017-05-03 11:21:45 +02:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2017-05-03 11:21:45 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-08 16:26:58 +01:00
|
|
|
public String read() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
|
2021-03-04 11:45:27 +01:00
|
|
|
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2016-12-30 17:31:12 +01:00
|
|
|
try {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.READER);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
|
|
|
setOperation(Operation.READ);
|
|
|
|
|
2016-12-30 17:31:12 +01:00
|
|
|
getElement();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
return serializeAsJsonNode().toString();
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to read {} with UUID {}", accessType.getName(), uuid);
|
2016-12-30 17:31:12 +01:00
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to read {} with UUID {}", accessType.getName(), uuid, e);
|
2016-12-30 17:31:12 +01:00
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2018-06-04 15:31:13 +02:00
|
|
|
public String update() throws NotFoundException, AvailableInAnotherContextException, ResourceRegistryException {
|
2021-03-04 11:45:27 +01:00
|
|
|
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2016-12-30 17:31:12 +01:00
|
|
|
try {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.WRITER);
|
|
|
|
oDatabaseDocument.begin();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
2021-02-22 11:15:15 +01:00
|
|
|
internalUpdate();
|
2021-02-19 15:31:26 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument.commit();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-11-21 18:18:11 +01:00
|
|
|
setReload(true);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-10-26 17:09:07 +02:00
|
|
|
// TODO Notify to subscriptionNotification
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-17 11:29:43 +01:00
|
|
|
return serializeAsJsonNode().toString();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
} catch(ResourceRegistryException e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to update {} with UUID {}", accessType.getName(), uuid);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to update {} with UUID {}", accessType.getName(), uuid, e);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 15:14:51 +01:00
|
|
|
public void delete() throws NotFoundException, AvailableInAnotherContextException, SchemaViolationException, ResourceRegistryException {
|
2017-03-29 16:53:37 +02:00
|
|
|
logger.debug("Going to delete {} with UUID {}", accessType.getName(), uuid);
|
2019-11-11 16:09:47 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
2016-12-30 17:31:12 +01:00
|
|
|
try {
|
2021-09-16 15:23:04 +02:00
|
|
|
// oDatabaseDocument = ContextUtility.getAdminSecurityContext().getDatabaseDocument(PermissionMode.WRITER);
|
|
|
|
oDatabaseDocument = getWorkingContext().getDatabaseDocument(PermissionMode.WRITER);
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument.begin();
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
internalDelete();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-03-05 11:59:24 +01:00
|
|
|
if(!dryRun) {
|
2019-11-05 18:36:44 +01:00
|
|
|
oDatabaseDocument.commit();
|
2017-11-28 17:34:43 +01:00
|
|
|
logger.info("{} with UUID {} was successfully deleted.", accessType.getName(), uuid);
|
2021-03-05 11:59:24 +01:00
|
|
|
}else {
|
|
|
|
oDatabaseDocument.rollback();
|
2017-04-04 15:03:25 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2017-11-23 12:40:35 +01:00
|
|
|
logger.error("Unable to delete {} with UUID {}", accessType.getName(), uuid);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
throw e;
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-03-29 16:53:37 +02:00
|
|
|
logger.error("Unable to delete {} with UUID {}", accessType.getName(), uuid, e);
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.rollback();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
throw new ResourceRegistryException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2020-11-03 16:30:24 +01:00
|
|
|
|
2020-11-09 15:45:07 +01:00
|
|
|
public Set<String> getContextsSet() throws NotFoundException, ContextException, ResourceRegistryException {
|
2021-02-18 09:42:51 +01:00
|
|
|
logger.debug("Going to get contexts for {} with UUID", typeName, uuid);
|
2020-11-03 16:30:24 +01:00
|
|
|
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
|
|
|
try {
|
|
|
|
AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext();
|
|
|
|
oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.READER);
|
|
|
|
|
2021-03-04 11:45:27 +01:00
|
|
|
setAsEntryPoint();
|
|
|
|
setOperation(Operation.GET_METADATA);
|
|
|
|
|
2020-11-03 16:30:24 +01:00
|
|
|
Set<String> contexts = SecurityContext.getContexts(getElement());
|
2020-11-09 15:45:07 +01:00
|
|
|
return contexts;
|
2020-11-03 16:30:24 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2021-02-18 09:42:51 +01:00
|
|
|
logger.error("Unable to get contexts for {} with UUID {}", typeName, uuid, e);
|
2020-11-03 16:30:24 +01:00
|
|
|
throw e;
|
|
|
|
} catch(Exception e) {
|
2021-02-18 09:42:51 +01:00
|
|
|
logger.error("Unable to get contexts for {} with UUID {}", typeName, uuid, e);
|
2020-11-03 16:30:24 +01:00
|
|
|
throw new ContextException(e);
|
|
|
|
} finally {
|
2019-11-05 18:36:44 +01:00
|
|
|
if(oDatabaseDocument != null) {
|
|
|
|
oDatabaseDocument.close();
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2019-11-11 16:09:47 +01:00
|
|
|
|
|
|
|
if(current!=null) {
|
|
|
|
current.activateOnCurrentThread();
|
|
|
|
}
|
2016-12-30 17:31:12 +01:00
|
|
|
}
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2020-11-09 15:45:07 +01:00
|
|
|
public String getContexts() throws NotFoundException, ContextException, ResourceRegistryException {
|
|
|
|
try {
|
|
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
ArrayNode arrayNode = getContextsAsArrayNode(objectMapper);
|
|
|
|
return objectMapper.writeValueAsString(arrayNode);
|
|
|
|
} catch(ResourceRegistryException e) {
|
|
|
|
throw e;
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new ContextException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ArrayNode getContextsAsArrayNode(ObjectMapper objectMapper) throws NotFoundException, ContextException, ResourceRegistryException {
|
|
|
|
try {
|
|
|
|
Set<String> contexts = getContextsSet();
|
|
|
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
|
|
|
for(String contextUUID : contexts) {
|
|
|
|
arrayNode.add(contextUUID);
|
|
|
|
}
|
|
|
|
return arrayNode;
|
|
|
|
} catch(ResourceRegistryException e) {
|
|
|
|
throw e;
|
|
|
|
} catch (Exception e) {
|
|
|
|
throw new ContextException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
public static String getClassProperty(JsonNode jsonNode) {
|
2020-01-30 11:04:16 +01:00
|
|
|
if(jsonNode.has(Element.CLASS_PROPERTY)) {
|
|
|
|
return jsonNode.get(Element.CLASS_PROPERTY).asText();
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
public static Object getObjectFromElement(JsonNode value)
|
2017-11-28 17:34:43 +01:00
|
|
|
throws UnsupportedDataTypeException, ResourceRegistryException {
|
2016-12-19 14:59:27 +01:00
|
|
|
JsonNodeType jsonNodeType = value.getNodeType();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
switch(jsonNodeType) {
|
|
|
|
case OBJECT:
|
2020-01-30 11:53:15 +01:00
|
|
|
return PropertyElementManagement.getPropertyDocument(value);
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
case ARRAY:
|
|
|
|
List<Object> list = new ArrayList<Object>();
|
|
|
|
Iterator<JsonNode> arrayElement = value.elements();
|
|
|
|
while(arrayElement.hasNext()) {
|
|
|
|
JsonNode arrayNode = arrayElement.next();
|
|
|
|
Object objectNode = getObjectFromElement(arrayNode);
|
|
|
|
if(objectNode != null) {
|
|
|
|
list.add(objectNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return list;
|
2019-11-04 18:01:20 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* List/Set support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354
|
|
|
|
*
|
2017-11-30 18:06:08 +01:00
|
|
|
throw new UnsupportedDataTypeException(
|
|
|
|
"List/Set support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354");
|
2019-11-04 18:01:20 +01:00
|
|
|
*/
|
2017-11-30 18:06:08 +01:00
|
|
|
case BINARY:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case BOOLEAN:
|
|
|
|
return value.asBoolean();
|
|
|
|
|
|
|
|
case NULL:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NUMBER:
|
|
|
|
if(value.isDouble() || value.isFloat()) {
|
|
|
|
return value.asDouble();
|
|
|
|
}
|
|
|
|
if(value.isBigInteger() || value.isShort() || value.isInt()) {
|
|
|
|
return value.asInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(value.isLong()) {
|
|
|
|
return value.asLong();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STRING:
|
|
|
|
return value.asText();
|
|
|
|
|
|
|
|
case MISSING:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case POJO:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
return null;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-08 16:26:58 +01:00
|
|
|
public Map<String,Object> getPropertyMap(JsonNode jsonNode, Set<String> ignoreKeys,
|
2017-11-28 17:34:43 +01:00
|
|
|
Set<String> ignoreStartWith) throws JsonProcessingException, IOException {
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
Map<String,Object> map = new HashMap<>();
|
|
|
|
|
|
|
|
if(ignoreKeys == null) {
|
2016-12-19 14:59:27 +01:00
|
|
|
ignoreKeys = new HashSet<>();
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(ignoreStartWith == null) {
|
2016-12-19 14:59:27 +01:00
|
|
|
ignoreStartWith = new HashSet<>();
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
Iterator<Entry<String,JsonNode>> fields = jsonNode.fields();
|
|
|
|
|
|
|
|
OUTER_WHILE: while(fields.hasNext()) {
|
|
|
|
Entry<String,JsonNode> entry = fields.next();
|
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
String key = entry.getKey();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(ignoreKeys.contains(key)) {
|
2016-12-19 14:59:27 +01:00
|
|
|
continue;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
for(String prefix : ignoreStartWith) {
|
|
|
|
if(key.startsWith(prefix)) {
|
2016-12-19 14:59:27 +01:00
|
|
|
continue OUTER_WHILE;
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
JsonNode value = entry.getValue();
|
|
|
|
Object object = null;
|
|
|
|
try {
|
|
|
|
object = getObjectFromElement(value);
|
2017-11-30 18:06:08 +01:00
|
|
|
if(object != null) {
|
2016-12-19 14:59:27 +01:00
|
|
|
map.put(key, object);
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(ResourceRegistryException e) {
|
2021-02-08 16:26:58 +01:00
|
|
|
logger.warn("An invalidy property has been provided. It will be ignored.");
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
return map;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-08 16:26:58 +01:00
|
|
|
public OElement updateProperties(OClass oClass, OElement element, JsonNode jsonNode, Set<String> ignoreKeys,
|
2017-11-28 17:34:43 +01:00
|
|
|
Set<String> ignoreStartWithKeys) throws ResourceRegistryException {
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
Set<String> oldKeys = element.getPropertyNames();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
Map<String,Object> properties;
|
2019-11-08 12:29:32 +01:00
|
|
|
try {
|
|
|
|
properties = getPropertyMap(jsonNode, ignoreKeys, ignoreStartWithKeys);
|
|
|
|
} catch(IOException e) {
|
|
|
|
throw new ResourceRegistryException(e);
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
oldKeys.removeAll(properties.keySet());
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
for(String key : properties.keySet()) {
|
2016-12-19 14:59:27 +01:00
|
|
|
try {
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2017-03-27 15:04:44 +02:00
|
|
|
Object object = properties.get(key);
|
2019-02-13 12:33:29 +01:00
|
|
|
|
|
|
|
boolean set = false;
|
|
|
|
|
|
|
|
if(object instanceof ODocument) {
|
|
|
|
ODocument oDocument = (ODocument) object;
|
2019-11-05 18:36:44 +01:00
|
|
|
element.setProperty(key, oDocument, OType.EMBEDDED);
|
2019-02-13 12:33:29 +01:00
|
|
|
set = true;
|
2017-03-27 15:04:44 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
/*
|
|
|
|
* List/Set support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354
|
|
|
|
*/
|
|
|
|
if(object instanceof Set) {
|
2019-11-05 18:36:44 +01:00
|
|
|
element.setProperty(key, object, OType.EMBEDDEDSET);
|
2019-02-13 12:33:29 +01:00
|
|
|
set = true;
|
|
|
|
}
|
|
|
|
if(object instanceof List) {
|
2019-11-05 18:36:44 +01:00
|
|
|
element.setProperty(key, object, OType.EMBEDDEDLIST);
|
2019-02-13 12:33:29 +01:00
|
|
|
set = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!set) {
|
|
|
|
element.setProperty(key, object);
|
|
|
|
}
|
|
|
|
|
2017-11-30 18:06:08 +01:00
|
|
|
} catch(Exception e) {
|
2017-11-28 17:34:43 +01:00
|
|
|
String error = String.format("Error while setting property %s : %s (%s)", key,
|
|
|
|
properties.get(key).toString(), e.getMessage());
|
2021-02-08 16:26:58 +01:00
|
|
|
logger.error(error);
|
2016-12-19 14:59:27 +01:00
|
|
|
throw new ResourceRegistryException(error, e);
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
OUTER_FOR: for(String key : oldKeys) {
|
|
|
|
|
|
|
|
if(ignoreKeys.contains(key)) {
|
2016-12-19 14:59:27 +01:00
|
|
|
continue;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
for(String prefix : ignoreStartWithKeys) {
|
|
|
|
if(key.startsWith(prefix)) {
|
2016-12-19 14:59:27 +01:00
|
|
|
continue OUTER_FOR;
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
element.removeProperty(key);
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-11-05 18:36:44 +01:00
|
|
|
element.save();
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
return element;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
protected JsonNode getPropertyForJson(String key, Object object) throws ResourceRegistryException {
|
2017-01-18 14:57:20 +01:00
|
|
|
try {
|
2021-08-05 16:41:29 +02:00
|
|
|
if(object == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
if(object instanceof JsonNode) {
|
|
|
|
return (JsonNode) object;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
2020-02-03 10:52:09 +01:00
|
|
|
if(key.compareTo(IdentifiableElement.HEADER_PROPERTY) == 0) {
|
2017-03-29 16:14:03 +02:00
|
|
|
// Keeping the header
|
|
|
|
HeaderOrient headerOrient = HeaderUtility.getHeaderOrient((ODocument) object);
|
2020-11-09 15:45:07 +01:00
|
|
|
JsonNode headerJson = Utility.toJsonNode(headerOrient, false);
|
|
|
|
if(ContextUtility.getIncludeInstanceContexts().get()) {
|
|
|
|
((ObjectNode) headerJson).set(Header.__CONTEXTS, getContextsAsArrayNode(objectMapper));
|
|
|
|
}
|
|
|
|
return headerJson;
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(ignoreKeys.contains(key)) {
|
2017-03-29 16:14:03 +02:00
|
|
|
return null;
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
for(String prefix : ignoreStartWithKeys) {
|
|
|
|
if(key.startsWith(prefix)) {
|
2017-03-29 16:14:03 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(object instanceof ODocument) {
|
2019-02-13 12:33:29 +01:00
|
|
|
ODocument oDocument = (ODocument) object;
|
2020-01-30 11:53:15 +01:00
|
|
|
return PropertyElementManagement.getJsonNode(oDocument);
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(object instanceof Date) {
|
2017-03-29 16:14:03 +02:00
|
|
|
OProperty oProperty = getOClass().getProperty(key);
|
|
|
|
OType oType = oProperty.getType();
|
|
|
|
DateFormat dateFormat = ODateHelper.getDateTimeFormatInstance();
|
2017-11-30 18:06:08 +01:00
|
|
|
switch(oType) {
|
|
|
|
case DATE:
|
|
|
|
dateFormat = ODateHelper.getDateFormatInstance();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DATETIME:
|
|
|
|
dateFormat = ODateHelper.getDateTimeFormatInstance();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
2017-01-18 14:57:20 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
return new TextNode(dateFormat.format((Date) object));
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
if(object instanceof Collection) {
|
2017-04-26 11:40:34 +02:00
|
|
|
Collection<?> collection = (Collection<?>) object;
|
2019-02-13 12:33:29 +01:00
|
|
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
|
|
|
|
2017-11-30 18:06:08 +01:00
|
|
|
for(Object o : collection) {
|
2017-11-28 17:34:43 +01:00
|
|
|
Object obj = getPropertyForJson("PLACEHOLDER", o);
|
2019-02-13 12:33:29 +01:00
|
|
|
|
|
|
|
if(obj!=null) {
|
|
|
|
arrayNode.add((JsonNode) obj);
|
|
|
|
}
|
2017-01-18 14:57:20 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
return arrayNode;
|
2017-01-18 14:57:20 +01:00
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2019-02-13 12:33:29 +01:00
|
|
|
return new TextNode(object.toString());
|
2017-11-30 18:06:08 +01:00
|
|
|
|
|
|
|
} catch(Exception e) {
|
2017-11-28 17:34:43 +01:00
|
|
|
throw new ResourceRegistryException(
|
|
|
|
"Error while serializing " + key + "=" + object.toString() + " in " + getElement().toString(), e);
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
|
|
|
}
|
2017-11-30 18:06:08 +01:00
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
/*
|
2021-01-29 16:13:33 +01:00
|
|
|
protected List<String> getSuperclasses() throws SchemaException, ResourceRegistryException {
|
|
|
|
List<String> superClasses = new ArrayList<>();
|
|
|
|
List<OClass> allSuperClasses = getOClass().getSuperClasses();
|
|
|
|
while(allSuperClasses.size()>0) {
|
|
|
|
List<OClass> toBeAnalysed = new ArrayList<>(allSuperClasses);
|
|
|
|
allSuperClasses = new ArrayList<>();
|
|
|
|
for(OClass oSuperClass : toBeAnalysed) {
|
|
|
|
String name = oSuperClass.getName();
|
|
|
|
if(name.compareTo(StringFactory.V.toUpperCase()) == 0 || name.compareTo(StringFactory.E.toUpperCase()) == 0
|
|
|
|
|| name.compareTo(DatabaseEnvironment.O_RESTRICTED_CLASS) == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(superClassesToBeExcluded.contains(name)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
superClasses.add(superClasses.size(), name);
|
|
|
|
allSuperClasses.addAll(oSuperClass.getSuperClasses());
|
2017-03-29 16:14:03 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return superClasses;
|
|
|
|
}
|
2021-02-22 16:36:19 +01:00
|
|
|
*/
|
2021-02-02 16:50:48 +01:00
|
|
|
|
2021-02-22 12:38:12 +01:00
|
|
|
protected String getNotNullErrorMessage(String fieldName) {
|
|
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
stringBuffer.append("The type ");
|
|
|
|
stringBuffer.append(typeName);
|
|
|
|
stringBuffer.append(" defines the fields ");
|
|
|
|
stringBuffer.append(fieldName);
|
|
|
|
stringBuffer.append(" as not nullable. Null or no value has been provided instead.");
|
|
|
|
return stringBuffer.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected String getMandatoryErrorMessage(String fieldName) {
|
|
|
|
StringBuffer stringBuffer = new StringBuffer();
|
|
|
|
stringBuffer.append("The type ");
|
|
|
|
stringBuffer.append(typeName);
|
|
|
|
stringBuffer.append(" defines the fields ");
|
|
|
|
stringBuffer.append(fieldName);
|
|
|
|
stringBuffer.append(" as mandatory but no value has been provided.");
|
|
|
|
return stringBuffer.toString();
|
|
|
|
}
|
|
|
|
|
2021-02-23 17:31:46 +01:00
|
|
|
protected boolean typeSatified(TypesCache typesCache, String requiredType, String effectiveType) throws SchemaException, ResourceRegistryException {
|
|
|
|
if(requiredType.compareTo(effectiveType)==0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
CachedType<ResourceType> cachedType = (CachedType<ResourceType>) typesCache.getCachedType(requiredType);
|
|
|
|
if(cachedType.getSubTypes().contains(effectiveType)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-22 12:38:12 +01:00
|
|
|
/*
|
|
|
|
* Get not only the properties defined in the type but also the properties
|
|
|
|
* defined in the super types
|
|
|
|
*/
|
|
|
|
protected Set<PropertyDefinition> getAllProperties() throws SchemaException, ResourceRegistryException{
|
|
|
|
TypesCache typesCache = TypesCache.getInstance();
|
2021-02-22 16:36:19 +01:00
|
|
|
Set<PropertyDefinition> definedProperties = getCachedType().getType().getProperties();
|
2021-02-22 12:38:12 +01:00
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
Set<CachedType<T>> cachedSuperTypes = new HashSet<>();
|
2021-02-22 12:38:12 +01:00
|
|
|
List<String> superTypes = cachedType.getSuperTypes();
|
|
|
|
for(String superTypeName : superTypes) {
|
2021-02-22 16:36:19 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
CachedType<T> cachedSuperType = (CachedType<T>) typesCache.getCachedType(superTypeName);
|
2021-02-22 12:38:12 +01:00
|
|
|
cachedSuperTypes.add(cachedSuperType);
|
|
|
|
|
|
|
|
Type superType = cachedSuperType.getType();
|
2021-02-22 16:36:19 +01:00
|
|
|
Set<PropertyDefinition> properties = superType.getProperties();
|
|
|
|
if(properties!=null) {
|
|
|
|
definedProperties.addAll(properties);
|
|
|
|
}
|
2021-02-22 12:38:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return definedProperties;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void sanityCheck() throws SchemaViolationException, ResourceRegistryException {
|
|
|
|
// OrientDB distributed mode does not support
|
|
|
|
// mandatory and notnull constraints due to technical problem
|
|
|
|
// https://www.orientdb.com/docs/last/java/Graph-Schema-Property.html#using-constraints
|
|
|
|
// Going to validate them here
|
|
|
|
|
2021-09-16 15:23:04 +02:00
|
|
|
if(operation.isSafe()) {
|
|
|
|
/*
|
|
|
|
* The sanity check is not required for a safe operation.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-02-22 12:38:12 +01:00
|
|
|
Set<PropertyDefinition> definedProperties = getAllProperties();
|
|
|
|
|
2021-03-02 16:39:30 +01:00
|
|
|
if(definedProperties==null) {
|
|
|
|
// The type could define no property
|
|
|
|
return;
|
|
|
|
}
|
2021-02-22 12:38:12 +01:00
|
|
|
|
2021-03-04 10:24:21 +01:00
|
|
|
Set<String> elementPropertyNames = getElement().getPropertyNames();
|
|
|
|
|
2021-02-22 12:38:12 +01:00
|
|
|
for(PropertyDefinition propertyDefinition : definedProperties) {
|
2021-02-22 16:36:19 +01:00
|
|
|
|
2021-02-22 12:38:12 +01:00
|
|
|
String fieldName = propertyDefinition.getName();
|
|
|
|
|
2021-03-04 10:24:21 +01:00
|
|
|
if(propertyDefinition.isMandatory() && !elementPropertyNames.contains(fieldName)) {
|
2021-02-22 12:38:12 +01:00
|
|
|
if(propertyDefinition.isNotnull()) {
|
|
|
|
// If the field is mandatory but null value is accepted I add the
|
|
|
|
// field as null value
|
|
|
|
element.setProperty(fieldName, null);
|
|
|
|
} else {
|
|
|
|
throw new SchemaViolationException(getMandatoryErrorMessage(fieldName));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
/*
|
2021-02-22 12:38:12 +01:00
|
|
|
JsonNode jsonNode = instances.get(fieldName);
|
|
|
|
|
|
|
|
if(!propertyDefinition.isNotnull() && jsonNode==null) {
|
|
|
|
throw new SchemaViolationException(getNotNullErrorMessage(fieldName));
|
|
|
|
}
|
2021-02-22 16:36:19 +01:00
|
|
|
*/
|
2021-02-22 12:38:12 +01:00
|
|
|
|
2021-02-22 16:36:19 +01:00
|
|
|
// This validation was required to check if all mandatory fields are presents
|
|
|
|
// The validation of the values has been performed at create/update time.
|
2021-02-22 12:38:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-12-19 14:59:27 +01:00
|
|
|
}
|