/** * */ 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 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 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 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 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 getSuperclassesAndCheckCompliancy(ODatabaseDocument oDatabaseDocument, Type type, String baseType) throws SchemaException, SchemaNotFoundException { Set 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 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 baseElementTypes; public static Set typeList; static { baseElementTypes = new HashSet(); baseElementTypes.add(PropertyElement.NAME); baseElementTypes.add(EntityElement.NAME); baseElementTypes.add(RelationElement.NAME); typeList = new HashSet(); 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 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 oSuperclasses = getSuperclassesAndCheckCompliancy(oDatabaseDocument, type, accessType.getName()); oClass.setSuperClasses(oSuperclasses); } if(!(type instanceof ResourceType)) { // A Resource cannot contains any properties. Set 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 actualSuperClasses = new HashSet<>(actualTypeDefinition.getSuperClasses()); Set 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 actualPropertyDefinitions = new HashSet<>(actualTypeDefinition.getProperties()); Map actualPropertyDefinitionMap = new HashMap<>(actualPropertyDefinitions.size()); for(PropertyDefinition actualPropertyDefinition : actualPropertyDefinitions) { actualPropertyDefinitionMap.put(actualPropertyDefinition.getName(), actualPropertyDefinition); } Set newPropertyDefinitions = newTypeDefinition.getProperties(); Map 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 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 typeDefinitions = new ArrayList<>(); typeDefinitions.add(getType(baseOClass)); if(includeSubtypes) { Collection 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 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(); } } } }