de.dhbw.humbuch.util.PDFHandler.java Source code

Java tutorial

Introduction

Here is the source code for de.dhbw.humbuch.util.PDFHandler.java

Source

package de.dhbw.humbuch.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.Image;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.RectangleReadOnly;
import com.lowagie.text.pdf.ColumnText;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;
import com.vaadin.server.StreamResource.StreamSource;

/**
 * Abstract super class for PDF creation. Determines general layout of PDFs.
 * @author Benjamin Rthlein
 *
 */
public abstract class PDFHandler {

    private Document document;
    private HeaderFooter event;
    protected final static float TABLEWIDTH = 460f;
    protected final static float CELL_PADDING = 7f;

    /**
     * 
     * @param path
     *            links to the directory where the PDF file should be saved
     */
    public PDFHandler(String path) {
        this.document = new Document();
    }

    /**
     * Create a document with the specified sizes and margins. This document is the internal representation 
     * of the PDF.
     */
    public PDFHandler() {
        this.document = new Document(new RectangleReadOnly(595, 842), 30f, 30f, 25f, 35f);
    }

    /**
     * Creates the pdf with the information in the object that was passed to the
     * constructor previously.
     * 
     * @param path
     *            where the file will be saved
     */
    public void savePDF(String path) {
        try {
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(path));
            event = new HeaderFooter();
            writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
            writer.setPageEvent(event);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        this.document.open();
        this.addMetaData(document);
        this.insertDocumentParts(document);
        this.document.close();
    }

    /**
     * Creates a ByteArrayOutputStream which contains the PDF as a byte array.
     * 
     * @return the byteArrayOutputStream the PDF is stored in, null if an error
     *         occurred.
     */
    public ByteArrayOutputStream createByteArrayOutputStreamForPDF() {
        ByteArrayOutputStream byteArrayOutputStream;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            PdfWriter writer = PdfWriter.getInstance(document, byteArrayOutputStream);
            event = new HeaderFooter();
            writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
            writer.setPageEvent(event);

            this.document.open();
            this.addMetaData(document);
            int initialDocumentSize = writer.getCurrentDocumentSize();
            this.insertDocumentParts(document);

            if (byteArrayOutputStream.size() > 0 || writer.getCurrentDocumentSize() > initialDocumentSize) {
                this.document.close();
            } else {
                return null;
            }

            return byteArrayOutputStream;
        } catch (DocumentException e) {
            System.err.println("Could not create ByteArrayOutputStream of PDF data. " + e.getMessage());
        }

