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