Package it.eng.spagobi.engines.qbe.services.worksheet.exporter

Source Code of it.eng.spagobi.engines.qbe.services.worksheet.exporter.WorkSheetPDFExporter$MyHeaderFooter

/**

SpagoBI - The Business Intelligence Free Platform

Copyright (C) 2005-2009 Engineering Ingegneria Informatica S.p.A.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) 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
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

**/
package it.eng.spagobi.engines.qbe.services.worksheet.exporter;

import it.eng.spagobi.engines.qbe.QbeEngineConfig;
import it.eng.spagobi.engines.qbe.crosstable.exporter.CrosstabPDFExporter;
import it.eng.spagobi.tools.dataset.common.datastore.IDataStore;
import it.eng.spagobi.utilities.engines.SpagoBIEngineRuntimeException;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.text.DecimalFormat;
import java.util.ArrayList;

import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.log4j.Logger;
import org.json.JSONObject;

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.html.simpleparser.HTMLWorker;
import com.lowagie.text.html.simpleparser.StyleSheet;
import com.lowagie.text.pdf.ColumnText;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;

/**
*
* @author Davide Zerbetto (davide.zerbetto@eng.it)
*/
public class WorkSheetPDFExporter {

  private Document pdfDocument = null;
  private PdfWriter docWriter = null;
  private IDataStore dataStore = null;
  private JSONObject currentSheetConf = null;
 
  private static float IMAGE_MAX_WIDTH = 250;
  private static float IMAGE_MAX_HEIGHT = 100;
  private static float TITLE_MAX_HEIGHT = 50;
 
  private static float MARGIN_TOP = 36;
  private static float MARGIN_RIGHT = 36;
  private static float MARGIN_BOTTOM = 36;
  private static float MARGIN_LEFT = 36;
 
  public static final String HEADER = "HEADER";
  public static final String FOOTER = "FOOTER";
  public static final String CONTENT = "CONTENT";

  public static final String SHEET_TYPE = "SHEET_TYPE";
  public static final String CHART = "CHART";
  public static final String CROSSTAB = "CROSSTAB";
  public static final String TABLE = "TABLE";
 
  public static final String POSITION = "position";
  public static final String TITLE = "title";
  public static final String IMG = "img";
 
  public static final String CENTER = "center";
  public static final String RIGHT = "right";
  public static final String LEFT = "left";

  public static final String SVG = "SVG";
 
  private DecimalFormat numberFormat;
  private String userDateFormat;
 
 
  /** Logger component. */
  public static transient Logger logger = Logger.getLogger(WorkSheetPDFExporter.class);

  public void open( OutputStream outputStream ) throws DocumentException {
      pdfDocument = new Document(PageSize.A4.rotate());
      docWriter = PdfWriter.getInstance(pdfDocument, outputStream);
      docWriter.setPageEvent(new MyHeaderFooter());
      pdfDocument.open();
  }
 
  public void close() {
      pdfDocument.close();
      docWriter.close();
  }

  public void addSheet(JSONObject sheetJSON, IDataStore dataStore){
    this.dataStore = dataStore;
    addSheet(sheetJSON);
  }
 
  public void addSheet(JSONObject sheetJSON) {
    try {
      float[] margins = getContentMargins(sheetJSON);
     
      setCurrentSheetConf(sheetJSON);
     
      // new margins will be applied on next page
      pdfDocument.setMargins(MARGIN_LEFT, MARGIN_RIGHT, margins[0], margins[1]);
     
      pdfDocument.newPage();
     
      JSONObject content = sheetJSON.getJSONObject(WorkSheetPDFExporter.CONTENT);
      String sheetType = content.getString(WorkSheetPDFExporter.SHEET_TYPE);
           
      if (WorkSheetPDFExporter.CHART.equalsIgnoreCase(sheetType)) {
        addChart(content, margins);
      } else if (WorkSheetPDFExporter.TABLE.equalsIgnoreCase(sheetType)) {
        addTable(content);
      } else if (WorkSheetPDFExporter.CROSSTAB.equalsIgnoreCase(sheetType)) {
        addCrosstab(content);
      } else {
        logger.error("Sheet type " + sheetType + " not recognized");
      }
     
      pdfDocument.newPage(); // finalize page (necessary for MyHeaderFooter onEndPage trigger)
     
    } catch (Exception e) {
      throw new RuntimeException("Error while adding sheet", e);
    }
   
  }

