001/* 002 * (C) Copyright 2006-20012 Nuxeo SAS (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 * Nuxeo - initial API and implementation 016 * 017 */ 018package org.nuxeo.template.adapters.source; 019 020import java.io.IOException; 021import java.io.Serializable; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.List; 025 026import org.dom4j.DocumentException; 027import org.nuxeo.ecm.core.api.Blob; 028import org.nuxeo.ecm.core.api.DocumentModel; 029import org.nuxeo.ecm.core.api.NuxeoException; 030import org.nuxeo.ecm.core.api.PropertyException; 031import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 032import org.nuxeo.runtime.api.Framework; 033import org.nuxeo.template.XMLSerializer; 034import org.nuxeo.template.adapters.AbstractTemplateDocument; 035import org.nuxeo.template.api.TemplateInput; 036import org.nuxeo.template.api.TemplateProcessor; 037import org.nuxeo.template.api.TemplateProcessorService; 038import org.nuxeo.template.api.adapters.TemplateBasedDocument; 039import org.nuxeo.template.api.adapters.TemplateSourceDocument; 040 041/** 042 * Default implementation of {@link TemplateSourceDocument}. It mainly expect from the underlying DocumentModel to have 043 * the "Template" facet. 044 * 045 * @author Tiry (tdelprat@nuxeo.com) 046 */ 047public class TemplateSourceDocumentAdapterImpl extends AbstractTemplateDocument implements Serializable, 048 TemplateSourceDocument { 049 050 public static final String TEMPLATE_DATA_PROP = "tmpl:templateData"; 051 052 public static final String TEMPLATE_NAME_PROP = "tmpl:templateName"; 053 054 public static final String TEMPLATE_TYPE_PROP = "tmpl:templateType"; 055 056 public static final String TEMPLATE_TYPE_AUTO = "auto"; 057 058 public static final String TEMPLATE_APPLICABLE_TYPES_PROP = "tmpl:applicableTypes"; 059 060 public static final String TEMPLATE_APPLICABLE_TYPES_ALL = "all"; 061 062 public static final String TEMPLATE_FORCED_TYPES_PROP = "tmpl:forcedTypes"; 063 064 public static final String TEMPLATE_FORCED_TYPES_ITEM_PROP = "tmpl:forcedTypes/*"; 065 066 public static final String TEMPLATE_FORCED_TYPES_NONE = "none"; 067 068 public static final String TEMPLATE_RENDITION_NONE = "none"; 069 070 public static final String TEMPLATE_OUTPUT_PROP = "tmpl:outputFormat"; 071 072 public static final String TEMPLATE_OVERRIDE_PROP = "tmpl:allowOverride"; 073 074 public static final String TEMPLATE_USEASMAIN_PROP = "tmpl:useAsMainContent"; 075 076 public static final String TEMPLATE_RENDITION_PROP = "tmpl:targetRenditionName"; 077 078 public static final String TEMPLATE_FACET = "Template"; 079 080 private static final long serialVersionUID = 1L; 081 082 public TemplateSourceDocumentAdapterImpl(DocumentModel doc) { 083 this.adaptedDoc = doc; 084 } 085 086 protected String getTemplateParamsXPath() { 087 return TEMPLATE_DATA_PROP; 088 } 089 090 public List<TemplateInput> getParams() { 091 String dataPath = getTemplateParamsXPath(); 092 093 if (adaptedDoc.getPropertyValue(dataPath) == null) { 094 return new ArrayList<TemplateInput>(); 095 } 096 String xml = adaptedDoc.getPropertyValue(dataPath).toString(); 097 098 try { 099 return XMLSerializer.readFromXml(xml); 100 } catch (DocumentException e) { 101 log.error("Unable to parse parameters", e); 102 return new ArrayList<TemplateInput>(); 103 } 104 } 105 106 public boolean hasEditableParams() { 107 for (TemplateInput param : getParams()) { 108 if (!param.isReadOnly()) { 109 return true; 110 } 111 } 112 return false; 113 } 114 115 public DocumentModel saveParams(List<TemplateInput> params, boolean save) { 116 String dataPath = getTemplateParamsXPath(); 117 String xml = XMLSerializer.serialize(params); 118 adaptedDoc.setPropertyValue(dataPath, xml); 119 adaptedDoc.putContextData(TemplateSourceDocument.INIT_DONE_FLAG, true); 120 if (save) { 121 doSave(); 122 } 123 return adaptedDoc; 124 } 125 126 protected TemplateProcessor getTemplateProcessor() { 127 TemplateProcessorService tps = Framework.getLocalService(TemplateProcessorService.class); 128 return tps.getProcessor(getTemplateType()); 129 } 130 131 public String getParamsAsString() throws PropertyException { 132 String dataPath = getTemplateParamsXPath(); 133 134 if (adaptedDoc.getPropertyValue(dataPath) == null) { 135 return null; 136 } 137 return adaptedDoc.getPropertyValue(dataPath).toString(); 138 } 139 140 public List<TemplateInput> addInput(TemplateInput input) { 141 142 List<TemplateInput> params = getParams(); 143 if (input == null) { 144 return params; 145 } 146 147 boolean newParam = true; 148 if (params == null) { 149 params = new ArrayList<TemplateInput>(); 150 } 151 for (TemplateInput param : params) { 152 if (param.getName().equals(input.getName())) { 153 newParam = false; 154 param.update(input); 155 break; 156 } 157 } 158 if (newParam) { 159 params.add(input); 160 } 161 saveParams(params, false); 162 163 return params; 164 } 165 166 public String getTemplateType() { 167 String ttype = (String) getAdaptedDoc().getPropertyValue(TEMPLATE_TYPE_PROP); 168 if (TEMPLATE_TYPE_AUTO.equals(ttype)) { 169 return null; 170 } 171 return ttype; 172 } 173 174 public void initTemplate(boolean save) { 175 // avoid duplicate init 176 if (getAdaptedDoc().getContextData(TemplateSourceDocument.INIT_DONE_FLAG) == null) { 177 Blob blob = getTemplateBlob(); 178 if (blob != null) { 179 if (getTemplateType() == null) { 180 TemplateProcessorService tps = Framework.getLocalService(TemplateProcessorService.class); 181 String templateType = tps.findProcessorName(blob); 182 if (templateType != null) { 183 getAdaptedDoc().setPropertyValue(TEMPLATE_TYPE_PROP, templateType); 184 } 185 } 186 187 String tmplName = (String) getAdaptedDoc().getPropertyValue(TEMPLATE_NAME_PROP); 188 if (tmplName == null || tmplName.isEmpty()) { 189 tmplName = computeTemplateName(); 190 getAdaptedDoc().setPropertyValue(TEMPLATE_NAME_PROP, tmplName); 191 } 192 193 TemplateProcessor processor = getTemplateProcessor(); 194 if (processor != null) { 195 List<TemplateInput> params; 196 try { 197 params = processor.getInitialParametersDefinition(blob); 198 } catch (IOException e) { 199 throw new NuxeoException(e); 200 } 201 saveParams(params, save); 202 } 203 getAdaptedDoc().getContextData().put(TemplateSourceDocument.INIT_DONE_FLAG, true); 204 } 205 } 206 } 207 208 protected String computeTemplateName() { 209 return getAdaptedDoc().getTitle(); 210 } 211 212 public boolean allowInstanceOverride() { 213 Boolean allowOverride = (Boolean) getAdaptedDoc().getPropertyValue(TEMPLATE_OVERRIDE_PROP); 214 if (allowOverride == null) { 215 allowOverride = true; 216 } 217 return allowOverride; 218 } 219 220 public void initTypesBindings() { 221 222 // manage applicable types 223 String[] applicableTypesArray = (String[]) getAdaptedDoc().getPropertyValue(TEMPLATE_APPLICABLE_TYPES_PROP); 224 225 String[] newApplicableTypesArray = null; 226 227 if (applicableTypesArray == null || applicableTypesArray.length == 0) { 228 newApplicableTypesArray = new String[] { TEMPLATE_APPLICABLE_TYPES_ALL }; 229 } else if (applicableTypesArray.length > 1) { 230 if (TEMPLATE_APPLICABLE_TYPES_ALL.equals(applicableTypesArray[0])) { 231 List<String> at = Arrays.asList(applicableTypesArray); 232 at.remove(0); 233 newApplicableTypesArray = at.toArray(new String[at.size()]);; 234 } 235 } 236 if (newApplicableTypesArray != null) { 237 getAdaptedDoc().setPropertyValue(TEMPLATE_APPLICABLE_TYPES_PROP, newApplicableTypesArray); 238 } 239 240 // manage forcedTypes 241 String[] forcedTypesArray = (String[]) getAdaptedDoc().getPropertyValue(TEMPLATE_FORCED_TYPES_PROP); 242 String[] newForcedTypesArray = null; 243 if (forcedTypesArray == null || forcedTypesArray.length == 0) { 244 newForcedTypesArray = new String[] { TEMPLATE_FORCED_TYPES_NONE }; 245 } else if (forcedTypesArray.length > 1) { 246 if (TEMPLATE_FORCED_TYPES_NONE.equals(forcedTypesArray[0])) { 247 List<String> ft = Arrays.asList(forcedTypesArray); 248 ft.remove(0); 249 newForcedTypesArray = ft.toArray(new String[ft.size()]);; 250 } 251 } 252 if (newForcedTypesArray != null) { 253 getAdaptedDoc().setPropertyValue(TEMPLATE_FORCED_TYPES_PROP, newForcedTypesArray); 254 } 255 256 } 257 258 public List<String> getApplicableTypes() { 259 String[] applicableTypesArray = (String[]) getAdaptedDoc().getPropertyValue(TEMPLATE_APPLICABLE_TYPES_PROP); 260 List<String> applicableTypes = new ArrayList<String>(); 261 if (applicableTypesArray != null) { 262 applicableTypes.addAll((Arrays.asList(applicableTypesArray))); 263 } 264 if (applicableTypes.size() > 0 && applicableTypes.get(0).equals(TEMPLATE_APPLICABLE_TYPES_ALL)) { 265 applicableTypes.remove(0); 266 } 267 return applicableTypes; 268 } 269 270 public List<String> getForcedTypes() { 271 String[] forcedTypesArray = (String[]) getAdaptedDoc().getPropertyValue(TEMPLATE_FORCED_TYPES_PROP); 272 List<String> applicableTypes = new ArrayList<String>(); 273 if (forcedTypesArray != null) { 274 applicableTypes.addAll((Arrays.asList(forcedTypesArray))); 275 } 276 if (applicableTypes.size() > 0 && applicableTypes.get(0).equals(TEMPLATE_FORCED_TYPES_NONE)) { 277 applicableTypes.remove(0); 278 } 279 return applicableTypes; 280 } 281 282 public void removeForcedType(String type, boolean save) { 283 List<String> types = getForcedTypes(); 284 if (types.contains(type)) { 285 types.remove(type); 286 String[] typesArray = types.toArray(new String[types.size()]); 287 getAdaptedDoc().setPropertyValue(TemplateSourceDocumentAdapterImpl.TEMPLATE_FORCED_TYPES_PROP, typesArray); 288 if (save) { 289 adaptedDoc = getAdaptedDoc().getCoreSession().saveDocument(getAdaptedDoc()); 290 } 291 } 292 } 293 294 public void setForcedTypes(String[] forcedTypes, boolean save) { 295 getAdaptedDoc().setPropertyValue(TemplateSourceDocumentAdapterImpl.TEMPLATE_FORCED_TYPES_PROP, forcedTypes); 296 if (save) { 297 adaptedDoc = getAdaptedDoc().getCoreSession().saveDocument(getAdaptedDoc()); 298 } 299 } 300 301 public List<TemplateBasedDocument> getTemplateBasedDocuments() { 302 return Framework.getLocalService(TemplateProcessorService.class).getLinkedTemplateBasedDocuments(adaptedDoc); 303 } 304 305 public String getOutputFormat() { 306 return (String) getAdaptedDoc().getPropertyValue(TEMPLATE_OUTPUT_PROP); 307 } 308 309 public void setOutputFormat(String mimetype, boolean save) { 310 getAdaptedDoc().setPropertyValue(TEMPLATE_OUTPUT_PROP, mimetype); 311 if (save) { 312 doSave(); 313 } 314 } 315 316 public boolean useAsMainContent() { 317 Boolean useAsMain = (Boolean) getAdaptedDoc().getPropertyValue(TEMPLATE_USEASMAIN_PROP); 318 if (useAsMain == null) { 319 useAsMain = false; 320 } 321 return useAsMain; 322 } 323 324 public Blob getTemplateBlob() { 325 BlobHolder bh = getAdaptedDoc().getAdapter(BlobHolder.class); 326 if (bh != null) { 327 return bh.getBlob(); 328 } 329 return null; 330 } 331 332 public void setTemplateBlob(Blob blob, boolean save) { 333 BlobHolder bh = getAdaptedDoc().getAdapter(BlobHolder.class); 334 if (bh != null) { 335 bh.setBlob(blob); 336 initTemplate(false); 337 if (save) { 338 doSave(); 339 } 340 } 341 } 342 343 public String getName() { 344 String name = (String) getAdaptedDoc().getPropertyValue(TEMPLATE_NAME_PROP); 345 if (name == null) { 346 name = getAdaptedDoc().getTitle(); 347 } 348 return name; 349 } 350 351 public String getFileName() { 352 Blob blob = getTemplateBlob(); 353 if (blob != null) { 354 return blob.getFilename(); 355 } 356 return null; 357 } 358 359 public String getTitle() { 360 return getAdaptedDoc().getTitle(); 361 } 362 363 public String getVersionLabel() { 364 return getAdaptedDoc().getVersionLabel(); 365 } 366 367 public String getId() { 368 return getAdaptedDoc().getId(); 369 } 370 371 public String getLabel() { 372 StringBuffer sb = new StringBuffer(getTitle()); 373 if (!getTitle().equals(getFileName())) { 374 sb.append(" (" + getFileName() + ")"); 375 } 376 if (getVersionLabel() != null) { 377 sb.append(" [" + getVersionLabel() + "]"); 378 } 379 return sb.toString(); 380 } 381 382 @Override 383 public String getTargetRenditionName() { 384 String targetRendition = (String) getAdaptedDoc().getPropertyValue(TEMPLATE_RENDITION_PROP); 385 if (TEMPLATE_RENDITION_NONE.equals(targetRendition)) { 386 return null; 387 } 388 return targetRendition; 389 } 390 391 public void setTargetRenditioName(String renditionName, boolean save) { 392 getAdaptedDoc().setPropertyValue(TEMPLATE_RENDITION_PROP, renditionName); 393 if (save) { 394 doSave(); 395 } 396 } 397 398}