webBoltOns.server.reportWriter.JRivetWriter.java Source code

Java tutorial

Introduction

Here is the source code for webBoltOns.server.reportWriter.JRivetWriter.java

Source

package webBoltOns.server.reportWriter;

/*
 * $Id: JRivetWriter.java,v 1.1 2007/04/20 19:37:20 paujones2005 Exp $ $Name:  $
 *
 *   Copyright  2004, 2005, 2006  www.jrivet.com  -   All Rights Reserved 
 * 
 *   @author P. Jones  
 *     @version 2.060719
 *
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the License.
 *
 * The Original Code is 'jRivet Framework - Java Solutions for Enterprise Applications'.
 *
 * The Initial Developer of the Original Code is Paul Jones.
 * 
 *  Copyright (C) 2004, 2005, 2006  by Paul Jones.
 *
 *  **All Rights Reserved **.
 *
 * Contributor(s): all the names of the contributors are added in the source code
 * where applicable.
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
 * provisions of LGPL are applicable instead of those above.  If you wish to
 * allow use of your version of this file only under the terms of the LGPL
 * License and not to allow others to use your version of this file under
 * the MPL, indicate your decision by deleting the provisions above and
 * replace them with the notice and other provisions required by the LGPL.
 * If you do not delete the provisions above, a recipient may use your version
 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the MPL as stated above or under the terms of the GNU
 * Library General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or any later version.
 *
 * This library 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 Library general Public License for more
 * details.
 *
 * If you didn't download this code from the following link, you should check if
 * you aren't using an obsolete version:
 *
 * http://www.jRivet.com/download/
 * 
 */

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import webBoltOns.dataContol.DataAccess;
import webBoltOns.dataContol.DataSet;

import com.lowagie.text.BadElementException;
import com.lowagie.text.Cell;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfDestination;
import com.lowagie.text.pdf.PdfOutline;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

/**
 * <h1>GenericReport</h1>
 * 
 * <p>
 *    the jRivet Framework Server-side PDF Report Generator -
 * </p>
 * 
 * 
 */
public class JRivetWriter extends GenericReport {

    private PdfContentByte contentByte;
    private Document document;
    private boolean newpage = true;
    private ByteArrayOutputStream outputStream;
    private int pageLength = 25;
    private PdfPTable reportBody;
    private Object[] reportColumns;
    private PdfOutline root;
    private int rowCount, totalRows;
    private ReportAccumulator topA, bottomA;
    private final Color totalColor = new Color(250, 250, 250), detailColor = Color.WHITE;
    private PdfWriter writer;
    private static final long serialVersionUID = 3411892708301107850L;

    /**
     * <h2><code>accumulateReportTotals</code></h2>
     * 
     * <p>
     *  accumulate all report totals, 
     *  calculate averages, minimums and maximums    
     * </p>
     * 
     * 
     * @param   String [] record - The record to accumulate
     * 
     */
    private void accumulateReportTotals(String record[]) {
        double totals[] = new double[reportColumns.length];
        for (int c = 0; c < reportColumns.length; c++) {
            ReportColumn column = (ReportColumn) reportColumns[c];

            if (column.isSubTotaled() || column.isSubMaximum() || column.isSubMinumum() || column.isSubAveraged())
                totals[c] = Double.parseDouble(record[c]);
        }
        bottomA.accumulateTotals(totals);
    }

