All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ro.nextreports.engine.ReportRunner Maven / Gradle / Ivy

Go to download

NextReports Engine is a lightweight Java platform development library which can be used to run NextReports inside your applications.

There is a newer version: 9.2
Show newest version
/*
 * 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;
	}	
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy