001/* 002 * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 */ 020 021package org.nuxeo.ecm.automation.core.util; 022 023import java.io.IOException; 024import java.util.ArrayList; 025import java.util.Calendar; 026import java.util.HashMap; 027import java.util.Iterator; 028import java.util.List; 029import java.util.Map; 030 031import org.codehaus.jackson.JsonNode; 032import org.codehaus.jackson.JsonParser; 033import org.codehaus.jackson.map.ObjectMapper; 034import org.codehaus.jackson.node.ArrayNode; 035import org.codehaus.jackson.node.ObjectNode; 036import org.nuxeo.ecm.core.api.Blob; 037import org.nuxeo.ecm.core.schema.types.ComplexType; 038import org.nuxeo.ecm.core.schema.types.Field; 039import org.nuxeo.ecm.core.schema.types.ListType; 040import org.nuxeo.ecm.core.schema.types.SimpleType; 041import org.nuxeo.ecm.core.schema.types.Type; 042import org.nuxeo.ecm.core.schema.types.primitives.DateType; 043 044/** 045 * Helper to handle Complex types decoding from a JSON encoded String entries of a property file 046 * 047 * @author Tiry (tdelprat@nuxeo.com) 048 * @since 5.5 049 */ 050public class ComplexTypeJSONDecoder { 051 052 private static final ObjectMapper mapper = new ObjectMapper(); 053 054 protected static List<JSONBlobDecoder> blobDecoders = new ArrayList<JSONBlobDecoder>(); 055 static { 056 mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); 057 blobDecoders.add(new JSONStringBlobDecoder()); 058 } 059 060 public static void registerBlobDecoder(JSONBlobDecoder blobDecoder) { 061 blobDecoders.add(blobDecoder); 062 } 063 064 public static List<Object> decodeList(ListType lt, String json) throws IOException { 065 ArrayNode jsonArray = (ArrayNode) mapper.readTree(json); 066 return decodeList(lt, jsonArray); 067 } 068 069 public static List<Object> decodeList(ListType lt, ArrayNode jsonArray) { 070 List<Object> result = new ArrayList<Object>(); 071 Type currentObjectType = lt.getFieldType(); 072 for (int i = 0; i < jsonArray.size(); i++) { 073 JsonNode node = jsonArray.get(i); 074 if (node.isArray()) { 075 result.add(decodeList((ListType) currentObjectType, (ArrayNode) node)); 076 } else if (node.isObject()) { 077 result.add(decode((ComplexType) currentObjectType, (ObjectNode) node)); 078 } else if (node.isTextual()) { 079 result.add(node.getTextValue()); 080 } else if (node.isNumber()) { 081 result.add(node.getNumberValue()); 082 } else if (node.isBoolean()) { 083 result.add(node.getBooleanValue()); 084 } 085 } 086 return result; 087 } 088 089 public static Object decode(ComplexType ct, String json) throws IOException { 090 ObjectNode jsonObject = (ObjectNode) mapper.readTree(json); 091 return decode(ct, jsonObject); 092 } 093 094 public static Object decode(ComplexType ct, ObjectNode jsonObject) { 095 096 Map<String, Object> result = new HashMap<String, Object>(); 097 098 String jsonType = ""; 099 if (jsonObject.has("type")) { 100 jsonType = jsonObject.get("type").getTextValue(); 101 } 102 if (jsonType.equals("blob") || ct.getName().equals("content")) { 103 return getBlobFromJSON(jsonObject); 104 } 105 106 Iterator<Map.Entry<String, JsonNode>> it = jsonObject.getFields(); 107 108 while (it.hasNext()) { 109 Map.Entry<String, JsonNode> nodeEntry = it.next(); 110 if (ct.hasField(nodeEntry.getKey())) { 111 112 Field field = ct.getField(nodeEntry.getKey()); 113 Type fieldType = field.getType(); 114 if (fieldType.isSimpleType()) { 115 Object value; 116 if (fieldType == DateType.INSTANCE && nodeEntry.getValue().isIntegralNumber()) { 117 value = Calendar.getInstance(); 118 ((Calendar) value).setTimeInMillis(nodeEntry.getValue().getValueAsLong()); 119 } else { 120 value = ((SimpleType) fieldType).decode(nodeEntry.getValue().getValueAsText()); 121 } 122 result.put(nodeEntry.getKey(), value); 123 } else { 124 JsonNode subNode = nodeEntry.getValue(); 125 if (subNode.isArray()) { 126 result.put(nodeEntry.getKey(), decodeList(((ListType) fieldType), (ArrayNode) subNode)); 127 } else { 128 result.put(nodeEntry.getKey(), decode(((ComplexType) fieldType), (ObjectNode) subNode)); 129 } 130 } 131 } 132 } 133 134 return result; 135 } 136 137 public static Blob getBlobFromJSON(ObjectNode jsonObject) { 138 Blob blob = null; 139 for (JSONBlobDecoder blobDecoder : blobDecoders) { 140 blob = blobDecoder.getBlobFromJSON(jsonObject); 141 if (blob != null) { 142 return blob; 143 } 144 } 145 return blob; 146 } 147 148}