    /**
     * <h2><code>buildBlankLine</code></h2>
     * 
     * <p>
     *  build a 'blank' line     
     * </p>
     */
    private void buildBlankLine() throws DocumentException {

        if (++rowCount < pageLength) {
            PdfPCell cell;
            for (int c = 0; c < reportColumns.length; c++) {
                cell = new PdfPCell(
                        new Paragraph(" ", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL)));
                cell.setBorder(0);
                cell.setBackgroundColor(totalColor);
                reportBody.addCell(cell);

            }
        }
    }

    /**
     * <h2><code>buildDetilLine</code></h2>
     * 
     * <p>
     *  create and print a detail line on the report    
     * </p>
     * 
     * 
     * @param   String [] record - report record to print
     * 
     */
    private void buildDetilLine(String[] record) throws DocumentException {
        newpage = isNewPage(++rowCount);
        PdfPCell cell;

        if (record != null) {
            for (int c = 0; c < reportColumns.length; c++) {
                ReportColumn column = (ReportColumn) reportColumns[c];
                String value = " ";

                if (record != null) {
                    if (column.getLevelBreak() > 0)
                        value = column.getAccumulator().getPrintValue(newpage);
                    else
                        value = record[c];
                }

                cell = new PdfPCell(
                        new Paragraph(value, FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL)));

                cell.setBorder(0);
                cell.setNoWrap(true);

                cell.setBackgroundColor(detailColor);

                if (column.getAlignment().equals(ReportColumn.LEFT))
                    cell.setHorizontalAlignment(Cell.ALIGN_LEFT);
                else if (column.getAlignment().equals(ReportColumn.RIGHT))
                    cell.setHorizontalAlignment(Cell.ALIGN_RIGHT);
                else
                    cell.setHorizontalAlignment(Cell.ALIGN_CENTER);

                reportBody.addCell(cell);

            }
        }
    }

    /**
     * <h2><code>buildReport</code></h2>
     * 
     * <p>
     *  Create the PDF report        
     * </p>
     * 
     * @param   ServletRequest request  - the HTTP request
     * @param   ServletResponse response - the HTTP respones
     * 
     */
    private void buildReport(ServletRequest request, ServletResponse response, DataSet reportTable) {
        try {

            rowCount = 999;
            totalRows = 0;
            document = new Document(PageSize.LEGAL.rotate());
            document.setMargins(8.0f, 8.0f, 8.0f, 18.0f);

            outputStream = new ByteArrayOutputStream();
            writer = PdfWriter.getInstance(document, outputStream);
            writer.setViewerPreferences(PdfWriter.PageModeUseOutlines);
            buildReportTitles(reportTable);

            document.open();

            contentByte = writer.getDirectContent();
            root = new PdfOutline(contentByte.getRootOutline(), new PdfDestination(PdfDestination.FIT), "Report");

            topA.setOutline(root);

            ResultSet resultSet;
            Statement statement = dataAccess.execConnectReadOnly();

            sql = new StringBuffer(reportTable.getStringField(ReportColumn.SQL_QUERY));

            sql = DataSet.removeFormat(sql, "\n");
            sql = DataSet.removeFormat(sql, "\t");

            Enumeration parameters = request.getParameterNames();
            while (parameters.hasMoreElements()) {
                String p = (String) parameters.nextElement();
                String v = request.getParameter(p);
                if (!p.equals("ReportScript") && !p.equals("") && !v.equals(""))
                    sql = mergeTagValues(sql, p, v);
            }

            resultSet = statement.executeQuery(sql.toString().trim());
            String[] record = new String[reportColumns.length];

            while (resultSet.next()) {
                for (int c = 0; c < reportColumns.length; c++) {
                    ReportColumn column = (ReportColumn) reportColumns[c];
                    String value = (String) DataAccess.getFieldValue(resultSet, column.getFeildName(),
                            column.getDataType());
                    record[c] = formatField(value, column.getDataType(), column.getDecimals());
                }

                topA.recursiveLevelBreaks(record);
                buildDetilLine(record);
                accumulateReportTotals(record);
                totalRows++;
            }

            if (totalRows == 0) {
                buildEmptyPage(request, response);

            } else {
                topA.fireGrandTotalBreak();
                resultSet.close();
                dataAccess.execClose(statement);
                document.add(reportBody);
                document.close();
                buildPDFReportPage(request, response, outputStream.toByteArray());
            }

        } catch (DocumentException e) {
            gs.log("** DocumentException: " + e);
            buildErrorPage(request, response, e.toString());
        } catch (IOException e) {
            gs.log("** IOException: " + e);
            buildErrorPage(request, response, e.toString());
        } catch (Exception e) {
            gs.log("** Exception: " + e);
            buildErrorPage(request, response, e.toString());
        }

    }

    /**
     * <h2><code>buildReportTitles</code></h2>
     * 
     * <p>
     *  Create the report headings        
     * </p>
     * 
     * @param   DataSet reportTable - the report data object
     * 
     */
    private void buildReportTitles(DataSet reportTable)
            throws DocumentException, BadElementException, MalformedURLException, IOException {

        Paragraph title = new Paragraph();

        title.add(Image.getInstance(dataAccess.getImagePath() + "reportLogo.gif"));
        title.add(new Chunk(
                new SimpleDateFormat("                           " + "hh:mm:ss - dd MMM yyyy").format(new Date()),
                FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL)));

        title.add(new Chunk("           " + reportTable.getStringField(ReportColumn.REPORT_TITLE),
                FontFactory.getFont(FontFactory.HELVETICA, 16, Font.BOLD)));

        HeaderFooter header = new HeaderFooter(title, false);
        header.setBorder(0);

        HeaderFooter footer = new HeaderFooter(
                new Phrase("page:", FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL)), true);
        footer.setAlignment(HeaderFooter.ALIGN_CENTER);

        document.setHeader(header);
        document.setFooter(footer);

        reportColumns = reportTable.getTableVector(ReportColumn.REPORT_DETAILS).toArray();

        topA = new ReportAccumulator(this, -1, reportColumns.length);
        bottomA = topA;

        reportBody = new PdfPTable(reportColumns.length);
        reportBody.setTotalWidth(1.100f);
        reportBody.setHeaderRows(1);

        float cW[] = new float[reportColumns.length];

        for (int c = 0; c < reportColumns.length; c++) {
            ReportColumn column = (ReportColumn) reportColumns[c];
            if (column.getLevelBreak() > 0) {
                ReportAccumulator r = new ReportAccumulator(this, c, reportColumns.length);
                bottomA.setChildAccumulator(r);
                r.setParentAccumulator(bottomA);
                column.setAccumulator(r);
                bottomA = r;
            }

            PdfPCell hdr = new PdfPCell(new Paragraph(column.getDescription(),
                    FontFactory.getFont(FontFactory.HELVETICA, 12, Font.BOLD)));

            hdr.setBorder(Rectangle.BOTTOM);
            if (column.getAlignment().equals(ReportColumn.LEFT))
                hdr.setHorizontalAlignment(Cell.ALIGN_LEFT);
            else if (column.getAlignment().equals(ReportColumn.RIGHT))
                hdr.setHorizontalAlignment(Cell.ALIGN_RIGHT);
            else
                hdr.setHorizontalAlignment(Cell.ALIGN_CENTER);

            reportBody.addCell(hdr);
            cW[c] = (float) column.getLength();
        }
        reportBody.setWidths(cW);
    }

    /**
     * <h2><code>buildTotalLine</code></h2>
     * 
     * <p>
     *  Create printed total lines        
     * </p>
     * 
     * @param   String[] record - A report total line
     * 
     */
    private void buildTotalLine(String[] record) throws DocumentException {
        ++rowCount;
        PdfPCell cell;

        if (record != null) {
            for (int c = 0; c < reportColumns.length; c++) {
                ReportColumn column = (ReportColumn) reportColumns[c];
                String value = record[c];

                cell = new PdfPCell(
                        new Paragraph(value, FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL)));

                cell.setBorder(0);
                cell.setNoWrap(true);

                cell.setBackgroundColor(totalColor);

                if (column.getAlignment().equals(ReportColumn.LEFT))
                    cell.setHorizontalAlignment(Cell.ALIGN_LEFT);
                else if (column.getAlignment().equals(ReportColumn.RIGHT))
                    cell.setHorizontalAlignment(Cell.ALIGN_RIGHT);
                else
                    cell.setHorizontalAlignment(Cell.ALIGN_CENTER);

                reportBody.addCell(cell);

            }
        }
    }

    /**
     * <h2><code>fireNewSection</code></h2>
     * 
     * <p>
     *  Executed by <code>ReportAccumulator</code> when a new section is 
     *  detected      
     * </p>
     * 
     * @param   ReportAccumulator ac - Source creating the new section. 
     * @param   String newValue - the value of the new section.
     * 
     */
    public void fireNewSection(ReportAccumulator ac, String newValue) {
        PdfOutline outLine = new PdfOutline(ac.getParentAccumulator().getOutline(),
                new PdfDestination(PdfDestination.FITH, 50), newValue);
        outLine.setOpen(false);
        ac.setOutline(outLine);
    }

    /**
     * <h2><code>fireTotalLine</code></h2>
     * 
     * <p>
     *  Executed by <code>ReportAccumulator</code> when a total line 
     *  needs to be printed on the report.  
     * </p>
     * 
     * @param   ReportAccumulator ac - Source of the total line. 
     * 
     */
    public void fireTotalLine(ReportAccumulator ac) throws DocumentException {
        int cl = ac.getColumnNumber();
        ReportColumn clc;
        if (cl > -1)
            clc = (ReportColumn) reportColumns[cl];
        else
            clc = null;

        String[] cntsRecord = new String[reportColumns.length];
        String[] totsRecord = new String[reportColumns.length];
        double[] tots = ac.getTotals();
        String[] maxsRecord = new String[reportColumns.length];
        double[] maxs = ac.getMaxs();
        String[] minsRecord = new String[reportColumns.length];
        double[] mins = ac.getMins();
        String[] avrsRecord = new String[reportColumns.length];
        double[] avrs = ac.getAvrs();
        int counts = ac.getCounters();
        boolean sb = false, mx = false, mn = false, av = false;

        for (int c = 0; c < reportColumns.length; c++) {
            ReportColumn column = (ReportColumn) reportColumns[c];

            if (c == 0 && cl == -1) {

                totsRecord[c] = " Grand-total:";
                maxsRecord[c] = " Maximum:";
                minsRecord[c] = " Minimum:";
                avrsRecord[c] = " Average:";

            } else if (c == cl) {
                cntsRecord[c] = "     Count: " + +counts;

                totsRecord[c] = "     Sub-total:";
                maxsRecord[c] = "     Maximum:";
                minsRecord[c] = "     Minimum:";
                avrsRecord[c] = "     Average:";

            } else {

                cntsRecord[c] = " ";

                if (column.isSubTotaled()) {
                    totsRecord[c] = formatField(Double.toString(tots[c]), column.getDataType(),
                            column.getDecimals());
                    sb = true;
                } else {
                    totsRecord[c] = " ";
                }

                if (column.isSubMaximum()) {
                    maxsRecord[c] = formatField(Double.toString(maxs[c]), column.getDataType(),
                            column.getDecimals());
                    mx = true;
                } else {
                    maxsRecord[c] = " ";
                }

                if (column.isSubMinumum()) {
                    minsRecord[c] = formatField(Double.toString(mins[c]), column.getDataType(),
                            column.getDecimals());
                    mn = true;
                } else {
                    minsRecord[c] = " ";
                }

                if (column.isSubAveraged()) {
                    avrsRecord[c] = formatField(Double.toString(avrs[c]), column.getDataType(),
                            column.getDecimals());
                    av = true;
                } else {
                    avrsRecord[c] = " ";
                }

            }
        }
        if (clc != null && clc.isSubCounted())
            buildTotalLine(cntsRecord);
        if (sb)
            buildTotalLine(totsRecord);
        if (mx)
            buildTotalLine(maxsRecord);
        if (mn)
            buildTotalLine(minsRecord);
        if (av)
            buildTotalLine(avrsRecord);
        buildBlankLine();
    }

    /**
     * <h2><code>getReportScript</code></h2>
     * 
     * <p>
     *  Request and retrieve the report XML from the server.  
     *  Execute the SQL query and build the report when the XML is returned    
     * </p>
     * 
     * @param  String scripName - Name of the XML containing the report script
     *
     * @return   DataSet - DataSet with the report layout
     * 
     */
    private DataSet getReportScript(String scripName) {
        DataSet reportTable;

        try {
            String script = dataAccess.getMenuPath() + scripName + ".xml";

            FileReader reader = new FileReader(new File(script));
            SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
            ReportHandler handler = new ReportHandler();
            sp.parse(new InputSource(reader), handler);
            reportTable = handler.getReportTable();

        } catch (FileNotFoundException e) {
            gs.log("** File Not Found Exception : " + e);
            return null;
        } catch (ParserConfigurationException e) {
            gs.log("** Parser Configuration Exception : " + e);
            return null;
        } catch (SAXException e) {
            gs.log("** SAX Exception : " + e);
            return null;
        } catch (IOException e) {
            gs.log("** IO Exception[ : " + e);
            return null;
        }

        return reportTable;
    }

    /**
     * <h2><code>isNewPage</code></h2>
     * 
     * <p>
     *  Method to test for a page break.  When a page break occurs 
     *  the contents of the table are added to the document and 
     *  the table is cleared out.    
     * </p>
     * 
     * @param  int rowcount - the current report page line number
     * @throws DocumentException
     * @return - boolean - true when a new page is printed
     * 
     */
    private boolean isNewPage(int rowcount) throws DocumentException {
        if (rowcount < pageLength)
            return false;

        document.add(reportBody);
        reportBody.deleteBodyRows();
        document.newPage();
        rowCount = 1;
        return true;
    }

    /**
     * <h2><code>service</code></h2>
     * 
     * <p>
     *   Proces Http Service and create report.    
     * </p>
     * 
     * @param  ServletRequest request
     * @param ServletResponse response
     * 
     */
    public void reportService(ServletRequest request, ServletResponse response) {

        DataSet reportTable = getReportScript(request.getParameter("Lng").trim()
                + System.getProperty("file.separator") + request.getParameter(ReportColumn.REPORT_SCRIPT).trim());

        if (reportTable != null)
            buildReport(request, response, reportTable);
        else
            buildErrorPage(request, response, " -- Report Script Not Loaded --");

    }

}