001/* 002 * (C) Copyright 2011-2016 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 * Thierry Delprat 018 */ 019package org.nuxeo.template.web; 020 021import java.util.ArrayList; 022import java.util.List; 023 024import javax.faces.model.SelectItem; 025 026import org.jboss.seam.ScopeType; 027import org.jboss.seam.annotations.Factory; 028import org.jboss.seam.annotations.In; 029import org.jboss.seam.annotations.Name; 030import org.jboss.seam.annotations.Observer; 031import org.jboss.seam.annotations.Scope; 032import org.jboss.seam.annotations.intercept.BypassInterceptors; 033import org.jboss.seam.faces.FacesMessages; 034import org.jboss.seam.international.StatusMessage; 035import org.nuxeo.ecm.core.api.Blob; 036import org.nuxeo.ecm.core.api.DocumentModel; 037import org.nuxeo.ecm.core.api.IdRef; 038import org.nuxeo.ecm.core.api.NuxeoException; 039import org.nuxeo.ecm.core.api.PropertyException; 040import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 041import org.nuxeo.ecm.core.api.security.SecurityConstants; 042import org.nuxeo.ecm.platform.ui.web.api.WebActions; 043import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils; 044import org.nuxeo.ecm.webapp.contentbrowser.DocumentActions; 045import org.nuxeo.ecm.webapp.helpers.EventManager; 046import org.nuxeo.ecm.webapp.helpers.EventNames; 047import org.nuxeo.ecm.webapp.helpers.ResourcesAccessor; 048import org.nuxeo.runtime.api.Framework; 049import org.nuxeo.template.api.TemplateInput; 050import org.nuxeo.template.api.TemplateProcessorService; 051import org.nuxeo.template.api.adapters.TemplateBasedDocument; 052import org.nuxeo.template.api.adapters.TemplateSourceDocument; 053 054@Name("templateBasedActions") 055@Scope(ScopeType.CONVERSATION) 056public class TemplateBasedActionBean extends BaseTemplateAction { 057 058 private static final long serialVersionUID = 1L; 059 060 @In(create = true) 061 protected transient DocumentActions documentActions; 062 063 @In(create = true) 064 protected transient WebActions webActions; 065 066 @In(create = true, required = false) 067 protected FacesMessages facesMessages; 068 069 @In(create = true) 070 protected ResourcesAccessor resourcesAccessor; 071 072 protected List<TemplateInput> templateInputs; 073 074 protected String templateIdToAssociate; 075 076 protected String editableTemplateName; 077 078 public String createTemplate() { 079 DocumentModel changeableDocument = navigationContext.getChangeableDocument(); 080 TemplateSourceDocument sourceTemplate = changeableDocument.getAdapter(TemplateSourceDocument.class); 081 if (sourceTemplate != null && sourceTemplate.getTemplateBlob() != null) { 082 try { 083 sourceTemplate.initTemplate(false); 084 if (sourceTemplate.hasEditableParams()) { 085 templateInputs = sourceTemplate.getParams(); 086 return "editTemplateRelatedData"; 087 } 088 } catch (PropertyException e) { 089 log.error("Error during parameter automatic initialization", e); 090 facesMessages.add(StatusMessage.Severity.ERROR, 091 resourcesAccessor.getMessages().get("label.template.err.parameterInit")); 092 } 093 } 094 return documentActions.saveDocument(changeableDocument); 095 } 096 097 public List<TemplateInput> getTemplateInputs() { 098 return templateInputs; 099 } 100 101 public void setTemplateInputs(List<TemplateInput> templateInputs) { 102 this.templateInputs = templateInputs; 103 } 104 105 public String saveDocument() { 106 DocumentModel changeableDocument = navigationContext.getChangeableDocument(); 107 108 for (TemplateInput ti : templateInputs) { 109 log.info(ti.toString()); 110 } 111 TemplateSourceDocument source = changeableDocument.getAdapter(TemplateSourceDocument.class); 112 if (source != null) { 113 source.saveParams(templateInputs, false); 114 } 115 116 return documentActions.saveDocument(changeableDocument); 117 } 118 119 @Observer(value = { EventNames.DOCUMENT_SELECTION_CHANGED, EventNames.NEW_DOCUMENT_CREATED, 120 EventNames.DOCUMENT_CHANGED }, create = false) 121 @BypassInterceptors 122 public void reset() { 123 templateInputs = null; 124 templateEditableInputs = null; 125 editableTemplateName = null; 126 templateIdToAssociate = null; 127 } 128 129 public List<TemplateInput> getTemplateEditableInputs() { 130 if (editableTemplateName == null) { 131 return new ArrayList<>(); 132 } 133 if (templateEditableInputs == null) { 134 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 135 136 TemplateBasedDocument templateBasedDoc = currentDocument.getAdapter(TemplateBasedDocument.class); 137 templateEditableInputs = templateBasedDoc.getParams(editableTemplateName); 138 } 139 return templateEditableInputs; 140 } 141 142 public void setTemplateEditableInputs(List<TemplateInput> templateEditableInputs) { 143 this.templateEditableInputs = templateEditableInputs; 144 } 145 146 public String saveTemplateInputs() { 147 148 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 149 150 TemplateBasedDocument template = currentDocument.getAdapter(TemplateBasedDocument.class); 151 if (template != null) { 152 currentDocument = template.saveParams(editableTemplateName, templateEditableInputs, true); 153 } 154 reset(); 155 navigationContext.invalidateCurrentDocument(); 156 return navigationContext.navigateToDocument(currentDocument); 157 } 158 159 public void cancelTemplateInputsEdit() { 160 reset(); 161 } 162 163 public TemplateInput getNewInput() { 164 if (newInput == null) { 165 newInput = new TemplateInput("newField"); 166 } 167 return newInput; 168 } 169 170 public void setNewInput(TemplateInput newInput) { 171 this.newInput = newInput; 172 } 173 174 public String render(String templateName) { 175 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 176 TemplateBasedDocument doc = currentDocument.getAdapter(TemplateBasedDocument.class); 177 if (doc == null) { 178 return null; 179 } 180 try { 181 Blob rendition = doc.renderWithTemplate(templateName); 182 String filename = rendition.getFilename(); 183 ComponentUtils.download(currentDocument, null, rendition, filename, "templateRendition"); 184 return null; 185 } catch (NuxeoException e) { 186 log.error("Unable to render template ", e); 187 facesMessages.add(StatusMessage.Severity.ERROR, 188 resourcesAccessor.getMessages().get("label.template.err.renderingFailed")); 189 return null; 190 } 191 } 192 193 public String renderAndStore(String templateName) { 194 195 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 196 TemplateBasedDocument doc = currentDocument.getAdapter(TemplateBasedDocument.class); 197 if (doc == null) { 198 return null; 199 } 200 doc.renderAndStoreAsAttachment(templateName, true); 201 documentManager.save(); 202 return navigationContext.navigateToDocument(doc.getAdaptedDoc()); 203 } 204 205 @Override 206 public boolean canResetParameters() { 207 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 208 if (!documentManager.hasPermission(currentDocument.getRef(), SecurityConstants.WRITE)) { 209 return false; 210 } 211 TemplateBasedDocument templateBased = currentDocument.getAdapter(TemplateBasedDocument.class); 212 if (templateBased != null) { 213 return true; 214 } 215 return false; 216 } 217 218 public void resetParameters(String templateName) { 219 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 220 TemplateBasedDocument templateBased = currentDocument.getAdapter(TemplateBasedDocument.class); 221 if (templateBased != null) { 222 templateBased.initializeFromTemplate(templateName, true); 223 templateEditableInputs = null; 224 } 225 } 226 227 public boolean canDetachTemplate(String templateName) { 228 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 229 if (!documentManager.hasPermission(currentDocument.getRef(), SecurityConstants.WRITE)) { 230 return false; 231 } 232 TemplateBasedDocument templateBased = currentDocument.getAdapter(TemplateBasedDocument.class); 233 if (templateBased != null) { 234 return true; 235 } 236 return false; 237 } 238 239 public String detachTemplate(String templateName) { 240 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 241 TemplateProcessorService tps = Framework.getLocalService(TemplateProcessorService.class); 242 DocumentModel detachedDocument = tps.detachTemplateBasedDocument(currentDocument, templateName, true); 243 webActions.resetTabList(); 244 // because of cacheKey issue 245 navigationContext.setCurrentDocument(null); 246 return navigationContext.navigateToDocument(detachedDocument); 247 } 248 249 public String getTemplateIdToAssociate() { 250 return templateIdToAssociate; 251 } 252 253 public void setTemplateIdToAssociate(String templateIdToAssociate) { 254 this.templateIdToAssociate = templateIdToAssociate; 255 } 256 257 public void associateDocumentToTemplate() { 258 if (templateIdToAssociate == null) { 259 // return null; 260 return; 261 } 262 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 263 DocumentModel sourceTemplate = documentManager.getDocument(new IdRef(templateIdToAssociate)); 264 TemplateProcessorService tps = Framework.getLocalService(TemplateProcessorService.class); 265 try { 266 currentDocument = tps.makeTemplateBasedDocument(currentDocument, sourceTemplate, true); 267 } catch (NuxeoException e) { 268 log.error("Unable to do template association", e); 269 facesMessages.add(StatusMessage.Severity.ERROR, 270 resourcesAccessor.getMessages().get("label.template.err.associationFailed"), 271 sourceTemplate.getName()); 272 } 273 navigationContext.invalidateCurrentDocument(); 274 EventManager.raiseEventsOnDocumentChange(currentDocument); 275 templateIdToAssociate = null; 276 } 277 278 public boolean canRenderAndStore() { 279 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 280 // check that templating is supported 281 TemplateBasedDocument template = currentDocument.getAdapter(TemplateBasedDocument.class); 282 if (template == null) { 283 return false; 284 } 285 // check that we can store the result 286 BlobHolder bh = currentDocument.getAdapter(BlobHolder.class); 287 if (bh == null) { 288 return false; 289 } 290 return true; 291 } 292 293 public String getEditableTemplateName() { 294 return editableTemplateName; 295 } 296 297 public void setEditableTemplateName(String editableTemplateName) { 298 if (editableTemplateName == null || !editableTemplateName.equals(this.editableTemplateName)) { 299 this.editableTemplateName = editableTemplateName; 300 templateEditableInputs = null; 301 } 302 } 303 304 public List<TemplateSourceDocument> getBindableTemplatesForDocument() { 305 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 306 String targetType = currentDocument.getType(); 307 TemplateProcessorService tps = Framework.getLocalService(TemplateProcessorService.class); 308 List<DocumentModel> templates = tps.getAvailableTemplateDocs(documentManager, targetType); 309 310 List<TemplateSourceDocument> result = new ArrayList<>(); 311 TemplateBasedDocument currentTBD = currentDocument.getAdapter(TemplateBasedDocument.class); 312 List<String> alreadyBoundTemplateNames = new ArrayList<>(); 313 if (currentTBD != null) { 314 alreadyBoundTemplateNames = currentTBD.getTemplateNames(); 315 } 316 for (DocumentModel doc : templates) { 317 TemplateSourceDocument source = doc.getAdapter(TemplateSourceDocument.class); 318 if (!alreadyBoundTemplateNames.contains(source.getName())) { 319 result.add(source); 320 } 321 } 322 return result; 323 324 } 325 326 public List<SelectItem> getBindableTemplatesForDocumentAsSelectItems() { 327 328 List<SelectItem> items = new ArrayList<>(); 329 List<TemplateSourceDocument> sources = getBindableTemplatesForDocument(); 330 for (TemplateSourceDocument sd : sources) { 331 DocumentModel doc = sd.getAdaptedDoc(); 332 String label = doc.getTitle(); 333 if (doc.isVersion()) { 334 label = label + " (V " + doc.getVersionLabel() + ")"; 335 } 336 items.add(new SelectItem(doc.getId(), label)); 337 } 338 339 return items; 340 } 341 342 public boolean canBindNewTemplate() { 343 DocumentModel currentDocument = navigationContext.getCurrentDocument(); 344 if (!currentDocument.getCoreSession().hasPermission(currentDocument.getRef(), SecurityConstants.WRITE)) { 345 return false; 346 } 347 if (getBindableTemplatesForDocument().size() == 0) { 348 return false; 349 } 350 return true; 351 } 352 353 @Factory(value = "currentTemplateBasedDocument", scope = ScopeType.EVENT) 354 public TemplateBasedDocument getCurrentDocumentAsTemplateBasedDocument() { 355 return navigationContext.getCurrentDocument().getAdapter(TemplateBasedDocument.class); 356 } 357 358 @Factory(value = "associatedRenderableTemplates", scope = ScopeType.EVENT) 359 public List<TemplateSourceDocument> getRenderableTemplates() { 360 List<TemplateSourceDocument> result = new ArrayList<>(); 361 TemplateBasedDocument template = getCurrentDocumentAsTemplateBasedDocument(); 362 if (template != null) { 363 List<TemplateSourceDocument> sources = template.getSourceTemplates(); 364 for (TemplateSourceDocument source : sources) { 365 if (source.getTargetRenditionName() == null || source.getTargetRenditionName().isEmpty()) { 366 result.add(source); 367 } 368 } 369 } 370 return result; 371 } 372}