Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
Luca Frosini | dc8595d13e | |
Luca Frosini | 8ac4511bde | |
Luca Frosini | 0559bc031f | |
Luca Frosini | 6eecea2ab1 | |
Luca Frosini | c68826637c | |
luca.frosini | acf51f9dfb | |
luca.frosini | ef74dd31ea | |
luca.frosini | 118e058c90 | |
luca.frosini | 6dc26a43b8 | |
luca.frosini | 8b7aa5660a | |
luca.frosini | 27854806df | |
luca.frosini | b05f0c51f3 | |
luca.frosini | 6db5256e70 | |
luca.frosini | b3cb92f55a | |
luca.frosini | 58b688a9ad | |
luca.frosini | 590be162b8 | |
luca.frosini | 185030acc2 | |
luca.frosini | 58e5e70db6 | |
luca.frosini | 9a32f3c534 | |
luca.frosini | d2b715a318 | |
luca.frosini | ff0c6aec9d | |
luca.frosini | d1d9ae4a4a | |
luca.frosini | e403b2459c | |
luca.frosini | 3895abdac3 |
|
@ -2,6 +2,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||
|
||||
# Changelog for Information System Model
|
||||
|
||||
## [v7.1.0-SNAPSHOT]
|
||||
|
||||
- Improved support for model knowledge [#25922]
|
||||
|
||||
|
||||
## [v7.0.0]
|
||||
|
||||
- Reorganized E/R format [#24992]
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -10,7 +10,7 @@
|
|||
|
||||
<groupId>org.gcube.information-system</groupId>
|
||||
<artifactId>information-system-model</artifactId>
|
||||
<version>7.0.0</version>
|
||||
<version>7.1.0-SNAPSHOT</version>
|
||||
<name>Information System Model</name>
|
||||
<description>Information System Model is the reference model of the gCube Information System</description>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
@ -41,7 +41,6 @@ public class PropertyElementImpl extends ElementImpl implements Property {
|
|||
super();
|
||||
this.additionalProperties = new HashMap<>();
|
||||
this.allowedAdditionalKeys = new HashSet<>();
|
||||
this.allowedAdditionalKeys.add(SUPERTYPES_PROPERTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -81,6 +81,7 @@ public enum AccessType {
|
|||
private static Logger logger = LoggerFactory.getLogger(AccessType.class);
|
||||
|
||||
private static AccessType[] modelTypes;
|
||||
private static AccessType[] erTypes;
|
||||
private static Set<String> names;
|
||||
|
||||
static {
|
||||
|
@ -96,6 +97,11 @@ public enum AccessType {
|
|||
AccessType.RESOURCE, AccessType.FACET,
|
||||
AccessType.IS_RELATED_TO, AccessType.CONSISTS_OF
|
||||
};
|
||||
|
||||
erTypes = new AccessType[] {
|
||||
AccessType.RESOURCE, AccessType.FACET,
|
||||
AccessType.IS_RELATED_TO, AccessType.CONSISTS_OF
|
||||
};
|
||||
}
|
||||
|
||||
private final Class<? extends Element> clz;
|
||||
|
@ -186,8 +192,20 @@ public enum AccessType {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an array of AccessTypes containing only
|
||||
* Model Types (i.e. Property, Resource, Facet, IsRelatedTo, ConsistsOf)
|
||||
*/
|
||||
public static AccessType[] getModelTypes() {
|
||||
return modelTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an array of AccessTypes containing only
|
||||
* Entity/Relation Model Types (i.e. Resource, Facet, IsRelatedTo, ConsistsOf)
|
||||
*/
|
||||
public static AccessType[] getERTypes() {
|
||||
return erTypes;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,17 +4,25 @@
|
|||
package org.gcube.informationsystem.contexts.impl.entities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.gcube.com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import org.gcube.informationsystem.base.impl.entities.EntityElementImpl;
|
||||
import org.gcube.informationsystem.base.reference.Element;
|
||||
import org.gcube.informationsystem.contexts.impl.relations.IsParentOfImpl;
|
||||
import org.gcube.informationsystem.contexts.reference.entities.Context;
|
||||
import org.gcube.informationsystem.contexts.reference.relations.IsParentOf;
|
||||
import org.gcube.informationsystem.model.impl.properties.MetadataImpl;
|
||||
import org.gcube.informationsystem.model.reference.properties.Property;
|
||||
import org.gcube.informationsystem.serialization.ElementMapper;
|
||||
import org.gcube.informationsystem.utils.UUIDManager;
|
||||
|
||||
/**
|
||||
|
@ -34,10 +42,21 @@ public final class ContextImpl extends EntityElementImpl implements Context {
|
|||
protected IsParentOf parent;
|
||||
protected List<IsParentOf> children;
|
||||
|
||||
@JsonIgnore
|
||||
protected Map<String, Object> additionalProperties;
|
||||
|
||||
@JsonIgnore
|
||||
/**
|
||||
* Used to allow to have an additional property starting with '_' or '@'
|
||||
*/
|
||||
protected final Set<String> allowedAdditionalKeys;
|
||||
|
||||
protected ContextImpl() {
|
||||
super();
|
||||
this.parent = null;
|
||||
this.children = new ArrayList<>();
|
||||
this.additionalProperties = new HashMap<>();
|
||||
this.allowedAdditionalKeys = new HashSet<>();
|
||||
}
|
||||
|
||||
public ContextImpl(UUID uuid) {
|
||||
|
@ -158,4 +177,55 @@ public final class ContextImpl extends EntityElementImpl implements Context {
|
|||
children.add(isParentOf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAdditionalProperties() {
|
||||
return additionalProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
|
||||
this.additionalProperties = additionalProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAdditionalProperty(String key) {
|
||||
return additionalProperties.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdditionalProperty(String key, Object value) {
|
||||
|
||||
if(!allowedAdditionalKeys.contains(key)){
|
||||
if(key.startsWith("_")) {
|
||||
return;
|
||||
}
|
||||
if(key.startsWith("@")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Additional properties are not deserialized to the proper property type.
|
||||
The first attempt was to try to write a specific deserializer but it fails.
|
||||
This fix the issue.
|
||||
*/
|
||||
try {
|
||||
if(value instanceof Map<?,?>) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String,Object>) value;
|
||||
if(map.containsKey(Element.TYPE_PROPERTY)) {
|
||||
String reserialized = ElementMapper.getObjectMapper().writeValueAsString(map);
|
||||
Property property = ElementMapper.unmarshal(Property.class, reserialized);
|
||||
value = property;
|
||||
}
|
||||
}
|
||||
}catch (Throwable e) {
|
||||
e.getMessage();
|
||||
// Any type of error/exception must be catched
|
||||
}
|
||||
/* END of fix to properly deserialize Property types*/
|
||||
|
||||
this.additionalProperties.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,19 +4,25 @@
|
|||
package org.gcube.informationsystem.contexts.reference.entities;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonAnyGetter;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonAnySetter;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
import org.gcube.com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import org.gcube.com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import org.gcube.informationsystem.base.reference.Element;
|
||||
import org.gcube.informationsystem.base.reference.IdentifiableElement;
|
||||
import org.gcube.informationsystem.base.reference.SchemaMixedElement;
|
||||
import org.gcube.informationsystem.base.reference.entities.EntityElement;
|
||||
import org.gcube.informationsystem.contexts.impl.entities.ContextImpl;
|
||||
import org.gcube.informationsystem.contexts.reference.relations.IsParentOf;
|
||||
import org.gcube.informationsystem.model.reference.relations.Relation;
|
||||
import org.gcube.informationsystem.serialization.AdditionalPropertiesSerializer;
|
||||
import org.gcube.informationsystem.types.annotations.ISProperty;
|
||||
import org.gcube.informationsystem.types.reference.Change;
|
||||
import org.gcube.informationsystem.types.reference.TypeMetadata;
|
||||
|
@ -31,14 +37,59 @@ import org.gcube.informationsystem.utils.Version;
|
|||
@JsonPropertyOrder({ Element.TYPE_PROPERTY, IdentifiableElement.ID_PROPERTY, IdentifiableElement.METADATA_PROPERTY})
|
||||
@TypeMetadata(name = Context.NAME, description = "This type is the used to define a Context", version = Version.MINIMAL_VERSION_STRING)
|
||||
@Change(version = Version.MINIMAL_VERSION_STRING, description = Version.MINIMAL_VERSION_DESCRIPTION)
|
||||
public interface Context extends EntityElement {
|
||||
public interface Context extends EntityElement, SchemaMixedElement {
|
||||
|
||||
public static final String NAME = "Context"; // Context.class.getSimpleName();
|
||||
|
||||
public static final String NAME_PROPERTY = "name";
|
||||
public static final String PARENT_PROPERTY = "parent";
|
||||
public static final String CHILDREN_PROPERTY = "children";
|
||||
|
||||
|
||||
/**
|
||||
* {
|
||||
* ...
|
||||
* "availableAt" : [
|
||||
* "https://i-marine.d4science.org/group/alienandinvasivespecies",
|
||||
* "https://services.d4science.org/group/alienandinvasivespecies"
|
||||
* ]
|
||||
* ...
|
||||
* }
|
||||
* For non VRE context this field could be null or could have multiple value
|
||||
* For VRE it is normally one value only (but some exception could exists
|
||||
*/
|
||||
public static final String AVAILABLE_AT_PROPERTY = "availableAt";
|
||||
|
||||
//
|
||||
/**
|
||||
* This information is provided to allowed user only (by role)
|
||||
* {
|
||||
* ...
|
||||
* "fullpaths" : [
|
||||
* {
|
||||
* "fullpath": "/gcube/devsec/myTest",
|
||||
* "time": "2023-12-11 15:35:41.289 +0000", // Same of creationTime in metadata
|
||||
* },
|
||||
* {
|
||||
* "fullpath": "/gcube/devsec/myTestVRE",
|
||||
* "time": "2023-12-13 16:13:12.336 +0000",
|
||||
* }
|
||||
* {
|
||||
* "fullpath": "/gcube/devsec/myVRE",
|
||||
* "time": "2023-12-18 12:37:48.172 +0000", // Same of lastUpdateTime in metadata
|
||||
* }
|
||||
* ]
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
public static final String CONTEXT_FULLPATH_CHANGES_LOG_PROPERTY = "fullpathChangelog";
|
||||
|
||||
/**
|
||||
* This information is provided to allowed user only (by role)
|
||||
* The symmetric key for the context
|
||||
*/
|
||||
public static final String CONTEXT_KEY_PROPERTY = "key";
|
||||
|
||||
|
||||
@ISProperty(name = NAME_PROPERTY, mandatory = true, nullable = false)
|
||||
public String getName();
|
||||
|
||||
|
@ -66,5 +117,20 @@ public interface Context extends EntityElement {
|
|||
public void addChild(Context child);
|
||||
|
||||
public void addChild(IsParentOf isParentOf);
|
||||
|
||||
@JsonAnyGetter
|
||||
@JsonSerialize(using = AdditionalPropertiesSerializer.class)
|
||||
@Override
|
||||
public Map<String,Object> getAdditionalProperties();
|
||||
|
||||
@Override
|
||||
public void setAdditionalProperties(Map<String,Object> additionalProperties);
|
||||
|
||||
@Override
|
||||
public Object getAdditionalProperty(String key);
|
||||
|
||||
@JsonAnySetter
|
||||
@Override
|
||||
public void setAdditionalProperty(String key, Object value);
|
||||
|
||||
}
|
||||
|
|
|
@ -3,14 +3,15 @@ package org.gcube.informationsystem.discovery.knowledge;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
import org.gcube.informationsystem.base.reference.Element;
|
||||
import org.gcube.informationsystem.tree.NodeInformation;
|
||||
import org.gcube.informationsystem.model.knowledge.TypeInformation;
|
||||
import org.gcube.informationsystem.types.TypeMapper;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public class ClassInformation implements NodeInformation<Class<Element>> {
|
||||
public class ClassInformation implements TypeInformation<Class<Element>> {
|
||||
|
||||
@Override
|
||||
public String getIdentifier(Class<Element> clz) {
|
||||
|
@ -35,4 +36,14 @@ public class ClassInformation implements NodeInformation<Class<Element>> {
|
|||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessType getAccessType(Class<Element> clz) {
|
||||
return AccessType.getAccessType(clz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Element> getRoot(AccessType accessType) {
|
||||
return accessType.getTypeClass();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public class ModelKnowledgeValidator implements DiscoveredElementAction<Element>
|
|||
}
|
||||
|
||||
String typeName = TypeMapper.getType(e);
|
||||
if(node.getTree().getRoot().getNodeElement() == e) {
|
||||
if(node.getTree().getRootNode().getNodeElement() == e) {
|
||||
logger.info("{}- Type {} is the root type", stringBuffer.toString(), typeName);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import java.util.Set;
|
|||
import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.gcube.com.fasterxml.jackson.annotation.JsonTypeName;
|
||||
import org.gcube.informationsystem.base.reference.Element;
|
||||
import org.gcube.informationsystem.model.reference.ModelElement;
|
||||
import org.gcube.informationsystem.model.reference.entities.Facet;
|
||||
import org.gcube.informationsystem.model.reference.properties.Property;
|
||||
import org.gcube.informationsystem.serialization.ElementMapper;
|
||||
|
@ -40,8 +39,6 @@ public abstract class FacetImpl extends EntityImpl implements Facet {
|
|||
super();
|
||||
this.additionalProperties = new HashMap<>();
|
||||
this.allowedAdditionalKeys = new HashSet<>();
|
||||
this.allowedAdditionalKeys.add(ModelElement.SUPERTYPES_PROPERTY);
|
||||
this.allowedAdditionalKeys.add(ModelElement.EXPECTED_TYPE_PROPERTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -53,7 +53,6 @@ public abstract class RelationImpl<S extends Resource, T extends Entity>
|
|||
super();
|
||||
this.additionalProperties = new HashMap<>();
|
||||
this.allowedAdditionalKeys = new HashSet<>();
|
||||
this.allowedAdditionalKeys.add(SUPERTYPES_PROPERTY);
|
||||
}
|
||||
|
||||
protected RelationImpl(S source, T target,
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
package org.gcube.informationsystem.model.knowledge;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
import org.gcube.informationsystem.base.reference.entities.EntityElement;
|
||||
import org.gcube.informationsystem.base.reference.relations.RelationElement;
|
||||
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;
|
||||
import org.gcube.informationsystem.tree.Node;
|
||||
import org.gcube.informationsystem.tree.Tree;
|
||||
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.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, TI extends TypeInformation<T>> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ModelKnowledge.class);
|
||||
|
||||
protected TI typeInformation;
|
||||
protected Map<AccessType, Tree<T>> trees;
|
||||
|
||||
protected UsageKnowledge<Entry<String,PropertyDefinition>> propertyUsage;
|
||||
protected Map<AccessType, UsageKnowledge<LinkedEntity>> erTypesUsage;
|
||||
|
||||
protected Map<String, AccessType> locate;
|
||||
|
||||
public ModelKnowledge(TI typeInformation) {
|
||||
this.typeInformation = typeInformation;
|
||||
reset();
|
||||
}
|
||||
|
||||
protected void reset() {
|
||||
|
||||
this.trees = new HashMap<>();
|
||||
this.erTypesUsage = new HashMap<>();
|
||||
this.locate = new HashMap<>();
|
||||
|
||||
AccessType[] modelTypes = AccessType.getModelTypes();
|
||||
for(AccessType accessType : modelTypes) {
|
||||
|
||||
/*
|
||||
* T t = typeInformation.getRoot(accessType);
|
||||
* Tree<T> tree = new Tree<>(t, typeInformation);
|
||||
*/
|
||||
|
||||
Tree<T> tree = new Tree<>(typeInformation);
|
||||
trees.put(accessType, tree);
|
||||
|
||||
if(accessType == AccessType.PROPERTY) {
|
||||
/*
|
||||
* In this case we get the type which uses such a property
|
||||
* and the property definition.
|
||||
* In this way we have a complete overview of the usage of the
|
||||
* property type
|
||||
*/
|
||||
propertyUsage = new UsageKnowledge<>(accessType);
|
||||
}else {
|
||||
UsageKnowledge<LinkedEntity> usageKnowledge = new UsageKnowledge<LinkedEntity>(accessType);
|
||||
erTypesUsage.put(accessType, usageKnowledge);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void addUsage(LinkedEntity linkedEntity, UsageKnowledge<LinkedEntity> relationUsage, UsageKnowledge<LinkedEntity> targetEntityUsage) {
|
||||
if (linkedEntity != null) {
|
||||
UsageKnowledge<LinkedEntity> resourceUsage = erTypesUsage.get(AccessType.RESOURCE);
|
||||
String source = linkedEntity.getSource();
|
||||
resourceUsage.add(source, linkedEntity);
|
||||
String relation = linkedEntity.getRelation();
|
||||
relationUsage.add(relation, linkedEntity);
|
||||
String target = linkedEntity.getTarget();
|
||||
targetEntityUsage.add(target, linkedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addAllUsage(Collection<LinkedEntity> linkedEntities, UsageKnowledge<LinkedEntity> relationUsage, UsageKnowledge<LinkedEntity> targetEntityUsage) {
|
||||
if(linkedEntities!=null) {
|
||||
for(LinkedEntity le : linkedEntities) {
|
||||
addUsage(le, relationUsage, targetEntityUsage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void addPropertyUsage(T t, Set<PropertyDefinition> properties) {
|
||||
if(properties==null || properties.size()==0) {
|
||||
return;
|
||||
}
|
||||
String typeName = typeInformation.getIdentifier(t);
|
||||
for(PropertyDefinition propertyDefinition : properties) {
|
||||
PropertyTypeName propertyTypeName = ((PropertyDefinitionImpl) propertyDefinition).getPropertyTypeName();
|
||||
if(propertyTypeName.isGenericType()) {
|
||||
SimpleEntry<String,PropertyDefinition> entry = new SimpleEntry<>(typeName, propertyDefinition);
|
||||
propertyUsage.add(propertyTypeName.getGenericClassName(), entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void addEntityMetadataUsage(T t) {
|
||||
Type type = TypeMapper.createTypeDefinition(EntityElement.class);
|
||||
addPropertyUsage(t, type.getProperties());
|
||||
}
|
||||
|
||||
protected void addRelationMetadataUsage(T t) {
|
||||
Type type = TypeMapper.createTypeDefinition(RelationElement.class);
|
||||
addPropertyUsage(t, type.getProperties());
|
||||
}
|
||||
|
||||
protected void addPropagationConstraintUsage(T t) {
|
||||
Type type = TypeMapper.createTypeDefinition(Relation.class);
|
||||
addPropertyUsage(t, type.getProperties());
|
||||
}
|
||||
|
||||
public void addAllType(Collection<T> types) {
|
||||
Set<T> toRetry = new HashSet<>();
|
||||
|
||||
for(T t : types) {
|
||||
logger.trace("Going to add {}", typeInformation.getIdentifier(t));
|
||||
try {
|
||||
addType(t);
|
||||
}catch (RuntimeException e) {
|
||||
toRetry.add(t);
|
||||
}
|
||||
}
|
||||
|
||||
if(types.size()==toRetry.size()) {
|
||||
throw new RuntimeException("Unable to find parent for " + toRetry.toString());
|
||||
}
|
||||
|
||||
if(toRetry.size()>0) {
|
||||
addAllType(toRetry);
|
||||
}
|
||||
}
|
||||
|
||||
public void addType(T t) {
|
||||
AccessType accessType = typeInformation.getAccessType(t);
|
||||
String typeName = typeInformation.getIdentifier(t);
|
||||
|
||||
if(locate.get(typeName)!=null) {
|
||||
logger.trace("The type {} was already added to the ModelKnowledge", typeName);
|
||||
return;
|
||||
}
|
||||
|
||||
Tree<T> tree = trees.get(accessType);
|
||||
tree.addNode(t);
|
||||
locate.put(typeName, accessType);
|
||||
|
||||
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);
|
||||
|
||||
switch (accessType) {
|
||||
case PROPERTY:
|
||||
// Nothing to do
|
||||
break;
|
||||
|
||||
case RESOURCE:
|
||||
ResourceType resourceType = (ResourceType) t;
|
||||
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) {
|
||||
addEntityMetadataUsage(t);
|
||||
}
|
||||
break;
|
||||
|
||||
case FACET:
|
||||
FacetType facetType = (FacetType) t;
|
||||
/*
|
||||
* Metadata is defined in parent type i.e. EntityElement.
|
||||
* We want to have a reference to all Base type
|
||||
*/
|
||||
if(typeName.compareTo(Facet.NAME)==0) {
|
||||
addEntityMetadataUsage(t);
|
||||
}
|
||||
addPropertyUsage(t, facetType.getProperties());
|
||||
|
||||
break;
|
||||
|
||||
case IS_RELATED_TO:
|
||||
IsRelatedToType isRelatedToType = (IsRelatedToType) t;
|
||||
/*
|
||||
* Metadata is defined in parent type i.e. RelationElement.
|
||||
* We want to have a reference to all Base type
|
||||
*/
|
||||
if(typeName.compareTo(IsRelatedTo.NAME)==0) {
|
||||
addRelationMetadataUsage(t);
|
||||
addPropagationConstraintUsage(t);
|
||||
}
|
||||
addPropertyUsage(t, isRelatedToType.getProperties());
|
||||
break;
|
||||
|
||||
case CONSISTS_OF:
|
||||
ConsistsOfType consistsOfType = (ConsistsOfType) t;
|
||||
/*
|
||||
* Metadata is defined in parent type i.e. RelationElement.
|
||||
* We want to have a reference to all Base type
|
||||
*/
|
||||
if(typeName.compareTo(ConsistsOf.NAME)==0) {
|
||||
addRelationMetadataUsage(t);
|
||||
addPropagationConstraintUsage(t);
|
||||
}
|
||||
addPropertyUsage(t, consistsOfType.getProperties());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Tree<T> getTree(AccessType accessType) {
|
||||
return trees.get(accessType);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type if it is contained in the Knowledge
|
||||
* @param typeName the type we are looking for
|
||||
* @return the Type
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public T getTypeByName(String typeName) throws RuntimeException {
|
||||
return getNodeByName(typeName).getNodeElement();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the node fro the type if it is contained in the Knowledge
|
||||
* @param typeName the type we are looking for
|
||||
* @return the Type
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public Node<T> getNodeByName(String typeName) throws RuntimeException {
|
||||
AccessType accessType = locate.get(typeName);
|
||||
if(accessType==null) {
|
||||
throw new RuntimeException("The type " + typeName + " is not contained in the Knowledge");
|
||||
}
|
||||
|
||||
Tree<T> tree = trees.get(accessType);
|
||||
return tree.getNodeByIdentifier(typeName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.gcube.informationsystem.model.knowledge;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
import org.gcube.informationsystem.tree.NodeInformation;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public interface TypeInformation<T> extends NodeInformation<T> {
|
||||
|
||||
public AccessType getAccessType(T t);
|
||||
|
||||
public T getRoot(AccessType accessType);
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.gcube.informationsystem.model.knowledge;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public interface TypesDiscoverer<T> {
|
||||
|
||||
/**
|
||||
* This function discover all available types of a certain
|
||||
* AccessType. Allowed AccessTypes are only IS Model Types
|
||||
* see {@link AccessType#getModelTypes()}
|
||||
* @param accessType
|
||||
* @return
|
||||
*/
|
||||
public Collection<T> discover(AccessType accessType);
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.gcube.informationsystem.model.knowledge;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public class UsageKnowledge<U> {
|
||||
|
||||
protected Map<String, List<U>> map;
|
||||
|
||||
public UsageKnowledge(AccessType accessType){
|
||||
this.map = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public void add(String typeName, U u) {
|
||||
List<U> list = map.get(typeName);
|
||||
if(list==null) {
|
||||
list = new ArrayList<>();
|
||||
map.put(typeName, list);
|
||||
}
|
||||
list.add(u);
|
||||
}
|
||||
|
||||
public List<U> getUsage(String typeName){
|
||||
List<U> list = map.get(typeName);
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
|
@ -25,6 +25,7 @@ import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import org.gcube.com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.gcube.com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.JsonNodeType;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.TextNode;
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
|
@ -32,6 +33,7 @@ import org.gcube.informationsystem.base.reference.Element;
|
|||
import org.gcube.informationsystem.discovery.Discovery;
|
||||
import org.gcube.informationsystem.discovery.knowledge.Knowledge;
|
||||
import org.gcube.informationsystem.model.reference.ModelElement;
|
||||
import org.gcube.informationsystem.model.reference.properties.Property;
|
||||
import org.gcube.informationsystem.types.TypeMapper;
|
||||
import org.gcube.informationsystem.types.reference.Type;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -207,24 +209,26 @@ public abstract class ElementMapper {
|
|||
ArrayNode arrayNode = (ArrayNode) objectNode.get(ModelElement.SUPERTYPES_PROPERTY);
|
||||
|
||||
String candidatedSupertype = null;
|
||||
for(int i = 0; i < arrayNode.size(); i++) {
|
||||
String superType = arrayNode.get(i).asText();
|
||||
if(knownTypes.containsKey(superType)) {
|
||||
candidatedSupertype = superType;
|
||||
try {
|
||||
// Checking if it is one of the base type. In some cases we need to use dummy
|
||||
// implementation
|
||||
AccessType accessType = AccessType.getAccessType(superType);
|
||||
// It is one of the BaseType.
|
||||
// Looking if we need to set the dummy implementation class
|
||||
if(accessType.getDummyImplementationClass()!=null) {
|
||||
// This should not happen because the type has been assigned already to the dummy class.
|
||||
candidatedSupertype = accessType.getDummyImplementationClass().getSimpleName();
|
||||
if(arrayNode!=null) {
|
||||
for(int i = 0; i < arrayNode.size(); i++) {
|
||||
String superType = arrayNode.get(i).asText();
|
||||
if(knownTypes.containsKey(superType)) {
|
||||
candidatedSupertype = superType;
|
||||
try {
|
||||
// Checking if it is one of the base type. In some cases we need to use dummy
|
||||
// implementation
|
||||
AccessType accessType = AccessType.getAccessType(superType);
|
||||
// It is one of the BaseType.
|
||||
// Looking if we need to set the dummy implementation class
|
||||
if(accessType.getDummyImplementationClass()!=null) {
|
||||
// This should not happen because the type has been assigned already to the dummy class.
|
||||
candidatedSupertype = accessType.getDummyImplementationClass().getSimpleName();
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
// can continue discovery
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
// can continue discovery
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,7 +247,17 @@ public abstract class ElementMapper {
|
|||
}
|
||||
|
||||
protected static JsonNode analizeTypes(ObjectNode objectNode) {
|
||||
String cls = objectNode.get(Element.TYPE_PROPERTY).asText();
|
||||
String cls = null;
|
||||
|
||||
JsonNode typeJN = objectNode.get(Element.TYPE_PROPERTY);
|
||||
if(typeJN !=null) {
|
||||
cls = objectNode.get(Element.TYPE_PROPERTY).asText();
|
||||
}
|
||||
|
||||
if(cls==null && objectNode.getNodeType()==JsonNodeType.OBJECT) {
|
||||
cls = Property.NAME;
|
||||
}
|
||||
|
||||
if(!knownTypes.containsKey(cls)) {
|
||||
objectNode = setTypeToBestAvailable(objectNode);
|
||||
}
|
||||
|
@ -267,7 +281,7 @@ public abstract class ElementMapper {
|
|||
}
|
||||
return objectNode;
|
||||
}
|
||||
|
||||
|
||||
protected static ArrayNode analizeTypes(ArrayNode arrayNode) {
|
||||
ArrayNode ret = mapper.createArrayNode();
|
||||
|
||||
|
|
|
@ -2,10 +2,13 @@ package org.gcube.informationsystem.tree;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public interface NodeInformation<T> {
|
||||
|
||||
public abstract String getIdentifier(T t);
|
||||
public String getIdentifier(T t);
|
||||
|
||||
public abstract Set<String> getParentIdentifiers(T root, T t);
|
||||
public Set<String> getParentIdentifiers(T root, T t);
|
||||
|
||||
}
|
||||
|
|
|
@ -11,18 +11,53 @@ public class Tree<T> {
|
|||
|
||||
private boolean allowMultipleInheritance;
|
||||
|
||||
private Node<T> root;
|
||||
private Node<T> rootNode;
|
||||
private NodeInformation<T> ni;
|
||||
private Map<String, Node<T>> locate;
|
||||
|
||||
public Tree(T t, NodeInformation<T> ni) throws Exception {
|
||||
public Tree() {
|
||||
this.allowMultipleInheritance = true;
|
||||
this.ni = ni;
|
||||
this.locate = new HashMap<>();
|
||||
this.root = new Node<>(t);
|
||||
this.root.setTree(this);
|
||||
String identifier = ni.getIdentifier(t);
|
||||
this.locate.put(identifier, root);
|
||||
}
|
||||
|
||||
public Tree(NodeInformation<T> ni) {
|
||||
this();
|
||||
setNodeInformation(ni);
|
||||
}
|
||||
|
||||
public Tree(T root, NodeInformation<T> ni) {
|
||||
this(ni);
|
||||
setRoot(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the NodeInformation if and only if it was not previously set.
|
||||
* Otherwise this function has no effect.
|
||||
* @param ni the NodeInformation to set
|
||||
*/
|
||||
public void setNodeInformation(NodeInformation<T> ni) {
|
||||
if(this.ni==null) {
|
||||
this.ni = ni;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the root if and only if it was not previously set.
|
||||
* Otherwise this function has no effect.
|
||||
* This function raises a RuntimeException is the
|
||||
* NodeInformation was not previously set.
|
||||
* @param root the root to set
|
||||
*/
|
||||
public void setRoot(T root) throws RuntimeException {
|
||||
if(this.ni==null) {
|
||||
throw new RuntimeException("You must set the NodeInformation instance first");
|
||||
}
|
||||
if(this.rootNode==null) {
|
||||
this.rootNode = new Node<>(root);
|
||||
this.rootNode.setTree(this);
|
||||
String identifier = ni.getIdentifier(root);
|
||||
this.locate.put(identifier, rootNode);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAllowMultipleInheritance(boolean allowMultipleInheritance) {
|
||||
|
@ -43,17 +78,25 @@ public class Tree<T> {
|
|||
Node<T> node = new Node<>(t);
|
||||
node.setTree(this);
|
||||
|
||||
Set<String> parentIdentifiers = ni.getParentIdentifiers(root.getNodeElement(), t);
|
||||
for(String parentIdentifier : parentIdentifiers) {
|
||||
Node<T> parentNode = locate.get(parentIdentifier);
|
||||
if(parentNode==null) {
|
||||
throw new RuntimeException("I can find parent for " + identifier + ". Missing parent is " + parentIdentifier);
|
||||
Set<String> parentIdentifiers = ni.getParentIdentifiers(rootNode!= null ? rootNode.getNodeElement() : null, t);
|
||||
if(parentIdentifiers==null || parentIdentifiers.size()==0) {
|
||||
if(this.rootNode==null) {
|
||||
this.rootNode = node;
|
||||
}else {
|
||||
throw new RuntimeException("A Tree cannot have two root. " + t.toString() + " has not parent.");
|
||||
}
|
||||
|
||||
parentNode.addChild(node);
|
||||
|
||||
if(!allowMultipleInheritance) {
|
||||
break;
|
||||
} else {
|
||||
for(String parentIdentifier : parentIdentifiers) {
|
||||
Node<T> parentNode = locate.get(parentIdentifier);
|
||||
if(parentNode==null) {
|
||||
throw new RuntimeException("I can find parent for " + identifier + ". Missing parent is " + parentIdentifier);
|
||||
}
|
||||
|
||||
parentNode.addChild(node);
|
||||
|
||||
if(!allowMultipleInheritance) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,16 +105,20 @@ public class Tree<T> {
|
|||
return node;
|
||||
}
|
||||
|
||||
public Node<T> getRoot() {
|
||||
return root;
|
||||
public Node<T> getRootNode() {
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return root.toString();
|
||||
return rootNode.toString();
|
||||
}
|
||||
|
||||
public void elaborate(NodeElaborator<T> nodeElaborator) throws Exception {
|
||||
root.elaborate(nodeElaborator);
|
||||
rootNode.elaborate(nodeElaborator);
|
||||
}
|
||||
|
||||
public Node<T> getNodeByIdentifier(String identifier){
|
||||
return locate.get(identifier);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,30 @@ public class PropertyTypeName {
|
|||
|
||||
private static Logger logger = LoggerFactory.getLogger(PropertyTypeName.class);
|
||||
|
||||
public enum BaseTypeGroup {
|
||||
|
||||
ANY( BaseType.values()),
|
||||
BOOLEAN( new BaseType[]{ BaseType.BOOLEAN } ),
|
||||
NUMERIC( new BaseType[]{ BaseType.INTEGER, BaseType.SHORT, BaseType.LONG, BaseType.FLOAT }),
|
||||
STRING( new BaseType[]{ BaseType.STRING }),
|
||||
DATE( new BaseType[]{ BaseType.DATE } ),
|
||||
BITS( new BaseType[]{ BaseType.BINARY, BaseType.BYTE } ),
|
||||
COMPLEX( new BaseType[]{ BaseType.PROPERTY } ),
|
||||
COLLECTION( new BaseType[]{ BaseType.LIST, BaseType.SET } ),
|
||||
MAP( new BaseType[]{ BaseType.MAP });
|
||||
|
||||
private final BaseType[] group;
|
||||
|
||||
private BaseTypeGroup(BaseType[] group) {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public BaseType[] getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum BaseType {
|
||||
|
||||
BOOLEAN("Boolean"),
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package org.gcube.informationsystem.types.knowledge;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
import org.gcube.informationsystem.types.TypeMapper;
|
||||
import org.gcube.informationsystem.types.reference.Type;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public class TypeInformation implements org.gcube.informationsystem.model.knowledge.TypeInformation<Type> {
|
||||
|
||||
@Override
|
||||
public String getIdentifier(Type type) {
|
||||
return type.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getParentIdentifiers(Type root, Type type) {
|
||||
if(root!=null && type.getName().compareTo(root.getName())==0) {
|
||||
return new LinkedHashSet<>();
|
||||
}
|
||||
if(root==null && AccessType.getAccessType(type.getName())!=null) {
|
||||
return new LinkedHashSet<>();
|
||||
}
|
||||
return type.getExtendedTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessType getAccessType(Type type) {
|
||||
return type.getAccessType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRoot(AccessType accessType) {
|
||||
return TypeMapper.createTypeDefinition(accessType.getTypeClass());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package org.gcube.informationsystem.types.knowledge;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
import org.gcube.informationsystem.model.knowledge.ModelKnowledge;
|
||||
import org.gcube.informationsystem.model.knowledge.TypesDiscoverer;
|
||||
import org.gcube.informationsystem.types.reference.Type;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public class TypesKnowledge {
|
||||
|
||||
private static TypesKnowledge instance;
|
||||
|
||||
public synchronized static TypesKnowledge getInstance() {
|
||||
if(instance==null) {
|
||||
instance = new TypesKnowledge();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
// in millisec
|
||||
public static final long DEFAULT_EXPIRING_TIMEOUT;
|
||||
|
||||
static {
|
||||
DEFAULT_EXPIRING_TIMEOUT = TimeUnit.HOURS.toMillis(6);
|
||||
|
||||
}
|
||||
|
||||
protected boolean initialized;
|
||||
public int expiringTimeout;
|
||||
|
||||
// in millisec used only for logging and debugging
|
||||
protected Calendar creationTime;
|
||||
// in millisec
|
||||
protected Calendar expiringTime;
|
||||
|
||||
protected ModelKnowledge<Type, TypeInformation> modelKnowledge;
|
||||
protected TypesDiscoverer<Type> typesDiscoverer;
|
||||
|
||||
public TypesKnowledge() {
|
||||
initialized = false;
|
||||
expiringTimeout = (int) DEFAULT_EXPIRING_TIMEOUT;
|
||||
modelKnowledge = new ModelKnowledge<>(new TypeInformation());
|
||||
}
|
||||
|
||||
public void setExpiringTimeout(int expiringTimeout) {
|
||||
this.expiringTimeout = expiringTimeout;
|
||||
}
|
||||
|
||||
public TypesDiscoverer<Type> getTypesDiscoverer() {
|
||||
return typesDiscoverer;
|
||||
}
|
||||
|
||||
public void setTypesDiscoverer(TypesDiscoverer<Type> typesDiscoverer) {
|
||||
this.typesDiscoverer = typesDiscoverer;
|
||||
}
|
||||
|
||||
public ModelKnowledge<Type, TypeInformation> getModelKnowledge() {
|
||||
if(!initialized) {
|
||||
discover();
|
||||
}else {
|
||||
Calendar now = Calendar.getInstance();
|
||||
if(now.after(expiringTime)) {
|
||||
renew();
|
||||
}
|
||||
}
|
||||
return modelKnowledge;
|
||||
}
|
||||
|
||||
protected synchronized void init(boolean forceReinitialization) {
|
||||
if(typesDiscoverer!=null && (initialized==false || forceReinitialization)) {
|
||||
initialized = false;
|
||||
modelKnowledge = new ModelKnowledge<>(new TypeInformation());
|
||||
AccessType[] modelTypes = AccessType.getModelTypes();
|
||||
for(AccessType modelType : modelTypes) {
|
||||
Collection<Type> types = typesDiscoverer.discover(modelType);
|
||||
modelKnowledge.addAllType(types);
|
||||
}
|
||||
initialized = true;
|
||||
this.creationTime = Calendar.getInstance();
|
||||
this.expiringTime = Calendar.getInstance();
|
||||
this.expiringTime.setTimeInMillis(creationTime.getTimeInMillis());
|
||||
this.expiringTime.add(Calendar.MILLISECOND, -1);
|
||||
this.expiringTime.add(Calendar.MILLISECOND, expiringTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method do nothing if TypesDiscoverer
|
||||
* was not set.
|
||||
* Otherwise initialized the ModelKnowledge
|
||||
* if it was not already initialized.
|
||||
* To enforce rediscovery use renew method.
|
||||
*/
|
||||
public void discover() {
|
||||
init(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force reinitialization of
|
||||
*/
|
||||
public void renew() {
|
||||
init(true);
|
||||
}
|
||||
}
|
|
@ -33,7 +33,11 @@ public class UUIDUtility {
|
|||
}
|
||||
|
||||
public static String getUUIDAsString(JsonNode jsonNode){
|
||||
return getUUID(jsonNode).toString();
|
||||
UUID uuid = getUUID(jsonNode);
|
||||
if(uuid!=null) {
|
||||
return uuid.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getUUIDAsString(String json) throws JsonProcessingException, IOException{
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.gcube.informationsystem.queries.templates.reference.properties.Templa
|
|||
import org.gcube.informationsystem.serialization.ElementMapper;
|
||||
import org.gcube.informationsystem.types.annotations.Final;
|
||||
import org.gcube.informationsystem.types.reference.Change;
|
||||
import org.gcube.informationsystem.types.reference.Type;
|
||||
import org.gcube.informationsystem.types.reference.TypeMetadata;
|
||||
import org.gcube.informationsystem.types.reference.entities.EntityType;
|
||||
import org.gcube.informationsystem.types.reference.entities.FacetType;
|
||||
|
@ -63,6 +64,13 @@ public class SerializationTest {
|
|||
EntityType resourceTypeDefinitionSelf = (EntityType) TypeMapper.createTypeDefinition(ResourceType.class);
|
||||
logger.info(ElementMapper.marshal(resourceTypeDefinitionSelf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void entityElementDefinition() throws Exception{
|
||||
Type type = TypeMapper.createTypeDefinition(EntityElement.class);
|
||||
logger.info(ElementMapper.marshal(type));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPropertyTypeDefinition() throws Exception{
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
package org.gcube.informationsystem.types.knowledge;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.AccessType;
|
||||
import org.gcube.informationsystem.model.knowledge.ModelKnowledge;
|
||||
import org.gcube.informationsystem.model.knowledge.UsageKnowledge;
|
||||
import org.gcube.informationsystem.tree.Node;
|
||||
import org.gcube.informationsystem.tree.NodeElaborator;
|
||||
import org.gcube.informationsystem.tree.Tree;
|
||||
import org.gcube.informationsystem.types.TypeMapper;
|
||||
import org.gcube.informationsystem.types.reference.Type;
|
||||
import org.gcube.informationsystem.types.reference.properties.LinkedEntity;
|
||||
import org.gcube.informationsystem.types.reference.properties.PropertyDefinition;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @author Luca Frosini (ISTI - CNR)
|
||||
*/
|
||||
public class ModelKnowledgeTest{
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ModelKnowledgeTest.class);
|
||||
|
||||
protected File getTypesDirectory() throws Exception {
|
||||
URL logbackFileURL = ModelKnowledgeTest.class.getClassLoader().getResource("logback-test.xml");
|
||||
File logbackFile = new File(logbackFileURL.toURI());
|
||||
File resourcesDirectory = logbackFile.getParentFile();
|
||||
return new File(resourcesDirectory, "types");
|
||||
}
|
||||
|
||||
protected String readFile(File file) throws IOException {
|
||||
byte[] encoded = Files.readAllBytes(file.toPath());
|
||||
return new String(encoded, Charset.defaultCharset());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
ModelKnowledge<Type, TypeInformation> modelKnowledge = TypesKnowledge.getInstance().getModelKnowledge();
|
||||
|
||||
File typesDirectory = getTypesDirectory();
|
||||
|
||||
AccessType[] modelTypes = AccessType.getModelTypes();
|
||||
for(AccessType modelType : modelTypes) {
|
||||
File file = new File(typesDirectory, modelType.getName() + ".json");
|
||||
String json = readFile(file);
|
||||
List<Type> types = TypeMapper.deserializeTypeDefinitions(json);
|
||||
modelKnowledge.addAllType(types);
|
||||
logger.trace("-------------------------------------------------------");
|
||||
}
|
||||
|
||||
for(AccessType modelType : modelTypes) {
|
||||
Tree<Type> tree = modelKnowledge.getTree(modelType);
|
||||
|
||||
tree.elaborate(new NodeElaborator<Type>() {
|
||||
|
||||
@Override
|
||||
public void elaborate(Node<Type> node, int level) throws Exception {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
for (int i = 0; i < level; ++i) {
|
||||
stringBuffer.append(Node.INDENTATION);
|
||||
}
|
||||
|
||||
String typeName = node.getNodeElement().getName();
|
||||
logger.info("{}- {}{}", stringBuffer.toString(), typeName, level==0 ? " (ROOT)" : "");
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
logger.info("---------------------------------------------------\n\n\n");
|
||||
|
||||
for(AccessType modelType : modelTypes) {
|
||||
Tree<Type> tree = modelKnowledge.getTree(modelType);
|
||||
UsageKnowledge<?> usageKnowledge = modelKnowledge.getModelTypesUsage(modelType);
|
||||
|
||||
tree.elaborate(new NodeElaborator<Type>() {
|
||||
|
||||
@Override
|
||||
public void elaborate(Node<Type> node, int level) throws Exception {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
for (int i = 0; i < level; ++i) {
|
||||
stringBuffer.append(Node.INDENTATION);
|
||||
}
|
||||
|
||||
Type type = node.getNodeElement();
|
||||
String typeName = type.getName();
|
||||
|
||||
|
||||
if(type.getAccessType()!=AccessType.PROPERTY) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<LinkedEntity> usage = (List<LinkedEntity>) usageKnowledge.getUsage(typeName);
|
||||
logger.info("{}- {}{} {}", stringBuffer.toString(), typeName, level==0 ? " (ROOT) " : "", usage!=null ? "known static usage " + usage : "No known static usage");
|
||||
}else {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map.Entry<String,PropertyDefinition>> usage = (List<Entry<String, PropertyDefinition>>) usageKnowledge.getUsage(typeName);
|
||||
logger.info("{}- {}{} {}", stringBuffer.toString(), typeName, level==0 ? " (ROOT) " : "", usage!=null ? "known static usage " + usage : "No known static usage");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue