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}