Fixed the serialization/deserialization with Jackosn 2.8.11

This commit is contained in:
Luca Frosini 2020-07-02 18:05:15 +02:00
parent fb34224e73
commit f1d52d3b04
12 changed files with 286 additions and 75 deletions

View File

@ -8,14 +8,16 @@ import java.io.StringWriter;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.utils.ElementMapper;
import com.fasterxml.jackson.annotation.JsonTypeName;
/**
* @author Luca Frosini (ISTI - CNR)
*
*/
@JsonTypeName(value=Element.NAME)
public class ElementImpl implements Element {
/**
*
* Generated Serial Version UID
*/
private static final long serialVersionUID = 7338083489551084860L;

View File

@ -20,10 +20,8 @@ import org.gcube.informationsystem.model.impl.entities.DummyResource;
import org.gcube.informationsystem.model.impl.entities.EntityImpl;
import org.gcube.informationsystem.model.impl.entities.FacetImpl;
import org.gcube.informationsystem.model.impl.entities.ResourceImpl;
import org.gcube.informationsystem.model.impl.properties.DummyProperty;
import org.gcube.informationsystem.model.impl.properties.PropertyImpl;
import org.gcube.informationsystem.model.impl.relations.ConsistsOfImpl;
import org.gcube.informationsystem.model.impl.relations.DummyConsistsOf;
import org.gcube.informationsystem.model.impl.relations.DummyIsRelatedTo;
import org.gcube.informationsystem.model.impl.relations.IsRelatedToImpl;
import org.gcube.informationsystem.model.impl.relations.RelationImpl;
@ -53,7 +51,7 @@ import org.slf4j.LoggerFactory;
public enum AccessType {
PROPERTY_ELEMENT(PropertyElement.class, PropertyElement.NAME, PropertyElementImpl.class, null),
PROPERTY(Property.class, Property.NAME, PropertyImpl.class, DummyProperty.class),
PROPERTY(Property.class, Property.NAME, PropertyImpl.class, null),
CONTEXT(Context.class, Context.NAME, ContextImpl.class, null),
IS_PARENT_OF(IsParentOf.class, IsParentOf.NAME, IsParentOfImpl.class, null),
@ -73,7 +71,7 @@ public enum AccessType {
RELATION_ELEMENT(RelationElement.class, RelationElement.NAME, RelationElementImpl.class, null),
RELATION(Relation.class, Relation.NAME, RelationImpl.class, null),
IS_RELATED_TO(IsRelatedTo.class, IsRelatedTo.NAME, IsRelatedToImpl.class, DummyIsRelatedTo.class),
CONSISTS_OF(ConsistsOf.class, ConsistsOf.NAME, ConsistsOfImpl.class, DummyConsistsOf.class);
CONSISTS_OF(ConsistsOf.class, ConsistsOf.NAME, ConsistsOfImpl.class, null);
private static Logger logger = LoggerFactory.getLogger(AccessType.class);

View File

@ -14,6 +14,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
*/
@Abstract
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = Element.CLASS_PROPERTY)
// @JsonTypeIdResolver(ElementTypeIdResolver.class)
public interface Element extends Serializable {
public static final String NAME = "Element"; //Element.class.getSimpleName();

View File

@ -1,13 +1,16 @@
package org.gcube.informationsystem.base.reference.properties;
import org.gcube.informationsystem.base.impl.properties.PropertyElementImpl;
import org.gcube.informationsystem.base.reference.Element;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
/**
* @author Luca Frosini (ISTI - CNR)
* Root Class for Property types. It creates a base common type, which is useful
* for management purpose.
*/
// @JsonDeserialize(as=PropertyElementImpl.class) Do not uncomment to manage subclasses
@JsonDeserialize(as=PropertyElementImpl.class)
public interface PropertyElement extends Element {
public static final String NAME = "PropertyElement"; //PropertyElement.class.getSimpleName();

View File

@ -1,23 +0,0 @@
/**
*
*/
package org.gcube.informationsystem.model.impl.properties;
import org.gcube.informationsystem.model.reference.properties.Property;
/**
* @author Luca Frosini (ISTI - CNR)
*
*/
public class DummyProperty extends PropertyImpl implements Property {
/**
* Generated Serial version UID
*/
private static final long serialVersionUID = 2458531826742344451L;
public DummyProperty(){
super();
}
}

View File

@ -1,34 +0,0 @@
/**
*
*/
package org.gcube.informationsystem.model.impl.relations;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import com.fasterxml.jackson.annotation.JsonTypeName;
/**
* @author Luca Frosini (ISTI - CNR)
*/
@JsonTypeName(value=ConsistsOf.NAME)
public class DummyConsistsOf<S extends Resource, T extends Facet> extends
ConsistsOfImpl<S, T> implements ConsistsOf<S, T> {
/**
* Generated Serial Version UID
*/
private static final long serialVersionUID = -8195862723295398163L;
public DummyConsistsOf(){
super();
}
public DummyConsistsOf(S source, T target,
PropagationConstraint propagationConstraint) {
super(source, target, propagationConstraint);
}
}

View File

@ -4,6 +4,9 @@
package org.gcube.informationsystem.model.reference.properties;
import org.gcube.informationsystem.base.reference.properties.PropertyElement;
import org.gcube.informationsystem.model.impl.properties.PropertyImpl;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
/**
* @author Luca Frosini (ISTI - CNR)
@ -11,7 +14,7 @@ import org.gcube.informationsystem.base.reference.properties.PropertyElement;
* for management purpose.
*/
// @JsonIgnoreProperties(ignoreUnknown=true)
// @JsonDeserialize(as=PropertyImpl.class) Do not uncomment to manage subclasses
@JsonDeserialize(as=PropertyImpl.class)
public interface Property extends PropertyElement {
public static final String NAME = "Property"; //Property.class.getSimpleName();

View File

@ -3,14 +3,17 @@
*/
package org.gcube.informationsystem.model.reference.relations;
import org.gcube.informationsystem.model.impl.relations.ConsistsOfImpl;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
/**
* @author Luca Frosini (ISTI - CNR)
* https://wiki.gcube-system.org/gcube/Facet_Based_Resource_Model#consistsOf
*/
// @JsonDeserialize(as=ConsistsOfImpl.class) Do not uncomment to manage subclasses
@JsonDeserialize(as=ConsistsOfImpl.class)
public interface ConsistsOf<S extends Resource, T extends Facet>
extends Relation<S, T> {

View File

@ -17,6 +17,7 @@ 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 com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -89,6 +90,10 @@ public class TypeMapper {
}
public static String getType(Class<? extends Element> clz){
if(clz.isAnnotationPresent(JsonTypeName.class)) {
JsonTypeName jsonTypeName = clz.getAnnotation(JsonTypeName.class);
return jsonTypeName.value();
}
return getStaticStringFieldByName(clz, NAME, clz.getSimpleName());
}

View File

@ -9,6 +9,7 @@ import java.util.List;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.types.TypeMapper;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
@ -19,6 +20,7 @@ import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
@ -51,7 +53,7 @@ public class ElementDeserializer<ISM extends Element> extends StdDeserializer<IS
clonedJP.nextToken();
try {
return typeDeserializer.deserializeTypedFromAny(clonedJP, ctxt);
} catch (Exception e) {
} catch (InvalidTypeIdException e) {
Class<?> candidatedSuperClass = _valueClass;
List<TextNode> toBeKeepSuperClasses = new ArrayList<>();
@ -117,13 +119,17 @@ public class ElementDeserializer<ISM extends Element> extends StdDeserializer<IS
// No suitable class found Using Dummy Implementation
candidatedSuperClass = AccessType.getAccessType(_valueClass).getDummyImplementationClass();
}
objectNode.set(Element.CLASS_PROPERTY,
new TextNode(candidatedSuperClass.getSimpleName()));
@SuppressWarnings("unchecked")
String typeName = TypeMapper.getType((Class<? extends Element>) candidatedSuperClass);
objectNode.set(Element.CLASS_PROPERTY, new TextNode(typeName));
JsonParser jsonParser = jsonFactory.createParser(objectNode
.toString());
jsonParser.nextToken();
return typeDeserializer.deserializeTypedFromAny(jsonParser, ctxt);
}catch (Exception e) {
throw e;
}
}
@ -132,7 +138,8 @@ public class ElementDeserializer<ISM extends Element> extends StdDeserializer<IS
@Override
public ISM deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
return (ISM) deserializeWithType(jp, ctxt, null);
TypeDeserializer typeDeserializer = ctxt.getFactory().findTypeDeserializer(ctxt.getConfig(), ctxt.constructType(Element.class));
return (ISM) deserializeWithType(jp, ctxt, typeDeserializer);
}
}

View File

@ -6,11 +6,15 @@ import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import org.gcube.informationsystem.base.reference.AccessType;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.types.TypeMapper;
import org.gcube.informationsystem.types.reference.Type;
import org.gcube.informationsystem.utils.discovery.ElementSpecilizationDiscovery;
import org.gcube.informationsystem.utils.discovery.RegistrationProvider;
@ -24,8 +28,14 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
/**
* @author Luca Frosini (ISTI - CNR)
@ -37,6 +47,10 @@ public abstract class ElementMapper {
protected static final ObjectMapper mapper;
protected static final Map<String, Class<? extends Element>> knownTypes;
// // protected static final Map<Class<? extends Element>, Class<? extends ElementImpl>> interfaceToImplementation;
// protected static final Map<String, Class<? extends ElementImpl>> nameToImplementation;
/**
* @return the ObjectMapper
*/
@ -48,6 +62,11 @@ public abstract class ElementMapper {
mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
knownTypes = new HashMap<>();
//interfaceToImplementation = new HashMap<>();
// nameToImplementation = new HashMap<>();
List<Package> packages = new ArrayList<Package>();
/*
@ -68,14 +87,19 @@ public abstract class ElementMapper {
mapper.registerModule(isModule);
ElementMapper.registerSubtypes(dummyClz);
}
/* else {
ElementMapper.registerSubtypes(clz);
}*/
packages.add(clz.getPackage());
}
}
registerPackages(packages);
ServiceLoader<? extends RegistrationProvider> regsitrationProviders = ServiceLoader.load(RegistrationProvider.class);
for (RegistrationProvider registrationProvider : regsitrationProviders) {
ServiceLoader<? extends RegistrationProvider> regsitrationProviders = ServiceLoader
.load(RegistrationProvider.class);
for(RegistrationProvider registrationProvider : regsitrationProviders) {
registerPackages(registrationProvider.getPackagesToRegister());
}
@ -90,7 +114,6 @@ public abstract class ElementMapper {
}
}
public static void registerPackages(Package... packages) {
SchemaAction schemaAction = new ElementMappingAction();
try {
@ -100,8 +123,19 @@ public abstract class ElementMapper {
}
}
public static <El extends Element> void registerSubtypes(Class<El>... classes) {
for(Class<El> clz : classes) {
String typeName = TypeMapper.getType(clz);
knownTypes.put(typeName, clz);
// if(clz.isAnnotationPresent(JsonDeserialize.class)) {
// JsonDeserialize jsonDeserialize = clz.getAnnotation(JsonDeserialize.class);
// Class<? extends ElementImpl> impl = (Class<? extends ElementImpl>) jsonDeserialize.as();
// nameToImplementation.put(typeName, impl);
// }
}
mapper.registerSubtypes(classes);
}
@ -196,6 +230,87 @@ public abstract class ElementMapper {
return mapper.readValue(stream, clz);
}
public static JsonNode analizeJsonToReplaceType(JsonNode jsonNodeToAnalize, String typeIdToReplace) throws Exception {
boolean replaced = false;
String candidatedSuperClass = null;
int index = 0;
String typeId = null;
if(jsonNodeToAnalize.has(Element.CLASS_PROPERTY)) {
typeId = jsonNodeToAnalize.get(Element.CLASS_PROPERTY).asText();
}
if(typeId != null && typeIdToReplace.compareTo(typeId) == 0) {
JsonNode superClassesTreeNode = jsonNodeToAnalize.get(Element.SUPERCLASSES_PROPERTY);
if(superClassesTreeNode != null && superClassesTreeNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) superClassesTreeNode;
for(int i = 0; i < arrayNode.size(); i++) {
try {
JsonNode jsonNode = arrayNode.get(i);
JsonNodeType jsonNodeType = jsonNode.getNodeType();
switch(jsonNodeType) {
case STRING:
String superClass = jsonNode.asText();
try {
Enum.valueOf(AccessType.class, superClass.toUpperCase());
// It is one of the BaseType. Looking for
// another type because the base one
continue;
} catch(Exception ex) {
// can continue discovery
}
if(knownTypes.containsKey(superClass)) {
candidatedSuperClass = superClass;
index = i;
}
break;
default:
break;
}
if(candidatedSuperClass!=null) {
break;
}
} catch(Exception ex) {
// Trying the next one
}
}
arrayNode.remove(index);
((ObjectNode) jsonNodeToAnalize).set(Element.CLASS_PROPERTY, new TextNode(candidatedSuperClass));
replaced = true;
}
}
if(!replaced) {
// continue to search inside the object
Iterator<String> iterator = jsonNodeToAnalize.fieldNames();
while(iterator.hasNext()) {
String fieldName = iterator.next();
JsonNode jn = jsonNodeToAnalize.get(fieldName);
if(jn.getNodeType() == JsonNodeType.OBJECT) {
try {
JsonNode newValue = analizeJsonToReplaceType(jn,typeIdToReplace);
replaced = true;
((ObjectNode) jsonNodeToAnalize).set(fieldName, newValue);
break;
}catch (Exception e) {
continue;
}
}
}
}
if(!replaced) {
throw new Exception();
}
return jsonNodeToAnalize;
}
/**
* Creates a resource of given class from its serialization in a given String
* @param clz the class of the resource
@ -207,7 +322,18 @@ public abstract class ElementMapper {
*/
public static <ISM extends Element> ISM unmarshal(Class<ISM> clz, String string)
throws JsonParseException, JsonMappingException, IOException {
return mapper.readValue(string, clz);
try {
return mapper.readValue(string, clz);
} catch(InvalidTypeIdException e) {
String typeId = e.getTypeId();
JsonNode jsonNode = mapper.readTree(string);
try {
jsonNode = analizeJsonToReplaceType(jsonNode, typeId);
}catch (Exception ex) {
throw e;
}
return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode));
}
}
/**

View File

@ -0,0 +1,120 @@
package org.gcube.informationsystem.model.impl.properties;
import java.util.Calendar;
import java.util.UUID;
import org.gcube.informationsystem.base.reference.Element;
import org.gcube.informationsystem.model.reference.entities.Facet;
import org.gcube.informationsystem.model.reference.entities.Resource;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.AddConstraint;
import org.gcube.informationsystem.model.reference.properties.PropagationConstraint.RemoveConstraint;
import org.gcube.informationsystem.model.reference.properties.Property;
import org.gcube.informationsystem.model.reference.relations.ConsistsOf;
import org.gcube.informationsystem.utils.ElementMapper;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PropagationConstraintTest {
private static Logger logger = LoggerFactory.getLogger(PropagationConstraintTest.class);
@Test
public void testPropagationConstraint() throws Exception {
PropagationConstraint propagationConstraint = new PropagationConstraintImpl();
propagationConstraint.setAddConstraint(AddConstraint.propagate);
propagationConstraint.setRemoveConstraint(RemoveConstraint.cascadeWhenOrphan);
String pg = ElementMapper.marshal(propagationConstraint);
Property property = ElementMapper.unmarshal(Property.class, pg);
Assert.assertTrue(property instanceof PropagationConstraint);
logger.debug(ElementMapper.marshal(property));
PropagationConstraint pgUnm = ElementMapper.unmarshal(PropagationConstraint.class, pg);
Assert.assertTrue(property instanceof PropagationConstraint);
logger.debug(ElementMapper.marshal(pgUnm));
}
@Test
public void testPropagationConstraintByString() throws Exception {
AddConstraint addConstraint = AddConstraint.propagate;
RemoveConstraint removeConstraint = RemoveConstraint.cascade;
PropagationConstraint pc = new PropagationConstraintImpl();
pc.setAddConstraint(addConstraint);
pc.setRemoveConstraint(removeConstraint);
String json = ElementMapper.marshal(pc);
logger.debug(json);
Property property = ElementMapper.unmarshal(Property.class, json);
Assert.assertTrue(property instanceof PropagationConstraint);
Assert.assertTrue(((PropagationConstraint) property).getAddConstraint().compareTo(addConstraint)==0);
Assert.assertTrue(((PropagationConstraint) property).getRemoveConstraint().compareTo(removeConstraint)==0);
logger.debug(ElementMapper.marshal(property));
PropagationConstraint propagationConstraint = ElementMapper.unmarshal(PropagationConstraint.class, json);
Assert.assertTrue(propagationConstraint instanceof PropagationConstraint);
Assert.assertTrue(propagationConstraint.getAddConstraint().compareTo(addConstraint)==0);
Assert.assertTrue(propagationConstraint.getRemoveConstraint().compareTo(removeConstraint)==0);
logger.debug(ElementMapper.marshal(property));
}
@Test
public void testPropagationConstraintSpecilization() throws Exception {
AddConstraint addConstraint = AddConstraint.propagate;
RemoveConstraint removeConstraint = RemoveConstraint.cascade;
String marshalled = "{\"" + Element.CLASS_PROPERTY + "\":\"MyPropagationConstraint\",\"" + Element.SUPERCLASSES_PROPERTY + "\":[\"" + PropagationConstraint.NAME + "\", \"" + Property.NAME + "\"],\"" + PropagationConstraint.ADD_PROPERTY + "\":\""+ addConstraint + "\",\""+ PropagationConstraint.REMOVE_PROPERTY + "\":\"" + removeConstraint + "\"}";
logger.debug(marshalled);
Property property = ElementMapper.unmarshal(Property.class, marshalled);
Assert.assertTrue(property instanceof PropagationConstraint);
Assert.assertTrue(((PropagationConstraint) property).getAddConstraint().compareTo(addConstraint)==0);
Assert.assertTrue(((PropagationConstraint) property).getRemoveConstraint().compareTo(removeConstraint)==0);
logger.debug(ElementMapper.marshal(property));
PropagationConstraint propagationConstraint = ElementMapper.unmarshal(PropagationConstraint.class, marshalled);
Assert.assertTrue(propagationConstraint instanceof PropagationConstraint);
Assert.assertTrue(propagationConstraint.getAddConstraint().compareTo(addConstraint)==0);
Assert.assertTrue(propagationConstraint.getRemoveConstraint().compareTo(removeConstraint)==0);
logger.debug(ElementMapper.marshal(property));
}
@Test
public void testPropagationConstraintSpecilizationInside() throws Exception {
AddConstraint addConstraint = AddConstraint.propagate;
RemoveConstraint removeConstraint = RemoveConstraint.cascade;
String pcString = "{\"" + Element.CLASS_PROPERTY + "\":\"My" + PropagationConstraint.NAME + "\",\"" + Element.SUPERCLASSES_PROPERTY + "\":[\"" + PropagationConstraint.NAME + "\", \"" + Property.NAME + "\"],\"" + PropagationConstraint.ADD_PROPERTY + "\":\""+ addConstraint + "\",\""+ PropagationConstraint.REMOVE_PROPERTY + "\":\"" + removeConstraint + "\"}";
logger.debug(pcString);
HeaderImpl header = new HeaderImpl();
header.setUUID(UUID.randomUUID());
header.creator = "luca.frosini";
header.modifiedBy = "luca.frosini";
header.creationTime = Calendar.getInstance().getTime();
header.lastUpdateTime = Calendar.getInstance().getTime();
String hString = ElementMapper.marshal(header);
String consistsOfString = "{\"" + Element.CLASS_PROPERTY + "\":\"" + ConsistsOf.NAME + "\",\"" + ConsistsOf.PROPAGATION_CONSTRAINT + "\":"+ pcString + ",\"" + ConsistsOf.HEADER_PROPERTY + "\": " + hString + ",\"" + ConsistsOf.TARGET_PROPERTY + "\":{\"@superClasses\":[\"SoftwareFacet\", \"Facet\", \"Entity\"],\"@class\":\"MySoftwareFacet\",\"header\":"+ "{\"@class\":\"Header\",\"uuid\":\"3ace4bd0-e5cd-49a3-97a8-a0a9468ce6d4\",\"creator\":null, \"creationTime\":null, \"lastUpdateTime\":null}" + ",\"name\":\"WhnManager\",\"group\":\"VREManagement\",\"version\":\"2.0.0-SNAPSHOT\",\"description\":\"Web Hosting Node Service\",\"qualifier\":null,\"optional\":false}" + "}";
logger.debug(consistsOfString);
@SuppressWarnings("unchecked")
ConsistsOf<Resource,Facet> consistsOf = ElementMapper.unmarshal(ConsistsOf.class, consistsOfString);
Assert.assertTrue(consistsOf instanceof ConsistsOf);
PropagationConstraint propagationConstraint = consistsOf.getPropagationConstraint();
Assert.assertTrue(propagationConstraint instanceof PropagationConstraint);
Assert.assertTrue(propagationConstraint.getAddConstraint().compareTo(addConstraint)==0);
Assert.assertTrue(propagationConstraint.getRemoveConstraint().compareTo(removeConstraint)==0);
logger.debug(ElementMapper.marshal(propagationConstraint));
Facet facet = consistsOf.getTarget();
logger.debug(ElementMapper.marshal(facet));
Assert.assertTrue(facet.getAdditionalProperties().containsKey("version"));
}
}