diff --git a/src/main/java/org/gcube/informationsystem/contexts/impl/entities/ContextImpl.java b/src/main/java/org/gcube/informationsystem/contexts/impl/entities/ContextImpl.java index 646b465..6bc6854 100644 --- a/src/main/java/org/gcube/informationsystem/contexts/impl/entities/ContextImpl.java +++ b/src/main/java/org/gcube/informationsystem/contexts/impl/entities/ContextImpl.java @@ -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 children; + @JsonIgnore + protected Map additionalProperties; + + @JsonIgnore + /** + * Used to allow to have an additional property starting with '_' or '@' + */ + protected final Set 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 getAdditionalProperties() { + return additionalProperties; + } + + @Override + public void setAdditionalProperties(Map 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 map = (Map) 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); + } + } diff --git a/src/main/java/org/gcube/informationsystem/contexts/reference/entities/Context.java b/src/main/java/org/gcube/informationsystem/contexts/reference/entities/Context.java index 725db19..a348904 100644 --- a/src/main/java/org/gcube/informationsystem/contexts/reference/entities/Context.java +++ b/src/main/java/org/gcube/informationsystem/contexts/reference/entities/Context.java @@ -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,7 +37,7 @@ 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(); @@ -66,5 +72,20 @@ public interface Context extends EntityElement { public void addChild(Context child); public void addChild(IsParentOf isParentOf); + + @JsonAnyGetter + @JsonSerialize(using = AdditionalPropertiesSerializer.class) + @Override + public Map getAdditionalProperties(); + + @Override + public void setAdditionalProperties(Map additionalProperties); + + @Override + public Object getAdditionalProperty(String key); + + @JsonAnySetter + @Override + public void setAdditionalProperty(String key, Object value); }