001/*
002 * (C) Copyright 2006-20011 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 */
018
019package org.nuxeo.ecm.platform.reporting.api;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.io.Serializable;
024import java.util.ArrayList;
025import java.util.Date;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029
030import org.eclipse.birt.core.exception.BirtException;
031import org.eclipse.birt.report.engine.api.IRenderOption;
032import org.eclipse.birt.report.engine.api.IReportRunnable;
033import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
034import org.nuxeo.ecm.core.api.DocumentModel;
035import org.nuxeo.ecm.core.api.IdRef;
036import org.nuxeo.ecm.core.api.NuxeoException;
037import org.nuxeo.ecm.core.api.PropertyException;
038import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner;
039import org.nuxeo.ecm.platform.reporting.engine.BirtEngine;
040import org.nuxeo.ecm.platform.reporting.report.ReportContext;
041import org.nuxeo.ecm.platform.reporting.report.ReportHelper;
042import org.nuxeo.ecm.platform.reporting.report.ReportParameter;
043
044/**
045 * This is the implementation of the {@link ReportInstance} adapter. Holds most of the rendering logic.
046 *
047 * @author Tiry (tdelprat@nuxeo.com)
048 */
049public class BirtReportInstance extends BaseBirtReportAdapter implements ReportInstance {
050
051    protected static final String PREFIX = "birt";
052
053    public BirtReportInstance(DocumentModel doc) {
054        super(doc);
055    }
056
057    @Override
058    public ReportModel getModel() {
059        String modelUUID = (String) doc.getPropertyValue(PREFIX + ":modelRef");
060        final IdRef modelRef = new IdRef(modelUUID);
061
062        final DocumentModel[] docs = new DocumentModel[1];
063        new UnrestrictedSessionRunner(getSession()) {
064            @Override
065            public void run() {
066                DocumentModel doc = session.getDocument(modelRef);
067                doc.detach(true);
068                docs[0] = doc;
069            }
070        }.runUnrestricted();
071
072        return docs[0].getAdapter(ReportModel.class);
073    }
074
075    @Override
076    @SuppressWarnings("unchecked")
077    public Map<String, String> getStoredParameters() {
078
079        Map<String, String> params = new HashMap<String, String>();
080
081        List<Map<String, Serializable>> localParams = (List<Map<String, Serializable>>) doc.getPropertyValue(PREFIX
082                + ":parameters");
083        if (localParams != null) {
084            for (Map<String, Serializable> localParam : localParams) {
085                String name = (String) localParam.get("pName");
086                String value = (String) localParam.get("pValue");
087                if (value != null) {
088                    params.put(name, value);
089                }
090            }
091        }
092        return params;
093    }
094
095    @Override
096    public List<ReportParameter> getReportParameters() throws IOException {
097
098        List<ReportParameter> params = getModel().getReportParameters();
099        Map<String, String> modelParams = getModel().getStoredParameters();
100        Map<String, String> localParams = getStoredParameters();
101
102        for (ReportParameter param : params) {
103            String value = modelParams.get(param.getName());
104            if (value != null && !value.isEmpty()) {
105                param.setValue(value);
106                param.setEditable(false);
107            }
108            value = localParams.get(param.getName());
109            if (value != null && !value.isEmpty()) {
110                param.setValue(value);
111            }
112        }
113        return params;
114    }
115
116    @Override
117    public List<ReportParameter> getReportUserParameters() throws IOException {
118        List<ReportParameter> params = getReportParameters();
119        ReportContext.setContextualParameters(params, doc);
120
121        List<ReportParameter> userParams = new ArrayList<ReportParameter>();
122        for (ReportParameter param : params) {
123            if (param.getStringValue() == null || param.getStringValue().isEmpty()) {
124                userParams.add(param);
125            }
126        }
127        return userParams;
128    }
129
130    @Override
131    public void initParameterList() throws IOException {
132        String oldModelRef = (String) doc.getPropertyValue(PREFIX + ":oldModelRef");
133        String modelRef = (String) doc.getPropertyValue(PREFIX + ":modelRef");
134
135        if (oldModelRef == null || oldModelRef.isEmpty() || !oldModelRef.equals(modelRef)) {
136            doc.setPropertyValue(PREFIX + ":oldModelRef", modelRef);
137            // get model params
138            List<ReportParameter> params = getModel().getReportParameters();
139            // remove all stored params
140            List<Map<String, Serializable>> localParams = new ArrayList<Map<String, Serializable>>();
141            doc.setPropertyValue(getPrefix() + ":parameters", (Serializable) localParams);
142            // init params
143            for (ReportParameter param : params) {
144                setParameter(param.getName(), null, false);
145            }
146        }
147    }
148
149    @Override
150    public void render(IRenderOption options, Map<String, Object> userParameters) throws IOException {
151        // get Stored params
152        List<ReportParameter> params = getReportParameters();
153        // fill with user supplied parameters
154        for (ReportParameter param : params) {
155            if (userParameters.containsKey(param.getName())) {
156                param.setObjectValue(userParameters.get(param.getName()));
157            }
158        }
159        // replace values by contextual parameters if needed
160        ReportContext.setContextualParameters(params, doc);
161
162        InputStream report = getModel().getReportFileAsStream();
163        IReportRunnable nuxeoReport = ReportHelper.getNuxeoReport(report, doc.getRepositoryName());
164        IRunAndRenderTask task = BirtEngine.getBirtEngine().createRunAndRenderTask(nuxeoReport);
165        Map<String, Object> birtParams = computeParametersForBirt(params);
166        task.setParameterValues(birtParams);
167        task.setRenderOption(options);
168        try {
169            task.run();
170        } catch (BirtException e) {
171            throw new NuxeoException(e);
172        }
173        task.close();
174    }
175
176    protected Map<String, Object> computeParametersForBirt(List<ReportParameter> parameters) {
177        Map<String, Object> birtParameters = new HashMap<String, Object>();
178        for (ReportParameter param : parameters) {
179            Object value = param.getObjectValue();
180            if (value instanceof Date) {
181                Date date = (Date) value;
182                value = new java.sql.Date(date.getTime());
183            }
184            birtParameters.put(param.getName(), value);
185        }
186        return birtParameters;
187    }
188
189    @Override
190    public String getReportKey() {
191        try {
192            return (String) doc.getPropertyValue(PREFIX + ":reportKey");
193        } catch (PropertyException e) {
194            return null;
195        }
196    }
197
198    @Override
199    public void setReportKey(String key) {
200        doc.setPropertyValue(PREFIX + ":reportKey", key);
201    }
202
203    @Override
204    protected String getPrefix() {
205        return PREFIX;
206    }
207
208}