Fixed unmarshalling in case of unknown types
This commit is contained in:
parent
44056157e1
commit
60e9de983a
|
@ -62,7 +62,7 @@ public class TypeMapper {
|
|||
return json;
|
||||
}
|
||||
|
||||
public static Type deserializeTypeDefinition(String json) throws Exception{
|
||||
public static Type deserializeTypeDefinition(String json) throws Exception {
|
||||
Type type = mapper.readValue(json, Type.class);
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import org.gcube.com.fasterxml.jackson.databind.JavaType;
|
|||
import org.gcube.com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.gcube.com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
|
||||
import org.gcube.com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import org.gcube.com.fasterxml.jackson.databind.node.JsonNodeType;
|
||||
|
@ -217,85 +216,71 @@ public abstract class ElementMapper {
|
|||
return mapper.readValue(stream, clz);
|
||||
}
|
||||
|
||||
public static JsonNode analizeJsonToReplaceType(JsonNode jsonNodeToAnalize, String typeIdToReplace) throws Exception {
|
||||
boolean replaced = false;
|
||||
protected static StringBuffer getError(String unknownType) {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
stringBuffer.append(unknownType);
|
||||
stringBuffer.append(" is an unknown type. Please provide ");
|
||||
stringBuffer.append(Element.SUPERCLASSES_PROPERTY);
|
||||
stringBuffer.append(" property as string array to allow to instantiate the most appropriated class.");
|
||||
return stringBuffer;
|
||||
}
|
||||
|
||||
protected static JsonNode setAvailableSuperclass(JsonNode jsonNode) {
|
||||
String unknownType = jsonNode.get(Element.CLASS_PROPERTY).asText();
|
||||
ArrayNode arrayNode = (ArrayNode) jsonNode.get(Element.SUPERCLASSES_PROPERTY);
|
||||
|
||||
// TODO save original class and superclasses
|
||||
|
||||
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
|
||||
for(int i = 0; i < arrayNode.size(); i++) {
|
||||
String superClass = arrayNode.get(i).asText();
|
||||
if(knownTypes.containsKey(superClass)) {
|
||||
candidatedSuperClass = superClass;
|
||||
try {
|
||||
// Checking if it is one of the base type. In some cases we need to use dummy
|
||||
// implementation
|
||||
AccessType accessType = Enum.valueOf(AccessType.class, superClass.toUpperCase());
|
||||
// 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.
|
||||
candidatedSuperClass = accessType.getDummyImplementationClass().getSimpleName();
|
||||
}
|
||||
|
||||
} catch(Exception ex) {
|
||||
// can continue discovery
|
||||
}
|
||||
arrayNode.remove(index);
|
||||
|
||||
((ObjectNode) jsonNodeToAnalize).set(Element.CLASS_PROPERTY, new TextNode(candidatedSuperClass));
|
||||
replaced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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(candidatedSuperClass!=null) {
|
||||
((ObjectNode) jsonNode).set(Element.CLASS_PROPERTY, new TextNode(candidatedSuperClass));
|
||||
return jsonNode;
|
||||
}
|
||||
|
||||
if(!replaced) {
|
||||
throw new Exception();
|
||||
StringBuffer stringBuffer = getError(unknownType);
|
||||
logger.trace("Unable to unmarshall {}. {}", jsonNode.toString(), stringBuffer.toString());
|
||||
throw new RuntimeException(stringBuffer.toString());
|
||||
}
|
||||
|
||||
|
||||
protected static JsonNode analizeFullJson(JsonNode jsonNode) {
|
||||
Iterator<String> iterator = jsonNode.fieldNames();
|
||||
while(iterator.hasNext()) {
|
||||
String fieldName = iterator.next();
|
||||
JsonNode jn = jsonNode.get(fieldName);
|
||||
if(jn.getNodeType() == JsonNodeType.OBJECT) {
|
||||
if(jn.has(Element.CLASS_PROPERTY)) {
|
||||
String cls = jn.get(Element.CLASS_PROPERTY).asText();
|
||||
if(!knownTypes.containsKey(cls)) {
|
||||
jn = setAvailableSuperclass(jn);
|
||||
}
|
||||
}
|
||||
jn = analizeFullJson(jn);
|
||||
((ObjectNode) jsonNode).set(fieldName, jn);
|
||||
}
|
||||
}
|
||||
return jsonNodeToAnalize;
|
||||
return jsonNode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -311,40 +296,10 @@ public abstract class ElementMapper {
|
|||
throws JsonParseException, JsonMappingException, IOException {
|
||||
try {
|
||||
return mapper.readValue(string, clz);
|
||||
} catch(InvalidTypeIdException e) {
|
||||
String typeId = e.getTypeId();
|
||||
|
||||
/* An initial step to support the Jackson 2.11
|
||||
if(knownTypes.containsKey(typeId)) {
|
||||
// problem of type is not subtype of itself
|
||||
|
||||
Class<? extends Element> superClass = null;
|
||||
Class<?>[] interfaces = clz.getInterfaces();
|
||||
for(Class<?> interfaceClass : interfaces) {
|
||||
if(Element.class.isAssignableFrom(interfaceClass)) {
|
||||
try {
|
||||
superClass = (Class<? extends Element>) interfaceClass;
|
||||
return (ISM) ElementMapper.unmarshal(superClass, string);
|
||||
}catch (Exception ex) {
|
||||
// Trying the next type
|
||||
logger.error("", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
*/
|
||||
|
||||
} catch (JsonMappingException e) {
|
||||
JsonNode jsonNode = mapper.readTree(string);
|
||||
try {
|
||||
jsonNode = analizeJsonToReplaceType(jsonNode, typeId);
|
||||
}catch (Exception ex) {
|
||||
throw e;
|
||||
}
|
||||
jsonNode = analizeFullJson(jsonNode);
|
||||
return ElementMapper.unmarshal(clz, mapper.writeValueAsString(jsonNode));
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ import java.util.Calendar;
|
|||
import java.util.UUID;
|
||||
|
||||
import org.gcube.informationsystem.base.reference.Element;
|
||||
import org.gcube.informationsystem.model.impl.entities.DummyFacet;
|
||||
import org.gcube.informationsystem.model.impl.entities.DummyResource;
|
||||
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 org.gcube.informationsystem.model.reference.properties.PropagationConstraint;
|
||||
|
@ -85,6 +88,76 @@ public class PropagationConstraintTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
Resource resource = new DummyResource();
|
||||
Facet facet = new DummyFacet();
|
||||
ConsistsOf<Resource, Facet> consistsOf = new ConsistsOfImpl<Resource, Facet>(resource, facet);
|
||||
String json = ElementMapper.marshal(consistsOf);
|
||||
logger.debug(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOk() throws Exception {
|
||||
String ok ="{\n"
|
||||
+ " \"@class\": \"ConsistsOf\",\n"
|
||||
+ " \"propagationConstraint\": {\n"
|
||||
+ " \"@class\": \"PropagationConstraint\",\n"
|
||||
+ " \"@superClasses\": [\n"
|
||||
+ " \"Property\"\n"
|
||||
+ " ],\n"
|
||||
+ " \"add\": \"propagate\",\n"
|
||||
+ " \"remove\": \"cascade\"\n"
|
||||
+ " },\n"
|
||||
+ " \"header\": {\n"
|
||||
+ " \"@class\": \"Header\",\n"
|
||||
+ " \"uuid\": \"4fbb4aeb-9755-4b8f-b997-0bf21a8f56ff\",\n"
|
||||
+ " \"creator\": \"luca.frosini\",\n"
|
||||
+ " \"modifiedBy\": \"luca.frosini\",\n"
|
||||
+ " \"creationTime\": \"2021-02-11 15:07:46.887 +0000\",\n"
|
||||
+ " \"lastUpdateTime\": \"2021-02-11 15:07:46.887 +0000\"\n"
|
||||
+ " },\n"
|
||||
+ " \"source\": {\n"
|
||||
+ " \"@class\": \"DummyResource\",\n"
|
||||
+ " \"@superClasses\": [\n"
|
||||
+ " \"EService\",\n"
|
||||
+ " \"Service\",\n"
|
||||
+ " \"Resource\"\n"
|
||||
+ " ],\n"
|
||||
+ " \"header\": {\n"
|
||||
+ " \"@class\": \"Header\",\n"
|
||||
+ " \"uuid\": \"4a971915-ca90-48cf-9975-63ee2dd28605\",\n"
|
||||
+ " \"creator\": null,\n"
|
||||
+ " \"creationTime\": null,\n"
|
||||
+ " \"lastUpdateTime\": null\n"
|
||||
+ " }\n"
|
||||
+ " },\n"
|
||||
+ " \"target\": {\n"
|
||||
+ " \"@class\": \"DummyFacet\",\n"
|
||||
+ " \"@superClasses\": [\n"
|
||||
+ " \"SoftwareFacet\",\n"
|
||||
+ " \"Facet\"\n"
|
||||
+ " ],\n"
|
||||
+ " \"header\": {\n"
|
||||
+ " \"@class\": \"Header\",\n"
|
||||
+ " \"uuid\": \"3ace4bd0-e5cd-49a3-97a8-a0a9468ce6d4\",\n"
|
||||
+ " \"creator\": null,\n"
|
||||
+ " \"creationTime\": null,\n"
|
||||
+ " \"lastUpdateTime\": null\n"
|
||||
+ " },\n"
|
||||
+ " \"name\": \"WhnManager\",\n"
|
||||
+ " \"group\": \"VREManagement\",\n"
|
||||
+ " \"version\": \"2.0.0-SNAPSHOT\",\n"
|
||||
+ " \"description\": \"Web Hosting Node Service\",\n"
|
||||
+ " \"qualifier\": null,\n"
|
||||
+ " \"optional\": false\n"
|
||||
+ " }\n"
|
||||
+ "}";
|
||||
@SuppressWarnings("unchecked")
|
||||
ConsistsOf<Resource,Facet> consistsOf = ElementMapper.unmarshal(ConsistsOf.class, ok);
|
||||
Assert.assertTrue(consistsOf instanceof ConsistsOf);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropagationConstraintSpecilizationInside() throws Exception {
|
||||
AddConstraint addConstraint = AddConstraint.propagate;
|
||||
|
@ -102,8 +175,9 @@ public class PropagationConstraintTest {
|
|||
String hString = ElementMapper.marshal(header);
|
||||
|
||||
|
||||
// TODO This fails
|
||||
String consistsOfString = "{\"" + Element.CLASS_PROPERTY + "\":\"" + ConsistsOf.NAME + "\",\"" + ConsistsOf.PROPAGATION_CONSTRAINT_PROPERTY + "\":"+ pcString + ",\"" + ConsistsOf.HEADER_PROPERTY + "\": " + hString + ",\"" + ConsistsOf.TARGET_PROPERTY + "\":{\"@superClasses\":[\"SoftwareFacet\", \"Facet\"],\"@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}" + "}";
|
||||
String consistsOfString = "{\"" + Element.CLASS_PROPERTY + "\":\"" + ConsistsOf.NAME + "\",\"" + ConsistsOf.PROPAGATION_CONSTRAINT_PROPERTY + "\":"+ pcString + ",\"" + ConsistsOf.HEADER_PROPERTY + "\": " + hString + "," +
|
||||
"\"" + ConsistsOf.SOURCE_PROPERTY + "\":{\"@class\":\"MyEService\", \"@superClasses\":[\"EService\", \"Service\", \"Resource\"],\"header\":"+ "{\"@class\":\"Header\",\"uuid\":\"4a971915-ca90-48cf-9975-63ee2dd28605\",\"creator\":null, \"creationTime\":null, \"lastUpdateTime\":null}" + "}," +
|
||||
"\"" + ConsistsOf.TARGET_PROPERTY + "\":{\"@class\":\"MySoftwareFacet\",\"@superClasses\":[\"SoftwareFacet\", \"Facet\"],\"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")
|
||||
|
|
Loading…
Reference in New Issue