001package com.identityworksllc.iiq.common.vo;
002
003import com.fasterxml.jackson.core.JsonParser;
004import com.fasterxml.jackson.core.JsonProcessingException;
005import com.fasterxml.jackson.databind.DeserializationContext;
006import com.fasterxml.jackson.databind.JsonNode;
007import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
008import sailpoint.api.SailPointContext;
009import sailpoint.api.SailPointFactory;
010import sailpoint.tools.GeneralException;
011import sailpoint.tools.xml.XMLObjectFactory;
012
013import java.io.IOException;
014import java.util.Arrays;
015import java.util.HashSet;
016import java.util.Set;
017
018public class IIQObjectDeserializer extends StdDeserializer<Object> {
019    private static final Set<String> VALID_TYPES = new HashSet<>(Arrays.asList(
020            "java.util.Map",
021            "java.util.List",
022            "java.lang.String",
023            "java.lang.Boolean",
024            "java.util.Date"
025    ));
026
027    protected IIQObjectDeserializer() {
028        this(null);
029    }
030
031    public IIQObjectDeserializer(Class<Object> t) {
032        super(t);
033    }
034
035    @Override
036    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
037        JsonNode node = p.getCodec().readTree(p);
038        if (node.isObject()) {
039            JsonNode xml = node.get("xml");
040            JsonNode type = node.get("type");
041
042            String typeStr = type.asText();
043            if (typeStr == null || typeStr.trim().isEmpty()) {
044                throw new IOException("Unable to read a serialized IIQObject without a type");
045            }
046            if (typeStr.equals("null") || xml.isNull()) {
047                return null;
048            }
049            if (typeStr.startsWith("sailpoint.object") || VALID_TYPES.contains(typeStr)) {
050                String xmlStr = xml.asText();
051
052                try {
053                    SailPointContext context = SailPointFactory.getCurrentContext();
054                    if (context == null) {
055                        // TODO create a private context here?
056                        throw new IOException("IIQObject JSON must be deserialized in a SailPointContext session");
057                    }
058                    return XMLObjectFactory.getInstance().parseXml(context, xmlStr, true);
059                } catch(GeneralException e) {
060                    throw new IOException(e);
061                }
062            } else {
063                throw new IOException("Unexpected IIQObject type: " + typeStr);
064            }
065        } else if (node.isNull()) {
066            return null;
067        } else {
068            throw new IOException("Unexpected JsonNode type: " + node.getNodeType());
069        }
070    }
071
072}