edu.ku.brc.specify.web.JasperReportHelper.java Source code

Java tutorial

Introduction

Here is the source code for edu.ku.brc.specify.web.JasperReportHelper.java

Source

/* Copyright (C) 2015, University of Kansas Center for Research
 * 
 * Specify Software Project, specify@ku.edu, Biodiversity Institute,
 * 1345 Jayhawk Boulevard, Lawrence, Kansas, 66045, USA
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package edu.ku.brc.specify.web;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Vector;

import javax.swing.JLabel;

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.fill.AsynchronousFillHandle;
import net.sf.jasperreports.engine.fill.AsynchronousFilllListener;
import net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory;
import net.sf.jasperreports.engine.util.JRLoader;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.hibernate.Session;

import edu.ku.brc.af.core.AppContextMgr;
import edu.ku.brc.af.core.AppResourceIFace;
import edu.ku.brc.af.core.db.DBTableIdMgr;
import edu.ku.brc.dbsupport.DBConnection;
import edu.ku.brc.dbsupport.HibernateUtil;
import edu.ku.brc.dbsupport.RecordSetIFace;
import edu.ku.brc.specify.tasks.subpane.JasperReportsCache;
import edu.ku.brc.specify.tasks.subpane.ReportCompileInfo;

/**
 * @author rod
 *
 * @code_status Alpha
 *
 * Apr 29, 2008
 *
 */
public class JasperReportHelper implements AsynchronousFilllListener, JasperCompilerListener {
    private static final Logger log = Logger.getLogger(JasperReportHelper.class);

    // Data Members
    protected JasperReportHelperListener listener;
    protected boolean isAsynchronous;

    protected AsynchronousFillHandle asyncFillHandler = null;
    protected JLabel label = null;
    protected JasperCompilerRunnable compiler = null;

    protected RecordSetIFace recordSet = null;
    protected JRDataSource dataSource = null;
    protected File cachePath = null;

    protected Properties params = null;
    protected boolean requiresHibernate = false;
    protected Session session = null;

    /**
     * Constructor.
     * @param listener
     * @param isAsynchronous
     */
    public JasperReportHelper(final JasperReportHelperListener listener, final boolean isAsynchronous) {
        this.listener = listener;
        this.isAsynchronous = isAsynchronous;

        cachePath = JasperReportsCache.checkAndCreateReportsCache();

        // Checks for out of date Labels / Reports
        // and copies them over to the cache for compiling
        JasperReportsCache.refreshCacheFromDatabase();
    }

    /**
     * Starts the report creation process
     * @param fileName the XML file name of the report definition
     * @param recrdSet the recordset to use to fill the labels
     * @param paramsArg parameters for the report
    */
    public void createReport(final String mainReportName, final Object data, final Properties paramsArg) {
        if (data instanceof RecordSetIFace) {
            this.recordSet = (RecordSetIFace) data;
            this.dataSource = null;

        } else if (data instanceof JRDataSource) {
            this.recordSet = null;
            this.dataSource = (JRDataSource) data;
        }
        this.params = paramsArg;

        JasperReportsCache.refreshCacheFromDatabase();

        Vector<File> reportFiles = new Vector<File>();
        AppResourceIFace appRes = AppContextMgr.getInstance().getResource(mainReportName);
        if (appRes != null) {
            String subReportsStr = appRes.getMetaData("subreports");
            String hqlStr = appRes.getMetaData("hql");

            if (StringUtils.isNotEmpty(hqlStr)) {
                requiresHibernate = Boolean.parseBoolean(hqlStr.toLowerCase());
            }

            if (StringUtils.isNotEmpty(subReportsStr)) {
                String[] subReportNames = subReportsStr.split(",");
                for (String subReportName : subReportNames) {
                    AppResourceIFace subReportAppRes = AppContextMgr.getInstance().getResource(subReportName);
                    if (subReportAppRes != null) {
                        File subReportPath = new File(cachePath.getAbsoluteFile() + File.separator + subReportName);
                        if (subReportPath.exists()) {
                            reportFiles.add(subReportPath);

                        } else {
                            throw new RuntimeException(
                                    "Subreport doesn't exist on disk [" + subReportPath.getAbsolutePath() + "]");
                        }

                    } else {
                        throw new RuntimeException("Couldn't load subreport [" + mainReportName + "]"); // ??
                    }
                }
            }

            File reportPath = new File(cachePath.getAbsoluteFile() + File.separator + mainReportName);
            if (reportPath.exists()) {
                reportFiles.add(reportPath);

            } else {
                throw new RuntimeException(
                        "Subreport doesn't exist on disk [" + reportPath.getAbsolutePath() + "]");
            }

        } else {
            throw new RuntimeException("Couldn't load report/label [" + mainReportName + "]");
        }

        boolean allAreCompiled = true;
        Vector<ReportCompileInfo> files = new Vector<ReportCompileInfo>();
        for (File file : reportFiles) {
            ReportCompileInfo info = JasperReportsCache.checkReport(file);
            files.add(info);
            if (!info.isCompiled()) {
                allAreCompiled = false;
            }
        }

        // Check to see if it needs to be recompiled, if it doesn't need compiling then
        // call "compileComplete" directly to have it start filling the labels
        // otherswise create the compiler runnable and have it be compiled 
        // asynchronously
        if (allAreCompiled) {
            System.out.println("Everything is compiled");

            this.compileComplete(files.get(files.size() - 1).getCompiledFile());

        } else {
            System.out.println("About to Compile " + isAsynchronous);
            //progressLabel.setText(getResourceString("JasperReportCompiling"));
            compiler = new JasperCompilerRunnable(this, files);
            if (isAsynchronous) {
                compiler.start();
            } else {
                compiler.run();
            }
        }
    }

