From ed795d88fdfa8f65af75c8c0d446273cb477ad68 Mon Sep 17 00:00:00 2001 From: "CORP\\vapadwal" Date: Tue, 21 Jan 2020 20:20:20 +0530 Subject: [PATCH 1/3] added a module reporting from devonfw --- modules/pom.xml | 1 + modules/reporting/pom.xml | 44 ++ .../reporting/common/ReportingModuleApp.java | 22 + .../module/reporting/common/api/Report.java | 102 +++++ .../reporting/common/api/Reporting.java | 74 +++ .../api/exception/ReportingException.java | 46 ++ .../config/ReportExporterConfiguration.java | 217 +++++++++ .../config/ReportingConfigProperties.java | 34 ++ .../common/config/ReportingConstants.java | 66 +++ .../common/config/ReportingUtil.java | 140 ++++++ .../common/impl/ReportingJasperImpl.java | 271 +++++++++++ .../src/main/resources/application.properties | 17 + .../base/ConcatenatedReportingTest.java | 291 ++++++++++++ .../module/reporting/base/ReportingTest.java | 264 +++++++++++ .../reporting/base/SubreportingTest.java | 429 ++++++++++++++++++ .../SimpleReportTest.jrxml | 120 +++++ .../ReportingTest/reportingtest.jrxml | 116 +++++ .../SubreportingTest/AddressReport.jrxml | 134 ++++++ .../SubreportingTest/MasterReport.jrxml | 124 +++++ .../SubreportingTest/ProductReport.jrxml | 201 ++++++++ .../src/test/resources/application.properties | 16 + 21 files changed, 2729 insertions(+) create mode 100644 modules/reporting/pom.xml create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/ReportingModuleApp.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Report.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Reporting.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/exception/ReportingException.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportExporterConfiguration.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConfigProperties.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConstants.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingUtil.java create mode 100644 modules/reporting/src/main/java/com/devonfw/module/reporting/common/impl/ReportingJasperImpl.java create mode 100644 modules/reporting/src/main/resources/application.properties create mode 100644 modules/reporting/src/test/java/com/devonfw/module/reporting/base/ConcatenatedReportingTest.java create mode 100644 modules/reporting/src/test/java/com/devonfw/module/reporting/base/ReportingTest.java create mode 100644 modules/reporting/src/test/java/com/devonfw/module/reporting/base/SubreportingTest.java create mode 100644 modules/reporting/src/test/resources/ConcatenatedReportingTest/SimpleReportTest.jrxml create mode 100644 modules/reporting/src/test/resources/ReportingTest/reportingtest.jrxml create mode 100644 modules/reporting/src/test/resources/SubreportingTest/AddressReport.jrxml create mode 100644 modules/reporting/src/test/resources/SubreportingTest/MasterReport.jrxml create mode 100644 modules/reporting/src/test/resources/SubreportingTest/ProductReport.jrxml create mode 100644 modules/reporting/src/test/resources/application.properties diff --git a/modules/pom.xml b/modules/pom.xml index 9214f520..c22d500f 100644 --- a/modules/pom.xml +++ b/modules/pom.xml @@ -34,6 +34,7 @@ batch web basic + reporting diff --git a/modules/reporting/pom.xml b/modules/reporting/pom.xml new file mode 100644 index 00000000..026a0957 --- /dev/null +++ b/modules/reporting/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + com.devonfw.java.dev + devon4j-modules + dev-SNAPSHOT + + com.devonfw.java.modules + devon4j-reporting + ${devon4j.version} + jar + ${project.artifactId} + Module for reporting. + + + org.springframework.boot + spring-boot-starter + + + com.devonfw.java.modules + devon4j-test + test + + + + net.sf.jasperreports + jasperreports + 6.11.0 + + + org.apache.poi + poi + 4.1.1 + + + net.sf.m-m-m + mmm-util-exception + + + + diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/ReportingModuleApp.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/ReportingModuleApp.java new file mode 100644 index 00000000..cf0526f3 --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/ReportingModuleApp.java @@ -0,0 +1,22 @@ +package com.devonfw.module.reporting.common; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * This is the entry point for unit tests. + * + */ +@SpringBootApplication +public class ReportingModuleApp { + /** + * Entry point for spring-boot based app + * + * @param args - arguments + */ + public static void main(String[] args) { + + SpringApplication.run(ReportingModuleApp.class, args); + + } +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Report.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Report.java new file mode 100644 index 00000000..d6b57ff6 --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Report.java @@ -0,0 +1,102 @@ +package com.devonfw.module.reporting.common.api; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Class to encapsulate a report + * + * @param type of the data that is provided to be included in the report + */ +public class Report { + private String name; + + private String dataSourceName; + + private List data; + + private String templatePath; + + private HashMap params; + + /** + * @return name + */ + public String getName() { + + return this.name; + } + + /** + * @param name new value of {@link #getName}. + */ + public void setName(String name) { + + this.name = name; + } + + /** + * @return dataSourceName + */ + public String getDataSourceName() { + + return this.dataSourceName; + } + + /** + * @param dataSourceName new value of {@link #getDataSourceName}. + */ + public void setDataSourceName(String dataSourceName) { + + this.dataSourceName = dataSourceName; + } + + /** + * @return data + */ + public List getData() { + + return this.data; + } + + /** + * @param data new value of {@link #getData}. + */ + public void setData(List data) { + + this.data = data; + } + + /** + * @return templatePath + */ + public String getTemplatePath() { + + return this.templatePath; + } + + /** + * @param templatePath new value of {@link #getTemplatePath}. + */ + public void setTemplatePath(String templatePath) { + + this.templatePath = templatePath; + } + + /** + * @return params + */ + public Map getParams() { + + return this.params; + } + + /** + * @param params new value of {@link #getParams}. + */ + public void setParams(HashMap params) { + + this.params = params; + } +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Reporting.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Reporting.java new file mode 100644 index 00000000..7a76a20b --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/Reporting.java @@ -0,0 +1,74 @@ +package com.devonfw.module.reporting.common.api; + +import java.io.File; +import java.io.OutputStream; +import java.util.List; + +/** + * This is the interface for a simple facade to generate a report based on Jasper Reports library. + * + * @param type of the data that is provided to be included in the report. + */ +public interface Reporting { + + /** + * Generates a report file with the given data, the template located in the templatePath and the type of file. + * specified. + * + * @param report the {@link Report} that encapsulates the data to be included in the report, the location of the + * report template and the values of the parameters defined in the report template (in case template uses + * parameters). + * @param file the file where the report must be created. + * @param format - report format + */ + public void generateReport(Report report, File file, String format); + + /** + * Generates a report stream with the given data, the template located in the templatePath and the type of file. + * + * @param report the {@link Report} that encapsulates the data to be included in the report, the location of the + * report template and the values of the parameters defined in the report template (in case template uses + * parameters). + * @param stream the stream where the report will be written. + * @param format - report format + */ + public void generateReport(Report report, OutputStream stream, String format); + + /** + * Generates a file with a main report that stores other sub-reports. + * + * @param masterReport the main {@link Report}. + * @param reports a list of {@link Report} reports to be included within the main report. + * @param file the file where the report must be created. + * @param format - report format + */ + public void generateSubreport(Report masterReport, List reports, File file, String format); + + /** + * Generates a stream with a main report that stores other sub-reports. + * + * @param masterReport the main {@link Report}. + * @param reports a list of {@link Report} reports to be included within the main report. + * @param stream the stream to manage the resultant report. + * @param format - report format + */ + public void generateSubreport(Report masterReport, List reports, OutputStream stream, String format); + + /** + * Generates a report file that contains a concatenation of reports. + * + * @param reports the list of reports to be included in the report file. + * @param file the file where the report must be created. + * @param format - report format + */ + public void concatenateReports(List reports, File file, String format); + + /** + * Generates a stream that contains a concatenation of reports. + * + * @param reports the list of reports to be included in the report stream. + * @param stream the stream to manage the resultant report. + * @param format - report format + */ + public void concatenateReports(List reports, OutputStream stream, String format); +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/exception/ReportingException.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/exception/ReportingException.java new file mode 100644 index 00000000..babd9e95 --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/api/exception/ReportingException.java @@ -0,0 +1,46 @@ +package com.devonfw.module.reporting.common.api.exception; + +import net.sf.mmm.util.exception.api.NlsRuntimeException; +import net.sf.mmm.util.nls.api.NlsMessage; + +/** + * This is the checked exception for Reporting module. + * + */ +public class ReportingException extends NlsRuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * The constructor. + * + * @param message the error {@link #getNlsMessage() message}. + */ + public ReportingException(NlsMessage message) { + + super(message); + } + + /** + * Constructs an {@code ReportingException} with the root cause. + * + * @param cause the error {@link #getCause() cause}. + * @param message the error {@link #getNlsMessage() message}. + */ + public ReportingException(Throwable cause, NlsMessage message) { + + super(cause, message); + } + + /** + * The constructor. + * + * @param cause the error {@link #getCause() cause}. + * @param message the error message. + */ + public ReportingException(Throwable cause, String message) { + + super(cause, message); + } + +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportExporterConfiguration.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportExporterConfiguration.java new file mode 100644 index 00000000..5438c5ff --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportExporterConfiguration.java @@ -0,0 +1,217 @@ +package com.devonfw.module.reporting.common.config; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import net.sf.jasperreports.engine.JRAbstractExporter; +import net.sf.jasperreports.engine.export.HtmlExporter; +import net.sf.jasperreports.engine.export.JRCsvExporter; +import net.sf.jasperreports.engine.export.JRPdfExporter; +import net.sf.jasperreports.engine.export.JRRtfExporter; +import net.sf.jasperreports.engine.export.JRTextExporter; +import net.sf.jasperreports.engine.export.JRXlsExporter; +import net.sf.jasperreports.engine.export.oasis.JROdsExporter; +import net.sf.jasperreports.engine.export.oasis.JROdtExporter; +import net.sf.jasperreports.engine.export.ooxml.JRDocxExporter; +import net.sf.jasperreports.engine.export.ooxml.JRPptxExporter; +import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Configuration class that returns the {@link JRAbstractExporter exporter} according to the {@link ReportingConstants} + * + */ +@Configuration +public class ReportExporterConfiguration { + + private final Map exporterMap; + + /** + * The constructor. + */ + public ReportExporterConfiguration() { + + super(); + this.exporterMap = new HashMap<>(); + } + + /** + * puts the {@link JRAbstractExporter} Instance in to the {@link Map} according to {@link ReportingConstants} + * + * @param jrAbstractExporters + */ + @Inject + public void setReportExporters(List jrAbstractExporters) { + + for (JRAbstractExporter exporter : jrAbstractExporters) { + this.exporterMap.put(exporter.getExporterKey(), exporter); + } + + } + + @Bean + public JRAbstractExporter getExcelExporter() { + + return new JRXlsExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.XLS; + } + }; + } + + /** + * Returns the {@link JRAbstractExporter} for Xls version + * + * @return + */ + @Bean + public JRAbstractExporter getPdfExporter() { + + return new JRPdfExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.PDF; + } + }; + } + + @Bean + public JRAbstractExporter getCsvExporter() { + + return new JRCsvExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.CSV; + } + }; + } + + @Bean + public JRAbstractExporter getRtfExporter() { + + return new JRRtfExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.RTF; + } + }; + } + + @Bean + public JRAbstractExporter getWordExporter() { + + return new JRRtfExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.WORD; + } + }; + } + + @Bean + public JRAbstractExporter getTextExporter() { + + return new JRTextExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.TEXT; + } + }; + } + + @Bean + public JRAbstractExporter getDocxExporter() { + + return new JRDocxExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.DOCX; + } + }; + } + + @Bean + public JRAbstractExporter getXlsxExporter() { + + return new JRXlsxExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.XLSX; + } + }; + } + + @Bean + public JRAbstractExporter getHtmlExporter() { + + return new HtmlExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.HTML; + } + }; + } + + @Bean + public JRAbstractExporter getOdtExporter() { + + return new JROdtExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.ODT; + } + }; + } + + @Bean + public JRAbstractExporter getOdsExporter() { + + return new JROdsExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.ODS; + } + }; + } + + @Bean + public JRAbstractExporter getPptxExporter() { + + return new JRPptxExporter() { + @Override + public String getExporterKey() { + + return ReportingConstants.PPTX; + } + }; + } + + /** + * Returns the {@link JRAbstractExporter} instance + * + * @param format key according the {@link ReportingConstants} + * @return + */ + public JRAbstractExporter getReportExporter(String format) { + + return this.exporterMap.get(format); + } + +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConfigProperties.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConfigProperties.java new file mode 100644 index 00000000..6b4378ab --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConfigProperties.java @@ -0,0 +1,34 @@ +package com.devonfw.module.reporting.common.config; + +import java.util.HashMap; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * Configuration for Reporting + */ +@Configuration +@ConfigurationProperties(prefix = "jasper.reporting") +public class ReportingConfigProperties { + + private HashMap txtConfig; + + /** + * @return txtConfig + */ + + public HashMap getTxtConfig() { + + return this.txtConfig; + } + + /** + * @param txtConfig collection of properties + */ + public void setTxtConfig(HashMap txtConfig) { + + this.txtConfig = txtConfig; + } + +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConstants.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConstants.java new file mode 100644 index 00000000..fa161a7a --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingConstants.java @@ -0,0 +1,66 @@ +package com.devonfw.module.reporting.common.config; + +/** + * Constants of types of file outputs for the report. + */ +public class ReportingConstants { + /** + * Format type PDF + */ + public static final String PDF = "pdf"; + + /** + * Format type EXCEL + */ + public static final String XLS = "xls"; + + /** + * Format type TEXT + */ + public static final String TEXT = "text"; + + /** + * Format type CSV + */ + public static final String CSV = "csv"; + + /** + * Format type HTML + */ + public static final String HTML = "html"; + + /** + * Format type WORD + */ + public static final String WORD = "word"; + + /** + * Format type RTF + */ + public static final String RTF = "rtf"; + + /** + * Format type TEXT + */ + public static final String DOCX = "docx"; + + /** + * Format type EXCEL XLSX + */ + public static final String XLSX = "xlsx"; + + /** + * Format type OPEN DOCUMENT TEXT + */ + public static final String ODT = "odt"; + + /** + * Format type OPEN DOCUMENT SHEET + */ + public static final String ODS = "ods"; + + /** + * Format type PPTX + */ + public static final String PPTX = "pptx"; +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingUtil.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingUtil.java new file mode 100644 index 00000000..75d905a9 --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/config/ReportingUtil.java @@ -0,0 +1,140 @@ +package com.devonfw.module.reporting.common.config; + +import java.io.OutputStream; +import java.security.InvalidParameterException; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import net.sf.jasperreports.engine.JRAbstractExporter; +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JREmptyDataSource; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.data.JRMapCollectionDataSource; +import net.sf.jasperreports.export.ExporterInput; +import net.sf.jasperreports.export.ExporterOutput; +import net.sf.jasperreports.export.SimpleExporterInput; +import net.sf.jasperreports.export.SimpleHtmlExporterOutput; +import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput; +import net.sf.jasperreports.export.SimpleTextReportConfiguration; +import net.sf.jasperreports.export.SimpleWriterExporterOutput; +import net.sf.jasperreports.export.SimpleXlsReportConfiguration; +import net.sf.jasperreports.export.SimpleXlsxReportConfiguration; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.devonfw.module.reporting.common.api.exception.ReportingException; + +/** + * This is the implementation of several basic functionalities associated to Jasper Reports Library. + */ +@Named +public class ReportingUtil { + + private static final Log log = LogFactory.getLog(ReportingUtil.class); + + @Inject + private ReportingConfigProperties reportingConfigProperties; + + /** + * Returns the data provided as JRDataSource type in order to fill the report. + * + * @param data the data to be included in the report. + * @return {@link JRDataSource} + */ + public JRDataSource getDataSource(Collection data) { + + if (data.size() == 0) { + return new JREmptyDataSource(); + } else { + return new JRMapCollectionDataSource((Collection>) data); + } + } + + /** + * Configures a Jasper Reports Exporter setting its input (a JasperPrint object) and output (a FileOutputStream + * object) + * + * @param exporter the {@linkplain JRAbstractExporter} to configure + * @param print the {@link JasperPrint} object to configure as the exporter input it can be a list of JasperPrint + * objects. + * @param stream the {@link OutputStream} to configure as the exporter output. + * @param format the {@link ReportingConstants} according to which the exporter will be configured. + * @throws ReportingException if the configuration process of the exporter fails. + */ + public void configureExporter(JRAbstractExporter exporter, Object print, OutputStream stream, String format) + throws ReportingException { + + ExporterInput exporterInput = print instanceof List ? SimpleExporterInput.getInstance((List) print) + : new SimpleExporterInput((JasperPrint) print); + ExporterOutput exporterOutput = null; + if (print instanceof List || print instanceof JasperPrint) { + + switch (format) { + case ReportingConstants.XLS: + exporterOutput = new SimpleOutputStreamExporterOutput(stream); + exporter.setConfiguration(getXlsConfiguration()); + break; + case ReportingConstants.CSV: + case ReportingConstants.WORD: + case ReportingConstants.RTF: + exporterOutput = new SimpleWriterExporterOutput(stream); + break; + case ReportingConstants.TEXT: + exporterOutput = new SimpleWriterExporterOutput(stream); + exporter.setConfiguration(getTxtConfiguration()); + break; + case ReportingConstants.XLSX: + exporterOutput = new SimpleOutputStreamExporterOutput(stream); + exporter.setConfiguration(getXlsxConfiguration()); + break; + case ReportingConstants.HTML: + exporterOutput = new SimpleHtmlExporterOutput(stream); + break; + default: + exporterOutput = new SimpleOutputStreamExporterOutput(stream); + } + + exporter.setExporterInput(exporterInput); + exporter.setExporterOutput(exporterOutput); + } else { + throw new InvalidParameterException( + "In order to configure the JRAbstractExporter the object supplied must be of type JasperPrint or a List of JasperPrint objects"); + } + } + + private SimpleTextReportConfiguration getTxtConfiguration() throws ReportingException { + + SimpleTextReportConfiguration txtConfiguration = new SimpleTextReportConfiguration(); + try { + txtConfiguration.setCharWidth(Float.parseFloat(this.reportingConfigProperties.getTxtConfig().get("charwidth"))); + txtConfiguration.setCharHeight(Float.parseFloat(this.reportingConfigProperties.getTxtConfig().get("charheight"))); + txtConfiguration + .setPageWidthInChars(Integer.parseInt(this.reportingConfigProperties.getTxtConfig().get("pagewidthinchars"))); + txtConfiguration.setPageHeightInChars( + Integer.parseInt(this.reportingConfigProperties.getTxtConfig().get("pageheightinchars"))); + return txtConfiguration; + } catch (NumberFormatException e) { + log.error(e.getMessage(), e); + throw new ReportingException(e, "Some txtConfig parameter in application.properties may have an invalid value."); + } + } + + private SimpleXlsReportConfiguration getXlsConfiguration() { + + SimpleXlsReportConfiguration xlsConfiguration = new SimpleXlsReportConfiguration(); + xlsConfiguration.setOnePagePerSheet(false); + return xlsConfiguration; + } + + private SimpleXlsxReportConfiguration getXlsxConfiguration() { + + SimpleXlsxReportConfiguration xlsxConfiguration = new SimpleXlsxReportConfiguration(); + xlsxConfiguration.setOnePagePerSheet(false); + return xlsxConfiguration; + } +} diff --git a/modules/reporting/src/main/java/com/devonfw/module/reporting/common/impl/ReportingJasperImpl.java b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/impl/ReportingJasperImpl.java new file mode 100644 index 00000000..fca9e75a --- /dev/null +++ b/modules/reporting/src/main/java/com/devonfw/module/reporting/common/impl/ReportingJasperImpl.java @@ -0,0 +1,271 @@ +package com.devonfw.module.reporting.common.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; + +import net.sf.jasperreports.engine.JRAbstractExporter; +import net.sf.jasperreports.engine.JRDataSource; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.design.JasperDesign; +import net.sf.jasperreports.engine.xml.JRXmlLoader; +import net.sf.jasperreports.export.ExporterOutput; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.devonfw.module.reporting.common.api.Report; +import com.devonfw.module.reporting.common.api.Reporting; +import com.devonfw.module.reporting.common.api.exception.ReportingException; +import com.devonfw.module.reporting.common.config.ReportExporterConfiguration; +import com.devonfw.module.reporting.common.config.ReportingUtil; + +/** + * This is the simple implementation of {@link Reporting} + * + * @param type of the data that is provided to be included in the report. + */ +@Named +public class ReportingJasperImpl implements Reporting { + + @Inject + private ReportingUtil utils; + + private static final Log log = LogFactory.getLog(ReportingJasperImpl.class); + + private JRDataSource dataSource = null; + + /** + * the start index for each report in concatenated reports + */ + private static String PAGES_INIT_NUM = "PAGES_INIT_NUM"; + + @Inject + private ReportExporterConfiguration reportExporterConfiguration; + + @Override + public void generateReport(Report report, File file, String format) { + + FileOutputStream stream = null; + + try { + + this.dataSource = this.utils.getDataSource(report.getData()); + JRAbstractExporter exporter = this.reportExporterConfiguration.getReportExporter(format); + JasperDesign design = JRXmlLoader.load(report.getTemplatePath()); + JasperReport jreport = JasperCompileManager.compileReport(design); + JasperPrint jasperPrint = JasperFillManager.fillReport(jreport, report.getParams(), this.dataSource); + + stream = new FileOutputStream(file); + this.utils.configureExporter(exporter, jasperPrint, stream, format); + exporter.exportReport(); + + } catch (ReportingException | JRException | IOException e) { + log.error("An error occurred while trying to create the report: " + e.getMessage(), e); + throw new ReportingException(e, e.getMessage()); + + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException ioex) { + throw new ReportingException(ioex, + "The stream associated to the temp file could not be closed. " + ioex.getMessage()); + } + } + + } + + @Override + public void generateReport(Report report, OutputStream stream, String format) { + + try { + this.dataSource = this.utils.getDataSource(report.getData()); + JRAbstractExporter exporter = this.reportExporterConfiguration.getReportExporter(format); + JasperDesign design = JRXmlLoader.load(report.getTemplatePath()); + JasperReport jreport = JasperCompileManager.compileReport(design); + JasperPrint jasperPrint = JasperFillManager.fillReport(jreport, report.getParams(), this.dataSource); + this.utils.configureExporter(exporter, jasperPrint, stream, format); + exporter.exportReport(); + } catch (ReportingException | JRException e) { + log.error("An error occurred while trying to create the report. " + e.getMessage(), e); + throw new ReportingException(e, e.getMessage()); + } + + } + + @Override + public void generateSubreport(Report master, List subs, File file, String format) { + + FileOutputStream stream = null; + + try { + + Map subReportsParams = new HashMap<>(); + + JasperDesign design = null; + JasperReport subReport = null; + JasperPrint jasperPrint = null; + JRDataSource subDataSource = null; + + Map masterParams = master.getParams(); + this.dataSource = this.utils.getDataSource(master.getData()); + JRAbstractExporter exporter = this.reportExporterConfiguration.getReportExporter(format); + JasperDesign masterDesign = JRXmlLoader.load(master.getTemplatePath()); + JasperReport masterReport = JasperCompileManager.compileReport(masterDesign); + + for (Report sub : subs) { + subDataSource = this.utils.getDataSource(sub.getData()); + design = JRXmlLoader.load(sub.getTemplatePath()); + subReport = JasperCompileManager.compileReport(design); + subReportsParams.put(sub.getName(), subReport); + subReportsParams.put(sub.getDataSourceName(), subDataSource); + } + + masterParams.putAll(subReportsParams); + jasperPrint = JasperFillManager.fillReport(masterReport, masterParams, this.dataSource); + + stream = new FileOutputStream(file); + this.utils.configureExporter(exporter, jasperPrint, stream, format); + exporter.exportReport(); + + } catch (ReportingException | JRException | IOException e) { + log.error("An error occurred while trying to create the subreport. " + e.getMessage()); + throw new ReportingException(e, e.getMessage()); + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException ioex) { + throw new ReportingException(ioex, + "The stream associated to the temp file could not be closed. " + ioex.getMessage()); + } + } + } + + @Override + public void generateSubreport(Report master, List subs, OutputStream stream, String format) { + + try { + + Map subReportsParams = new HashMap<>(); + + JasperDesign design = null; + JasperReport subReport = null; + JasperPrint jasperPrint = null; + JRDataSource subDataSource = null; + + Map masterParams = master.getParams(); + this.dataSource = this.utils.getDataSource(master.getData()); + JRAbstractExporter exporter = this.reportExporterConfiguration.getReportExporter(format); + JasperDesign masterDesign = JRXmlLoader.load(master.getTemplatePath()); + JasperReport masterReport = JasperCompileManager.compileReport(masterDesign); + + for (Report sub : subs) { + subDataSource = this.utils.getDataSource(sub.getData()); + design = JRXmlLoader.load(sub.getTemplatePath()); + subReport = JasperCompileManager.compileReport(design); + subReportsParams.put(sub.getName(), subReport); + subReportsParams.put(sub.getDataSourceName(), subDataSource); + } + + masterParams.putAll(subReportsParams); + jasperPrint = JasperFillManager.fillReport(masterReport, masterParams, this.dataSource); + + this.utils.configureExporter(exporter, jasperPrint, stream, format); + exporter.exportReport(); + + } catch (ReportingException | JRException e) { + log.error("An error occurred while trying to create the subreport. " + e.getMessage()); + throw new ReportingException(e, e.getMessage()); + } + + } + + @Override + public void concatenateReports(List reports, File file, String format) { + + FileOutputStream stream = null; + List printList = new ArrayList<>(); + try { + JRAbstractExporter exporter = this.reportExporterConfiguration.getReportExporter(format); + + int numPages = 0; + for (Report report : reports) { + HashMap params = new HashMap<>(); + params.put(PAGES_INIT_NUM, numPages); + params.putAll(report.getParams()); + report.setParams(params); + JasperDesign design = JRXmlLoader.load(report.getTemplatePath()); + JasperReport jasperReport = JasperCompileManager.compileReport(design); + JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, report.getParams(), + this.utils.getDataSource(report.getData())); + printList.add(jasperPrint); + + numPages += jasperPrint.getPages().size(); + } + + stream = new FileOutputStream(file); + this.utils.configureExporter(exporter, printList, stream, format); + exporter.exportReport(); + + } catch (Exception e) { + log.error("An error occurred while trying to create the concatenated report: " + e.getMessage(), e); + throw new ReportingException(e, e.getMessage()); + } finally { + try { + if (stream != null) + stream.close(); + } catch (IOException ioex) { + throw new ReportingException(ioex, + "The stream associated to the temp file for the concatenated report could not be closed. " + + ioex.getMessage()); + } + } + + } + + @Override + public void concatenateReports(List reports, OutputStream stream, String format) { + + List printList = new ArrayList<>(); + try { + JRAbstractExporter exporter = this.reportExporterConfiguration.getReportExporter(format); + + int numPages = 0; + for (Report report : reports) { + HashMap params = new HashMap<>(); + params.put(PAGES_INIT_NUM, numPages); + params.putAll(report.getParams()); + report.setParams(params); + JasperDesign design = JRXmlLoader.load(report.getTemplatePath()); + JasperReport jasperReport = JasperCompileManager.compileReport(design); + JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, report.getParams(), + this.utils.getDataSource(report.getData())); + printList.add(jasperPrint); + + numPages += jasperPrint.getPages().size(); + } + + this.utils.configureExporter(exporter, printList, stream, format); + exporter.exportReport(); + + } catch (Exception e) { + log.error("An error occurred while trying to create the concatenated report: " + e.getMessage(), e); + throw new ReportingException(e, e.getMessage()); + } + } + +} diff --git a/modules/reporting/src/main/resources/application.properties b/modules/reporting/src/main/resources/application.properties new file mode 100644 index 00000000..ff75e035 --- /dev/null +++ b/modules/reporting/src/main/resources/application.properties @@ -0,0 +1,17 @@ +# --------------------------------------------------------------------------- +# Base values +# --------------------------------------------------------------------------- + +#devon.foo.baz=baz +#devon.foo.bar.one=bar1 +#devon.foo.bar.two=bar2 + +# Activate spring profiles +#spring.profiles.active = integrationTest + +jasper.reporting.txtconfig.charwidth=7 +jasper.reporting.txtconfig.charheight=13.9 +jasper.reporting.txtconfig.pagewidthinchars=80 +jasper.reporting.txtconfig.pageheightinchars=47 +jasper.reporting.test1=123 + diff --git a/modules/reporting/src/test/java/com/devonfw/module/reporting/base/ConcatenatedReportingTest.java b/modules/reporting/src/test/java/com/devonfw/module/reporting/base/ConcatenatedReportingTest.java new file mode 100644 index 00000000..1ac313c1 --- /dev/null +++ b/modules/reporting/src/test/java/com/devonfw/module/reporting/base/ConcatenatedReportingTest.java @@ -0,0 +1,291 @@ +package com.devonfw.module.reporting.base; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.inject.Inject; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import com.devonfw.module.reporting.common.ReportingModuleApp; +import com.devonfw.module.reporting.common.api.Report; +import com.devonfw.module.reporting.common.api.Reporting; +import com.devonfw.module.reporting.common.config.ReportingConstants; +import com.devonfw.module.test.common.base.ComponentTest; + +/** + * Test class to test the concatenated reports functionality + * + */ +@SpringBootTest(classes = ReportingModuleApp.class) +public class ConcatenatedReportingTest extends ComponentTest { + @SuppressWarnings("rawtypes") + @Inject + Reporting reportManager; + + private Resource template = new ClassPathResource("ConcatenatedReportingTest/SimpleReportTest.jrxml"); + + private static Random rnd = new Random(); + + @SuppressWarnings("rawtypes") + List reports = null; + + private OutputStream stream = null; + + /** + * @throws IOException if the template for the report can not be found. + */ + @BeforeEach + public void init() throws IOException { + + this.reports = getReportsList(); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with pdf format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedPdfReport() throws IOException { + + File pdf = File.createTempFile("concReports_", ".pdf"); + this.reportManager.concatenateReports(this.reports, pdf, ReportingConstants.PDF); + assertThat(pdf.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with xls format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedXlsReport() throws IOException { + + File excel = File.createTempFile("concReports_", ".xls"); + this.reportManager.concatenateReports(this.reports, excel, ReportingConstants.XLS); + assertThat(excel.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with xlsx format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedXlsxReport() throws IOException { + + File excel_xlsx = File.createTempFile("concReports_", ".xlsx"); + this.reportManager.concatenateReports(this.reports, excel_xlsx, ReportingConstants.XLSX); + assertThat(excel_xlsx.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with html format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedHtmlReport() throws IOException { + + File html = File.createTempFile("concReports_", ".html"); + this.reportManager.concatenateReports(this.reports, html, ReportingConstants.HTML); + assertThat(html.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with ods format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedOdsReport() throws IOException { + + File ods = File.createTempFile("concReports_", ".ods"); + this.reportManager.concatenateReports(this.reports, ods, ReportingConstants.ODS); + assertThat(ods.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with odt format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedOdtReport() throws IOException { + + File odt = File.createTempFile("concReports_", ".odt"); + this.reportManager.concatenateReports(this.reports, odt, ReportingConstants.ODT); + assertThat(odt.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with doc format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedDocReport() throws IOException { + + File doc = File.createTempFile("concReports_", ".doc"); + this.reportManager.concatenateReports(this.reports, doc, ReportingConstants.WORD); + assertThat(doc.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with docx format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedDocxReport() throws IOException { + + File docx = File.createTempFile("concReports_", ".docx"); + this.reportManager.concatenateReports(this.reports, docx, ReportingConstants.DOCX); + assertThat(docx.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with pptx format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedPptxReport() throws IOException { + + File pptx = File.createTempFile("concReports_", ".pptx"); + this.reportManager.concatenateReports(this.reports, pptx, ReportingConstants.PPTX); + assertThat(pptx.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with rtf format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedRtfReport() throws IOException { + + File rtf = File.createTempFile("concReports_", ".rtf"); + this.reportManager.concatenateReports(this.reports, rtf, ReportingConstants.RTF); + assertThat(rtf.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with csv format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedCsvReport() throws IOException { + + File csv = File.createTempFile("concReports_", ".csv"); + this.reportManager.concatenateReports(this.reports, csv, ReportingConstants.CSV); + assertThat(csv.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with txt format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedTxtReport() throws IOException { + + File txt = File.createTempFile("concReports_", ".txt"); + this.reportManager.concatenateReports(this.reports, txt, ReportingConstants.TEXT); + assertThat(txt.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a stream with pdf format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateConcatenatedStreamReport() throws IOException { + + this.stream = new ByteArrayOutputStream(); + this.reportManager.concatenateReports(this.reports, this.stream, ReportingConstants.PDF); + assertThat(((ByteArrayOutputStream) this.stream).size()).isGreaterThan(0); + } + + @SuppressWarnings("javadoc") + @AfterEach + public void end() throws IOException { + + if (this.stream != null) + this.stream.close(); + } + + @SuppressWarnings({ "javadoc", "rawtypes", "unchecked" }) + public static List createList() { + + List lst = new ArrayList(); + lst.add(createItem("Tom Waits", 92)); + lst.add(createItem("Nick Cave", 97)); + lst.add(createItem("PJ Harvey", 95)); + + return lst; + } + + @SuppressWarnings({ "javadoc", "rawtypes", "unchecked" }) + public static Object createItem(String name, int rating) { + + Map map = new HashMap(); + map.put("ID", rnd.nextLong()); + map.put("Name", name); + map.put("Rating", rating); + return map; + } + + @SuppressWarnings({ "rawtypes", "unchecked", "javadoc" }) + public List getReportsList() throws IOException { + + HashMap params = null; + List reportsList = new ArrayList<>(); + + Report report1 = new Report(); + params = new HashMap<>(); + params.put("ReportTitle", "Report 1"); + params.put("ReportDescription", "First concatenated report."); + report1.setData(createList()); + report1.setTemplatePath(this.template.getURI().getPath()); + report1.setParams(params); + + Report report2 = new Report(); + params = new HashMap<>(); + params.put("ReportTitle", "Report 2"); + params.put("ReportDescription", "Second concatenated report."); + report2.setData(createList()); + report2.setTemplatePath(this.template.getURI().getPath()); + report2.setParams(params); + + Report report3 = new Report(); + params = new HashMap<>(); + params.put("ReportTitle", "Report 3"); + params.put("ReportDescription", "Third concatenated report."); + report3.setData(createList()); + report3.setTemplatePath(this.template.getURI().getPath()); + report3.setParams(params); + + reportsList.add(report1); + reportsList.add(report2); + reportsList.add(report3); + + return reportsList; + } + +} diff --git a/modules/reporting/src/test/java/com/devonfw/module/reporting/base/ReportingTest.java b/modules/reporting/src/test/java/com/devonfw/module/reporting/base/ReportingTest.java new file mode 100644 index 00000000..c2db755e --- /dev/null +++ b/modules/reporting/src/test/java/com/devonfw/module/reporting/base/ReportingTest.java @@ -0,0 +1,264 @@ +package com.devonfw.module.reporting.base; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.inject.Inject; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import com.devonfw.module.reporting.common.ReportingModuleApp; +import com.devonfw.module.reporting.common.api.Report; +import com.devonfw.module.reporting.common.api.Reporting; +import com.devonfw.module.reporting.common.config.ReportingConstants; +import com.devonfw.module.test.common.base.ComponentTest; + +/** + * Tests the Reporting functionality + * + */ +@SpringBootTest(classes = ReportingModuleApp.class) +public class ReportingTest extends ComponentTest { + + private Resource template = new ClassPathResource("ReportingTest/reportingtest.jrxml"); + + @SuppressWarnings("rawtypes") + private Report report = null; + + @SuppressWarnings("rawtypes") + @Inject + private Reporting reportManager; + + private HashMap params = new HashMap<>(); + + private static Random rnd = new Random(); + + OutputStream stream = null; + + @SuppressWarnings({ "javadoc", "rawtypes", "unchecked" }) + @BeforeEach + public void init() throws IOException { + + this.report = new Report(); + + this.params.put("ReportTitle", "Test"); + this.params.put("ReportDescription", "This is a Test File Report"); + + this.report.setName("Test"); + this.report.setData(createList()); + this.report.setParams(this.params); + this.report.setTemplatePath(this.template.getURI().getPath()); + + } + + /** + * Test that checks the creation of a report file in pdf format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportPdfFile() throws IOException { + + File pdf = File.createTempFile("tst", ".pdf"); + this.reportManager.generateReport(this.report, pdf, ReportingConstants.PDF); + assertThat(pdf.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in xls format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportExcelFile() throws IOException { + + File excel = File.createTempFile("tst", ".xls"); + this.reportManager.generateReport(this.report, excel, ReportingConstants.XLS); + assertThat(excel.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in xlsx format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportXlsxFile() throws IOException { + + File excel_xlsx = File.createTempFile("tst", ".xlsx"); + this.reportManager.generateReport(this.report, excel_xlsx, ReportingConstants.XLSX); + assertThat(excel_xlsx.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in html format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportHtmlFile() throws IOException { + + File html = File.createTempFile("tst", ".html"); + this.reportManager.generateReport(this.report, html, ReportingConstants.HTML); + assertThat(html.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in ods format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportOdsFile() throws IOException { + + File ods = File.createTempFile("tst", ".ods"); + this.reportManager.generateReport(this.report, ods, ReportingConstants.ODS); + assertThat(ods.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in odt format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportOdtFile() throws IOException { + + File odt = File.createTempFile("tst", ".odt"); + this.reportManager.generateReport(this.report, odt, ReportingConstants.ODT); + assertThat(odt.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in doc format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportDocFile() throws IOException { + + File doc = File.createTempFile("tst", ".doc"); + this.reportManager.generateReport(this.report, doc, ReportingConstants.WORD); + assertThat(doc.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in docx format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportDocxFile() throws IOException { + + File docx = File.createTempFile("tst", ".docx"); + this.reportManager.generateReport(this.report, docx, ReportingConstants.DOCX); + assertThat(docx.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in pptx format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportPowerpointFile() throws IOException { + + File pptx = File.createTempFile("tst", ".pptx"); + this.reportManager.generateReport(this.report, pptx, ReportingConstants.PPTX); + assertThat(pptx.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in rtf format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportRtfFile() throws IOException { + + File rtf = File.createTempFile("tst", ".rtf"); + this.reportManager.generateReport(this.report, rtf, ReportingConstants.RTF); + assertThat(rtf.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in csv format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportCsvFile() throws IOException { + + File csv = File.createTempFile("tst", ".csv"); + this.reportManager.generateReport(this.report, csv, ReportingConstants.CSV); + assertThat(csv.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report file in txt format. + * + * @throws IOException if the temp file can not be created. + */ + @Test + public void generateReportTextFile() throws IOException { + + File txt = File.createTempFile("tst", ".txt"); + this.reportManager.generateReport(this.report, txt, ReportingConstants.TEXT); + assertThat(txt.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a report stream in pdf format. + * + * + * + */ + @Test + public void generateReportStream() { + + this.stream = new ByteArrayOutputStream(); + this.reportManager.generateReport(this.report, this.stream, ReportingConstants.PDF); + assertThat(((ByteArrayOutputStream) this.stream).size()).isGreaterThan(0); + } + + @SuppressWarnings("javadoc") + @AfterEach + public void end() throws IOException { + + if (this.stream != null) + this.stream.close(); + } + + @SuppressWarnings({ "javadoc", "rawtypes", "unchecked" }) + public static List createList() { + + List lst = new ArrayList(); + lst.add(createItem("Tom Waits", 92)); + lst.add(createItem("Nick Cave", 97)); + lst.add(createItem("PJ Harvey", 95)); + return lst; + } + + @SuppressWarnings({ "javadoc", "rawtypes", "unchecked" }) + public static Object createItem(String name, int rating) { + + Map map = new HashMap(); + map.put("ID", rnd.nextLong()); + map.put("Name", name); + map.put("Rating", rating); + return map; + } + +} diff --git a/modules/reporting/src/test/java/com/devonfw/module/reporting/base/SubreportingTest.java b/modules/reporting/src/test/java/com/devonfw/module/reporting/base/SubreportingTest.java new file mode 100644 index 00000000..0d313901 --- /dev/null +++ b/modules/reporting/src/test/java/com/devonfw/module/reporting/base/SubreportingTest.java @@ -0,0 +1,429 @@ +package com.devonfw.module.reporting.base; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +import com.devonfw.module.reporting.common.ReportingModuleApp; +import com.devonfw.module.reporting.common.api.Report; +import com.devonfw.module.reporting.common.api.Reporting; +import com.devonfw.module.reporting.common.config.ReportingConstants; +import com.devonfw.module.test.common.base.ComponentTest; + +/** + * Test class to test the subreports functionality + * + */ +@SpringBootTest(classes = ReportingModuleApp.class) +public class SubreportingTest extends ComponentTest { + + @SuppressWarnings("rawtypes") + @Inject + Reporting reportManager; + + @SuppressWarnings("rawtypes") + Report masterReport = null; + + @SuppressWarnings("rawtypes") + List subreports = null; + + private final String CITY = "Valencia"; + + private OutputStream stream = null; + + private Resource masterTemplate = new ClassPathResource("SubreportingTest/MasterReport.jrxml"); + + private Resource productTemplate = new ClassPathResource("SubreportingTest/ProductReport.jrxml"); + + private Resource addressTemplate = new ClassPathResource("SubreportingTest/AddressReport.jrxml"); + + @SuppressWarnings({ "javadoc", "rawtypes", "unchecked" }) + @BeforeEach + public void init() throws IOException { + + this.masterReport = new Report(); + this.subreports = new ArrayList<>(); + HashMap allParams = new HashMap<>(); + + // subreport Products + Report products = new Report(); + HashMap productsParams = new HashMap<>(); + productsParams.put("City", this.CITY); + allParams.putAll(productsParams); + products.setName("Products"); + products.setDataSourceName("ProductsDS"); + products.setData(getProductsAsMapList()); + products.setTemplatePath(this.productTemplate.getURI().getPath()); + this.subreports.add(products); + + // subreport Address + Report address = new Report(); + address.setName("Address"); + address.setDataSourceName("AddressDS"); + address.setData(getAddressAsMapList()); + address.setTemplatePath(this.addressTemplate.getURI().getPath()); + this.subreports.add(address); + + // subreport Address2 + Report address2 = new Report(); + address2.setName("Address2"); + address2.setDataSourceName("Address2DS"); + address2.setData(getAddress2AsMapList()); + address2.setTemplatePath(this.addressTemplate.getURI().getPath()); + this.subreports.add(address2); + + // master report + this.masterReport.setParams(allParams); + this.masterReport.setName("MasterTest"); + this.masterReport.setData(getCitiesAsMapList(new String[] { this.CITY })); + this.masterReport.setTemplatePath(this.masterTemplate.getURI().getPath()); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with pdf format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportPdfFile() throws IOException { + + File file = File.createTempFile("subreport_", ".pdf"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.PDF); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with xls format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportExcelFile() throws IOException { + + File file = File.createTempFile("subreport_", ".xls"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.XLS); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with xlsx format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportXlsxFile() throws IOException { + + File file = File.createTempFile("subreport_", ".xlsx"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.XLSX); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with html format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportHtmlFile() throws IOException { + + File file = File.createTempFile("subreport_", ".html"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.HTML); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with ods format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportOdsFile() throws IOException { + + File file = File.createTempFile("subreport_", ".ods"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.ODS); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with odt format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportOdtFile() throws IOException { + + File file = File.createTempFile("subreport_", ".odt"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.ODT); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with doc format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportDocFile() throws IOException { + + File file = File.createTempFile("subreport_", ".doc"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.WORD); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with docx format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportDocxFile() throws IOException { + + File file = File.createTempFile("subreport_", ".docx"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.DOCX); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with pptx format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportPptxFile() throws IOException { + + File file = File.createTempFile("subreport_", ".pptx"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.PPTX); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with rtf format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportRtfFile() throws IOException { + + File file = File.createTempFile("subreport_", ".rtf"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.RTF); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with csv format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportCsvFile() throws IOException { + + File file = File.createTempFile("subreport_", ".csv"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.CSV); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a file with txt format. + * + * @throws IOException if the temporal file can not be created. + */ + @Test + public void generateSubreportTxtFile() throws IOException { + + File file = File.createTempFile("subreport_", ".txt"); + this.reportManager.generateSubreport(this.masterReport, this.subreports, file, ReportingConstants.TEXT); + assertThat(file.length()).isGreaterThan(0); + } + + /** + * Test that checks the creation of a concatenation of reports in a stream. + * + */ + @Test + public void generateSubrerportStream() { + + this.stream = new ByteArrayOutputStream(); + this.reportManager.generateSubreport(this.masterReport, this.subreports, this.stream, ReportingConstants.PDF); + assertThat(((ByteArrayOutputStream) this.stream).size()).isGreaterThan(0); + } + + @SuppressWarnings("javadoc") + @AfterEach + public void end() throws IOException { + + if (this.stream != null) + this.stream.close(); + } + + @SuppressWarnings("rawtypes") + private List getCitiesAsMapList(String[] cities) { + + List citiesList = new ArrayList<>(); + for (String city : cities) { + citiesList.add(createCityItem(city)); + } + return citiesList; + } + + private HashMap createCityItem(String cityName) { + + HashMap cityItem = new HashMap<>(); + cityItem.put("City", cityName); + return cityItem; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static List getProductsAsMapList() { + + List productsList = new ArrayList(); + productsList.add(createProductItem(0, "Iron Iron", 3f, 8.10f)); + productsList.add(createProductItem(1, "Chair Shoe", 4f, 37.20f)); + productsList.add(createProductItem(4, "Ice Tea Shoe", 48f, 57.60f)); + productsList.add(createProductItem(5, "Clock Clock", 12f, 35.40f)); + productsList.add(createProductItem(6, "Ice Tea Chair", 23f, 14.70f)); + productsList.add(createProductItem(7, "Telephone Shoe", 5f, 12.60f)); + productsList.add(createProductItem(8, "Ice Tea Clock", 14f, 33.90f)); + productsList.add(createProductItem(10, "Telephone Ice Tea", 2f, 30.60f)); + productsList.add(createProductItem(11, "Telephone Iron", 17f, 13.20f)); + productsList.add(createProductItem(12, "Clock Ice Tea", 17f, 50.40f)); + productsList.add(createProductItem(14, "Telephone Iron", 15f, 18.60f)); + productsList.add(createProductItem(23, "Shoe Chair", 10f, 11.40f)); + productsList.add(createProductItem(24, "Chair Shoe", 16f, 10.80f)); + productsList.add(createProductItem(26, "Shoe Shoe", 39f, 75.60f)); + productsList.add(createProductItem(30, "Shoe Iron", 19f, 34.80f)); + productsList.add(createProductItem(31, "Ice Tea Telephone", 2f, 7.20f)); + productsList.add(createProductItem(33, "Iron Chair", 10f, 27.30f)); + productsList.add(createProductItem(35, "Telephone Shoe", 17f, 11.40f)); + productsList.add(createProductItem(36, "Ice Tea Iron", 24f, 4.80f)); + productsList.add(createProductItem(38, "Clock Ice Tea", 3f, 32.40f)); + productsList.add(createProductItem(41, "Clock Ice Tea", 10f, 30.90f)); + productsList.add(createProductItem(48, "Clock Clock", 4f, 31.50f)); + productsList.add(createProductItem(49, "Iron Iron", 23f, 3.30f)); + productsList.add(createProductItem(0, "Iron Iron", 3f, 8.10f)); + productsList.add(createProductItem(1, "Chair Shoe", 4f, 37.20f)); + productsList.add(createProductItem(4, "Ice Tea Shoe", 48f, 57.60f)); + productsList.add(createProductItem(5, "Clock Clock", 12f, 35.40f)); + productsList.add(createProductItem(6, "Ice Tea Chair", 23f, 14.70f)); + productsList.add(createProductItem(7, "Telephone Shoe", 5f, 12.60f)); + productsList.add(createProductItem(8, "Ice Tea Clock", 14f, 33.90f)); + productsList.add(createProductItem(10, "Telephone Ice Tea", 2f, 30.60f)); + productsList.add(createProductItem(11, "Telephone Iron", 17f, 13.20f)); + productsList.add(createProductItem(12, "Clock Ice Tea", 17f, 50.40f)); + productsList.add(createProductItem(14, "Telephone Iron", 15f, 18.60f)); + productsList.add(createProductItem(23, "Shoe Chair", 10f, 11.40f)); + productsList.add(createProductItem(24, "Chair Shoe", 16f, 10.80f)); + productsList.add(createProductItem(26, "Shoe Shoe", 39f, 75.60f)); + productsList.add(createProductItem(30, "Shoe Iron", 19f, 34.80f)); + productsList.add(createProductItem(31, "Ice Tea Telephone", 2f, 7.20f)); + productsList.add(createProductItem(33, "Iron Chair", 10f, 27.30f)); + productsList.add(createProductItem(35, "Telephone Shoe", 17f, 11.40f)); + productsList.add(createProductItem(36, "Ice Tea Iron", 24f, 4.80f)); + productsList.add(createProductItem(38, "Clock Ice Tea", 3f, 32.40f)); + productsList.add(createProductItem(41, "Clock Ice Tea", 10f, 30.90f)); + productsList.add(createProductItem(48, "Clock Clock", 4f, 31.50f)); + productsList.add(createProductItem(49, "Iron Iron", 23f, 3.30f)); + productsList.add(createProductItem(0, "Iron Iron", 3f, 8.10f)); + productsList.add(createProductItem(1, "Chair Shoe", 4f, 37.20f)); + productsList.add(createProductItem(4, "Ice Tea Shoe", 48f, 57.60f)); + productsList.add(createProductItem(5, "Clock Clock", 12f, 35.40f)); + productsList.add(createProductItem(6, "Ice Tea Chair", 23f, 14.70f)); + productsList.add(createProductItem(7, "Telephone Shoe", 5f, 12.60f)); + productsList.add(createProductItem(8, "Ice Tea Clock", 14f, 33.90f)); + productsList.add(createProductItem(10, "Telephone Ice Tea", 2f, 30.60f)); + productsList.add(createProductItem(11, "Telephone Iron", 17f, 13.20f)); + productsList.add(createProductItem(12, "Clock Ice Tea", 17f, 50.40f)); + productsList.add(createProductItem(14, "Telephone Iron", 15f, 18.60f)); + productsList.add(createProductItem(23, "Shoe Chair", 10f, 11.40f)); + productsList.add(createProductItem(24, "Chair Shoe", 16f, 10.80f)); + productsList.add(createProductItem(26, "Shoe Shoe", 39f, 75.60f)); + productsList.add(createProductItem(30, "Shoe Iron", 19f, 34.80f)); + productsList.add(createProductItem(31, "Ice Tea Telephone", 2f, 7.20f)); + productsList.add(createProductItem(33, "Iron Chair", 10f, 27.30f)); + productsList.add(createProductItem(35, "Telephone Shoe", 17f, 11.40f)); + productsList.add(createProductItem(36, "Ice Tea Iron", 24f, 4.80f)); + productsList.add(createProductItem(38, "Clock Ice Tea", 3f, 32.40f)); + productsList.add(createProductItem(41, "Clock Ice Tea", 10f, 30.90f)); + productsList.add(createProductItem(48, "Clock Clock", 4f, 31.50f)); + productsList.add(createProductItem(49, "Iron Iron", 23f, 3.30f)); + productsList.add(createProductItem(0, "Iron Iron", 3f, 8.10f)); + productsList.add(createProductItem(1, "Chair Shoe", 4f, 37.20f)); + productsList.add(createProductItem(4, "Ice Tea Shoe", 48f, 57.60f)); + productsList.add(createProductItem(5, "Clock Clock", 12f, 35.40f)); + productsList.add(createProductItem(6, "Ice Tea Chair", 23f, 14.70f)); + productsList.add(createProductItem(7, "Telephone Shoe", 5f, 12.60f)); + productsList.add(createProductItem(8, "Ice Tea Clock", 14f, 33.90f)); + productsList.add(createProductItem(10, "Telephone Ice Tea", 2f, 30.60f)); + productsList.add(createProductItem(11, "Telephone Iron", 17f, 13.20f)); + productsList.add(createProductItem(12, "Clock Ice Tea", 17f, 50.40f)); + productsList.add(createProductItem(14, "Telephone Iron", 15f, 18.60f)); + productsList.add(createProductItem(23, "Shoe Chair", 10f, 11.40f)); + productsList.add(createProductItem(24, "Chair Shoe", 16f, 10.80f)); + productsList.add(createProductItem(26, "Shoe Shoe", 39f, 75.60f)); + productsList.add(createProductItem(30, "Shoe Iron", 19f, 34.80f)); + productsList.add(createProductItem(31, "Ice Tea Telephone", 2f, 7.20f)); + productsList.add(createProductItem(33, "Iron Chair", 10f, 27.30f)); + productsList.add(createProductItem(35, "Telephone Shoe", 17f, 11.40f)); + productsList.add(createProductItem(36, "Ice Tea Iron", 24f, 4.80f)); + productsList.add(createProductItem(38, "Clock Ice Tea", 3f, 32.40f)); + productsList.add(createProductItem(41, "Clock Ice Tea", 10f, 30.90f)); + productsList.add(createProductItem(48, "Clock Clock", 4f, 31.50f)); + productsList.add(createProductItem(49, "Iron Iron", 23f, 3.30f)); + + return productsList; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static Object createProductItem(int id, String name, float quantity, float price) { + + Map map = new HashMap(); + map.put("Id", id); + map.put("Name", name); + map.put("Quantity", quantity); + map.put("Price", price); + return map; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static List getAddressAsMapList() { + + List addressList = new ArrayList(); + addressList.add(createAddressItem(9, "James", "Schneider", "277 Seventh Av.")); + addressList.add(createAddressItem(22, "Bill", "Ott", "250 - 20th Ave.")); + return addressList; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static List getAddress2AsMapList() { + + List addressList = new ArrayList(); + addressList.add(createAddressItem(23, "Julia", "Heiniger", "358 College Av.")); + addressList.add(createAddressItem(22, "Bill", "Ott", "250 - 20th Ave.")); + addressList.add(createAddressItem(32, "Michael", "Ott", "339 College Av.")); + return addressList; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + private static Object createAddressItem(int id, String firstName, String lastName, String street) { + + Map map = new HashMap(); + map.put("Id", id); + map.put("FirstName", firstName); + map.put("LastName", lastName); + map.put("Street", street); + return map; + } +} diff --git a/modules/reporting/src/test/resources/ConcatenatedReportingTest/SimpleReportTest.jrxml b/modules/reporting/src/test/resources/ConcatenatedReportingTest/SimpleReportTest.jrxml new file mode 100644 index 00000000..ce8fa9c0 --- /dev/null +++ b/modules/reporting/src/test/resources/ConcatenatedReportingTest/SimpleReportTest.jrxml @@ -0,0 +1,120 @@ + + + + + + + + + + $V{PAGE_NUMBER} + $P{PAGES_INIT_NUM} + + + + + + <band height="72"> + <frame> + <reportElement mode="Opaque" x="-20" y="-20" width="595" height="92" backcolor="#CC99FF"/> + <textField> + <reportElement x="20" y="20" width="234" height="43" forecolor="#FFFFFF"/> + <textElement> + <font size="34" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$P{ReportTitle}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="395" y="43" width="180" height="20" forecolor="#FFFFFF"/> + <textElement textAlignment="Right"> + <font size="14" isBold="false"/> + </textElement> + <textFieldExpression><![CDATA[$P{ReportDescription}]]></textFieldExpression> + </textField> + </frame> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/reporting/src/test/resources/ReportingTest/reportingtest.jrxml b/modules/reporting/src/test/resources/ReportingTest/reportingtest.jrxml new file mode 100644 index 00000000..c3f1bf97 --- /dev/null +++ b/modules/reporting/src/test/resources/ReportingTest/reportingtest.jrxml @@ -0,0 +1,116 @@ + + + + + + + + + + + + <band height="72"> + <frame> + <reportElement mode="Opaque" x="-20" y="-20" width="595" height="92" backcolor="#006699"/> + <textField> + <reportElement x="20" y="20" width="234" height="43" forecolor="#FFFFFF"/> + <textElement> + <font size="34" isBold="true"/> + </textElement> + <textFieldExpression><![CDATA[$P{ReportTitle}]]></textFieldExpression> + </textField> + <textField> + <reportElement x="395" y="43" width="180" height="20" forecolor="#FFFFFF"/> + <textElement textAlignment="Right"> + <font size="14" isBold="false"/> + </textElement> + <textFieldExpression><![CDATA[$P{ReportDescription}]]></textFieldExpression> + </textField> + </frame> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/reporting/src/test/resources/SubreportingTest/AddressReport.jrxml b/modules/reporting/src/test/resources/SubreportingTest/AddressReport.jrxml new file mode 100644 index 00000000..21d1c09b --- /dev/null +++ b/modules/reporting/src/test/resources/SubreportingTest/AddressReport.jrxml @@ -0,0 +1,134 @@ + + +