  private float[] getContentMargins(JSONObject sheetJSON) throws Exception {
    float top = 0;
    float bottom = 0;
    if (sheetJSON.has(WorkSheetPDFExporter.HEADER)) {
      top = getTopMargin(sheetJSON.getJSONObject(WorkSheetPDFExporter.HEADER));
    }
    if (sheetJSON.has(WorkSheetPDFExporter.FOOTER)) {
      bottom = getBottomMargin(sheetJSON.getJSONObject(WorkSheetPDFExporter.FOOTER));
    }
    float[] toReturn = new float[] {top, bottom};
    return toReturn;
  }

  private float getBottomMargin(JSONObject footer) throws Exception {
    return getMargin(footer) + MARGIN_BOTTOM;
  }

  private float getTopMargin(JSONObject header) throws Exception {
    return getMargin(header) + MARGIN_TOP;
  }

  private float getMargin(JSONObject headerOrFooter) throws Exception {
    float toReturn = 0;
    String title = headerOrFooter.optString(TITLE);
    String imgName = headerOrFooter.optString(IMG);
    String imagePosition = headerOrFooter.optString(POSITION);
    if (title != null && !title.trim().equals("") ) {
      toReturn = TITLE_MAX_HEIGHT;
    }
    if ( imgName != null && !imgName.equals("")
        && !imgName.equals("null") ) {
      if (CENTER.equals(imagePosition)) {
        toReturn += IMAGE_MAX_HEIGHT;
      } else {
        toReturn = IMAGE_MAX_HEIGHT;
      }
    }
    return toReturn;
  }
 
  private void setHeader(JSONObject header) {
    try {
      String title = header.optString(TITLE);
      String imgName = header.optString(IMG);
      String imagePosition = header.optString(POSITION);
      Image image = null;
      if ( imgName != null && !imgName.equals("")
          && !imgName.equals("null") ) {
        File imageFile = getImage(imgName);
        if (!imageFile.exists() || !imageFile.isFile()) {
          logger.error("Image " + imgName + " not found!!!");
        } else {
          image = Image.getInstance(imageFile.getPath());
          fitImage(image, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT);
          setHeaderImagePosition(image, imagePosition);
          pdfDocument.add(image);
        }
      }
      if (title != null && !title.trim().equals("") && !title.trim().equals("<br>") ) {
       
        title = new String(title.getBytes("ISO-8859-1")); // workaround for encoding problem
        float[] titlePosition = getHeaderTitlePosition(image, imagePosition);
        addHtmlToPdfContentByte(title, titlePosition);

      }
    } catch (Exception e) {
      throw new RuntimeException("Error while adding header", e);
    }
  }
 

  private float[] getHeaderTitlePosition(Image image, String imagePosition) {
    float llx, lly; // lower-left corner x and y position
    float urx, ury; // upper-right corner x and y position
    float imageHeight = image != null ? image.getHeight() : 0;
    float imageWidth = image != null ? image.getWidth() : 0;
    if ( LEFT.equals(imagePosition) ) {
      llx = MARGIN_LEFT + imageWidth + 30;
      lly = PageSize.A4.getWidth() - ( MARGIN_TOP + Math.max(imageHeight, IMAGE_MAX_HEIGHT) );
      urx = PageSize.A4.getHeight() - MARGIN_RIGHT;
      ury = PageSize.A4.getWidth() - MARGIN_TOP;
    } else if ( RIGHT.equals(imagePosition) ) {
      llx = MARGIN_LEFT;
      lly = PageSize.A4.getWidth() - ( MARGIN_TOP + Math.max(imageHeight, IMAGE_MAX_HEIGHT) );
      urx = PageSize.A4.getHeight() - ( MARGIN_RIGHT + imageWidth + 30 );
      ury = PageSize.A4.getWidth() - MARGIN_TOP;
    } else { // CENTER case
      llx = MARGIN_LEFT;
      lly = PageSize.A4.getWidth() - ( MARGIN_TOP + imageHeight + TITLE_MAX_HEIGHT );
      urx = PageSize.A4.getHeight() - MARGIN_RIGHT;
      ury = PageSize.A4.getWidth() - ( MARGIN_TOP + imageHeight );
    }
    float[] toReturn = new float[] {llx, lly, urx, ury};
    return toReturn;
  }
 
  public void addHtmlToPdfContentByte(String html, float[] pos) {
   
    PdfContentByte cb = docWriter.getDirectContent();
    StyleSheet styles = createDefaultStyleSheet();

    ColumnText ct = new ColumnText(cb);
    ct.setSimpleColumn(pos[0], pos[1], pos[2], pos[3]);
    ct.setYLine(pos[3]);
    try {
      ArrayList htmlObjs = HTMLWorker.parseToList(new StringReader(html),
          styles);
      for (int k = 0; k < htmlObjs.size(); ++k) {
        ct.addElement((Element) htmlObjs.get(k));
      }
      ct.go();
    } catch (Exception e) {
      throw new RuntimeException("Could not parse HTML", e);
    }
  }
 
  private StyleSheet createDefaultStyleSheet() {
    StyleSheet styles = new StyleSheet();

//    styles.loadTagStyle("ul", "face", "Times");
//    styles.loadTagStyle("ul", "size", "25px");
//    styles.loadTagStyle("ul", "leading", "15f");
//    styles.loadTagStyle("ul", "list-style-type", "square");
//    styles.loadTagStyle("li", "face", "Times");
//    styles.loadTagStyle("li", "size", "25px");
//    styles.loadTagStyle("li", "leading", "15f");
//    styles.loadTagStyle("p", "face", "Times");
//    styles.loadTagStyle("p", "size", "11px");
//    styles.loadTagStyle("p", "leading", "12f");
//    styles.loadTagStyle("p", "spacingAfter", "6x");

    return styles;
  }

  private void setHeaderImagePosition(Image image, String imagePosition) {
    float top = PageSize.A4.getWidth() - (MARGIN_TOP + image.getHeight()); // remember that the page is A4 rotated
    float left = MARGIN_LEFT;
    if (LEFT.equals(imagePosition)) {
      left = MARGIN_LEFT;
    } else if (CENTER.equals(imagePosition)) {
      left = PageSize.A4.getHeight() / 2 - image.getWidth() / 2;
    } else if (RIGHT.equals(imagePosition)) {
      left = PageSize.A4.getHeight() - (MARGIN_RIGHT + image.getWidth()); // remember that the page is A4 rotated
    }
    image.setAbsolutePosition(left, top);
  }

  private void setFooterImagePosition(Image image, String imagePosition) {
    float top = MARGIN_BOTTOM;
    float left = MARGIN_LEFT;
    if (LEFT.equals(imagePosition)) {
      left = MARGIN_LEFT;
    } else if (CENTER.equals(imagePosition)) {
      left = PageSize.A4.getHeight() / 2 - image.getWidth() / 2;
    } else if (RIGHT.equals(imagePosition)) {
      left = PageSize.A4.getHeight() - (MARGIN_RIGHT + image.getWidth()); // remember that the page is A4 rotated
    }
    image.setAbsolutePosition(left, top);
  }
 
  private void setFooter(JSONObject footer) {
    try {
      String title = footer.optString(TITLE);
      String imgName = footer.optString(IMG);
      String imagePosition = footer.optString(POSITION);
      Image image = null;
      if ( imgName != null && !imgName.equals("")
          && !imgName.equals("null") ) {
        File imageFile = getImage(imgName);
        if (!imageFile.exists() || !imageFile.isFile()) {
          logger.error("Image " + imgName + " not found!!!");
        } else {
          image = Image.getInstance(imageFile.getPath());
          fitImage(image, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT);
          setFooterImagePosition(image, imagePosition);
          pdfDocument.add(image);
        }
      }
      if (title != null && !title.trim().equals("") && !title.trim().equals("<br>") ) {
       
        title = new String(title.getBytes("ISO-8859-1")); // workaround for encoding problem
        float[] titlePosition = getFooterTitlePosition(image, imagePosition);
        addHtmlToPdfContentByte(title, titlePosition);
       
      }
    } catch (Exception e) {
      throw new RuntimeException("Error while adding header", e);
    }
  }
 
 
  private float[] getFooterTitlePosition(Image image, String imagePosition) {
    float llx, lly; // lower-left corner x and y position
    float urx, ury; // upper-right corner x and y position
    float imageHeight = image != null ? image.getHeight() : 0;
    float imageWidth = image != null ? image.getWidth() : 0;
    if ( LEFT.equals(imagePosition) ) {
      llx = MARGIN_LEFT + imageWidth + 30;
      lly = MARGIN_BOTTOM;
      urx = PageSize.A4.getHeight() - MARGIN_RIGHT;
      ury = MARGIN_BOTTOM + Math.max(imageHeight, IMAGE_MAX_HEIGHT);
    } else if ( RIGHT.equals(imagePosition) ) {
      llx = MARGIN_LEFT;
      lly = MARGIN_BOTTOM;
      urx = PageSize.A4.getHeight() - ( MARGIN_RIGHT + imageWidth + 30 );
      ury = MARGIN_BOTTOM + Math.max(imageHeight, IMAGE_MAX_HEIGHT);
    } else { // CENTER case
      llx = MARGIN_LEFT;
      lly = MARGIN_BOTTOM + imageHeight;
      urx = PageSize.A4.getHeight() - MARGIN_RIGHT;
      ury = MARGIN_BOTTOM + imageHeight + TITLE_MAX_HEIGHT;
    }
    float[] toReturn = new float[] {llx, lly, urx, ury};
    return toReturn;
  }


  private File getImage(String fileName) {
    logger.debug("IN");
    File toReturn = null;
    File imagesDir = QbeEngineConfig.getInstance().getWorksheetImagesDir();
    toReturn = new File(imagesDir, fileName);
    logger.debug("OUT");
    return toReturn;
  }

  private void addChart(JSONObject content, float[] margins) {
    try {
      InputStream inputStream = null;
      OutputStream outputStream = null;
      String svg = content.getString(SVG);
      //Don't change ISO-8859-1 because it's the only way to export specific symbols
      inputStream = new ByteArrayInputStream(svg.getBytes("ISO-8859-1"));
      File imageFile = File.createTempFile("chart", ".jpg");
      outputStream = new FileOutputStream(imageFile);
      transformSVGIntoJPEG(inputStream, outputStream);
     
        Image jpg = Image.getInstance(imageFile.getPath());
       
        float topMargin = margins[0];
        float bottomMargin = margins[1];
       
        float chartMaxHeight = PageSize.A4.getWidth() - (topMargin + bottomMargin)// remember that the page is A4 rotated
        float chartMaxWidth = PageSize.A4.getHeight() - (MARGIN_LEFT + MARGIN_RIGHT)// remember that the page is A4 rotated
       
        float[] newDimensions = fitImage( jpg, chartMaxWidth, chartMaxHeight );

        float positionX = (PageSize.A4.getHeight() - newDimensions[0]) / 2;
        float positionY = bottomMargin + (chartMaxHeight - newDimensions[1]) / 2; // center the image into the available height
        jpg.setAbsolutePosition(positionX, positionY);
       
        pdfDocument.add(jpg);
    } catch (Exception e) {
      throw new RuntimeException("Error while adding chart", e);
    }
  }
 
  private void addTable(JSONObject content) {
    try {
      DataSourceTablePDFExporter tableExp = new DataSourceTablePDFExporter(dataStore, numberFormat, userDateFormat);
      tableExp.export(pdfDocument);

    } catch (Exception e) {
      throw new RuntimeException("Error while adding chart", e);
    }
  }
 
