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