001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Florent Guillaume 016 */ 017package org.nuxeo.ecm.platform.routing.core.impl; 018 019import java.io.ByteArrayOutputStream; 020import java.io.IOException; 021import java.io.Serializable; 022import java.util.Calendar; 023import java.util.HashMap; 024import java.util.LinkedHashMap; 025import java.util.Map; 026 027import org.apache.commons.lang.StringUtils; 028import org.codehaus.jackson.JsonFactory; 029import org.codehaus.jackson.JsonGenerator; 030import org.nuxeo.ecm.automation.core.util.DocumentHelper; 031import org.nuxeo.ecm.automation.core.util.Properties; 032import org.nuxeo.ecm.core.api.CoreSession; 033import org.nuxeo.ecm.core.api.DocumentModel; 034import org.nuxeo.ecm.core.api.NuxeoException; 035import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 036import org.nuxeo.ecm.core.schema.SchemaManager; 037import org.nuxeo.ecm.core.schema.types.CompositeType; 038import org.nuxeo.ecm.core.schema.types.Field; 039import org.nuxeo.ecm.core.schema.utils.DateParser; 040import org.nuxeo.ecm.platform.routing.api.DocumentRoutingConstants; 041import org.nuxeo.ecm.webengine.JsonFactoryManager; 042import org.nuxeo.runtime.api.Framework; 043 044/** 045 * Helper to set/get variables on a document that are stored in a facet. 046 * 047 * @since 5.6 048 */ 049public class GraphVariablesUtil { 050 051 private GraphVariablesUtil() { 052 } 053 054 protected static SchemaManager getSchemaManager() { 055 return Framework.getLocalService(SchemaManager.class); 056 } 057 058 private static JsonFactory getFactory() { 059 JsonFactoryManager jsonFactoryManager = Framework.getLocalService(JsonFactoryManager.class); 060 return jsonFactoryManager.getJsonFactory(); 061 } 062 063 /** 064 * @since 7.2 065 */ 066 public static Map<String, Serializable> getVariables(DocumentModel doc, String facetProp, boolean mapToJSON) { 067 String facet = (String) doc.getPropertyValue(facetProp); 068 Map<String, Serializable> map = new LinkedHashMap<String, Serializable>(); 069 if (StringUtils.isBlank(facet)) { 070 return map; 071 } 072 CompositeType type = getSchemaManager().getFacet(facet); 073 if (type == null) { 074 return map; 075 } 076 boolean hasFacet = doc.hasFacet(facet); 077 for (Field f : type.getFields()) { 078 String name = f.getName().getLocalName(); 079 Serializable value = hasFacet ? doc.getPropertyValue(name) : null; 080 if (value instanceof Calendar) { 081 if (mapToJSON) { 082 value = DateParser.formatW3CDateTime(((Calendar) value).getTime()); 083 } else { 084 value = ((Calendar) value).getTime(); 085 } 086 } else if (value instanceof Object[] && mapToJSON) { 087 try { 088 Object[] objects = (Object[]) value; 089 ByteArrayOutputStream out = new ByteArrayOutputStream(); 090 JsonGenerator jg = getFactory().createJsonGenerator(out); 091 jg.writeStartArray(); 092 for (Object object : objects) { 093 jg.writeString(type.encode(object)); 094 } 095 jg.writeEndArray(); 096 jg.flush(); 097 jg.close(); 098 value = out.toString("UTF-8"); 099 } catch (IOException e) { 100 throw new NuxeoException(e); 101 } 102 } 103 if (mapToJSON) { 104 map.put(name, value != null ? value.toString() : null); 105 } else { 106 map.put(name, value); 107 } 108 } 109 return map; 110 } 111 112 public static Map<String, Serializable> getVariables(DocumentModel doc, String facetProp) { 113 return getVariables(doc, facetProp, false); 114 } 115 116 public static void setVariables(DocumentModel doc, String facetProp, Map<String, Serializable> map) { 117 setVariables(doc, facetProp, map, true); 118 } 119 120 /** 121 * @since 7.2 122 */ 123 public static void setVariables(DocumentModel doc, String facetProp, Map<String, Serializable> map, final boolean save) { 124 if (map.containsKey(DocumentRoutingConstants._MAP_VAR_FORMAT_JSON) 125 && (Boolean) map.get(DocumentRoutingConstants._MAP_VAR_FORMAT_JSON)) { 126 Map<String, String> vars = new HashMap<String, String>(); 127 map.remove(DocumentRoutingConstants._MAP_VAR_FORMAT_JSON); 128 for (String key : map.keySet()) { 129 if (map.get(key) != null && !(map.get(key) instanceof String)) { 130 throw new NuxeoException( 131 "Trying to decode JSON variables: The parameter 'map' should contain only Strings as it contains the marker '_MAP_VAR_FORMAT_JSON' "); 132 } 133 vars.put(key, (String) map.get(key)); 134 } 135 GraphVariablesUtil.setJSONVariables(doc, facetProp, vars, save); 136 } else { 137 String facet = null; 138 try { 139 facet = (String) doc.getPropertyValue(facetProp); 140 } catch (PropertyNotFoundException e) { 141 facet = facetProp; 142 } 143 if (StringUtils.isBlank(facet)) { 144 return; 145 } 146 CompositeType type = getSchemaManager().getFacet(facet); 147 if (type == null) { 148 return; 149 } 150 boolean hasFacet = doc.hasFacet(facet); 151 for (Field f : type.getFields()) { 152 String name = f.getName().getLocalName(); 153 if (!map.containsKey(name)) { 154 continue; 155 } 156 Serializable value = map.get(name); 157 if (value == null && !hasFacet) { 158 continue; 159 } 160 if (!hasFacet) { 161 doc.addFacet(facet); 162 hasFacet = true; 163 } 164 doc.setPropertyValue(name, value); 165 } 166 if (save) { 167 CoreSession session = doc.getCoreSession(); 168 session.saveDocument(doc); 169 } 170 } 171 } 172 173 /** 174 * Sets the variables of the workflow based on their JSON representation (especially for scalar lists). 175 * 176 * @param doc 177 * @param facetProp 178 * @param map 179 * @param save 180 * @since 5.9.3, 5.8.0-HF10 181 */ 182 public static void setJSONVariables(DocumentModel doc, String facetProp, Map<String, String> map) { 183 setJSONVariables(doc, facetProp, map, true); 184 } 185 186 187 /** 188 * @since 7.2 189 */ 190 public static void setJSONVariables(DocumentModel doc, String facetProp, Map<String, String> map, final boolean save) { 191 // normally the variables in the map don't contain the schema prefix 192 Properties jsonProperties = new Properties(); 193 String facet = null; 194 try { 195 facet = (String) doc.getPropertyValue(facetProp); 196 } catch (PropertyNotFoundException e) { 197 facet = facetProp; 198 } 199 if (StringUtils.isBlank(facet)) { 200 return; 201 } 202 CompositeType type = getSchemaManager().getFacet(facet); 203 if (type == null) { 204 } 205 boolean hasFacet = doc.hasFacet(facet); 206 for (Field f : type.getFields()) { 207 String name = f.getName().getLocalName(); 208 if (!map.containsKey(name)) { 209 continue; 210 } 211 String value = map.get(name); 212 if (value == null && !hasFacet) { 213 continue; 214 } 215 if (!hasFacet) { 216 doc.addFacet(facet); 217 hasFacet = true; 218 } 219 jsonProperties.put(name, value); 220 } 221 CoreSession session = doc.getCoreSession(); 222 try { 223 DocumentHelper.setJSONProperties(session, doc, jsonProperties); 224 } catch (IOException e) { 225 throw new NuxeoException(e); 226 } 227 if (save) { 228 session.saveDocument(doc); 229 } 230 } 231 232}