| /** |
| * |
| * 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); |
| } |
| } |
| } |
| } |
| } |
| } |