ro.nextreports.engine.ReportRunner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nextreports-engine Show documentation
Show all versions of nextreports-engine Show documentation
NextReports Engine is a lightweight Java platform development library which
can be used to run NextReports inside your applications.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ro.nextreports.engine;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.sql.Connection;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import ro.nextreports.engine.exporter.AlarmExporter;
import ro.nextreports.engine.exporter.Alert;
import ro.nextreports.engine.exporter.CsvExporter;
import ro.nextreports.engine.exporter.DisplayExporter;
import ro.nextreports.engine.exporter.DocxExporter;
import ro.nextreports.engine.exporter.ExporterBean;
import ro.nextreports.engine.exporter.HtmlExporter;
import ro.nextreports.engine.exporter.IndicatorExporter;
import ro.nextreports.engine.exporter.PdfExporter;
import ro.nextreports.engine.exporter.ReportTableExporter;
import ro.nextreports.engine.exporter.ResultExporter;
import ro.nextreports.engine.exporter.RtfExporter;
import ro.nextreports.engine.exporter.TsvExporter;
import ro.nextreports.engine.exporter.TxtExporter;
import ro.nextreports.engine.exporter.XlsExporter;
import ro.nextreports.engine.exporter.XlsxExporter;
import ro.nextreports.engine.exporter.XmlExporter;
import ro.nextreports.engine.exporter.event.ExporterEventListener;
import ro.nextreports.engine.exporter.exception.NoDataFoundException;
import ro.nextreports.engine.exporter.util.AlarmData;
import ro.nextreports.engine.exporter.util.DisplayData;
import ro.nextreports.engine.exporter.util.IndicatorData;
import ro.nextreports.engine.exporter.util.ParametersBean;
import ro.nextreports.engine.exporter.util.TableData;
import ro.nextreports.engine.querybuilder.sql.dialect.Dialect;
import ro.nextreports.engine.queryexec.Query;
import ro.nextreports.engine.queryexec.QueryExecutor;
import ro.nextreports.engine.queryexec.QueryParameter;
import ro.nextreports.engine.queryexec.QueryResult;
import ro.nextreports.engine.util.DialectUtil;
import ro.nextreports.engine.util.QueryUtil;
import ro.nextreports.engine.util.ReportUtil;
//
// Created by IntelliJ IDEA.
// User: mihai.panaitescu
// Date: Feb 3, 2009
// Time: 2:42:51 PM
//
/** Utilities class to run a report
*/
public class ReportRunner implements Runner {
/** PDF output format */
public static final String PDF_FORMAT = "PDF";
/** EXCEL output format */
public static final String EXCEL_FORMAT = "EXCEL";
/** EXCEL XLSX output format */
public static final String EXCEL_XLSX_FORMAT = "EXCELX";
/** HTML output format */
public static final String HTML_FORMAT = "HTML";
/** RTF output format */
public static final String RTF_FORMAT = "RTF";
/** DOCX output format */
public static final String DOCX_FORMAT = "DOCX";
/** CSV output format */
public static final String CSV_FORMAT = "CSV";
/** TSV output format */
public static final String TSV_FORMAT = "TSV";
/** TXT output format */
public static final String TXT_FORMAT = "TXT";
/** XML output format */
public static final String XML_FORMAT = "XML";
/** Array of all output persistent formats */
public static final String[] FORMATS = { PDF_FORMAT, EXCEL_FORMAT, EXCEL_XLSX_FORMAT, HTML_FORMAT, DOCX_FORMAT, RTF_FORMAT,
CSV_FORMAT, TSV_FORMAT, TXT_FORMAT, XML_FORMAT };
/** Memory table output format */
public static final String TABLE_FORMAT = "TABLE";
/** Memory alarm output format */
public static final String ALARM_FORMAT = "ALARM";
/** Memory indicator output format */
public static final String INDICATOR_FORMAT = "INDICATOR";
/** Memory display output format */
public static final String DISPLAY_FORMAT = "DISPLAY";
private Connection connection;
private Dialect dialect;
private Report report;
private Map parameterValues = new HashMap();
private String format;
private int queryTimeout = 600; // seconds
private ResultExporter exporter;
private boolean cancelled = false;
private boolean count = false;
private List listenerList = new ArrayList();
private String chartImagePath;
private List alerts;
private boolean csv = false;
// to write excel in a existing template, in a specific sheet (other sheets may contain calculations on data sheet)
private String templateName;
private int sheetNumber;
// for TABLE_FORMAT we export raw data or formatted data
private boolean tableRawData = false;
private String language;
/** Get database connection
*
* @return database connection
*/
public Connection getConnection() {
return connection;
}
/** Set database connection
*
* @param connection database connection
*/
public void setConnection(Connection connection) {
setConnection(connection, false);
}
/** Set database connection
*
* @param connection database connection
* @param csv true for a csv file connection
*/
public void setConnection(Connection connection, boolean csv) {
this.connection = connection;
this.csv = csv;
try {
dialect = DialectUtil.getDialect(connection);
} catch (Exception e) {
e.printStackTrace();
}
if (report != null) {
if (this.report.getQuery() != null) {
report.getQuery().setDialect(dialect);
}
}
}
/** Get next report object
*
* @return next report object
*/
public Report getReport() {
return report;
}
/** Set next report object
*
* @param report next report object
*/
public void setReport(Report report) {
this.report = report;
if (this.report.getQuery() != null) {
this.report.getQuery().setDialect(dialect);
}
}
/** Get parameters values
*
* @return parameters values
*/
public Map getParameterValues() {
return parameterValues;
}
/** Set parameters values
* parameterValues is a map of parameters values where the key is the parameter name
* and the value is the parameter value(s)
* Such parameter value can be a simple java object if the parameter has SINGLE SELECTION,
* or in case of MULTIPLE SELECTION value is an array Object[] of java objects. For an empty
* list of values , the value must be : new Object[]{ParameterUtil.NULL}
*
* If we programatically add value(s) in parameterValues for a hidden parameter, the default values
* for that hidden parameter will be ignored and the engine will use those from the map.
*
* @param parameterValues parameters values
*/
public void setParameterValues(Map parameterValues) {
this.parameterValues = parameterValues;
}
/** Get output format
*
* @return output format
*/
public String getFormat() {
return format;
}
/** Set output format
*
* @param format output format
*/
public void setFormat(String format) {
this.format = format;
}
/** Get query execution timeout
*
* @return query execution timeout in seconds
*/
public int getQueryTimeout() {
return queryTimeout;
}
/** Set query execution timeout
*
* @param queryTimeout query execution timeout in seconds
*/
public void setQueryTimeout(int queryTimeout) {
this.queryTimeout = queryTimeout;
}
/** See if we want to compute count
*
* @return true if count will be computed, false otrherwise
*/
public boolean isCount() {
return count;
}
/** Set compute count
*
* @param count true for computing count
*/
public void setCount(boolean count) {
this.count = count;
}
/** Set a list of alert object for report of type alarm
*
* @param alerts list of alert object
*/
public void setAlerts(List alerts) {
if (format == null) {
throw new IllegalStateException("You have to use setFormat with a valid output format before using setAlert!");
}
if (!ALARM_FORMAT.equals(format) && !INDICATOR_FORMAT.equals(format) && !DISPLAY_FORMAT.equals(format)) {
throw new IllegalStateException("You can use setAlert only for ALARM, INDICATOR or DISPLAY output formats!");
}
this.alerts = alerts;
}
/** Export the current report to the TABLE memory format
*
* @throws ReportRunnerException if FluentReportRunner object is not correctly configured
* @return true if export process finished, or false if export process was stopped
*
* @throws NoDataFoundException if report has no data
*/
public boolean run() throws ReportRunnerException,
NoDataFoundException {
return run(null);
}
/** Execute query
* This method is useful in case you are not interested about report layout,
* but only query and you want to make your own business.
*
* @return QueryResult object
*
* @throws ReportRunnerException if Runner object is not correctly configured
* @throws InterruptedException if process was interrupted
*/
public QueryResult executeQuery() throws ReportRunnerException, InterruptedException {
if (connection == null) {
throw new ReportRunnerException("Connection is null!");
}
if (report == null) {
throw new ReportRunnerException("Report is null!");
}
String sql = getSql();
// retrieves the report parameters
Map parameters = getReportParameters();
if (QueryUtil.restrictQueryExecution(sql)) {
throw new ReportRunnerException("You are not allowed to execute queries that modify the database!");
}
if (QueryUtil.isProcedureCall(sql)) {
if (!QueryUtil.isValidProcedureCall(sql, dialect)) {
throw new ReportRunnerException("Invalid procedure call! Must be of form 'call (${P1}, ?)'");
}
}
QueryResult queryResult = null;
try {
Query query = getQuery(sql);
QueryExecutor executor = new QueryExecutor(query, parameters, parameterValues, connection, count, true, csv);
executor.setMaxRows(0);
executor.setTimeout(queryTimeout);
queryResult = executor.execute();
return queryResult;
} catch (Exception e) {
throw new ReportRunnerException(e);
}
}
/** Export the current report to the specified output format
*
* @param stream output stream to write the exported report
* @throws ReportRunnerException if FluentReportRunner object is not correctly configured
* @return true if export process finished, or false if export process was stopped
*
* @throws NoDataFoundException if report has no data
*/
public boolean run(OutputStream stream) throws ReportRunnerException, NoDataFoundException {
if ((stream == null) && !TABLE_FORMAT.equals(format) && !ALARM_FORMAT.equals(format) && !INDICATOR_FORMAT.equals(format) && !DISPLAY_FORMAT.equals(format)) {
throw new ReportRunnerException("OutputStream cannot be null!");
}
if ((stream != null) && TABLE_FORMAT.equals(format)) {
throw new ReportRunnerException("TABLE FORMAT does not need an output stream. Use run() method instead.");
}
if ((stream != null) && ALARM_FORMAT.equals(format)) {
throw new ReportRunnerException("ALARM FORMAT does not need an output stream. Use run() method instead.");
}
if ((stream != null) && INDICATOR_FORMAT.equals(format)) {
throw new ReportRunnerException("INDICATOR FORMAT does not need an output stream. Use run() method instead.");
}
if ((stream != null) && DISPLAY_FORMAT.equals(format)) {
throw new ReportRunnerException("DISPLAY FORMAT does not need an output stream. Use run() method instead.");
}
if (!formatAllowed(format)) {
throw new ReportRunnerException("Unsupported format : " + format + " !");
}
QueryResult queryResult = null;
try {
queryResult = executeQuery();
String sql = getSql();
ParametersBean bean = new ParametersBean(getQuery(sql), getReportParameters(), parameterValues);
ReportLayout convertedLayout = ReportUtil.getDynamicReportLayout(connection, report.getLayout(), bean);
boolean isProcedure = QueryUtil.isProcedureCall(sql);
ExporterBean eb = new ExporterBean(connection, queryTimeout, queryResult, stream, convertedLayout,
bean, report.getBaseName(), false, alerts, isProcedure);
if (language != null) {
eb.setLanguage(language);
}
createExporter(eb);
return exporter.export();
} catch (NoDataFoundException e) {
throw e;
} catch (Exception e) {
throw new ReportRunnerException(e);
} finally {
if (queryResult != null) {
queryResult.close();
}
}
}
private String getSql() throws ReportRunnerException {
String sql = report.getSql();
if (sql == null) {
// get sql from SelectQuery object (report built with next reporter !)
sql = report.getQuery().toString();
}
if (sql == null) {
throw new ReportRunnerException("Report sql expression not found");
} else {
return sql;
}
}
private Query getQuery(String sql) {
return new Query(sql);
}
private Map getReportParameters() {
Map parameters = new LinkedHashMap();
List parameterList = report.getParameters();
if (parameterList != null) {
for (QueryParameter param : parameterList) {
parameters.put(param.getName(), param);
}
}
return parameters;
}
private boolean formatAllowed(String format) {
if (TABLE_FORMAT.equals(format) || ALARM_FORMAT.equals(format) || INDICATOR_FORMAT.equals(format) || DISPLAY_FORMAT.equals(format)) {
return true;
}
for (String f : FORMATS) {
if (f.equals(format)) {
return true;
}
}
return false;
}
private void createExporter(ExporterBean bean) {
bean.setLanguage(language);
if (TABLE_FORMAT.equals(format)) {
bean.setConnection(null);
bean.setQueryTimeout(0);
bean.setOut(new ByteArrayOutputStream());
bean.setReportTableExporterRawData(tableRawData);
exporter = new ReportTableExporter(bean);
} else if (ALARM_FORMAT.equals(format)) {
bean.setConnection(null);
bean.setQueryTimeout(0);
bean.setOut(new ByteArrayOutputStream());
exporter = new AlarmExporter(bean);
} else if (INDICATOR_FORMAT.equals(format)) {
bean.setConnection(null);
bean.setQueryTimeout(0);
bean.setOut(new ByteArrayOutputStream());
exporter = new IndicatorExporter(bean);
} else if (DISPLAY_FORMAT.equals(format)) {
bean.setConnection(null);
bean.setQueryTimeout(0);
bean.setOut(new ByteArrayOutputStream());
exporter = new DisplayExporter(bean);
} else if (PDF_FORMAT.equals(format)) {
exporter = new PdfExporter(bean);
} else if (DOCX_FORMAT.equals(format)) {
exporter = new DocxExporter(bean);
} else if (CSV_FORMAT.equals(format)) {
exporter = new CsvExporter(bean);
} else if (TSV_FORMAT.equals(format)) {
exporter = new TsvExporter(bean);
} else if (TXT_FORMAT.equals(format)) {
exporter = new TxtExporter(bean);
} else if (EXCEL_FORMAT.equals(format)) {
exporter = new XlsExporter(bean);
} else if (EXCEL_XLSX_FORMAT.equals(format)) {
exporter = new XlsxExporter(bean);
} else if (RTF_FORMAT.equals(format)) {
exporter = new RtfExporter(bean);
} else if (XML_FORMAT.equals(format)) {
exporter = new XmlExporter(bean);
} else {
exporter = new HtmlExporter(bean);
}
exporter.setDocumentTitle(report.getBaseName());
for (ExporterEventListener listener : listenerList) {
exporter.addExporterEventListener(listener);
}
exporter.setImageChartPath(getChartImagePath());
}
/** Stop the export process
*/
public void stop() {
if (exporter != null) {
cancelled = true;
exporter.setStopExport(true);
}
}
/** See if export process was cancelled
*
* @return true if current process was cancelled, false otherwise
*/
public boolean isCancelled() {
return cancelled;
}
/** Add an exporter event listener
*
* @param listener exporter event listener
*/
public void addExporterEventListener(ExporterEventListener listener) {
listenerList.add(listener);
}
/** Remove an exporter event listener
*
* @param listener exporter event listener
*/
public void removeExporterEventListener(ExporterEventListener listener) {
listenerList.remove(listener);
if (exporter != null) {
exporter.removeExporterEventListener(listener);
}
}
/** Get table data TABLE exporter
*
* @return table data for TABLE exporter
*/
public TableData getTableData() {
if (TABLE_FORMAT.equals(format)) {
TableExporter tableExporter = (TableExporter)exporter;
return tableExporter.getTableData();
} else {
return new TableData();
}
}
/** Get alarm data ALARM exporter
*
* @return alarm data for ALARM exporter
*/
public AlarmData getAlarmData() {
if (ALARM_FORMAT.equals(format)) {
AlarmExporter alarmExporter = (AlarmExporter)exporter;
return alarmExporter.getData();
} else {
return new AlarmData();
}
}
/** Get indicator data INDICATOR exporter
*
* @return indicator data for INDICATOR exporter
*/
public IndicatorData getIndicatorData() {
if (INDICATOR_FORMAT.equals(format)) {
IndicatorExporter ie = (IndicatorExporter)exporter;
return ie.getData();
} else {
return new IndicatorData();
}
}
/** Get display data DISPLAY exporter
*
* @return display data for DISPLAY exporter
*/
public DisplayData getDisplayData() {
if (DISPLAY_FORMAT.equals(format)) {
DisplayExporter de = (DisplayExporter)exporter;
return de.getData();
} else {
return new DisplayData();
}
}
public String getChartImagePath() {
return chartImagePath;
}
public void setChartImagePath(String chartImagePath) {
this.chartImagePath = chartImagePath;
}
public String getTemplateName() {
return templateName;
}
public void setTemplateName(String templateName) {
this.templateName = templateName;
}
public int getSheetNumber() {
return sheetNumber;
}
public void setSheetNumber(int sheetNumber) {
this.sheetNumber = sheetNumber;
}
/** Get language for internationalization
*
* @return language for internationalization
*/
public String getLanguage() {
return language;
}
/** Set language for internationalization
*
* Language string is computed as :
* locale.getLanguage() + "_" + locale.getCountry()
*
* @param language language for internationalization
*/
public void setLanguage(String language) {
this.language = language;
}
public boolean isTableRawData() {
return tableRawData;
}
public void setTableRawData(boolean tableRawData) {
this.tableRawData = tableRawData;
}
}