        return null;
    }

    /**
     * Adds meta data to the PDF document. The information of using iText must
     * be part of the meta data due to the license of the iText library!
     * 
     * @param document
     *            represents the PDF before it is saved
     */
    private void addMetaData(Document document) {
        document.addTitle("Humbuch Schule");
        document.addSubject("Using iText");
        document.addKeywords("Java, PDF, iText");
        document.addAuthor("Schlager");
        document.addCreator("Schlager");
    }

    /**
     * Set the logo of Humboldt on the left corner and the current date on the
     * right corner
     * 
     * @param document
     *            reference of the pdfDocument object
     */
    protected void addHeading(Document document) {
        Paragraph paragraph = new Paragraph();
        PdfPTable table = createMyStandardTable(2);

        table.setTotalWidth(TABLEWIDTH);
        PdfPCell cell;

        Image img = new ResourceLoader("pdf/humboldt_logo.png").getImage();
        img.setAlignment(Element.ALIGN_BOTTOM);
        img.scaleToFit(205f, 65f);
        cell = new PdfPCell(img);

        cell.setBorder(0);
        table.addCell(cell);

        String date = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN).format(Calendar.getInstance().getTime());

        cell = new PdfPCell(new Phrase(date));
        cell.setBorder(0);
        cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
        cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
        table.addCell(cell);

        cell = new PdfPCell(new Phrase(""));
        cell.setBorder(Rectangle.BOTTOM);
        table.addCell(cell);
        cell = new PdfPCell(new Phrase(""));
        cell.setBorder(Rectangle.BOTTOM);
        table.addCell(cell);

        paragraph.add(table);
        addEmptyLine(paragraph, 1);

        try {
            document.add(paragraph);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * Adds a signature field with a date field to the document. Should be the
     * last part that is added to the document.
     * 
     * @param document
     *            represents the PDF before it is saved
     * @param role
     *            word for the kind of person that shall sign the paper
     */
    protected void addSignatureField(Document document, String role) {
        Paragraph paragraph = new Paragraph();

        //this table contains the signatureTable and the dataTable.
        // this purpose makes it easier to format
        PdfPTable table = createMyStandardTable(2);

        //the first column is double times greater than the second column
        try {
            table.setWidths(new float[] { 10f, 20f });
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        //create and fill date table
        PdfPTable dateTable = new PdfPTable(1);

        PdfPCell cell = new PdfPCell(new Phrase(""));
        //just the bottom border will be displayed (line for date)
        cell.setBorderWidthTop(0);
        cell.setBorderWidthLeft(0);
        cell.setBorderWidthRight(0);

        dateTable.addCell(cell);

        cell = new PdfPCell(new Phrase("Datum"));
        cell.setBorder(0);

        dateTable.addCell(cell);

        //put date table into the 'parent' table
        cell = new PdfPCell(dateTable);
        cell.setBorder(0);
        table.addCell(cell);

        //create and fill signature table
        PdfPTable signatureTable = new PdfPTable(1);
        cell = new PdfPCell(new Phrase(""));
        //just the bottom border will be displayed (line for signature)
        cell.setBorderWidthTop(0);
        cell.setBorderWidthLeft(0);
        cell.setBorderWidthRight(0);

        signatureTable.addCell(cell);

        cell = new PdfPCell(new Phrase("Unterschrift " + role));
        cell.setBorder(0);

        signatureTable.addCell(cell);

        //put signature table into the 'parent' table
        cell = new PdfPCell(signatureTable);
        cell.setBorder(0);
        table.addCell(cell);

        paragraph.add(table);
        try {
            document.add(paragraph);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * A table is generated with the header: Klasse, Bezeichnung Lehrmittel, Unterschrift
     * 
     * @return PdfPTable
     */
    protected PdfPTable createTableWithRentalInformationHeader() {
        PdfPTable table = createMyStandardTable(3, new float[] { 2.25f, 1f, 1f });
        Font font = FontFactory.getFont("Helvetica", 12, Font.BOLD);
        new PDFHandler.TableBuilder(table, new String[] { "Bezeichnung Lehrmittel", "bis Klasse", "Unterschrift" })
                .withBorder(true).isCenterAligned(true).font(font).padding(CELL_PADDING).fillTable();

        return table;
    }

    /**
     * A table is generated with the header: Klasse, Bezeichnung Lehrmittel
     * 
     * @return PdfPTable
     */
    protected PdfPTable createTableWithRentalInformationHeaderWithoutSignColumn() {
        PdfPTable table = createMyStandardTable(2, new float[] { 3f, 1f });
        Font font = FontFactory.getFont("Helvetica", 12, Font.BOLD);
        new PDFHandler.TableBuilder(table, new String[] { "Bezeichnung Lehrmittel", "bis Klasse" }).withBorder(true)
                .isCenterAligned(true).font(font).padding(CELL_PADDING).fillTable();

        return table;
    }

    /**
     * A table is generated with the header: Bezeichnung Lehrmittel, Anzahl
     * 
     * @return PdfPTable
     */
    protected PdfPTable createTableWithRentalInformationHeaderForClass() {
        PdfPTable table = createMyStandardTable(2, new float[] { 3f, 1f });
        Font font = FontFactory.getFont("Helvetica", 12, Font.BOLD);
        new PDFHandler.TableBuilder(table, new String[] { "Bezeichnung Lehrmittel", "Anzahl" }).withBorder(true)
                .font(font).isCenterAligned(true).padding(CELL_PADDING).fillTable();

        return table;
    }

    protected void addInformationAboutDocument(Document document, String informationText) {
        PdfPTable table = createMyStandardTable(1);
        new PDFHandler.TableBuilder(table, new String[] { informationText })
                .font(FontFactory.getFont("Times New Roman", 14, Font.BOLD)).fillTable();
        try {
            document.add(table);
            PDFHandler.addEmptyLineToDocument(document, 1);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }

    protected void resetPageNumber() {
        this.event.resetPageNumber();
    }

    protected static void addEmptyLine(Paragraph paragraph, int number) {
        for (int i = 0; i < number; i++) {
            paragraph.add(new Paragraph(" "));
        }
    }

    protected static void addEmptyLineToDocument(Document document, int number) {
        Paragraph paragraph = new Paragraph();
        for (int i = 0; i < number; i++) {
            paragraph.add(new Paragraph(" "));
        }

        try {
            document.add(paragraph);
        } catch (DocumentException e) {
            System.err.println("Could not add empty line to documnet " + e.getStackTrace());
        }
    }

    /**
     * Create a standard table with constant table width.
     * 
     * @param columnNumber
     *            set how many columns the table will have
     * @return table
     */
    protected static PdfPTable createMyStandardTable(int columnNumber) {
        PdfPTable table = new PdfPTable(columnNumber);
        table.setLockedWidth(true);
        table.setTotalWidth(TABLEWIDTH);

        return table;
    }

    /**
     * Create a standard table with constant table width.
     * 
     * @param columnNumber
     *            set how many columns the table will have
     * @param columnWidths
     *            set the ratio between the columns. If null, all columns will
     *            be equal.
     * @return table
     */
    protected static PdfPTable createMyStandardTable(int columnNumber, float[] columnWidths) {
        PdfPTable table = new PdfPTable(columnNumber);
        table.setLockedWidth(true);
        table.setTotalWidth(TABLEWIDTH);

        if (!(columnWidths == null) && (columnWidths.length != 0)) {
            try {
                table.setWidths(columnWidths);
            } catch (DocumentException e) {
                System.err.println("Could not set columnWidths of standardTable " + e.getStackTrace());
            }
        }

        return table;
    }

    /**
     * Use the configuration information to fill the table cells
     * @param tableBuilder Table configuration
     */
    private static void fillTableWithContent(TableBuilder tableBuilder) {
        PdfPCell cell = null;
        for (int i = 0; i < tableBuilder.contentArray.length; i++) {
            if (tableBuilder.contentArray[i] == null || tableBuilder.contentArray[i].equals("null")) {
                tableBuilder.contentArray[i] = "";
            }
            if (tableBuilder.font != null) {
                cell = new PdfPCell(new Phrase(tableBuilder.contentArray[i], tableBuilder.font));
            } else {
                cell = new PdfPCell(new Phrase(tableBuilder.contentArray[i]));
            }
            if (tableBuilder.isAlignedCentrally) {
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            }
            if (!tableBuilder.withBorder) {
                cell.setBorder(0);
            }
            if (tableBuilder.padding != 0f) {
                cell.setPadding(tableBuilder.padding);
            }
            if (tableBuilder.leading != 0f) {
                cell.setLeading(tableBuilder.leading, tableBuilder.leading);
            }
            tableBuilder.table.addCell(cell);
        }
    }

    /**
     * In this method all parts of the document shall be 'put' together.
     * 
     * @param document
     *            represents the PDF before it is saved
     */
    protected abstract void insertDocumentParts(Document document);

    /**
     * In this method the PDF-specific information shall be inserted into the
     * document.
     * 
     * @param document
     *            represents the PDF before it is saved
     */
    protected abstract void addContent(Document document);

    class TableBuilder {

        private PdfPTable table;
        private String[] contentArray;
        private boolean withBorder;
        private boolean isAlignedCentrally;
        private float padding;
        private Font font;
        private float leading;

        public TableBuilder(PdfPTable table, String[] contentArray) {
            this.table = table;
            this.contentArray = contentArray;
        }

        public TableBuilder withBorder(boolean withBorder) {
            this.withBorder = withBorder;
            return this;
        }

        public TableBuilder isCenterAligned(boolean isCenterAligned) {
            this.isAlignedCentrally = isCenterAligned;
            return this;
        }

        public TableBuilder padding(float padding) {
            this.padding = padding;
            return this;
        }

        public TableBuilder font(Font font) {
            this.font = font;
            return this;
        }

        public TableBuilder leading(float leading) {
            this.leading = leading;
            return this;
        }

        public void fillTable() {
            PDFHandler.fillTableWithContent(this);
        }
    }

    /** Inner class to add a header and a footer. */
    class HeaderFooter extends PdfPageEventHelper {

        /** Alternating phrase for the header. */
        Phrase[] header = new Phrase[2];
        /** Current page number (will be reset for every chapter). */
        int pagenumber;

        /**
         * Initialize one of the headers.
         * 
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(com.itextpdf.text.pdf.PdfWriter,
         *      com.itextpdf.text.Document)
         */
        public void onOpenDocument(PdfWriter writer, Document document) {
            header[0] = new Phrase("Movie history");
        }

        /**
         * Initialize one of the headers, based on the chapter title; reset the
         * page number.
         * 
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onChapter(com.itextpdf.text.pdf.PdfWriter,
         *      com.itextpdf.text.Document, float, com.itextpdf.text.Paragraph)
         */
        public void onChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) {
            header[1] = new Phrase(title.getContent());
            pagenumber = 1;
        }

        /**
         * Increase the page number.
         * 
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage(com.itextpdf.text.pdf.PdfWriter,
         *      com.itextpdf.text.Document)
         */
        public void onStartPage(PdfWriter writer, Document document) {
            pagenumber++;
        }

        /**
         * Adds the header and the footer.
         * 
         * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(com.itextpdf.text.pdf.PdfWriter,
         *      com.itextpdf.text.Document)
         */
        public void onEndPage(PdfWriter writer, Document document) {
            Rectangle rect = writer.getBoxSize("art");
            //            switch(writer.getPageNumber() % 2) {
            //            case 0:
            //                ColumnText.showTextAligned(writer.getDirectContent(),
            //                        Element.ALIGN_RIGHT, header[0],
            //                        rect.getRight(), rect.getTop(), 0);
            //                break;
            //            case 1:
            //                ColumnText.showTextAligned(writer.getDirectContent(),
            //                        Element.ALIGN_LEFT, header[0],
            //                        rect.getLeft(), rect.getTop(), 0);
            //                break;
            //            }
            ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER,
                    new Phrase(String.format("- Seite %d -", pagenumber)), (rect.getLeft() + rect.getRight()) / 2,
                    20, 0);
        }

        public void resetPageNumber() {
            this.pagenumber = 1;
        }
    }

    public static class PDFStreamSource implements StreamSource {

        private static final long serialVersionUID = 1L;
        ByteArrayOutputStream byteArrayOutputstream;

        public PDFStreamSource(ByteArrayOutputStream byteArrayOutputStream) {
            this.byteArrayOutputstream = byteArrayOutputStream;
        }

        @Override
        public InputStream getStream() {
            // Here we return the pdf contents as a byte-array
            return new ByteArrayInputStream(this.byteArrayOutputstream.toByteArray());
        }
    }
}