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