/* * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributors: * Nuxeo - initial API and implementation * */ package org.nuxeo.ecm.automation.core.util; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.node.ArrayNode; import org.codehaus.jackson.node.ObjectNode; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.schema.types.ComplexType; import org.nuxeo.ecm.core.schema.types.Field; import org.nuxeo.ecm.core.schema.types.ListType; import org.nuxeo.ecm.core.schema.types.SimpleType; import org.nuxeo.ecm.core.schema.types.Type; import org.nuxeo.ecm.core.schema.types.primitives.DateType; /** * Helper to handle Complex types decoding from a JSON encoded String entries of a property file * * @author Tiry (tdelprat@nuxeo.com) * @since 5.5 */ public class ComplexTypeJSONDecoder { private static final ObjectMapper mapper = new ObjectMapper(); protected static List<JSONBlobDecoder> blobDecoders = new ArrayList<JSONBlobDecoder>(); static { mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); blobDecoders.add(new JSONStringBlobDecoder()); } public static void registerBlobDecoder(JSONBlobDecoder blobDecoder) { blobDecoders.add(blobDecoder); } public static List<Object> decodeList(ListType lt, String json) throws IOException { ArrayNode jsonArray = (ArrayNode) mapper.readTree(json); return decodeList(lt, jsonArray); } public static List<Object> decodeList(ListType lt, ArrayNode jsonArray) { List<Object> result = new ArrayList<Object>(); Type currentObjectType = lt.getFieldType(); for (int i = 0; i < jsonArray.size(); i++) { JsonNode node = jsonArray.get(i); if (node.isArray()) { result.add(decodeList((ListType) currentObjectType, (ArrayNode) node)); } else if (node.isObject()) { result.add(decode((ComplexType) currentObjectType, (ObjectNode) node)); } else if (node.isTextual()) { result.add(node.getTextValue()); } else if (node.isNumber()) { result.add(node.getNumberValue()); } else if (node.isBoolean()) { result.add(node.getBooleanValue()); } } return result; } public static Object decode(ComplexType ct, String json) throws IOException { ObjectNode jsonObject = (ObjectNode) mapper.readTree(json); return decode(ct, jsonObject); } public static Object decode(ComplexType ct, ObjectNode jsonObject) { Map<String, Object> result = new HashMap<String, Object>(); String jsonType = ""; if (jsonObject.has("type")) { jsonType = jsonObject.get("type").getTextValue(); } if (jsonType.equals("blob") || ct.getName().equals("content")) { return getBlobFromJSON(jsonObject); } Iterator<Map.Entry<String, JsonNode>> it = jsonObject.getFields(); while (it.hasNext()) { Map.Entry<String, JsonNode> nodeEntry = it.next(); if (ct.hasField(nodeEntry.getKey())) { Field field = ct.getField(nodeEntry.getKey()); Type fieldType = field.getType(); if (fieldType.isSimpleType()) { Object value; if (fieldType == DateType.INSTANCE && nodeEntry.getValue().isIntegralNumber()) { value = Calendar.getInstance(); ((Calendar) value).setTimeInMillis(nodeEntry.getValue().getValueAsLong()); } else { value = ((SimpleType) fieldType).decode(nodeEntry.getValue().getValueAsText()); } result.put(nodeEntry.getKey(), value); } else { JsonNode subNode = nodeEntry.getValue(); if (subNode.isArray()) { result.put(nodeEntry.getKey(), decodeList(((ListType) fieldType), (ArrayNode) subNode)); } else { result.put(nodeEntry.getKey(), decode(((ComplexType) fieldType), (ObjectNode) subNode)); } } } } return result; } public static Blob getBlobFromJSON(ObjectNode jsonObject) { Blob blob = null; for (JSONBlobDecoder blobDecoder : blobDecoders) { blob = blobDecoder.getBlobFromJSON(jsonObject); if (blob != null) { return blob; } } return blob; } }