Validating instances

This commit is contained in:
Luca Frosini 2021-02-22 12:38:12 +01:00
parent b276fecdc8
commit 03271c0e41
5 changed files with 113 additions and 69 deletions

View File

@ -46,6 +46,12 @@ import org.gcube.informationsystem.resourceregistry.types.TypesCache;
import org.gcube.informationsystem.resourceregistry.utils.HeaderOrient;
import org.gcube.informationsystem.resourceregistry.utils.HeaderUtility;
import org.gcube.informationsystem.resourceregistry.utils.Utility;
import org.gcube.informationsystem.types.PropertyTypeName;
import org.gcube.informationsystem.types.PropertyTypeName.BaseType;
import org.gcube.informationsystem.types.impl.properties.PropertyDefinitionImpl;
import org.gcube.informationsystem.types.reference.Type;
import org.gcube.informationsystem.types.reference.entities.FacetType;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -453,8 +459,6 @@ public abstract class ElementManagement<El extends OElement> {
public abstract String reallyGetAll(boolean polymorphic) throws ResourceRegistryException;
public abstract void sanityCheck() throws SchemaViolationException, ResourceRegistryException;
public String all(boolean polymorphic) throws ResourceRegistryException {
ODatabaseDocument current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
try {
@ -1042,4 +1046,101 @@ public abstract class ElementManagement<El extends OElement> {
}
}
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();
}
/*
* 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();
CachedType cachedType = typesCache.getCachedType(typeName);
Type type = (FacetType) cachedType.getType();
Set<PropertyDefinition> definedProperties = type.getProperties();
Set<CachedType> cachedSuperTypes = new HashSet<>();
List<String> superTypes = cachedType.getSuperTypes();
for(String superTypeName : superTypes) {
CachedType cachedSuperType = typesCache.getCachedType(superTypeName);
cachedSuperTypes.add(cachedSuperType);
Type superType = cachedSuperType.getType();
definedProperties.addAll(superType.getProperties());
}
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
JsonNode instances = createCompleteJsonNode();
Set<PropertyDefinition> definedProperties = getAllProperties();
for(PropertyDefinition propertyDefinition : definedProperties) {
String fieldName = propertyDefinition.getName();
if(propertyDefinition.isMandatory() && !instances.has(fieldName)) {
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));
}
}
JsonNode jsonNode = instances.get(fieldName);
if(!propertyDefinition.isNotnull() && jsonNode==null) {
throw new SchemaViolationException(getNotNullErrorMessage(fieldName));
}
PropertyTypeName propertyTypeName = ((PropertyDefinitionImpl) propertyDefinition).getPropertyTypeName();
BaseType baseType = propertyTypeName.getBaseType();
switch (baseType) {
case PROPERTY:
break;
case LIST: case SET: case MAP:
propertyTypeName.getGenericBaseType();
break;
default:
break;
}
// leaving the rest of validation to OrientDB
}
}
}

View File

@ -162,6 +162,9 @@ public abstract class RelationElementManagement<SEM extends EntityElementManagem
OVertex source = (OVertex) getSourceEntityManagement().getElement();
OVertex target = (OVertex) getTargetEntityManagement().getElement();
// TODO check source and target type compatibility
logger.trace("Going to create {} beetween {} -> {}", typeName, source.toString(), target.toString());
element = oDatabaseDocument.newEdge(source, target, typeName);

View File

@ -1,7 +1,5 @@
package org.gcube.informationsystem.resourceregistry.instances.model.entities;
import java.util.Set;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.model.reference.entities.Facet;
@ -10,11 +8,6 @@ import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegis
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.facet.FacetAlreadyPresentException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.facet.FacetAvailableInAnotherContextException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.facet.FacetNotFoundException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaViolationException;
import org.gcube.informationsystem.resourceregistry.types.CachedType;
import org.gcube.informationsystem.resourceregistry.types.TypesCache;
import org.gcube.informationsystem.types.reference.entities.FacetType;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import com.orientechnologies.orient.core.record.OVertex;
@ -66,62 +59,4 @@ public class FacetManagement extends EntityManagement<Facet> {
return true;
}
private 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();
}
private 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();
}
@Override
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
JsonNode facetInstance = createCompleteJsonNode();
TypesCache typesCache = TypesCache.getInstance();
CachedType cachedType = typesCache.getCachedType(typeName);
FacetType facetType = (FacetType) cachedType.getType();
Set<PropertyDefinition> definedProperties = facetType.getProperties();
for(PropertyDefinition propertyDefinition : definedProperties) {
String fieldName = propertyDefinition.getName();
if(propertyDefinition.isMandatory() && !facetInstance.has(fieldName)) {
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));
}
}
JsonNode jsonNode = facetInstance.get(fieldName);
if(!propertyDefinition.isNotnull() && jsonNode==null) {
throw new SchemaViolationException(getNotNullErrorMessage(fieldName));
}
// leaving the rest of validation to OrientDB
}
}
}

View File

@ -399,6 +399,11 @@ public class ResourceManagement extends EntityManagement<Resource> {
return true;
}
/**
* The default sanity check is not valid for resources which do not have properties
* and instead must be validated in terms of facets.
* The Resource Header is managed with dedicated code for all instaces.
*/
@Override
public void sanityCheck() throws SchemaViolationException, ResourceRegistryException {
JsonNode resourceInstance = createCompleteJsonNode();

View File

@ -197,7 +197,7 @@ public class CachedType {
return accessType;
}
private List<String> internaGetSuperTypes() throws SchemaException, ResourceRegistryException {
private List<String> internalGetSuperTypes() throws SchemaException, ResourceRegistryException {
if(superTypes==null) {
superTypes = getAllSuperclasses(superClassesToBeExcluded);
}
@ -225,7 +225,7 @@ public class CachedType {
}
public synchronized List<String> getSuperTypes() throws SchemaException, ResourceRegistryException {
return internaGetSuperTypes();
return internalGetSuperTypes();
}
public synchronized List<String> getSubTypes() throws SchemaException, ResourceRegistryException {