bouttime.report.boutsheet.BoutSheetReport.java Source code

Java tutorial

Introduction

Here is the source code for bouttime.report.boutsheet.BoutSheetReport.java

Source

/**                 ***COPYRIGHT STARTS HERE***
 *  BoutTime - the wrestling tournament administrator.
 *
 *  Copyright (C) 2011  Jeffrey K. Rutt
 *
 *  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 3 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, see <http://www.gnu.org/licenses/>.
 *                  ***COPYRIGHT ENDS HERE***                                */

package bouttime.report.boutsheet;

import bouttime.dao.Dao;
import bouttime.mainview.BoutTimeApp;
import bouttime.model.Bout;
import bouttime.model.Group;
import bouttime.model.Wrestler;
import bouttime.report.bracketsheet.BracketSheetUtil;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.jdesktop.application.Application;
import org.jdesktop.application.ApplicationContext;
import org.jdesktop.application.ResourceMap;
import org.apache.log4j.Logger;

/**
 * A class to generate a PDF file of Bout Sheets.
 */
public class BoutSheetReport extends PdfPageEventHelper {
    static Logger logger = Logger.getLogger(BoutSheetReport.class);

    private static final String outputDirectory;
    private static final String outputFilePath;
    private BaseFont baseFont;
    private String headerString;

    // This stuff never changes, so only need to do it once.
    // Putting it in a static initialization block to ensure this.
    static {
        Application app = Application.getInstance(BoutTimeApp.class);
        ApplicationContext appCtx = app.getContext();
        ResourceMap map = appCtx.getResourceMap(BoutSheetReport.class);
        outputDirectory = map.getString("report.dir");
        outputFilePath = String.format("%s/%s", outputDirectory, map.getString("report.filename"));
    }

    public String getoutputFilePath() {
        return outputFilePath;
    }

    /**
     * Generate a bout sheet report that has no data in it (only the image).
     * The length is the given number of pages.
     * 
     * @param numPages
     * @return True if the report was generated.
     */
    public boolean generateBlank(Dao dao, Integer numPages) {
        // step 1: creation of a document-object
        // rotate to make page landscape
        Document document = new Document(PageSize.A4.rotate());

        try {

            // step 2: creation of the writer
            FileOutputStream fos = createOutputFile();
            if (fos == null) {
                return false;
            }
            PdfWriter writer = PdfWriter.getInstance(document, fos);
            writer.setPageEvent(this);

            // step 3: we open the document
            document.open();

            // step 4: we grab the ContentByte and do some stuff with it
            PdfContentByte cb = writer.getDirectContent();

            BaseFont bf = BaseFont.createFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.EMBEDDED);
            float pageWidth = cb.getPdfDocument().getPageSize().getWidth();
            float midPage = pageWidth / 2;

            setHeaderString(dao);

            int count = 1;
            while (true) {
                drawBout(cb, bf, 35, midPage - 35, null);
                drawBout(cb, bf, midPage + 35, pageWidth - 35, null);

                if (++count > numPages) {
                    break;
                }

                document.newPage();
            }

        } catch (DocumentException de) {
            logger.error("Document Exception", de);
            return false;
        } catch (IOException ioe) {
            logger.error("IO Exception", ioe);
            return false;
        }

        // step 5: we close the document
        document.close();

