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/types/SchemaManagement.java

880 lines
32 KiB
Java

/**
*
*/
package org.gcube.informationsystem.resourceregistry.types;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.activation.UnsupportedDataTypeException;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.base.reference.IdentifiableElement;
import org.gcube.informationsystem.base.reference.entities.EntityElement;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.base.reference.relations.RelationElement;
import org.gcube.informationsystem.model.reference.entities.Entity;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.model.reference.relations.IsRelatedTo;
import org.gcube.informationsystem.model.reference.relations.Relation;
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaAlreadyPresentException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaCreationException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaException;
import org.gcube.informationsystem.resourceregistry.api.exceptions.schema.SchemaNotFoundException;
import org.gcube.informationsystem.resourceregistry.contexts.ContextUtility;
import org.gcube.informationsystem.resourceregistry.contexts.security.AdminSecurityContext;
import org.gcube.informationsystem.resourceregistry.contexts.security.SecurityContext.PermissionMode;
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
import org.gcube.informationsystem.resourceregistry.types.entities.FacetTypeDefinitionManagement;
import org.gcube.informationsystem.resourceregistry.types.entities.ResourceTypeDefinitionManagement;
import org.gcube.informationsystem.resourceregistry.types.properties.PropertyTypeDefinitionManagement;
import org.gcube.informationsystem.resourceregistry.types.relations.ConsistsOfTypeDefinitionManagement;
import org.gcube.informationsystem.resourceregistry.types.relations.IsRelatedToTypeDefinitionManagement;
import org.gcube.informationsystem.types.PropertyTypeName;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.types.impl.properties.PropertyDefinitionImpl;
import org.gcube.informationsystem.types.reference.Type;
import org.gcube.informationsystem.types.reference.entities.EntityType;
import org.gcube.informationsystem.types.reference.entities.FacetType;
import org.gcube.informationsystem.types.reference.entities.ResourceType;
import org.gcube.informationsystem.types.reference.properties.LinkedEntity;
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
import org.gcube.informationsystem.types.reference.properties.PropertyType;
import org.gcube.informationsystem.types.reference.relations.ConsistsOfType;
import org.gcube.informationsystem.types.reference.relations.IsRelatedToType;
import org.gcube.informationsystem.types.reference.relations.RelationType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.orientechnologies.orient.core.db.document.ODatabaseDocument;
import com.orientechnologies.orient.core.exception.OSchemaException;
import com.orientechnologies.orient.core.metadata.OMetadata;
import com.orientechnologies.orient.core.metadata.schema.OClass;
import com.orientechnologies.orient.core.metadata.schema.OProperty;
import com.orientechnologies.orient.core.metadata.schema.OSchema;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.OElement;
/**
* @author Luca Frosini (ISTI - CNR)
*/
public class SchemaManagement {
private static Logger logger = LoggerFactory.getLogger(SchemaManagement.class);
protected String typeName;
protected String json;
protected Type type;
protected boolean skipVersionCheckOnUpdate;
public boolean isSkipVersionCheckOnUpdate() {
return skipVersionCheckOnUpdate;
}
public void setSkipVersionCheckOnUpdate(boolean skipVersionCheckOnUpdate) {
this.skipVersionCheckOnUpdate = skipVersionCheckOnUpdate;
}
protected boolean skipTypeDefinitionCreation;
public boolean isSkipTypeDefinitionCreation() {
return skipTypeDefinitionCreation;
}
public void setSkipTypeDefinitionCreation(boolean skipTypeDefinitionCreation) {
this.skipTypeDefinitionCreation = skipTypeDefinitionCreation;
}
public void setJson(String json) throws ResourceRegistryException {
this.json = json;
try {
this.type = TypeMapper.deserializeTypeDefinition(json);
}catch (Exception e) {
logger.error("Unable to create type definition from provided json {}", json);
throw new SchemaCreationException("Unable to create type definition from provided json" + json, e);
}
}
public SchemaManagement() {
this.skipTypeDefinitionCreation = false;
}
protected OClass getOClass(OSchema oSchema, String typeName) throws SchemaException {
return oSchema.getClass(typeName);
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public void setTypeAndTypeName(Class<? extends Element> clz) throws Exception {
this.type = TypeMapper.createTypeDefinition(clz);
this.typeName = type.getName();
this.json = TypeMapper.serializeTypeDefinition(type);
}
/*
private static TypeDefinition getOClassTypeDefinition(OClass oClass) throws SchemaException {
try {
ODocument oDocument = ((OClassImpl) oClass).toStream();
String json = oDocument.toJSON();
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = (ObjectNode) mapper.readTree(json);
if(oClass.isSubClassOf(Property.NAME)) {
node.put(ISManageable.CLASS_PROPERTY, PropertyTypeDefinition.NAME);
} else if(oClass.isSubClassOf(Resource.NAME)) {
node.put(ISManageable.CLASS_PROPERTY, ResourceTypeDefinition.NAME);
} else if(oClass.isSubClassOf(Facet.NAME)) {
node.put(ISManageable.CLASS_PROPERTY, FacetTypeDefinition.NAME);
} else if(oClass.isSubClassOf(IsRelatedTo.NAME)) {
node.put(ISManageable.CLASS_PROPERTY, IsRelatedToTypeDefinition.NAME);
} else if(oClass.isSubClassOf(ConsistsOf.NAME)) {
node.put(ISManageable.CLASS_PROPERTY, ConsistsOfTypeDefinition.NAME);
}
if(!oClass.isSubClassOf(Resource.NAME)) {
ArrayNode arrayNode = (ArrayNode) node.get(EntityTypeDefinition.PROPERTIES_PROPERTY);
Iterator<JsonNode> iterator = arrayNode.iterator();
while(iterator.hasNext()) {
ObjectNode propertyNode = (ObjectNode) iterator.next();
propertyNode.put(ISManageable.CLASS_PROPERTY, PropertyDefinition.NAME);
}
}
String managedJson = mapper.writeValueAsString(node);
logger.trace("{} -> {}", json, managedJson);
return TypeBinder.deserializeTypeDefinition(managedJson);
} catch(Exception e) {
throw new SchemaException(e);
}
}
*/
private static ElementManagement<?,?> getTypeManagement(AccessType accessType, String name) {
ElementManagement<? extends OElement,?> erManagement = null;
switch(accessType) {
case PROPERTY:
erManagement = new PropertyTypeDefinitionManagement();
((PropertyTypeDefinitionManagement) erManagement).setName(name);
break;
case RESOURCE:
erManagement = new ResourceTypeDefinitionManagement();
((ResourceTypeDefinitionManagement) erManagement).setName(name);
break;
case FACET:
erManagement = new FacetTypeDefinitionManagement();
((FacetTypeDefinitionManagement) erManagement).setName(name);
break;
case IS_RELATED_TO:
erManagement = new IsRelatedToTypeDefinitionManagement();
((IsRelatedToTypeDefinitionManagement) erManagement).setName(name);
break;
case CONSISTS_OF:
erManagement = new ConsistsOfTypeDefinitionManagement();
((ConsistsOfTypeDefinitionManagement) erManagement).setName(name);
break;
default:
break;
}
return erManagement;
}
public static ElementManagement<?,?> getTypeManagement(OClass oClass) {
ElementManagement<?,?> erManagement = null;
if(oClass.isSubClassOf(Property.NAME)) {
erManagement = new PropertyTypeDefinitionManagement();
((PropertyTypeDefinitionManagement) erManagement).setName(oClass.getName());
} else if(oClass.isSubClassOf(Resource.NAME)) {
erManagement = new ResourceTypeDefinitionManagement();
((ResourceTypeDefinitionManagement) erManagement).setName(oClass.getName());
} else if(oClass.isSubClassOf(Facet.NAME)) {
erManagement = new FacetTypeDefinitionManagement();
((FacetTypeDefinitionManagement) erManagement).setName(oClass.getName());
} else if(oClass.isSubClassOf(IsRelatedTo.NAME)) {
erManagement = new IsRelatedToTypeDefinitionManagement();
((IsRelatedToTypeDefinitionManagement) erManagement).setName(oClass.getName());
} else if(oClass.isSubClassOf(ConsistsOf.NAME)) {
erManagement = new ConsistsOfTypeDefinitionManagement();
((ConsistsOfTypeDefinitionManagement) erManagement).setName(oClass.getName());
}
return erManagement;
}
private String getTypeAsString(ElementManagement<?,?> erManagement) throws SchemaException {
try {
if(erManagement!=null) {
return erManagement.read();
}else {
throw new SchemaException("You can only request schema of IS Model types and their specilization");
}
} catch(Exception e) {
throw new SchemaException(e);
}
}
private String getTypeAsString(OClass oClass) throws SchemaException {
try {
ElementManagement<?,?> erManagement = getTypeManagement(oClass);
return getTypeAsString(erManagement);
} catch(Exception e) {
throw new SchemaException(e);
}
}
private Type getType(ElementManagement<?,?> erManagement) throws SchemaException {
try {
String typeString = getTypeAsString(erManagement);
return TypeMapper.deserializeTypeDefinition(typeString);
} catch(Exception e) {
throw new SchemaException(e);
}
}
/*
private String getTypeAsString(AccessType accessType, String name) throws SchemaException {
try {
ElementManagement<? extends OElement> erManagement = getTypeManagement(accessType, name);
return getTypeAsString(erManagement);
} catch(Exception e) {
throw new SchemaException(e);
}
}
/*
private Type getType(AccessType accessType, String name) throws SchemaException {
try {
String typeString = getTypeAsString(accessType, name);
return TypeMapper.deserializeTypeDefinition(typeString);
} catch(Exception e) {
throw new SchemaException(e);
}
}
*/
private Type getType(OClass oClass) throws SchemaException {
try {
String typeString = getTypeAsString(oClass);
return TypeMapper.deserializeTypeDefinition(typeString);
} catch(Exception e) {
throw new SchemaException(e);
}
}
protected List<OClass> getSuperclassesAndCheckCompliancy(ODatabaseDocument oDatabaseDocument,
Type type, String baseType) throws SchemaException, SchemaNotFoundException {
Set<String> superClasses = type.getSuperClasses();
if(baseType != null) {
if(superClasses == null || superClasses.size() == 0) {
throw new RuntimeException(
String.format("No Superclass found in schema %s. The Type Definition must extend %s",
type, baseType));
}
}
OMetadata oMetadata = oDatabaseDocument.getMetadata();
OSchema oSchema = oMetadata.getSchema();
List<OClass> oSuperclasses = new ArrayList<>();
for(String superClass : superClasses) {
OClass oSuperClass = getOClass(oSchema, superClass);
if(oSuperClass == null) {
throw new SchemaNotFoundException("Superclass " + superClass + " does not exists");
}
if(baseType != null) {
if(type.getName().compareTo(baseType) != 0) {
if(!oSuperClass.isSubClassOf(baseType)) {
throw new RuntimeException(superClass + " is not a subsclass of " + baseType
+ ". Each Superclass MUST be a subclass of " + baseType);
}
}
}
oSuperclasses.add(oSuperClass);
}
return oSuperclasses;
}
private static Set<String> baseElementTypes;
public static Set<String> typeList;
static {
baseElementTypes = new HashSet<String>();
baseElementTypes.add(PropertyElement.NAME);
baseElementTypes.add(EntityElement.NAME);
baseElementTypes.add(RelationElement.NAME);
typeList = new HashSet<String>();
typeList.add(PropertyType.NAME);
typeList.add(LinkedEntity.NAME);
typeList.add(EntityType.NAME);
typeList.add(ResourceType.NAME);
typeList.add(FacetType.NAME);
typeList.add(RelationType.NAME);
typeList.add(IsRelatedToType.NAME);
typeList.add(ConsistsOfType.NAME);
}
protected void registerTypeSchema()
throws SchemaAlreadyPresentException, SchemaException {
ODatabaseDocument oDatabaseDocument = null;
try {
if(typeName.compareTo(type.getName()) != 0) {
String error = String.format(
"Provided type name path argument %s does not match with the type name in the definition %S. Please be coherent.",
typeName, type.getName());
throw new SchemaCreationException(error);
}
AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext();
oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.WRITER);
OMetadata oMetadata = oDatabaseDocument.getMetadata();
OSchema oSchema = oMetadata.getSchema();
OClass oClass = null;
AccessType accessType = type.getAccessType();
Class<? extends Element> typeClass = accessType.getTypeClass();
String typeName = type.getName();
if(EntityElement.class.isAssignableFrom(typeClass)) {
oClass = oDatabaseDocument.createVertexClass(typeName);
} else if(RelationElement.class.isAssignableFrom(typeClass)) {
oClass = oDatabaseDocument.createEdgeClass(typeName);
} else if(PropertyElement.class.isAssignableFrom(typeClass)) {
oClass = oSchema.createClass(typeName);
} else {
String error = String.format("Allowed superclass are %s, %s, %s, or any subclasses of them.",
Entity.NAME, Relation.NAME, Property.NAME);
throw new SchemaCreationException(error);
}
try {
String description = type.getDescription();
if(description != null && description.compareTo("") != 0) {
try {
oClass.setDescription(description);
} catch(Exception e) {
logger.warn(
"Unable to set description. This is an orient bug. See https://github.com/orientechnologies/orientdb/issues/7065");
}
}
try {
// oClass.setAbstract(false); // Used to allow to persist Schema in Context
// Management
oClass.setAbstract(type.isAbstract());
} catch(Exception e) {
logger.error(
"Unable to set the Vertex Type {} as abstract. This is an OrientDB <= 2.2.12 bug. The Type will be created as it is not abstract.",
type.getName());
}
if(!baseElementTypes.contains(type.getName())) {
List<OClass> oSuperclasses = getSuperclassesAndCheckCompliancy(oDatabaseDocument, type,
accessType.getName());
oClass.setSuperClasses(oSuperclasses);
}
if(!(type instanceof ResourceType)) {
// A Resource cannot contains any properties.
Set<PropertyDefinition> propertyDefinitions = type.getProperties();
if(propertyDefinitions!=null) {
for(PropertyDefinition propertyDefinition : propertyDefinitions) {
PropertyTypeName propertyTypeName = ((PropertyDefinitionImpl) propertyDefinition).getPropertyTypeName();
/*
* Types update is not allowed,
* hence bug https://github.com/orientechnologies/orientdb/issues/7354 cannot occur
* Excluding the check from types used for type definition
*
*/
if(!typeList.contains(type.getName())) {
switch(propertyTypeName.getBaseType()) {
case LIST:
throw new UnsupportedDataTypeException(OType.EMBEDDEDLIST
+ " support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354");
case SET:
throw new UnsupportedDataTypeException(OType.EMBEDDEDSET
+ " support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354");
default:
break;
}
}
OType oType = OrientDBTypeMapping.getOTypeByBaseType(propertyTypeName.getBaseType());
OProperty op = oClass.createProperty(propertyDefinition.getName(), oType);
op.setDescription(propertyDefinition.getDescription());
/*
* Mandatory and notNull does not work in distributed mode: so that on Type
* declaration they are forced to false
* ovp.setMandatory(property.isMandatory());
* ovp.setNotNull(property.isNotnull()); This information are persisted in
* Management Context
*/
op.setMandatory(false);
op.setNotNull(false);
op.setReadonly(propertyDefinition.isReadonly());
op.setRegexp(propertyDefinition.getRegexp());
if (propertyTypeName.isGenericType()) {
if (propertyTypeName.getGenericClassName() != null) {
OClass linkedClass = getOClass(oSchema, propertyTypeName.getGenericClassName());
if (linkedClass == null) {
logger.trace("Class {} not found.", propertyTypeName.getGenericClassName());
throw new Exception(
"Class " + propertyTypeName.getGenericClassName() + " not found.");
}
if (linkedClass.isEdgeType() || linkedClass.isVertexType()) {
throw new Exception(
"A PropertyType cannot be an Entity type or a Relation type");
}
op.setLinkedClass(linkedClass);
} else {
OType linkedOType = OrientDBTypeMapping
.getOTypeByBaseType(propertyTypeName.getGenericBaseType());
op.setLinkedType(OType.getById(Integer.valueOf(linkedOType.ordinal()).byteValue()));
}
}
}
}
}
oDatabaseDocument.commit();
logger.info("{} {} registered successfully", accessType.getName(), type.getName());
} catch(Exception e) {
oSchema.dropClass(type.getName());
throw e;
}
} catch(OSchemaException ex) {
if(ex.getMessage().contains("already exists")) {
throw new SchemaAlreadyPresentException(ex);
}
throw new SchemaException(ex);
} catch(SchemaException e) {
throw e;
} catch(Exception ex) {
throw new SchemaCreationException(ex);
} finally {
oDatabaseDocument.close();
}
}
private boolean superClassesMatch(Type actualTypeDefinition, Type newTypeDefinition) {
// Checking superclasses. Must be the same. If differs the operation will be aborted.
Set<String> actualSuperClasses = new HashSet<>(actualTypeDefinition.getSuperClasses());
Set<String> newSuperClasses = new HashSet<>(newTypeDefinition.getSuperClasses());
if(actualSuperClasses.size()!=newSuperClasses.size()) {
return false;
}
actualSuperClasses.removeAll(newSuperClasses);
if(actualSuperClasses.size()>0) {
return false;
}
actualSuperClasses = new HashSet<>(actualTypeDefinition.getSuperClasses());
newSuperClasses.removeAll(actualSuperClasses);
if(newSuperClasses.size()>0) {
return false;
}
return true;
}
// TODO
protected void updateTypeSchema(Type actualTypeDefinition, Type newTypeDefinition, AccessType baseElementAccessType)
throws SchemaNotFoundException, SchemaException {
ODatabaseDocument oDatabaseDocument = null;
try {
AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext();
oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.WRITER);
OMetadata oMetadata = oDatabaseDocument.getMetadata();
OSchema oSchema = oMetadata.getSchema();
OClass oClass = oSchema.getClass(typeName);
if(oClass == null) {
throw new SchemaNotFoundException(typeName + " does not Exists");
}
if(!superClassesMatch(actualTypeDefinition, newTypeDefinition)){
StringBuffer error = new StringBuffer();
error.append("The new type definition has a different set of superclasses. Actual version superclasses are: ");
error.append(actualTypeDefinition.getSuperClasses());
error.append(". New version superclasses are: ");
error.append(newTypeDefinition.getSuperClasses());
error.append(". This kind update is not supported for a type.");
throw new SchemaException(error.toString());
}
try {
String description = newTypeDefinition.getDescription();
if(description != null && description.compareTo("") != 0) {
try {
oClass.setDescription(description);
} catch(Exception e) {
logger.warn(
"Unable to set description. This is an orient bug. See https://github.com/orientechnologies/orientdb/issues/7065");
}
}
try {
// oClass.setAbstract(false); // Used to allow to persist Schema in Context
// Management
oClass.setAbstract(newTypeDefinition.isAbstract());
} catch(Exception e) {
logger.error(
"Unable to set the Vertex Type {} as abstract. This is an OrientDB <= 2.2.12 bug. The Type will be created as it is not abstract.",
newTypeDefinition.getName());
}
if(!(newTypeDefinition instanceof ResourceType)) {
// A Resource cannot contains any properties.
Set<PropertyDefinition> actualPropertyDefinitions = new HashSet<>(actualTypeDefinition.getProperties());
Map<String, PropertyDefinition> actualPropertyDefinitionMap = new HashMap<>(actualPropertyDefinitions.size());
for(PropertyDefinition actualPropertyDefinition : actualPropertyDefinitions) {
actualPropertyDefinitionMap.put(actualPropertyDefinition.getName(), actualPropertyDefinition);
}
Set<PropertyDefinition> newPropertyDefinitions = newTypeDefinition.getProperties();
Map<String, PropertyDefinition> newPropertyDefinitionMap = new HashMap<>(actualPropertyDefinitions.size());
for(PropertyDefinition newPropertyDefinition : newPropertyDefinitions) {
newPropertyDefinitionMap.put(newPropertyDefinition.getName(), newPropertyDefinition);
}
if(newPropertyDefinitions!=null) {
for(PropertyDefinition newPropertyDefinition : newPropertyDefinitions) {
String propertyName = newPropertyDefinition.getName();
if(propertyName.compareTo(IdentifiableElement.HEADER_PROPERTY)==0 || propertyName.compareTo(Relation.PROPAGATION_CONSTRAINT_PROPERTY)==0) {
continue;
}
PropertyDefinition actualPropertyDefinition = actualPropertyDefinitionMap.get(propertyName);
if(newPropertyDefinition.equals(actualPropertyDefinition)) {
// This property was not changed. Going to managing the next one.
continue;
}
PropertyTypeName newPropertyTypeName = ((PropertyDefinitionImpl) newPropertyDefinition).getPropertyTypeName();
OType oType = OrientDBTypeMapping.getOTypeByBaseType(newPropertyTypeName.getBaseType());
/*
* Excluding EMBEDDEDLIST and EMBEDDEDSET
* to avoid bug https://github.com/orientechnologies/orientdb/issues/7354
*
*/
if(!typeList.contains(newTypeDefinition.getName())) {
switch(oType) {
case EMBEDDEDLIST:
throw new UnsupportedDataTypeException(OType.EMBEDDEDLIST
+ " support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354");
case EMBEDDEDSET:
throw new UnsupportedDataTypeException(OType.EMBEDDEDSET
+ " support is currently disabled due to OrientDB bug see https://github.com/orientechnologies/orientdb/issues/7354");
default:
break;
}
}
OProperty op;
if(actualPropertyDefinition!=null) {
// The property already exists and has changed (the check has been performed few lines above).
op = oClass.getProperty(propertyName);
}else {
op = oClass.createProperty(propertyName, oType);
}
op.setDescription(newPropertyDefinition.getDescription());
/*
* Mandatory and notNull does not work in distributed mode: so that on Type
* declaration they are forced to false
* ovp.setMandatory(property.isMandatory());
* ovp.setNotNull(property.isNotnull()); This information are persisted in
* Management Context
*/
op.setMandatory(false);
op.setNotNull(false);
op.setReadonly(newPropertyDefinition.isReadonly());
op.setRegexp(newPropertyDefinition.getRegexp());
if (newPropertyTypeName.isGenericType()) {
if (newPropertyTypeName.getGenericClassName() != null) {
OClass linkedClass = getOClass(oSchema, newPropertyTypeName.getGenericClassName());
if (linkedClass == null) {
logger.trace("Class {} not found.", newPropertyTypeName.getGenericClassName());
throw new Exception(
"Class " + newPropertyTypeName.getGenericClassName() + " not found.");
}
if (linkedClass.isEdgeType() || linkedClass.isVertexType()) {
throw new Exception(
"A PropertyType cannot be an Entity type or a Relation type");
}
op.setLinkedClass(linkedClass);
} else {
OType linkedOType = OrientDBTypeMapping.getOTypeByBaseType(newPropertyTypeName.getGenericBaseType());
op.setLinkedType(OType.getById(Integer.valueOf(linkedOType.ordinal()).byteValue()));
}
}
}
}
for(String propertyName : newPropertyDefinitionMap.keySet()) {
actualPropertyDefinitionMap.remove(propertyName);
}
// Removing old properties which are no more present in the new type definition
for(String propertyNameToRemove : actualPropertyDefinitionMap.keySet()) {
oClass.dropProperty(propertyNameToRemove);
}
}
oDatabaseDocument.commit();
logger.info("{} {} updated successfully", baseElementAccessType.getName(), newTypeDefinition.getName());
} catch(Exception e) {
oSchema.dropClass(newTypeDefinition.getName());
throw e;
}
} catch(SchemaNotFoundException e) {
throw e;
} catch(SchemaException e) {
throw e;
} catch(Exception ex) {
throw new SchemaException(ex);
} finally {
oDatabaseDocument.close();
}
}
protected List<Type> getSchema(boolean includeSubtypes) throws SchemaNotFoundException, SchemaException {
ODatabaseDocument oDatabaseDocument = null;
try {
AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext();
oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.READER);
OMetadata oMetadata = oDatabaseDocument.getMetadata();
OSchema oSchema = oMetadata.getSchema();
OClass baseOClass = oSchema.getClass(typeName);
if(baseOClass == null) {
throw new SchemaNotFoundException(typeName + " does not Exists");
}
List<Type> typeDefinitions = new ArrayList<>();
typeDefinitions.add(getType(baseOClass));
if(includeSubtypes) {
Collection<OClass> subClasses = baseOClass.getAllSubclasses();
for(OClass oClass : subClasses) {
typeDefinitions.add(getType(oClass));
}
}
return typeDefinitions;
} catch(SchemaException e) {
throw e;
} catch(SchemaNotFoundException e) {
throw e;
} catch(Exception e) {
throw new SchemaException(e);
} finally {
if(oDatabaseDocument != null) {
oDatabaseDocument.close();
}
}
}
public String create() throws SchemaAlreadyPresentException, SchemaException {
try {
AccessType accessType = type.getAccessType();
logger.info("Trying to register {} {} : {}", accessType.getName(), type.getName(), json);
registerTypeSchema();
ElementManagement<?,?> erManagement = null;
switch(accessType) {
case PROPERTY:
erManagement = new PropertyTypeDefinitionManagement();
break;
case RESOURCE:
erManagement = new ResourceTypeDefinitionManagement();
break;
case FACET:
erManagement = new FacetTypeDefinitionManagement();
break;
case IS_RELATED_TO:
erManagement = new IsRelatedToTypeDefinitionManagement();
break;
case CONSISTS_OF:
erManagement = new ConsistsOfTypeDefinitionManagement();
break;
default:
return json;
}
String ret = json;
if(!skipTypeDefinitionCreation) {
erManagement.setJson(json);
ret = erManagement.create();
}
return ret;
} catch(SchemaAlreadyPresentException e) {
throw e;
} catch(SchemaException e) {
throw e;
} catch(Exception ex) {
throw new SchemaCreationException(ex);
}
}
public List<Type> read(boolean includeSubtypes) throws SchemaNotFoundException, SchemaException {
return getSchema(includeSubtypes);
}
private boolean typeCanBeUpdated() throws SchemaException {
for(AccessType accessType : AccessType.values()) {
if(accessType.getName().compareTo(typeName)==0) {
return false;
}
}
return true;
}
public String update()
throws SchemaNotFoundException, SchemaException {
try {
AccessType accessType = type.getAccessType();
logger.info("Trying to update {} type definition", accessType.getName(), type.getName(), json);
logger.debug("Trying to update {} {} : {}", accessType.getName(), type.getName(), json);
if(typeName.compareTo(type.getName()) != 0) {
String error = String.format(
"Provided type name path argument %s does not match with the type name in the definition %S. Please be coherent.",
typeName, type.getName());
throw new SchemaCreationException(error);
}
if(!typeCanBeUpdated()) {
throw new SchemaException(typeName + " is a base type. Cannot update the definition of base types.");
}
ElementManagement<?,?> erManagement = getTypeManagement(accessType, type.getName());
Type actualTypeDefinition = getType(erManagement);
if(!skipVersionCheckOnUpdate) {
if(type.getVersion().compareTo(actualTypeDefinition.getVersion())<=0) {
throw new SchemaAlreadyPresentException("The type " + type.getName() +
" exists and the existing version (.i.e " + actualTypeDefinition.getVersion().toString() +
") is greater of equal to the one provided for update (i.e. " + type.getVersion() + ")");
}
}
updateTypeSchema(actualTypeDefinition, type, accessType);
String ret = json;
if(erManagement!=null) {
erManagement.setJson(json);
ret = erManagement.update();
}
return ret;
} catch(SchemaException e) {
throw e;
} catch(Exception ex) {
throw new SchemaCreationException(ex);
}
}
protected boolean delete(AccessType accessType) throws SchemaException, SchemaNotFoundException{
ODatabaseDocument oDatabaseDocument = null;
try {
AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext();
oDatabaseDocument = adminSecurityContext.getDatabaseDocument(PermissionMode.READER);
OMetadata oMetadata = oDatabaseDocument.getMetadata();
OSchema oSchema = oMetadata.getSchema();
oSchema.dropClass(typeName);
ElementManagement<?,?> erManagement = getTypeManagement(accessType, typeName);
erManagement.delete();
oDatabaseDocument.commit();
return true;
} catch(SchemaException e) {
throw e;
} catch(SchemaNotFoundException e) {
throw e;
} catch (OSchemaException e) {
if(e.getMessage().contains("was not found in current database")) {
throw new SchemaNotFoundException(e);
}else {
throw new SchemaException(e);
}
} catch(Exception e) {
throw new SchemaException(e);
} finally {
if(oDatabaseDocument != null) {
oDatabaseDocument.close();
}
}
}
}