2023-10-24 15:18:48 +02:00
|
|
|
package org.gcube.informationsystem.knowledge;
|
|
|
|
|
2023-10-25 18:01:11 +02:00
|
|
|
import java.util.AbstractMap.SimpleEntry;
|
2023-10-26 15:25:07 +02:00
|
|
|
import java.util.Arrays;
|
2023-10-24 15:18:48 +02:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.HashMap;
|
2023-10-25 18:01:11 +02:00
|
|
|
import java.util.HashSet;
|
2023-10-26 15:25:07 +02:00
|
|
|
import java.util.List;
|
2023-10-24 15:18:48 +02:00
|
|
|
import java.util.Map;
|
2023-10-25 18:01:11 +02:00
|
|
|
import java.util.Map.Entry;
|
2023-10-24 15:18:48 +02:00
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import org.gcube.informationsystem.base.reference.AccessType;
|
2023-10-25 18:01:11 +02:00
|
|
|
import org.gcube.informationsystem.base.reference.entities.EntityElement;
|
|
|
|
import org.gcube.informationsystem.model.reference.entities.Facet;
|
|
|
|
import org.gcube.informationsystem.model.reference.entities.Resource;
|
|
|
|
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
|
|
|
|
import org.gcube.informationsystem.model.reference.relations.IsRelatedTo;
|
|
|
|
import org.gcube.informationsystem.model.reference.relations.Relation;
|
2023-10-24 15:18:48 +02:00
|
|
|
import org.gcube.informationsystem.tree.NodeInformation;
|
|
|
|
import org.gcube.informationsystem.tree.Tree;
|
2023-10-25 18:01:11 +02:00
|
|
|
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;
|
2023-10-24 15:18:48 +02:00
|
|
|
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.relations.ConsistsOfType;
|
|
|
|
import org.gcube.informationsystem.types.reference.relations.IsRelatedToType;
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @author Luca Frosini (ISTI - CNR)
|
|
|
|
*/
|
|
|
|
public class ModelKnowledge<T, NI extends NodeInformation<T>> {
|
|
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ModelKnowledge.class);
|
|
|
|
|
|
|
|
protected NI nodeInformation;
|
|
|
|
protected Map<AccessType, Tree<T>> trees;
|
2023-10-26 15:25:07 +02:00
|
|
|
|
|
|
|
protected UsageKnowledge<Entry<String,PropertyDefinition>> propertyUsage;
|
|
|
|
protected Map<AccessType, UsageKnowledge<LinkedEntity>> erTypesUsage;
|
2023-10-24 15:18:48 +02:00
|
|
|
|
2023-10-25 18:01:11 +02:00
|
|
|
public ModelKnowledge(NI nodeInformation) {
|
|
|
|
this.nodeInformation = nodeInformation;
|
2023-10-24 15:18:48 +02:00
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void reset() {
|
|
|
|
|
|
|
|
this.trees = new HashMap<>();
|
2023-10-26 15:25:07 +02:00
|
|
|
this.erTypesUsage = new HashMap<>();
|
2023-10-24 15:18:48 +02:00
|
|
|
|
|
|
|
AccessType[] modelTypes = AccessType.getModelTypes();
|
|
|
|
for(AccessType accessType : modelTypes) {
|
|
|
|
T t = nodeInformation.getRoot(accessType);
|
|
|
|
|
|
|
|
Tree<T> tree = new Tree<>(t, nodeInformation);
|
|
|
|
trees.put(accessType, tree);
|
|
|
|
|
|
|
|
if(accessType == AccessType.PROPERTY) {
|
|
|
|
/*
|
|
|
|
* In this case we get the type which uses such a property
|
|
|
|
* and the property definition.
|
2023-10-26 15:25:07 +02:00
|
|
|
* In this way we have a complete overview of the usage of the
|
2023-10-24 15:18:48 +02:00
|
|
|
* property type
|
|
|
|
*/
|
2023-10-26 15:25:07 +02:00
|
|
|
propertyUsage = new UsageKnowledge<>(accessType);
|
2023-10-24 15:18:48 +02:00
|
|
|
}else {
|
2023-10-26 15:25:07 +02:00
|
|
|
UsageKnowledge<LinkedEntity> usageKnowledge = new UsageKnowledge<LinkedEntity>(accessType);
|
|
|
|
erTypesUsage.put(accessType, usageKnowledge);
|
2023-10-24 15:18:48 +02:00
|
|
|
}
|
2023-10-26 15:25:07 +02:00
|
|
|
|
2023-10-24 15:18:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-10-25 18:01:11 +02:00
|
|
|
protected void addUsage(LinkedEntity linkedEntity, UsageKnowledge<LinkedEntity> relationUsage, UsageKnowledge<LinkedEntity> targetEntityUsage) {
|
2023-10-24 15:18:48 +02:00
|
|
|
if (linkedEntity != null) {
|
2023-10-26 15:25:07 +02:00
|
|
|
UsageKnowledge<LinkedEntity> resourceUsage = erTypesUsage.get(AccessType.RESOURCE);
|
2023-10-24 15:18:48 +02:00
|
|
|
String source = linkedEntity.getSource();
|
|
|
|
resourceUsage.add(source, linkedEntity);
|
|
|
|
String relation = linkedEntity.getRelation();
|
|
|
|
relationUsage.add(relation, linkedEntity);
|
|
|
|
String target = linkedEntity.getTarget();
|
|
|
|
targetEntityUsage.add(target, linkedEntity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-25 18:01:11 +02:00
|
|
|
protected void addAllUsage(Collection<LinkedEntity> linkedEntities, UsageKnowledge<LinkedEntity> relationUsage, UsageKnowledge<LinkedEntity> targetEntityUsage) {
|
2023-10-24 15:18:48 +02:00
|
|
|
if(linkedEntities!=null) {
|
|
|
|
for(LinkedEntity le : linkedEntities) {
|
2023-10-25 18:01:11 +02:00
|
|
|
addUsage(le, relationUsage, targetEntityUsage);
|
2023-10-24 15:18:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-26 15:25:07 +02:00
|
|
|
protected void addPropertyUsage(T t, Set<PropertyDefinition> properties) {
|
2023-10-25 18:01:11 +02:00
|
|
|
if(properties==null || properties.size()==0) {
|
|
|
|
return;
|
|
|
|
}
|
2023-10-26 15:25:07 +02:00
|
|
|
String typeName = nodeInformation.getIdentifier(t);
|
2023-10-25 18:01:11 +02:00
|
|
|
for(PropertyDefinition propertyDefinition : properties) {
|
|
|
|
PropertyTypeName propertyTypeName = ((PropertyDefinitionImpl) propertyDefinition).getPropertyTypeName();
|
|
|
|
if(propertyTypeName.isGenericType()) {
|
2023-10-26 15:25:07 +02:00
|
|
|
SimpleEntry<String,PropertyDefinition> entry = new SimpleEntry<>(typeName, propertyDefinition);
|
2023-10-25 18:01:11 +02:00
|
|
|
propertyUsage.add(propertyTypeName.getGenericClassName(), entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-26 15:25:07 +02:00
|
|
|
protected void addMetadataUsage(T t) {
|
2023-10-25 18:01:11 +02:00
|
|
|
Type type = TypeMapper.createTypeDefinition(EntityElement.class);
|
2023-10-26 15:25:07 +02:00
|
|
|
addPropertyUsage(t, type.getProperties());
|
2023-10-25 18:01:11 +02:00
|
|
|
}
|
|
|
|
|
2023-10-26 15:25:07 +02:00
|
|
|
protected void addPropagationConstraintUsage(T t) {
|
2023-10-25 18:01:11 +02:00
|
|
|
Type type = TypeMapper.createTypeDefinition(Relation.class);
|
2023-10-26 15:25:07 +02:00
|
|
|
addPropertyUsage(t, type.getProperties());
|
2023-10-25 18:01:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addAllType(Collection<T> types) {
|
|
|
|
Set<T> toRetry = new HashSet<>();
|
|
|
|
|
|
|
|
for(T t : types) {
|
|
|
|
logger.trace("Going to add {}", nodeInformation.getIdentifier(t));
|
|
|
|
try {
|
|
|
|
addType(t);
|
|
|
|
}catch (RuntimeException e) {
|
|
|
|
toRetry.add(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(toRetry.size()>0) {
|
|
|
|
addAllType(toRetry);
|
|
|
|
}
|
2023-10-24 15:18:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addType(T t) {
|
|
|
|
AccessType accessType = nodeInformation.getAccessType(t);
|
2023-10-25 18:01:11 +02:00
|
|
|
String typeName = nodeInformation.getIdentifier(t);
|
|
|
|
|
|
|
|
Tree<T> tree = trees.get(accessType);
|
|
|
|
tree.addNode(t);
|
2023-10-24 15:18:48 +02:00
|
|
|
|
2023-10-26 15:25:07 +02:00
|
|
|
UsageKnowledge<LinkedEntity> resourceUsage = erTypesUsage.get(AccessType.RESOURCE);
|
|
|
|
UsageKnowledge<LinkedEntity> facetUsage = erTypesUsage.get(AccessType.FACET);
|
|
|
|
UsageKnowledge<LinkedEntity> isRelatedToUsage = erTypesUsage.get(AccessType.IS_RELATED_TO);
|
|
|
|
UsageKnowledge<LinkedEntity> consistsOfUsage = erTypesUsage.get(AccessType.CONSISTS_OF);
|
2023-10-24 15:18:48 +02:00
|
|
|
|
|
|
|
switch (accessType) {
|
|
|
|
case PROPERTY:
|
|
|
|
// Nothing to do
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RESOURCE:
|
|
|
|
ResourceType resourceType = (ResourceType) t;
|
2023-10-25 18:01:11 +02:00
|
|
|
addAllUsage(resourceType.getFacets(), consistsOfUsage, facetUsage);
|
|
|
|
addAllUsage(resourceType.getResources(), isRelatedToUsage, resourceUsage);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Metadata is defined in parent type i.e. EntityElement.
|
|
|
|
* We want to have a reference to all Base type
|
|
|
|
*/
|
|
|
|
if(typeName.compareTo(Resource.NAME)==0) {
|
2023-10-26 15:25:07 +02:00
|
|
|
addMetadataUsage(t);
|
2023-10-25 18:01:11 +02:00
|
|
|
}
|
2023-10-24 15:18:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FACET:
|
|
|
|
FacetType facetType = (FacetType) t;
|
2023-10-25 18:01:11 +02:00
|
|
|
if(typeName.compareTo(Facet.NAME)==0) {
|
2023-10-26 15:25:07 +02:00
|
|
|
addMetadataUsage(t);
|
2023-10-25 18:01:11 +02:00
|
|
|
}
|
2023-10-26 15:25:07 +02:00
|
|
|
addPropertyUsage(t, facetType.getProperties());
|
2023-10-25 18:01:11 +02:00
|
|
|
|
2023-10-24 15:18:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case IS_RELATED_TO:
|
|
|
|
IsRelatedToType isRelatedToType = (IsRelatedToType) t;
|
2023-10-25 18:01:11 +02:00
|
|
|
if(typeName.compareTo(IsRelatedTo.NAME)==0) {
|
2023-10-26 15:25:07 +02:00
|
|
|
addMetadataUsage(t);
|
|
|
|
addPropagationConstraintUsage(t);
|
2023-10-25 18:01:11 +02:00
|
|
|
}
|
2023-10-26 15:25:07 +02:00
|
|
|
addPropertyUsage(t, isRelatedToType.getProperties());
|
2023-10-24 15:18:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CONSISTS_OF:
|
|
|
|
ConsistsOfType consistsOfType = (ConsistsOfType) t;
|
2023-10-25 18:01:11 +02:00
|
|
|
if(typeName.compareTo(ConsistsOf.NAME)==0) {
|
2023-10-26 15:25:07 +02:00
|
|
|
addMetadataUsage(t);
|
|
|
|
addPropagationConstraintUsage(t);
|
2023-10-25 18:01:11 +02:00
|
|
|
}
|
2023-10-26 15:25:07 +02:00
|
|
|
addPropertyUsage(t, consistsOfType.getProperties());
|
2023-10-24 15:18:48 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public Tree<T> getTree(AccessType accessType) {
|
|
|
|
return trees.get(accessType);
|
|
|
|
}
|
|
|
|
|
2023-10-26 15:25:07 +02:00
|
|
|
public UsageKnowledge<?> getModelTypesUsage(AccessType accessType) {
|
|
|
|
List<AccessType> modelTypes = Arrays.asList(AccessType.getModelTypes());
|
|
|
|
if(!modelTypes.contains(accessType)) {
|
|
|
|
throw new RuntimeException("Only ModelTypes are allowed, i.e. " + modelTypes.toString());
|
|
|
|
}
|
|
|
|
if(accessType == AccessType.PROPERTY) {
|
|
|
|
return propertyUsage;
|
|
|
|
}else {
|
|
|
|
return erTypesUsage.get(accessType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public UsageKnowledge<LinkedEntity> getERTypesUsage(AccessType accessType) {
|
|
|
|
List<AccessType> erTypes = Arrays.asList(AccessType.getERTypes());
|
|
|
|
if(!erTypes.contains(accessType)) {
|
|
|
|
throw new RuntimeException("Only ERTypes are allowed, i.e. " + erTypes.toString());
|
|
|
|
}
|
|
|
|
return erTypesUsage.get(accessType);
|
|
|
|
}
|
|
|
|
|
|
|
|
public UsageKnowledge<Entry<String,PropertyDefinition>> getPropertyUsage(){
|
|
|
|
return propertyUsage;
|
2023-10-24 15:18:48 +02:00
|
|
|
}
|
2023-10-26 15:25:07 +02:00
|
|
|
|
|
|
|
public UsageKnowledge<LinkedEntity> getResourceUsage() {
|
|
|
|
return erTypesUsage.get(AccessType.RESOURCE);
|
|
|
|
}
|
|
|
|
|
|
|
|
public UsageKnowledge<LinkedEntity> getFacetUsage() {
|
|
|
|
return erTypesUsage.get(AccessType.FACET);
|
|
|
|
}
|
|
|
|
|
|
|
|
public UsageKnowledge<LinkedEntity> getIsRelatedToUsage() {
|
|
|
|
return erTypesUsage.get(AccessType.IS_RELATED_TO);
|
|
|
|
}
|
|
|
|
|
|
|
|
public UsageKnowledge<LinkedEntity> getConsistsOfUsage() {
|
|
|
|
return erTypesUsage.get(AccessType.CONSISTS_OF);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-10-24 15:18:48 +02:00
|
|
|
}
|