    /**
     * The compiling of the report is complete
     * @param report the completeed report, or null if there was a compiling error
     */
    public void compileComplete(final File compiledFile) {
        if (compiledFile != null) {
            try {
                System.out.println("Creating report...");

                JasperReport jasperReport = (JasperReport) JRLoader.loadObject(compiledFile.getAbsoluteFile());
                if (jasperReport != null) {
                    System.out.println("Loaded report...");

                    Map<String, Object> parameters = new HashMap<String, Object>();

                    parameters.put("RPT_IMAGE_DIR", JasperReportsCache.getImagePath().getAbsolutePath());
                    parameters.put("SUBREPORT_DIR", cachePath.getAbsoluteFile() + File.separator);
                    parameters.put("DATASOURCE", dataSource);

                    if (recordSet != null) {
                        parameters.put("itemnum", DBTableIdMgr.getInstance().getInClause(recordSet));
                    }

                    // Add external parameters
                    if (params != null) {
                        for (Object key : params.keySet()) {
                            //System.out.println("key["+key+"]  Val["+params.get(key)+"]");
                            parameters.put(key.toString(), params.get(key));
                        }
                    }

                    // XXX What about losing a connection here?
                    if (requiresHibernate) {
                        session = HibernateUtil.getNewSession();
                        parameters.put(JRHibernateQueryExecuterFactory.PARAMETER_HIBERNATE_SESSION, session);
                    }

                    if (isAsynchronous) {
                        System.out.println("Filling report asynchronously...");

                        //progressLabel.setText(getResourceString("JasperReportFilling"));
                        if (recordSet != null) {
                            asyncFillHandler = AsynchronousFillHandle.createHandle(jasperReport, parameters,
                                    DBConnection.getInstance().getConnection());
                        } else {
                            asyncFillHandler = AsynchronousFillHandle.createHandle(jasperReport, parameters,
                                    dataSource);
                        }
                        asyncFillHandler.addListener(this);
                        asyncFillHandler.startFill();

                    } else {
                        System.out.println("Filling report synchronously...");
                        JasperPrint jasperPrint;
                        if (recordSet != null) {
                            jasperPrint = JasperFillManager.fillReport(jasperReport, parameters,
                                    DBConnection.getInstance().getConnection());
                        } else {
                            jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
                        }

                        if (jasperPrint != null) {
                            listener.complete(jasperPrint);
                        } else {
                            listener.completedWithError();
                        }
                    }

                } else {
                    log.error("jasperReport came back null [" + compiledFile.getAbsolutePath() + "]");
                    //progressBar.setIndeterminate(false);
                    //setLabelText(getResourceString("JasperReportReadingCachedReport"));
                }

            } catch (JRException ex) {
                edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(JasperReportHelper.class, ex);
                //setLabelText(getResourceString("JasperReportCreatingViewer"));
                log.error(ex);
                ex.printStackTrace();
            }
        } else {
            //setLabelText(getResourceString("JasperReportCompileError"));
        }
        compiler = null;
    }