  private void addCrosstab(JSONObject content) {
    try {
     
      CrosstabPDFExporter csExporter = new CrosstabPDFExporter();
      String crosstab = content.getString(WorkSheetXLSExporter.CROSSTAB);
      JSONObject crosstabJSON = new JSONObject(crosstab)
      csExporter.export(crosstabJSON, pdfDocument,numberFormat);
       
    } catch (Exception e) {
      throw new RuntimeException("Error while adding chart", e);
    }
  }
 
 
  private float[] fitImage(Image jpg, float maxWidth, float maxHeight) {
    float newWidth = 0;
    float newHeight = 0;
    if (jpg.getWidth() > maxWidth) {
      newWidth = maxWidth;
      newHeight = (newWidth / jpg.getWidth())
          * jpg.getHeight();
      jpg.scalePercent(newWidth * 100 / jpg.getWidth());
    }
    if (jpg.getHeight() > maxHeight) {
      newHeight = maxHeight;
      newWidth = (newHeight / jpg.getHeight())
          * jpg.getWidth();
      jpg.scalePercent(newHeight * 100 / jpg.getHeight());
    }
    float[] toReturn = new float[] {newWidth, newHeight};
    return toReturn;
   
  }
 
  public static void transformSVGIntoJPEG (InputStream inputStream,  OutputStream outputStream) {
    // create a JPEG transcoder
    JPEGTranscoder t = new JPEGTranscoder();
   
    // set the transcoding hints
    t.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(1));
    t.addTranscodingHint(JPEGTranscoder.KEY_WIDTH, new Float(1000));
    t.addTranscodingHint(JPEGTranscoder.KEY_ALLOWED_SCRIPT_TYPES, "*");
    t.addTranscodingHint(JPEGTranscoder.KEY_CONSTRAIN_SCRIPT_ORIGIN, new Boolean(true));
    t.addTranscodingHint(JPEGTranscoder.KEY_EXECUTE_ONLOAD, new Boolean(true));
   
    // create the transcoder input
    Reader reader = new InputStreamReader(inputStream);
    TranscoderInput input = new TranscoderInput(reader);
   
    // create the transcoder output
    TranscoderOutput output = new TranscoderOutput(outputStream);
   
    // save the image
    try {
      t.transcode(input, output);
    } catch (TranscoderException e) {
      logger.error("Impossible to convert svg to jpeg: " + e.getCause(), e);
      throw new SpagoBIEngineRuntimeException("Impossible to convert svg to jpeg: " + e.getCause(), e);
    }
  }

  public void setNumberFormat(DecimalFormat numberFormat) {
    this.numberFormat = numberFormat;
  }

  public void setUserDateFormat(String userDateFormat) {
    this.userDateFormat = userDateFormat;
  }
 
  public JSONObject getCurrentSheetConf() {
    return currentSheetConf;
  }

  public void setCurrentSheetConf(JSONObject currentSheetConf) {
    this.currentSheetConf = currentSheetConf;
  }
 
  public class MyHeaderFooter extends PdfPageEventHelper {

    public MyHeaderFooter() {}
   
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
      super.onEndPage(writer, document);
      addHeaderAndFooter();
    }

    private void addHeaderAndFooter() {
     
      try {
       
        JSONObject sheetJSON = getCurrentSheetConf();
       
        if (sheetJSON.has(WorkSheetPDFExporter.HEADER)) {
          JSONObject header = sheetJSON
              .getJSONObject(WorkSheetPDFExporter.HEADER);
          setHeader(header);
        }
       
        if (sheetJSON.has(WorkSheetPDFExporter.FOOTER)) {
          JSONObject footer = sheetJSON
              .getJSONObject(WorkSheetPDFExporter.FOOTER);
          setFooter(footer);
        }
       
      } catch (Exception e) {
        logger.error("Error while adding header or footer", e);
      }
     
    }

   
  }
 
 
 
}
TOP

Related Classes of it.eng.spagobi.engines.qbe.services.worksheet.exporter.WorkSheetPDFExporter$MyHeaderFooter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.