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