001/* 002 * Copyright (c) 2004-2020, Oracle and/or its affiliates. 003 * 004 * Licensed under the 2-clause BSD license. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions are met: 008 * 009 * 1. Redistributions of source code must retain the above copyright notice, 010 * this list of conditions and the following disclaimer. 011 * 012 * 2. Redistributions in binary form must reproduce the above copyright notice, 013 * this list of conditions and the following disclaimer in the documentation 014 * and/or other materials provided with the distribution. 015 * 016 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 017 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 018 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 019 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 020 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 021 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 022 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 023 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 024 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 025 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 026 * POSSIBILITY OF SUCH DAMAGE. 027 */ 028 029package com.oracle.labs.mlrg.olcut.config.json; 030 031import com.fasterxml.jackson.core.JsonParseException; 032import com.fasterxml.jackson.core.JsonParser; 033import com.fasterxml.jackson.core.ObjectCodec; 034import com.fasterxml.jackson.databind.DeserializationContext; 035import com.fasterxml.jackson.databind.JsonNode; 036import com.fasterxml.jackson.databind.deser.std.StdDeserializer; 037import com.oracle.labs.mlrg.olcut.provenance.io.FlatMarshalledProvenance; 038import com.oracle.labs.mlrg.olcut.provenance.io.ListMarshalledProvenance; 039import com.oracle.labs.mlrg.olcut.provenance.io.MapMarshalledProvenance; 040import com.oracle.labs.mlrg.olcut.provenance.io.MarshalledProvenance; 041import com.oracle.labs.mlrg.olcut.provenance.io.ObjectMarshalledProvenance; 042import com.oracle.labs.mlrg.olcut.provenance.io.SimpleMarshalledProvenance; 043 044import java.io.IOException; 045import java.util.ArrayList; 046import java.util.HashMap; 047import java.util.Iterator; 048import java.util.Map; 049import java.util.Map.Entry; 050 051/** 052 * Deserialization class to convert JSON into {@link MarshalledProvenance}. 053 */ 054public class JsonProvenanceDeserializer extends StdDeserializer<MarshalledProvenance> { 055 056 public JsonProvenanceDeserializer(Class<? extends MarshalledProvenance> provClass) { 057 super(provClass); 058 } 059 060 @Override 061 public MarshalledProvenance deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 062 ObjectCodec oc = jsonParser.getCodec(); 063 064 JsonNode node = oc.readTree(jsonParser); 065 066 JsonNode classNode = node.get(JsonProvenanceModule.MARSHALLED_CLASS); 067 068 if (classNode != null) { 069 String className = classNode.textValue(); 070 if (ListMarshalledProvenance.class.getName().equals(className)) { 071 JsonNode arrayNode = node.get(JsonProvenanceModule.LIST); 072 if (arrayNode != null) { 073 ArrayList<FlatMarshalledProvenance> list = new ArrayList<>(); 074 for (JsonNode n : arrayNode) { 075 FlatMarshalledProvenance fmp = (FlatMarshalledProvenance) oc.treeToValue(n, MarshalledProvenance.class); 076 list.add(fmp); 077 } 078 return new ListMarshalledProvenance(list); 079 } else { 080 throw new JsonParseException(jsonParser, JsonProvenanceModule.LIST + " field not found in ListMarshalledProvenance."); 081 } 082 } else if (MapMarshalledProvenance.class.getName().equals(className)) { 083 JsonNode objectNode = node.get(JsonProvenanceModule.MAP); 084 if (objectNode != null) { 085 Map<String, FlatMarshalledProvenance> map = new HashMap<>(); 086 for (Iterator<Entry<String, JsonNode>> it = objectNode.fields(); it.hasNext(); ) { 087 Entry<String, JsonNode> n = it.next(); 088 map.put(n.getKey(), (FlatMarshalledProvenance) oc.treeToValue(n.getValue(), MarshalledProvenance.class)); 089 } 090 return new MapMarshalledProvenance(map); 091 } else { 092 throw new JsonParseException(jsonParser, JsonProvenanceModule.MAP + " field not found in MapMarshalledProvenance."); 093 } 094 } else if (ObjectMarshalledProvenance.class.getName().equals(className)) { 095 if (node.has(JsonProvenanceModule.OBJECT_NAME) && node.has(JsonProvenanceModule.OBJECT_CLASS_NAME) && 096 node.has(JsonProvenanceModule.PROVENANCE_CLASS) && node.has(JsonProvenanceModule.MAP)) { 097 String objectName = node.get(JsonProvenanceModule.OBJECT_NAME).textValue(); 098 String objectClassName = node.get(JsonProvenanceModule.OBJECT_CLASS_NAME).textValue(); 099 String provenanceClass = node.get(JsonProvenanceModule.PROVENANCE_CLASS).textValue(); 100 JsonNode objectNode = node.get(JsonProvenanceModule.MAP); 101 Map<String, FlatMarshalledProvenance> map = new HashMap<>(); 102 for (Iterator<Entry<String, JsonNode>> it = objectNode.fields(); it.hasNext(); ) { 103 Entry<String, JsonNode> n = it.next(); 104 map.put(n.getKey(), (FlatMarshalledProvenance) oc.treeToValue(n.getValue(), MarshalledProvenance.class)); 105 } 106 return new ObjectMarshalledProvenance(objectName,map,objectClassName,provenanceClass); 107 } else { 108 throw new JsonParseException(jsonParser,"ObjectMarshalledProvenance was missing a required field."); 109 } 110 } else if (SimpleMarshalledProvenance.class.getName().equals(className)) { 111 if (node.has(JsonProvenanceModule.KEY) && node.has(JsonProvenanceModule.VALUE) && 112 node.has(JsonProvenanceModule.PROVENANCE_CLASS) && node.has(JsonProvenanceModule.ADDITIONAL) && 113 node.has(JsonProvenanceModule.IS_REFERENCE)) { 114 String key = node.get(JsonProvenanceModule.KEY).textValue(); 115 String value = node.get(JsonProvenanceModule.VALUE).textValue(); 116 String provenanceClass = node.get(JsonProvenanceModule.PROVENANCE_CLASS).textValue(); 117 String additional = node.get(JsonProvenanceModule.ADDITIONAL).textValue(); 118 boolean isReference = node.get(JsonProvenanceModule.IS_REFERENCE).asBoolean(); 119 return new SimpleMarshalledProvenance(key,value,provenanceClass,isReference,additional); 120 } else { 121 throw new JsonParseException(jsonParser,"SimpleMarshalledProvenance was missing a required field."); 122 } 123 } else { 124 throw new JsonParseException(jsonParser,"Unexpected marshalled provenance class, found " + className); 125 } 126 } else { 127 throw new JsonParseException(jsonParser,"Marshalled provenance json did not contain subclass name."); 128 } 129 } 130}