    //------------------------------------------------------------
    // AsynchronousFilllListener
    //------------------------------------------------------------

    /* (non-Javadoc)
     * @see net.sf.jasperreports.engine.fill.AsynchronousFilllListener#reportCancelled()
     */
    public void reportCancelled() {
        asyncFillHandler = null;
    }

    protected void closeSession() {

        if (session != null) {
            try {
                session.close();

            } catch (Exception ex) {
                edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(JasperReportHelper.class, ex);
                log.error(ex);
            }
        }
    }

    /* (non-Javadoc)
     * @see net.sf.jasperreports.engine.fill.AsynchronousFilllListener#reportFillError(java.lang.Throwable)
     */
    public void reportFillError(java.lang.Throwable t) {
        //removeAll();
        //setLabelText(getResourceString("JasperReportFillError"));

        log.error(t);
        t.printStackTrace();
        asyncFillHandler = null;
        closeSession();
    }

    /* (non-Javadoc)
     * @see net.sf.jasperreports.engine.fill.AsynchronousFilllListener#reportFinished(net.sf.jasperreports.engine.JasperPrint)
     */
    public void reportFinished(JasperPrint print) {
        try {

            listener.complete(print);

            //?? JRViewer jasperViewer = new JRViewer(print);

            // ?? add(jasperViewer, BorderLayout.CENTER);

            // ?? UIRegistry.forceTopFrameRepaint();

            closeSession();

        } catch (Exception ex) {
            edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
            edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(JasperReportHelper.class, ex);
            log.error(ex);
            ex.printStackTrace();
        }
        asyncFillHandler = null;
    }

    //------------------------------------------------------------
    // Inner Classes
    //------------------------------------------------------------

    public interface JasperReportHelperListener {
        /**
         * @param compiledFile
         */
        public abstract void complete(final JasperPrint jasperPrint);

        /**
         * @param status
         */
        public abstract void status(final int status);

        /**
         * 
         */
        public abstract void completedWithError();
    }

    public class JasperCompilerRunnable implements Runnable {
        protected Thread thread;
        protected JasperCompilerListener compileListener;
        protected Vector<ReportCompileInfo> files;

        /**
         * Constructs a an object to execute an SQL statement and then notify the listener
         * @param listener the listener
         * @param reportFile the file that contains the report
         * @param compiledFile the file that will contain the compiled report
         */
        public JasperCompilerRunnable(final JasperCompilerListener listener,
                final Vector<ReportCompileInfo> files) {
            this.compileListener = listener;
            this.files = files;
        }

        /**
         * Starts the thread to make the SQL call
         *
         */
        public void start() {
            thread = new Thread(this);
            thread.start();
        }

        /**
         * Stops the thread making the call
         *
         */
        public synchronized void stop() {
            if (thread != null) {
                thread.interrupt();
            }
            thread = null;
            notifyAll();
        }

        /**
         * Creates a connection, makes the call and returns the results
         */
        public void run() {
            try {
                for (ReportCompileInfo info : files) {
                    JasperCompileManager.compileReportToFile(info.getReportFile().getAbsolutePath(),
                            info.getCompiledFile().getAbsolutePath());
                }
                System.out.println("Done  Compiling...");
                compileListener.compileComplete(files.get(files.size() - 1).getCompiledFile());

            } catch (Exception ex) {
                edu.ku.brc.af.core.UsageTracker.incrHandledUsageCount();
                edu.ku.brc.exceptions.ExceptionTracker.getInstance().capture(JasperReportHelper.class, ex);
                log.error(ex);
                ex.printStackTrace();

                compileListener.compileComplete(null);
            }
            compileListener = null;
            files.clear();
            files = null;
        }
    }

}