251 lines
8.3 KiB
Java
251 lines
8.3 KiB
Java
package org.gcube.informationsystem.resourceregistry.types;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.SchemaException;
|
|
import org.gcube.informationsystem.resourceregistry.api.exceptions.types.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.dbinitialization.DatabaseEnvironment;
|
|
import org.gcube.informationsystem.resourceregistry.instances.base.ElementManagement;
|
|
import org.gcube.informationsystem.types.TypeMapper;
|
|
import org.gcube.informationsystem.types.reference.Type;
|
|
import org.gcube.informationsystem.types.reference.properties.LinkedEntity;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import com.arcadedb.remote.RemoteDatabase;
|
|
import com.arcadedb.schema.DocumentType;
|
|
|
|
/**
|
|
* @author Luca Frosini (ISTI - CNR)
|
|
*/
|
|
public class CachedType<T extends Type> {
|
|
|
|
private static Logger logger = LoggerFactory.getLogger(CachedType.class);
|
|
|
|
private static final Set<String> superClassesToBeExcluded;
|
|
|
|
static {
|
|
superClassesToBeExcluded = AccessType.names();
|
|
AccessType[] modelTypes = AccessType.getModelTypes();
|
|
for(AccessType accessType : modelTypes) {
|
|
superClassesToBeExcluded.remove(accessType.getName());
|
|
}
|
|
}
|
|
|
|
protected final String typeName;
|
|
|
|
protected DocumentType documentType;
|
|
|
|
protected AccessType accessType;
|
|
|
|
protected T type;
|
|
protected List<String> superTypes;
|
|
protected List<String> subTypes;
|
|
|
|
/* Valid only for resource types */
|
|
protected Set<LinkedEntity> constraints;
|
|
|
|
|
|
public CachedType(String typeName) {
|
|
this.typeName = typeName;
|
|
}
|
|
|
|
private DocumentType retrieveDocumentType() throws SchemaException, SchemaNotFoundException, ResourceRegistryException {
|
|
RemoteDatabase current = ContextUtility.getCurrentODatabaseDocumentFromThreadLocal();
|
|
RemoteDatabase database = null;
|
|
try {
|
|
logger.debug("GettingType {} schema", typeName);
|
|
AdminSecurityContext adminSecurityContext = ContextUtility.getAdminSecurityContext();
|
|
database = adminSecurityContext.getRemoteDatabase(PermissionMode.READER);
|
|
OMetadata oMetadata = database.getMetadata();
|
|
OSchema oSchema = oMetadata.getSchema();
|
|
try {
|
|
DocumentType documentType = oSchema.getClass(typeName);
|
|
if(documentType == null) {
|
|
throw new SchemaNotFoundException(typeName + " was not registered");
|
|
}
|
|
return documentType;
|
|
} catch(SchemaNotFoundException snfe) {
|
|
throw snfe;
|
|
} catch(Exception e) {
|
|
throw new SchemaException(e.getMessage());
|
|
}
|
|
} catch(ResourceRegistryException e) {
|
|
throw e;
|
|
} catch(Exception e) {
|
|
throw new ResourceRegistryException(e);
|
|
} finally {
|
|
if(database != null) {
|
|
database.close();
|
|
}
|
|
|
|
// if(current!=null) {
|
|
// current.activateOnCurrentThread();
|
|
// }
|
|
}
|
|
|
|
|
|
}
|
|
|
|
public synchronized void setDocumentType(DocumentType documentType) throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
if(this.documentType==null) {
|
|
this.documentType = documentType;
|
|
}
|
|
}
|
|
|
|
private AccessType getAccessTypeFromDocumentType(DocumentType documentType) throws ResourceRegistryException {
|
|
AccessType[] accessTypes = AccessType.values();
|
|
for(int i=accessTypes.length-1; i>=0; i--) {
|
|
AccessType accessType = accessTypes[i];
|
|
if(documentType.isSubTypeOf(accessType.getName())) {
|
|
return accessType;
|
|
}
|
|
}
|
|
throw new ResourceRegistryException(typeName + " is not a base type");
|
|
}
|
|
|
|
private List<String> getAllSuperclasses(Collection<String> superClassesToBeExcluded) throws SchemaException, ResourceRegistryException {
|
|
TypesCache typesCache = TypesCache.getInstance();
|
|
|
|
List<String> allSuperClasses = new ArrayList<>();
|
|
|
|
// Instead of using getAllSuperClasses() we get just the first level superclasses and so on.
|
|
// This allow to have an order list where the first superclass is a a first level superclass.
|
|
List<DocumentType> superClasses = internalGetDocumentType().getSuperTypes();
|
|
while(superClasses.size()>0) {
|
|
List<DocumentType> toBeAnalysed = new ArrayList<>(superClasses);
|
|
superClasses = new ArrayList<>();
|
|
for(DocumentType oSuperClass : toBeAnalysed) {
|
|
String name = oSuperClass.getName();
|
|
CachedType<?> cachedType = typesCache.getCachedType(name);
|
|
cachedType.setDocumentType(oSuperClass);
|
|
if(name.compareTo(DatabaseEnvironment.VERTEX_CLASS_NAME) == 0 || name.compareTo(DatabaseEnvironment.EDGE_CLASS_NAME) == 0
|
|
|| name.compareTo(OSecurity.RESTRICTED_CLASSNAME) == 0) {
|
|
continue;
|
|
}
|
|
|
|
if(superClassesToBeExcluded.contains(name)) {
|
|
continue;
|
|
}
|
|
allSuperClasses.add(allSuperClasses.size(), name);
|
|
superClasses.addAll(oSuperClass.getSuperTypes());
|
|
}
|
|
}
|
|
return allSuperClasses;
|
|
}
|
|
|
|
protected List<String> getAllSubclasses() throws SchemaException, ResourceRegistryException {
|
|
TypesCache typesCache = TypesCache.getInstance();
|
|
|
|
List<String> allSubClasses = new ArrayList<>();
|
|
Collection<DocumentType> subclasses = internalGetDocumentType().getSubTypes();
|
|
while(subclasses.size()>0) {
|
|
List<DocumentType> toBeAnalysed = new ArrayList<>(subclasses);
|
|
subclasses = new ArrayList<>();
|
|
for(DocumentType oSubClass : toBeAnalysed) {
|
|
String name = oSubClass.getName();
|
|
CachedType<?> cachedType = typesCache.getCachedType(name);
|
|
cachedType.setDocumentType(oSubClass);
|
|
allSubClasses.add(allSubClasses.size(), name);
|
|
subclasses.addAll(oSubClass.getSubTypes());
|
|
}
|
|
}
|
|
return allSubClasses;
|
|
}
|
|
|
|
private DocumentType internalGetDocumentType() throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
if(documentType==null) {
|
|
documentType = retrieveDocumentType();
|
|
}
|
|
return documentType;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private T internalGetType() throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
if(type==null) {
|
|
ElementManagement<?,?> erManagement = TypeManagement.getTypeManagement(internalGetDocumentType());
|
|
String typeString = erManagement.read();
|
|
try {
|
|
type = (T) TypeMapper.deserializeTypeDefinition(typeString);
|
|
} catch (Exception e) {
|
|
throw new ResourceRegistryException(e);
|
|
}
|
|
}
|
|
return type;
|
|
}
|
|
|
|
private AccessType internalGetAccessType() throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
if(accessType==null) {
|
|
if(type!=null) {
|
|
accessType = type.getAccessType();
|
|
}else {
|
|
accessType = getAccessTypeFromDocumentType(internalGetDocumentType());
|
|
}
|
|
}
|
|
return accessType;
|
|
}
|
|
|
|
private List<String> internalGetSuperTypes() throws SchemaException, ResourceRegistryException {
|
|
if(superTypes==null) {
|
|
superTypes = getAllSuperclasses(superClassesToBeExcluded);
|
|
}
|
|
return superTypes;
|
|
}
|
|
|
|
private List<String> internalGetSubTypes() throws SchemaException, ResourceRegistryException {
|
|
if(subTypes==null) {
|
|
subTypes = getAllSubclasses();
|
|
}
|
|
return subTypes;
|
|
}
|
|
|
|
|
|
public synchronized DocumentType getDocumentType() throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
return internalGetDocumentType();
|
|
}
|
|
|
|
public synchronized T getType() throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
return internalGetType();
|
|
}
|
|
|
|
public synchronized AccessType getAccessType() throws SchemaNotFoundException, SchemaException, ResourceRegistryException {
|
|
return internalGetAccessType();
|
|
}
|
|
|
|
public synchronized List<String> getSuperTypes() throws SchemaException, ResourceRegistryException {
|
|
return internalGetSuperTypes();
|
|
}
|
|
|
|
public synchronized List<String> getSubTypes() throws SchemaException, ResourceRegistryException {
|
|
return internalGetSubTypes();
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(typeName);
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (this == obj)
|
|
return true;
|
|
if (obj == null)
|
|
return false;
|
|
if (getClass() != obj.getClass())
|
|
return false;
|
|
@SuppressWarnings("unchecked")
|
|
CachedType<T> other = (CachedType<T>) obj;
|
|
return Objects.equals(typeName, other.typeName);
|
|
}
|
|
|
|
}
|