/** * */ package org.gcube.informationsystem.utils; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.gcube.com.fasterxml.jackson.core.JsonFactory; import org.gcube.com.fasterxml.jackson.core.JsonParser; import org.gcube.com.fasterxml.jackson.core.JsonProcessingException; import org.gcube.com.fasterxml.jackson.core.TreeNode; import org.gcube.com.fasterxml.jackson.databind.DeserializationContext; import org.gcube.com.fasterxml.jackson.databind.JavaType; import org.gcube.com.fasterxml.jackson.databind.JsonNode; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.com.fasterxml.jackson.databind.deser.std.StdDeserializer; import org.gcube.com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import org.gcube.com.fasterxml.jackson.databind.jsontype.TypeDeserializer; 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; import org.gcube.informationsystem.base.reference.Element; import org.gcube.informationsystem.types.TypeMapper; /** * @author Luca Frosini (ISTI - CNR) */ public class ElementDeserializer extends StdDeserializer { private static final long serialVersionUID = -2551569658316955137L; protected final ObjectMapper mapper; public ElementDeserializer(Class clz, ObjectMapper mapper) { super(clz); this.mapper = mapper; } @Override public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, TypeDeserializer typeDeserializer) throws IOException { TreeNode treeNode = jp.readValueAsTree(); JsonFactory jsonFactory = mapper.getFactory(); JsonParser clonedJP = jsonFactory.createParser(treeNode.toString()); clonedJP.nextToken(); try { return typeDeserializer.deserializeTypedFromAny(clonedJP, ctxt); } catch (InvalidTypeIdException e) { Class candidatedSuperClass = _valueClass; List toBeKeepSuperClasses = new ArrayList<>(); ObjectNode objectNode = (ObjectNode) treeNode; try { JsonNode superClassesTreeNode = objectNode .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 } JavaType javaType = typeDeserializer .getTypeIdResolver().typeFromId(ctxt, superClass); if (javaType == null) { TextNode textNode = new TextNode(superClass); toBeKeepSuperClasses.add(textNode); continue; } Class clz = javaType.getRawClass(); if (candidatedSuperClass.isAssignableFrom(clz)) { // clz is a subClass so that is a candidate candidatedSuperClass = clz; } break; default: break; } } catch (Exception ex) { // Trying the next one } } arrayNode.removeAll(); arrayNode.addAll(toBeKeepSuperClasses); } } catch (Exception ex) { // Using already known candidatedSuperClass } if(candidatedSuperClass == _valueClass){ // No suitable class found Using Dummy Implementation candidatedSuperClass = AccessType.getAccessType(_valueClass).getDummyImplementationClass(); } @SuppressWarnings("unchecked") String typeName = TypeMapper.getType((Class) 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; } } @SuppressWarnings("unchecked") @Override public ISM deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { TypeDeserializer typeDeserializer = ctxt.getFactory().findTypeDeserializer(ctxt.getConfig(), ctxt.constructType(Element.class)); return (ISM) deserializeWithType(jp, ctxt, typeDeserializer); } }