        return true;
    }

    /**
     * Generate a bout sheet report for the given list of bouts.
     * It is assumed that the list is in the desired order (no sorting is done here).
     *
     * @param list
     * @return True if the report was generated.
     */
    public boolean generateReport(Dao dao, List<Bout> list) {

        // step 1: creation of a document-object
        // rotate to make page landscape
        Document document = new Document(PageSize.A4.rotate());

        try {

            // step 2: creation of the writer
            FileOutputStream fos = createOutputFile();
            if (fos == null) {
                return false;
            }
            PdfWriter writer = PdfWriter.getInstance(document, fos);
            writer.setPageEvent(this);

            // step 3: we open the document
            document.open();

            // step 4: we grab the ContentByte and do some stuff with it
            PdfContentByte cb = writer.getDirectContent();

            BaseFont bf = BaseFont.createFont(BaseFont.TIMES_ROMAN, BaseFont.CP1252, BaseFont.EMBEDDED);
            float pageWidth = cb.getPdfDocument().getPageSize().getWidth();
            float midPage = pageWidth / 2;

            setHeaderString(dao);

            int count = 0;
            for (Bout b : list) {
                boolean rightSide = false;
                if ((count++ % 2) == 0) {
                    if (count > 2) {
                        // We could put this after Bout 2 is added, but
                        // that could leave a blank last page.
                        document.newPage();
                    }

                    // Bout 1 (Left side)
                    drawBout(cb, bf, 35, midPage - 35, b);
                } else {
                    // Bout 2 (Right side)
                    drawBout(cb, bf, midPage + 35, pageWidth - 35, b);
                    rightSide = true;
                }

                // Print the watermark, if necessary
                boolean doWatermark = false;
                String gClass = b.getGroup().getClassification();
                String wmValues = dao.getBoutsheetWatermarkValues();
                if ((wmValues != null) && !wmValues.isEmpty()) {
                    String[] tokens = wmValues.split(",");
                    for (String s : tokens) {
                        if (s.trim().equalsIgnoreCase(gClass)) {
                            doWatermark = true;
                            break;
                        }
                    }
                }
                if (doWatermark) {
                    int rotation = 45;
                    PdfContentByte ucb = writer.getDirectContentUnder();
                    BaseFont helv = BaseFont.createFont("Helvetica", BaseFont.WINANSI, false);
                    ucb.saveState();
                    ucb.setColorFill(BaseColor.LIGHT_GRAY);
                    ucb.beginText();
                    ucb.setFontAndSize(helv, 86);
                    float centerWidth = document.getPageSize().getWidth() / 4;
                    if (rightSide) {
                        centerWidth = centerWidth * 3;
                    }
                    ucb.showTextAligned(Element.ALIGN_CENTER, gClass, centerWidth,
                            document.getPageSize().getHeight() / 2, rotation);
                    ucb.endText();
                    ucb.restoreState();
                }
            }

        } catch (DocumentException de) {
            logger.error("Document Exception", de);
            return false;
        } catch (IOException ioe) {
            logger.error("IO Exception", ioe);
            return false;
        }

        // step 5: we close the document
        document.close();

        return true;
    }

    /**
     * Create the file to write the report to.
     * @return FileOutputStream to write the report to.
     */
    private FileOutputStream createOutputFile() {
        File tmpDir = new File(outputDirectory);
        if (!tmpDir.exists() || !tmpDir.isDirectory()) {
            if (!tmpDir.mkdir()) {
                logger.warn("Unable to create directory : " + tmpDir);
                return null;
            }
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(outputFilePath);
        } catch (java.io.FileNotFoundException ex) {
            logger.error("File Not Found Exception", ex);
            fos = null;
        }

        return fos;
    }

    private void drawBout(PdfContentByte cb, BaseFont bf, float xStart, float xEnd, Bout b)
            throws DocumentException, IOException {

        Group g = (b != null) ? b.getGroup() : null;
        float midRange = xStart + ((xEnd - xStart) / 2);
        float x = xStart;
        float y = 560;
        float widthUnit = (xEnd - xStart) / 4;

        float fontSize = 10;

        // draw mat and bout boxes
        float width = widthUnit;
        float height = 20;
        y -= 30;
        float matX = x + (width / 2);
        fontSize = 12;
        BracketSheetUtil.drawStringCentered(cb, bf, matX, y + 5, fontSize, "Mat", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawStringCentered(cb, bf, x + (width / 2), y + 5, fontSize, (g != null) ? g.getMat() : "",
                0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        float boutX = x + (width / 2);
        BracketSheetUtil.drawStringCentered(cb, bf, boutX, y + 5, fontSize, "Bout", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawStringCentered(cb, bf, x + (width / 2), y + 5, fontSize,
                (b != null) ? b.getBoutNum() : "", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        // draw group name
        // String groupName = "Open    Div 5    135-140";
        String groupName = "";
        if (g != null) {
            String classification = g.getClassification();
            if (classification == null) {
                classification = "";
            }

            String div = g.getAgeDivision();
            if (div == null) {
                div = "";
            }

            String weightClass = g.getWeightClass();
            if (weightClass == null) {
                weightClass = "";
            }
            groupName = String.format("%s  %s  %s", classification, div, weightClass);
            groupName.trim();

            // append the bout time to the group name, if set
            String boutTime = b.getBoutTime();
            if ((boutTime != null) && !boutTime.isEmpty()) {
                groupName = groupName + "  [ " + boutTime + " ]";
            }
        }
        fontSize = 16;
        y -= 25;
        BracketSheetUtil.drawStringCentered(cb, bf, midRange, y, fontSize, groupName, 0);

        // draw judge's Score Sheet
        y -= 20;
        fontSize = 8;
        BracketSheetUtil.drawStringCentered(cb, bf, midRange, y, fontSize, "Judge's Score Sheet", 0);
        width = width * 2;
        height = 20;
        y -= 23;
        x = xStart;
        float redX = x + (width / 2);
        fontSize = 12;
        BracketSheetUtil.drawStringCentered(cb, bf, redX, y + 5, fontSize, "RED", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        float greenX = x + (width / 2);
        BracketSheetUtil.drawStringCentered(cb, bf, greenX, y + 5, fontSize, "GREEN", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        // Print wrestler names
        y -= height;
        x = xStart;
        fontSize = 10;
        Wrestler red = (b != null) ? b.getRed() : null;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 4, fontSize,
                (red != null) ? red.getFirstName() + " " + red.getLastName() : "");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        Wrestler green = (b != null) ? b.getGreen() : null;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 4, fontSize,
                (green != null) ? green.getFirstName() + " " + green.getLastName() : "");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        // Print wrestler team names
        y -= height;
        x = xStart;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 4, fontSize, (red != null) ? red.getTeamName() : "");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 4, fontSize, (green != null) ? green.getTeamName() : "");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        y -= height;
        x = xStart;
        fontSize = 8;
        BracketSheetUtil.drawStringCentered(cb, bf, midRange, y + 6, fontSize, "Points and Cautions", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width * 2, height, 1, 0);

        height = height * 3;
        y -= height;
        x = xStart;
        fontSize = 8;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + height - 10, fontSize, "Period 1");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + height - 10, fontSize, "Period 1");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        y -= height;
        x = xStart;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + height - 10, fontSize, "Period 2");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + height - 10, fontSize, "Period 2");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        y -= height;
        x = xStart;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + height - 10, fontSize, "Period 3/OT");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + height - 10, fontSize, "Period 3/OT");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        height = height / 3;
        y -= height;
        x = xStart;
        fontSize = 12;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 5, fontSize, "Total");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 5, fontSize, "Total");
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        // winner's signature
        height = height * 2;
        y = y - height - 10;
        x = xStart;
        fontSize = 10;
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 15, fontSize, "Winner's");
        BracketSheetUtil.drawString(cb, bf, x + 2, y + 2, fontSize, "Signature:");
        BracketSheetUtil.drawRectangle(cb, x, y, width * 2, height, 1, 0);

        height = height / 2;
        y -= height;
        x = xStart;
        width = width / 2;
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        y -= height;
        x = xStart;
        fontSize = 8;
        BracketSheetUtil.drawStringCentered(cb, bf, x + (width / 2), y + 8, fontSize, "Fall Time", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawStringCentered(cb, bf, x + (width / 2), y + 8, fontSize, "Tech Fall Time", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawStringCentered(cb, bf, x + (width / 2), y + 8, fontSize, "Decision Score", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);
        x += width;
        BracketSheetUtil.drawStringCentered(cb, bf, x + (width / 2), y + 8, fontSize, "Injury Default Time", 0);
        BracketSheetUtil.drawRectangle(cb, x, y, width, height, 1, 0);

        x = xStart;
        y -= 60;
        BracketSheetUtil.drawHorizontalLine(cb, x, y, width * 4, 1, 0);
        y -= 10;
        fontSize = 10;
        BracketSheetUtil.drawString(cb, bf, x, y, fontSize, "Judge's Signature");
    }

    /**
     * Set the string for the page header.
     * @param dao Dao object to use to retrieve data.
     */
    private void setHeaderString(Dao dao) {
        try {
            this.baseFont = BaseFont.createFont("Helvetica", BaseFont.WINANSI, false);
            this.headerString = String.format("%s    %s %s, %s", dao.getName(), dao.getMonth(), dao.getDay(),
                    dao.getYear());
        } catch (DocumentException de) {
            logger.error("Document Exception", de);
            this.headerString = null;
        } catch (IOException ioe) {
            logger.error("IO Exception", ioe);
            this.headerString = null;
        }
    }

    /**
     * Add the header string to the document.
     * @param writer PdfWriter object to use.
     * @param document Document object to add the header to.
     */
    private void addHeader(PdfWriter writer, Document document) {
        if (this.headerString == null) {
            return;
        }

        PdfContentByte cb = writer.getDirectContent();

        float textBase = document.top() + 5;
        cb.beginText();
        cb.setFontAndSize(this.baseFont, 12);
        cb.setTextMatrix(document.left(), textBase);
        cb.showText(this.headerString);
        cb.endText();
    }

    /**
     * Called when a page in the document is being closed.
     * Add the header at this time, otherwise the header will be overwritten
     * by the bout images being added.
     * @param writer
     * @param document
     */
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        addHeader(writer, document);
    }
}