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