blob: 05ff25edb23b4d2cac3b222423f85ad32a2a451a [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*/
package org.eclipse.osbp.report;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.IPlatformContext;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.core.framework.PlatformFileContext;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineException;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IRenderOption;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.PDFRenderOption;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.command.CustomMsgException;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.osbp.report.pdfservice.PDFService;
import org.eclipse.osbp.ui.api.datamart.DatamartFilter;
import org.eclipse.osbp.ui.api.datamart.DatamartFilter.FilterType;
import org.eclipse.osbp.ui.api.datamart.IDataMart;
import org.eclipse.osbp.ui.api.metadata.IDSLMetadataService;
import org.eclipse.osbp.ui.api.report.IReportProvider;
import org.eclipse.osbp.ui.api.user.IUser;
import org.eclipse.osbp.xtext.datamartdsl.DatamartDSLPackage;
import org.eclipse.osbp.xtext.datamartdsl.DatamartDefinition;
import org.eclipse.osbp.xtext.reportdsl.Container;
import org.eclipse.osbp.xtext.reportdsl.DatamartTable;
import org.eclipse.osbp.xtext.reportdsl.Element;
import org.eclipse.osbp.xtext.reportdsl.GridCell;
import org.eclipse.osbp.xtext.reportdsl.GridRow;
import org.eclipse.osbp.xtext.reportdsl.Report;
import org.eclipse.osbp.xtext.reportdsl.ReportDSLPackage;
import org.eclipse.osbp.xtext.reportdsl.ReportDesignTemplate;
import org.eclipse.osbp.xtext.reportdsl.SomeGrid;
import org.eclipse.osbp.xtext.reportdsl.jvmmodel.Utilities;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfCopyFields;
import com.lowagie.text.pdf.PdfReader;
@Component(immediate = true)
public class ReportProvider implements IReportProvider {
public enum Rendering {
PDF_FILE(false, true, true, false, false), PDF_STREAM(false, true,
false, true, false),
/** @see {@link http://www.eclipse.org/forums/index.php/t/204085/} */
PDF_PRINT_STREAM(false, true, false, true, true), HTML_FILE(true,
false, true, false, false), HTML_STREAM(true, false, false,
true, false);
public boolean asHtml() {
return asHtml;
}
public boolean asPdf() {
return asPdf;
}
public boolean asFile() {
return asFile;
}
public boolean asStream() {
return asStream;
}
public boolean forPrinting() {
return forPrinting;
}
private final boolean asHtml;
private final boolean asPdf;
private final boolean asFile;
private final boolean asStream;
private final boolean forPrinting;
private Rendering(boolean asHtml, boolean asPdf, boolean asFile,
boolean asStream, boolean forPrinting) {
this.asHtml = asHtml;
this.asPdf = asPdf;
this.asFile = asFile;
this.asStream = asStream;
this.forPrinting = forPrinting;
}
}
private final Logger LOGGER = LoggerFactory.getLogger(ReportProvider.class);
// private static java.util.logging.Logger BIRT_LOGGER = java.util.logging.Logger.getLogger(ReportProvider.class.getName());
private IReportEngineFactory reportFactory = (IReportEngineFactory) Platform
.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
private IReportEngine reportEngine;
private EngineConfig engineConfig = new EngineConfig();
public ReportProvider() {
IPlatformContext context = new PlatformFileContext();
engineConfig.setResourcePath("i18n");
engineConfig.setPlatformContext(context);
// ClassLoader clzLoader = ReportProvider.class.getClassLoader();
// URL resource = clzLoader.getResource("resources/log4j.properties");
// String path = resource.getFile();
// System.setProperty("java.util.logging.config.file", path);
// engineConfig.setLogger(BIRT_LOGGER);
// String logbackConfig = System.getProperty("logback.configurationFile");
// if(logbackConfig != null) {
// engineConfig.setLogConfig(logbackConfig.replace("META-INF/logback.xml", "log") , Level.FINE);
// engineConfig.setLogFile("birt.log");
// }
try {
Platform.startup(engineConfig);
reportEngine = reportFactory.createReportEngine(engineConfig);
} catch (BirtException e) {
LOGGER.error("{}", e);
}
}
public void printReportAsPdf(String reportId, IEclipseContext eclipseContext, Map<String, String> filters) {
PDFService.printReportAsPdf(get(reportId, eclipseContext, filters), eclipseContext.get(IUser.class).getPrintService());
}
public ByteArrayInputStream get(String reportId, IEclipseContext eclipseContext, Map<String, String> filters) {
return get(reportId, eclipseContext, filters, IReportProvider.Rendering.PDF_PRINT_STREAM, null);
}
@SuppressWarnings("unchecked")
public ByteArrayInputStream get(String reportId, IEclipseContext eclipseContext,
Map<String, String> filters,
IReportProvider.Rendering renderer,
String outputPath) {
IDSLMetadataService dslMetadataService = eclipseContext.get(IDSLMetadataService.class);
IUser user = eclipseContext.get(IUser.class);
if (reportEngine == null) {
LOGGER.error("report engine not initialized");
return null;
}
// prepare datamart instance
Report report = (Report) dslMetadataService.getMetadata(reportId, ReportDSLPackage.Literals.REPORT);
if(report == null) {
LOGGER.error("report with id "+reportId+" not found");
return null;
}
List<DatamartFilter> datamartFilters = new ArrayList<>();
Map<String, IDataMart> datamarts = new HashMap<>();
String datamartId = dslMetadataService.getFullyQualifiedName(report.getDatamartRef());
IDataMart datamartInstance = instantiateDatamart(reportId, user, dslMetadataService, datamartId);
if(datamartInstance != null) {
datamarts.put(Utilities.getDataSetName(null, report.getDatamartRef()), datamartInstance);
datamartFilters.addAll(computeFilters(user, dslMetadataService, filters, datamartInstance));
if(report.getDesign() instanceof ReportDesignTemplate) {
iterateReportForDatamarts(reportId, user, dslMetadataService, filters, ((ReportDesignTemplate)report.getDesign()).getDetail(), datamartFilters, datamarts);
}
}
// create report
ByteArrayInputStream bis = null;
IRunAndRenderTask task = null;
InputStream inputStream = null;
try {
URL url = dslMetadataService.getResourceURL(report.getName()+".rptdesign", "report");
inputStream = url.openStream();
if (inputStream != null) {
IReportRunnable design = reportEngine.openReportDesign(url.toExternalForm(), inputStream);
if (design.getDesignHandle() instanceof ReportDesignHandle) {
addTranslations(
(ReportDesignHandle) design.getDesignHandle(),
dslMetadataService);
}
task = reportEngine.createRunAndRenderTask(design);
task.getAppContext().put(
IReportProvider.APPCONTEXT_ECLIPSECONTEXT,
eclipseContext);
task.getAppContext().put(
IReportProvider.APPCONTEXT_DATAMARTINSTANCE,
datamarts);
task.getAppContext().put(
IReportProvider.APPCONTEXT_FILTERMAP,
datamartFilters);
task.setLocale(user.getLocale());
// set output options
IRenderOption options = null;
ByteArrayOutputStream bos = null;
if (renderer.asHtml()) {
options = new HTMLRenderOption();
options.setOutputFormat(HTMLRenderOption.OUTPUT_FORMAT_HTML);
((HTMLRenderOption) options).setEmbeddable(true);
} else if (renderer.asPdf()) {
options = new PDFRenderOption();
options.setOutputFormat(PDFRenderOption.OUTPUT_FORMAT_PDF);
}
if (options != null) {
if (renderer.asFile()) {
options.setOutputFileName(outputPath);
} else if (renderer.asStream()) {
bos = new ByteArrayOutputStream();
options.setOutputStream(bos);
}
}
task.setRenderOption(options);
task.run();
if (renderer.asStream()) {
if (renderer.forPrinting() && (bos != null)) {
PdfReader js1 = new PdfReader(bos.toByteArray());
bos = new ByteArrayOutputStream();
PdfCopyFields cpy = new PdfCopyFields(bos);
cpy.addDocument(js1);
cpy.addJavaScript("this.print({bUI: true,bSilent: false,bShrinkToFit:true});");
cpy.close();
}
if (bos != null) {
bis = new ByteArrayInputStream(bos.toByteArray());
}
}
}
} catch (EngineException | NullPointerException | IOException
| DocumentException e) {
LOGGER.error("{}", e);
} finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
}
}
if (task != null) {
task.close();
}
}
return bis;
}
private void iterateReportForDatamarts(String reportId, IUser user, IDSLMetadataService dslMetadataService,
Map<String, String> filters, Container container, List<DatamartFilter> datamartFilters,
Map<String, IDataMart> datamarts) {
for(Element element : container.getElements()) {
if (element instanceof DatamartTable){
String alias = ((DatamartTable)element).getName();
if(((DatamartTable)element).getDatamartRef() != null) {
String datamartSubId = dslMetadataService.getFullyQualifiedName(((DatamartTable)element).getDatamartRef());
IDataMart datamartSubInstance = instantiateDatamart(reportId, user, dslMetadataService, datamartSubId);
if(datamartSubInstance != null) {
datamarts.put(Utilities.getDataSetName(alias, ((DatamartTable)element).getDatamartRef()), datamartSubInstance);
datamartFilters.addAll(computeFilters(user, dslMetadataService, filters, datamartSubInstance));
}
}
} else if (element instanceof Container) {
iterateReportForDatamarts(reportId, user, dslMetadataService, filters, (Container)element, datamartFilters, datamarts);
} else if (element instanceof SomeGrid) {
for(GridRow row : ((SomeGrid)element).getRows()) {
for (GridCell cell : row.getCells()) {
iterateReportForDatamarts(reportId, user, dslMetadataService, filters, cell, datamartFilters, datamarts);
}
}
}
}
}
private ArrayList<DatamartFilter> computeFilters(IUser user, IDSLMetadataService dslMetadataService,
Map<String, String> filters, IDataMart datamartInstance) {
// transform filter
ArrayList<DatamartFilter> datamartFilters = datamartInstance.getFilters();
for(String inFilter:filters.keySet()) {
boolean found = false;
for(DatamartFilter outFilter:datamartFilters) {
if(outFilter.getName().equals(inFilter)) {
found = true;
if(outFilter.getType() == FilterType.BY_ID) {
StringBuilder builder = new StringBuilder();
builder.append("'");
builder.append(filters.get(inFilter));
builder.append("'");
outFilter.setSql(builder.toString());
} else {
outFilter.addSelectedItem(filters.get(inFilter));
}
}
}
if(!found) {
// append remaining filters - should be of type id
datamartFilters.add(new DatamartFilter(dslMetadataService, user, FilterType.BY_ID, inFilter, filters.get(inFilter)));
}
}
datamartInstance.computeConditions();
return datamartFilters;
}
private IDataMart instantiateDatamart(String reportId, IUser user, IDSLMetadataService dslMetadataService,
String datamartId) {
DatamartDefinition datamart = (DatamartDefinition) dslMetadataService.getMetadata(datamartId, DatamartDSLPackage.Literals.DATAMART_DEFINITION);
if(datamart == null) {
LOGGER.error("datamart with id {} not found", datamartId);
return null;
}
IDataMart datamartInstance = (IDataMart) dslMetadataService.getClassInstance(datamart, "datamart");
if(datamartInstance == null) {
LOGGER.error("report with id {} has invalid datamart {}", reportId, datamartId);
return null;
}
datamartInstance.setUser(user);
return datamartInstance;
}
private void addTranslations(ReportDesignHandle reportDesignHandle,
IDSLMetadataService dslMetadataService) {
for (String locale : dslMetadataService.getTranslations().keySet()) {
// TODO: birt4.4 cannot handle fallbacks of language variants with
// missing keys when locale was added - so don't supply for this
// version
if (!locale.contains("_")) {
for (Object key : dslMetadataService.getTranslations()
.get(locale).keySet()) {
try {
reportDesignHandle.addTranslation((String) key, locale,
(String) dslMetadataService.getTranslations()
.get(locale).get(key));
} catch (CustomMsgException e) {
LOGGER.error("{}", e);
}
}
}
}
}
}