001/* 002 * (C) Copyright 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 * Thierry Delprat 018 */ 019package org.nuxeo.template.processors.xdocreport; 020 021import java.io.File; 022import java.io.FileOutputStream; 023import java.io.IOException; 024import java.io.OutputStream; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Map; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.common.utils.FileUtils; 032import org.nuxeo.ecm.core.api.Blob; 033import org.nuxeo.ecm.core.api.Blobs; 034import org.nuxeo.ecm.core.api.DocumentModel; 035import org.nuxeo.ecm.core.api.impl.blob.FileBlob; 036import org.nuxeo.runtime.api.Framework; 037import org.nuxeo.template.api.InputType; 038import org.nuxeo.template.api.TemplateInput; 039import org.nuxeo.template.api.TemplateProcessor; 040import org.nuxeo.template.api.adapters.TemplateBasedDocument; 041import org.nuxeo.template.fm.FMContextBuilder; 042import org.nuxeo.template.fm.FreeMarkerVariableExtractor; 043import org.nuxeo.template.processors.AbstractTemplateProcessor; 044 045import fr.opensagres.xdocreport.core.XDocReportException; 046import fr.opensagres.xdocreport.document.IXDocReport; 047import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; 048import fr.opensagres.xdocreport.template.IContext; 049import fr.opensagres.xdocreport.template.TemplateEngineKind; 050import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; 051 052/** 053 * XDocReport based {@link TemplateProcessor} 054 * 055 * @author <a href="mailto:[email protected]">Tiry</a> 056 */ 057public class XDocReportProcessor extends AbstractTemplateProcessor implements TemplateProcessor { 058 059 protected static final Log log = LogFactory.getLog(XDocReportProcessor.class); 060 061 public static final String TEMPLATE_TYPE = "XDocReport"; 062 063 public static final String OOO_TEMPLATE_TYPE = "OpenDocument"; 064 065 public static final String DocX_TEMPLATE_TYPE = "DocX"; 066 067 protected FMContextBuilder fmContextBuilder = new FMContextBuilder(); 068 069 protected String getTemplateFormat(Blob blob) { 070 String filename = blob.getFilename(); 071 if (filename == null && blob instanceof FileBlob) { 072 File file = ((FileBlob) blob).getFile(); 073 if (file != null) { 074 filename = file.getName(); 075 } 076 } 077 if (filename != null && !filename.isEmpty()) { 078 if (filename.endsWith(".docx")) { 079 return DocX_TEMPLATE_TYPE; 080 } else if (filename.endsWith(".odt")) { 081 return OOO_TEMPLATE_TYPE; 082 } 083 } 084 return OOO_TEMPLATE_TYPE; 085 } 086 087 @Override 088 public List<TemplateInput> getInitialParametersDefinition(Blob blob) throws IOException { 089 090 List<TemplateInput> params = new ArrayList<TemplateInput>(); 091 String xmlContent = null; 092 093 if (OOO_TEMPLATE_TYPE.equals(getTemplateFormat(blob))) { 094 xmlContent = ZipXmlHelper.readXMLContent(blob, ZipXmlHelper.OOO_MAIN_FILE); 095 } else if (DocX_TEMPLATE_TYPE.equals(getTemplateFormat(blob))) { 096 xmlContent = ZipXmlHelper.readXMLContent(blob, ZipXmlHelper.DOCX_MAIN_FILE); 097 } 098 099 if (xmlContent != null) { 100 List<String> vars = FreeMarkerVariableExtractor.extractVariables(xmlContent); 101 102 for (String var : vars) { 103 TemplateInput input = new TemplateInput(var); 104 params.add(input); 105 } 106 } 107 return params; 108 } 109 110 @Override 111 public Blob renderTemplate(TemplateBasedDocument templateBasedDocument, String templateName) throws IOException { 112 113 Blob sourceTemplateBlob = getSourceTemplateBlob(templateBasedDocument, templateName); 114 115 // load the template 116 IXDocReport report; 117 try { 118 report = XDocReportRegistry.getRegistry().loadReport(sourceTemplateBlob.getStream(), 119 TemplateEngineKind.Freemarker, false); 120 } catch (XDocReportException e) { 121 throw new IOException(e); 122 } 123 124 // manage parameters 125 List<TemplateInput> params = templateBasedDocument.getParams(templateName); 126 FieldsMetadata metadata = new FieldsMetadata(); 127 for (TemplateInput param : params) { 128 if (param.getType() == InputType.PictureProperty) { 129 metadata.addFieldAsImage(param.getName()); 130 } 131 } 132 report.setFieldsMetadata(metadata); 133 134 // fill Freemarker context 135 DocumentModel doc = templateBasedDocument.getAdaptedDoc(); 136 Map<String, Object> ctx = fmContextBuilder.build(doc, templateName); 137 138 XDocReportBindingResolver resolver = new XDocReportBindingResolver(metadata); 139 resolver.resolve(params, ctx, templateBasedDocument); 140 141 // add default context vars 142 IContext context; 143 try { 144 context = report.createContext(); 145 } catch (XDocReportException e) { 146 throw new IOException(e); 147 } 148 for (String key : ctx.keySet()) { 149 context.put(key, ctx.get(key)); 150 } 151 // add automatic loop on audit entries 152 metadata.addFieldAsList("auditEntries.principalName"); 153 metadata.addFieldAsList("auditEntries.eventId"); 154 metadata.addFieldAsList("auditEntries.eventDate"); 155 metadata.addFieldAsList("auditEntries.docUUID"); 156 metadata.addFieldAsList("auditEntries.docPath"); 157 metadata.addFieldAsList("auditEntries.docType"); 158 metadata.addFieldAsList("auditEntries.category"); 159 metadata.addFieldAsList("auditEntries.comment"); 160 metadata.addFieldAsList("auditEntries.docLifeCycle"); 161 metadata.addFieldAsList("auditEntries.repositoryId"); 162 163 File workingDir = getWorkingDir(); 164 File generated = new File(workingDir, "XDOCReportresult-" + System.currentTimeMillis()); 165 generated.createNewFile(); 166 167 OutputStream out = new FileOutputStream(generated); 168 169 try { 170 report.process(context, out); 171 } catch (XDocReportException e) { 172 throw new IOException(e); 173 } 174 175 Blob newBlob = Blobs.createBlob(generated); 176 177 String templateFileName = sourceTemplateBlob.getFilename(); 178 179 // set the output file name 180 String targetFileExt = FileUtils.getFileExtension(templateFileName); 181 String targetFileName = FileUtils.getFileNameNoExt(templateBasedDocument.getAdaptedDoc().getTitle()); 182 targetFileName = targetFileName + "." + targetFileExt; 183 newBlob.setFilename(targetFileName); 184 185 // mark the file for automatic deletion on GC 186 Framework.trackFile(generated, newBlob); 187 return newBlob; 188 } 189}