it.eng.spagobi.engines.documentcomposition.exporterUtils.PdfCreator.java Source code

Java tutorial

Introduction

Here is the source code for it.eng.spagobi.engines.documentcomposition.exporterUtils.PdfCreator.java

Source

/* SpagoBI, the Open Source Business Intelligence suite
    
 * Copyright (C) 2012 Engineering Ingegneria Informatica S.p.A. - SpagoBI Competency Center
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0, without the "Incompatible With Secondary Licenses" notice. 
 * If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package it.eng.spagobi.engines.documentcomposition.exporterUtils;

import it.eng.spagobi.commons.utilities.ExecutionProxy;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Iterator;
import java.util.Map;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;

import com.lowagie.text.BadElementException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Image;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;

public class PdfCreator {

    Integer videoHeight;

    Integer videoWidth;

    float docHeight;

    float docWidth;

    static private Logger logger = Logger.getLogger(PdfCreator.class);

    public FileOutputStream createPdfFile(FileOutputStream fileOutputStream,
            Map<String, DocumentContainer> documentsMap, boolean defaultStyle)
            throws MalformedURLException, IOException, DocumentException {

        logger.debug("IN");

        Document document = new Document(PageSize.A4.rotate());
        Rectangle rect = document.getPageSize();
        docWidth = rect.getWidth();
        docHeight = rect.getHeight();

        logger.debug("document size width: " + docWidth + " height: " + docHeight);

        //PdfWriter writer=PdfWriter.getInstance(document,new FileOutputStream("C:/comp/SpagoBIProva.pdf"));
        PdfWriter writer = PdfWriter.getInstance(document, fileOutputStream);
        document.open();

        int documentsNumber = documentsMap.keySet().size();
        int columnnsNumber = 2;

        if (defaultStyle == true) {
            logger.debug("use default style");
            int cellsCounter = 0;

            PdfPTable table = new PdfPTable(columnnsNumber);
            table.setWidthPercentage(100);

            for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
                String label = (String) iterator.next();
                DocumentContainer docContainer = documentsMap.get(label);
                byte[] content = docContainer.getContent();
                if (content != null) {
                    Image img = null;
                    try {
                        img = Image.getInstance(content);
                        table.addCell(img);
                    } catch (Exception e) {
                        logger.debug("Trying to evaluate response as a PDF file... ");
                        table.addCell("");
                        //                  try {
                        //                     PdfReader reader = new PdfReader(content);
                        //                     PdfImportedPage page = writer.getImportedPage(reader, 1);
                        //                     writer.addPage(page);
                        //                     table.addCell("");
                        //                  } catch (Exception x) {
                        //                     logger.error("Error in inserting image for document " + label, e);
                        //                     logger.error("Error in inserting pdf file for document " + label, x);
                        //                     table.addCell("");
                        //                  }
                    }
                }
                cellsCounter++;
            }

            // if cell counter is not pair make it pair
            if (cellsCounter % 2 != 0) {
                table.addCell("");
            }
            document.add(table);

        } else { // ************* NO DEFAULT STYLE *****************
            logger.debug("No default style");

            // I want to calculate total height of scaled heights!!
            //int totalScaledHeight=calculateTotaleScaledHeights(documentsMap, defaultStyle);

            // run on all documents
            for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
                String label = (String) iterator.next();
                logger.debug("document with label " + label);

                DocumentContainer docContainer = documentsMap.get(label);
                MetadataStyle style = docContainer.getStyle();

                // one table for each image, set at absolute position
                PdfPTable table = new PdfPTable(1);

                // width and height specified for the container by style attribute
                int widthStyle = style.getWidth();
                int heightStyle = style.getHeight();
                logger.debug("style for document width: " + widthStyle + " height: " + heightStyle);

                // width and height for the table scaled to the document size
                int tableWidth = calculatePxSize(docWidth, widthStyle, videoWidth);
                int tableHeight = calculatePxSize(docHeight, heightStyle, videoHeight);

                logger.debug("table for document width: " + tableWidth + " height: " + tableHeight);

                // x and y position as specified for the container by the style attribute
                int yStyle = style.getY();
                int xStyle = style.getX();
                // width and height scaled to the document size
                int xPos = (calculatePxPos(docWidth, xStyle, videoWidth));
                int yPos = (int) docHeight - (calculatePxPos(docHeight, yStyle, videoHeight));
                logger.debug("Table position at x: " + xPos + " y: " + yPos);

                // get the image
                byte[] content = docContainer.getContent();
                if (content != null) {
                    Image img = null;
                    try {
                        img = Image.getInstance(content);
                    } catch (Exception e) {
                        logger.debug("Trying to evaluate response as a PDF file... ");
                        try {
                            PdfReader reader = new PdfReader(content);
                            PdfContentByte cb = writer.getDirectContent();
                            PdfImportedPage page = writer.getImportedPage(reader, 1);
                            float[] tm = getTransformationMatrix(page, xPos, yPos, tableWidth, tableHeight);
                            cb.addTemplate(page, tm[0], tm[1], tm[2], tm[3], tm[4], tm[5]);
                        } catch (Exception x) {
                            logger.error("Error in inserting image for document " + label, e);
                            logger.error("Error in inserting pdf file for document " + label, x);
                        }
                        continue;
                    }

                    //if it is a REPORT and has more than one page, too large, you have to resize the image, but how to understand it?
                    // if image size is more than double of the container size cut the first part,otherwise scale it
                    if (docContainer.getDocumentType().equals("REPORT")) {
                        boolean cutImageWIdth = isToCutWidth(img, tableWidth);
                        boolean cutImageHeight = isToCutHeight(img, tableWidth);

                        if (cutImageWIdth == true || cutImageHeight == true) {
                            logger.debug(
                                    "Report will be cut to width " + tableWidth + " and height " + tableHeight);
                            try {
                                img = cutImage(content, cutImageHeight, cutImageWIdth, tableHeight, tableWidth,
                                        (int) img.getWidth(), (int) img.getHeight());
                            } catch (Exception e) {
                                logger.error(
                                        "Error in image cut, cutt will be ignored and image will be drawn anyway ",
                                        e);
                            }
                        }
                    }

                    // this is percentage to resize
                    // The image must be size within the cell               
                    int percToResize = percentageToResize((int) img.getWidth(), (int) img.getHeight(), tableWidth,
                            tableHeight);
                    logger.debug("image will be scaled of percentage " + percToResize);
                    img.scalePercent(percToResize);

                    PdfPCell cell = new PdfPCell(img);
                    cell.setNoWrap(true);
                    cell.setFixedHeight(tableHeight);
                    cell.setBorderWidth(0);
                    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                    cell.setVerticalAlignment(Element.ALIGN_CENTER);
                    table.addCell(cell);

                    //table.setWidthPercentage(tableWidthPerc);
                    table.setTotalWidth(tableWidth);
                    table.setLockedWidth(true);
                } else {
                    // TODO: setALT!
                }
                logger.debug("Add table");
                table.writeSelectedRows(0, -1, xPos, yPos, writer.getDirectContent());
                logger.debug("Document added");
            }

        }
        document.close();
        logger.debug("OUT");
        return fileOutputStream;
    }

    private float[] getTransformationMatrix(PdfImportedPage page, int xPos, int yPos, int tableWidth,
            int tableHeight) {
        float pageWidth = page.getWidth();
        float pageHeight = page.getHeight();
        float scaleX = tableWidth / pageWidth;
        float scaleY = tableHeight / pageHeight;
        float scale = Math.min(scaleX, scaleY);
        //float[] toReturn = {scale, 0f, 0f, scale, xPos, docHeight - tableHeight};
        float dX = (float) xPos;
        float dY = yPos - tableHeight;
        float[] toReturn = { scale, 0f, 0f, scale, dX, dY };
        return toReturn;
    }

    int chooseDefaultColumnsNumber(int documentsNumber) {

        //      if(documentsNumber<=2)return documentsNumber;
        //      else if(documentsNumber==3 || documentsNumber==4) return 2;
        //      else return 3;
        return 2;

    }

    int calculatePercentage(float documentSize, int styleSize, int videoSize) {

        // this is x value to object in PDF
        int value = (styleSize * (int) documentSize) / videoSize;

        // get percentage of x within docyment
        int percentage = (value * 100) / (int) documentSize;
        return percentage;
    }

    int calculatePxSize(float documentSize, int styleSize, int videoSize) {

        // this is x value to object in PDF
        int value = (styleSize * (int) documentSize) / videoSize;
        return value;
        //      // get percentage of x within docyment
        //      int percentage=(value*100)/(int)documentSize;
        //      return percentage;
    }

    int calculatePxPos(float documentSize, int styleSize, int videoSize) {

        // this is x value to object in PDF
        int value = (styleSize * (int) documentSize) / videoSize;

        return value;
    }

    public Integer getVideoHeight() {
        return videoHeight;
    }

    public void setVideoHeight(Integer videoHeight) {
        this.videoHeight = videoHeight;
    }

    public Integer getVideoWidth() {
        return videoWidth;
    }

    public void setVideoWidth(Integer videoWidth) {
        this.videoWidth = videoWidth;
    }

    /**
     *  called only if not default style
     * @param documentsMap
     */
    int calculateTotalHeight(Map<String, DocumentContainer> documentsMap, boolean defaultStyle) {
        logger.debug("IN");
        int totalHeight = 0;
        if (defaultStyle == false) {
            // total height is the maximum top+height revealed!
            for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
                String label = (String) iterator.next();
                DocumentContainer docContainer = documentsMap.get(label);
                MetadataStyle style = docContainer.getStyle();
                int verticalLimit = style.getHeight() + style.getY();
                if (verticalLimit > totalHeight) {
                    totalHeight = verticalLimit;
                }

            }
        }
        logger.debug("OUT");
        return totalHeight;
    }

    int calculateTotalWidth(Map<String, DocumentContainer> documentsMap, boolean defaultStyle) {
        logger.debug("IN");
        int totalWidth = 0;
        if (defaultStyle == false) {
            // total height is the maximum top+height revealed!
            for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
                String label = (String) iterator.next();
                DocumentContainer docContainer = documentsMap.get(label);
                MetadataStyle style = docContainer.getStyle();
                int horizontalLimit = style.getWidth() + style.getX();
                if (horizontalLimit > totalWidth) {
                    totalWidth = horizontalLimit;
                }

            }
        }
        logger.debug("OUT");
        return totalWidth;
    }

    int calculateTotaleScaledHeights(Map<String, DocumentContainer> documentsMap, boolean defaultStyle) {
        logger.debug("IN");
        int totalHeight = 0;
        if (defaultStyle == false) {
            // total height is the maximum top+height revealed!
            for (Iterator iterator = documentsMap.keySet().iterator(); iterator.hasNext();) {
                String label = (String) iterator.next();
                DocumentContainer docContainer = documentsMap.get(label);
                MetadataStyle style = docContainer.getStyle();
                int height = style.getHeight() + style.getY();
                int verticalLimit = calculatePxSize(docHeight, height, videoHeight);
                if (verticalLimit > totalHeight) {
                    totalHeight = verticalLimit;
                }

            }
        }
        logger.debug("OUT");
        return totalHeight;
    }

    int percentageToResize(int imgWidth, int imgHeight, int tableWidth, int tableHeight) {
        logger.debug("IN");
        int perc = 100;
        int percReductionWidth = 100;
        if (imgWidth > tableWidth) {
            percReductionWidth = (tableWidth * 100) / imgWidth;
        }
        int percReductionHeight = 100;
        if (imgHeight > tableHeight) {
            percReductionHeight = (tableHeight * 100) / imgHeight;
        }

        perc = percReductionHeight < percReductionWidth ? percReductionHeight : percReductionWidth;
        logger.debug("OUT");
        return perc;
    }

    //                cutImage(content, cutImageHeight, cutImageWIdth, tableHeight, tableWidth);

    Image cutImage(byte[] bytes, boolean cutImageHeight, boolean cutImageWidth, int tableHeight, int tableWidth,
            int imgWidth, int imgHeight) throws IOException, BadElementException {
        logger.debug("IN");

        BufferedImage image = null; // Read from a file 
        BufferedImage region = null;

        int pxWidthToCut = (cutImageWidth == true) ? tableWidth : imgWidth;
        int pxHeightToCut = (cutImageHeight == true) ? tableHeight : imgHeight;

        InputStream inputStream = new ByteArrayInputStream(bytes);

        image = ImageIO.read(inputStream); // Read from an input stream 
        try {
            region = image.getSubimage(0, 0, pxWidthToCut, pxHeightToCut);
        } catch (Exception e) {
            e.printStackTrace();
        }
        byte[] newBytes = getBytes(region);
        Image cutImg = Image.getInstance(newBytes);
        //ImageIO.write(region,"PNG",new File("C:/nuovaImmagine222.PNG"));
        logger.debug("OUT");

        return cutImg;
    }

    private byte[] getBytes(BufferedImage image) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "PNG", baos);
        return baos.toByteArray();
    }

    boolean isToCutWidth(Image img, int tableWidth) {
        int imgWidth = (int) img.getWidth();
        if (imgWidth > (4 * tableWidth))
            return true;
        else
            return false;
    }

    boolean isToCutHeight(Image img, int tableHeight) {
        int imgHeight = (int) img.getHeight();
        if (imgHeight > (4 * tableHeight))
            return true;
        else
            return false;
    }

}