the class that generates PDFs
authorjohn <john>
Mon, 14 Apr 2003 19:18:06 +0000 (19:18 +0000)
committerjohn <john>
Mon, 14 Apr 2003 19:18:06 +0000 (19:18 +0000)
source/mircoders/pdf/PDFGenerator.java [new file with mode: 0755]

diff --git a/source/mircoders/pdf/PDFGenerator.java b/source/mircoders/pdf/PDFGenerator.java
new file mode 100755 (executable)
index 0000000..4b2c695
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2001, 2002  The Mir-coders group
+ *
+ * This file is part of Mir.
+ *
+ * Mir 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Mir 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 Mir; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * In addition, as a special exception, The Mir-coders gives permission to link
+ * the code of this program with the com.oreilly.servlet library, any library
+ * licensed under the Apache Software License, The Sun (tm) Java Advanced
+ * Imaging library (JAI), The Sun JIMI library (or with modified versions of
+ * the above that use the same license as the above), and distribute linked
+ * combinations including the two.  You must obey the GNU General Public
+ * License in all respects for all of the code used other than the above
+ * mentioned libraries.  If you modify this file, you may extend this exception
+ * to your version of the file, but you are not obligated to do so.  If you do
+ * not wish to do so, delete this exception statement from your version.
+ */
+
+package mircoders.pdf;
+
+import mir.log.LoggerWrapper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+
+import gnu.regexp.RE;
+import gnu.regexp.REException;
+
+import com.lowagie.text.*;
+import com.lowagie.text.pdf.*;
+
+import mir.entity.EntityList;
+
+import mircoders.entity.EntityContent;
+import mircoders.entity.EntityImages;
+import mircoders.storage.DatabaseContentToMedia;
+
+import mir.config.MirPropertiesConfiguration;
+import mir.config.MirPropertiesConfiguration.PropertiesConfigExc;
+
+
+
+public class PDFGenerator{
+
+  public Document document;
+  public PdfWriter writer;
+  public PdfContentByte cb;
+  public String localImageDir;
+  public float currentYPosition;
+  public int currentPage;
+  public float pageWidth;
+  public float pageHeight;
+  public float verticalMargin;
+  public float horizontalMargin;
+  public float topEdge;
+  public float bottomEdge;
+  public float rightEdge;
+  public float leftEdge;
+  public float footerHeight;
+  public String footerText;
+
+  protected LoggerWrapper logger;
+
+
+  protected MirPropertiesConfiguration configuration;
+
+
+  public PDFGenerator(ByteArrayOutputStream out){
+    logger = new LoggerWrapper("PDF.PDFGenerator");
+    try {
+      configuration = MirPropertiesConfiguration.instance();
+    }
+    catch (PropertiesConfigExc e) {
+      throw new RuntimeException("Can't get configuration: " + e.getMessage());
+    }
+    localImageDir=configuration.getString("Producer.Image.Path");
+    
+    // step 1: make a document
+    
+    String pageSize = configuration.getString("PDF.Pagesize");
+    
+    if (pageSize.equals("LETTER")){
+      document = new Document(PageSize.LETTER);
+      pageWidth = 612;
+      pageHeight = 792;
+    }
+    else {
+       document = new Document(PageSize.A4);
+       pageWidth=595;
+       pageHeight=842;
+    }
+
+    try {
+      
+      verticalMargin = 20;
+      horizontalMargin = 20;
+      
+      footerHeight = 54;
+
+      topEdge=pageHeight-verticalMargin;
+      bottomEdge=verticalMargin;
+      rightEdge=pageWidth-horizontalMargin;
+      leftEdge=horizontalMargin;
+      
+      currentYPosition=topEdge;
+      currentPage = 1;
+      
+      String headerText = configuration.getString("PDF.Title");
+      footerText = configuration.getString("PDF.Footer");
+
+      writer = PdfWriter.getInstance(document, out);
+      cb = writer.getDirectContent();
+
+      document.open();      
+
+      
+
+      ColumnText ct = new ColumnText(cb);   
+      //add a basic header
+      ct.addText(new Phrase(headerText, FontFactory.getFont(FontFactory.COURIER, 24,Font.BOLD)));
+      
+      float[] rightCol = {rightEdge,topEdge,rightEdge,topEdge-28};
+      float[] leftCol = {leftEdge,topEdge,leftEdge,topEdge-28};
+      //      int status = ct.go();
+      ct.setColumns(leftCol,rightCol);
+      //      int status=ct.go();
+      ct.setYLine(topEdge);
+      ct.setAlignment(Element.ALIGN_CENTER);
+      ct.go();
+      
+      currentYPosition = currentYPosition - 28;
+      
+    }
+    catch(DocumentException de) {
+      logger.error(de.getMessage());
+    }
+  }
+  
+  public void stop(){
+    addFooter();
+    document.close();
+  }
+
+  public void addIndexItem(EntityContent entityContent){
+    try {
+    float indexLineHeight = 16;
+    ColumnText ict = new ColumnText(cb);
+    String theTitle = entityContent.getValue("title");
+    String theCreator = entityContent.getValue("creator");
+    Phrase titleP=new Phrase(" - " +  theTitle,new Font(Font.HELVETICA,12,Font.BOLD));
+    Phrase creatorP=new Phrase( " :: " + theCreator,new Font(Font.HELVETICA,12));
+    float toYPosition = currentYPosition - indexLineHeight;
+    float[] leftIndexCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+    float[] rightIndexCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+    ict.addText(titleP);
+    ict.addText(creatorP);
+    ict.setColumns(leftIndexCols,rightIndexCols);
+    ict.setYLine(currentYPosition);
+    ict.setAlignment(Element.ALIGN_LEFT);
+    int status=ict.go();
+    currentYPosition = toYPosition;
+    }
+    catch(DocumentException de) {
+      logger.error(de.getMessage());
+    }
+    
+
+
+  }
+
+
+  public void addLine(){
+    cb.setLineWidth(1f);
+    cb.moveTo(rightEdge, currentYPosition-5);
+    cb.lineTo(leftEdge, currentYPosition-5);
+    cb.stroke();
+    currentYPosition = currentYPosition - 10;
+    
+  }
+  
+  public void addFooter(){
+    try{
+    ColumnText fct = new ColumnText(cb);
+    cb.setLineWidth(1f);
+    cb.moveTo(rightEdge, bottomEdge+footerHeight-5);
+    cb.lineTo(leftEdge, bottomEdge+footerHeight-5);
+    cb.stroke();
+    float[] leftFooterCols = {leftEdge,bottomEdge+footerHeight-1,leftEdge,bottomEdge};
+    float[] rightFooterCols = {rightEdge,bottomEdge+footerHeight-1,rightEdge,bottomEdge};
+    
+    Paragraph footerP=new Paragraph(footerText,new Font(Font.HELVETICA,12));
+    fct.addText(footerP);
+    
+    fct.setColumns(leftFooterCols,rightFooterCols);
+    fct.setYLine(bottomEdge+footerHeight-1);
+    fct.setAlignment(Element.ALIGN_JUSTIFIED);
+    int status=fct.go();
+
+    Paragraph numberP=new Paragraph((new Integer(currentPage)).toString(),new Font(Font.HELVETICA,12,Font.BOLD));
+    fct.addText(numberP);
+    fct.setAlignment(Element.ALIGN_RIGHT);
+    status=fct.go();
+
+    }
+    catch (DocumentException de){
+      logger.error(de.getMessage());
+    }
+
+
+  }
+
+  public void newPage(){
+    try{
+      //add a footer
+      addFooter();
+      document.newPage();   
+      currentPage++;
+      currentYPosition=topEdge;
+    }
+    catch(DocumentException de) {
+      logger.error(de.getMessage());
+    }
+  }
+  
+  public boolean enoughY(int heightOfBlockToAdd){
+    if ((currentYPosition - heightOfBlockToAdd - footerHeight) < bottomEdge )
+      return false;
+    else 
+      return true;
+  }
+  
+  
+  public void add(EntityContent entityContent){
+    logger.error("adding a content Entity");
+    EntityList images=DatabaseContentToMedia.getInstance().getImages(entityContent);
+    String theTitle = entityContent.getValue("title");
+    String theCreator = entityContent.getValue("creator");
+    String theDate = entityContent.getValue("webdb_create_formatted");
+    String theDescriptionRaw = entityContent.getValue("description");
+    String theContentRaw = entityContent.getValue("content_data");
+    String theSource =  configuration.getString("Producer.ProductionHost") + "/" + configuration.getString("StandardLanguage") + entityContent.getValue("publish_path") + entityContent.getValue("id") + ".shtml";
+
+    boolean addImageOnLeft = true;
+    
+    String theContent = "";
+    String theDescription = "";
+    
+    try { 
+      RE re1 = new RE("\r?\n\r?\n");
+      String theContent1 = re1.substituteAll(theContentRaw,"BREAKHERE");
+      String theDescription1 = re1.substituteAll(theDescriptionRaw,"BREAKHERE");
+      
+      RE re2 = new RE("\r?\n");
+      String theContent2 = re2.substituteAll(theContent1," ");
+      String theDescription2 = re2.substituteAll(theDescription1," ");
+      
+      RE re3 = new RE("BREAKHERE");
+      theContent = "    " + re3.substituteAll(theContent2,"\n    ");
+      theDescription = re3.substituteAll(theDescription2,"\n    ");
+
+    }
+    catch(REException ree){
+      logger.error(ree.getMessage());
+    }
+
+
+    try { 
+      
+      // make a line (don't worry about the bottomEdge, we should actually write in that area(it's a thin line!)
+      cb.setLineWidth(1f);
+      cb.moveTo(rightEdge, currentYPosition-5);
+      cb.lineTo(leftEdge, currentYPosition-5);
+      cb.stroke();
+      
+      currentYPosition = currentYPosition - 10;
+      
+
+      //see if we have room for the author and title
+      if (! enoughY(36)){
+       newPage();
+      }
+
+      ColumnText ct = new ColumnText(cb);
+
+      Paragraph titleP=new Paragraph(theTitle+"\n",new Font(Font.HELVETICA,14,Font.BOLD));
+      Paragraph whowhenP=new Paragraph(theCreator + "  " + theDate ,new Font(Font.HELVETICA,14));
+      ct.addText(titleP);
+      ct.addText(whowhenP);
+      
+      ct.setYLine(currentYPosition);
+      ct.setAlignment(Element.ALIGN_LEFT);
+      
+      float toYPosition = currentYPosition - 36;
+      float[] leftHeadCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+      float[] rightHeadCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+
+      ct.setColumns(leftHeadCols,rightHeadCols);
+      ct.go();
+      currentYPosition = toYPosition;
+    
+      
+      // Now add the description, one line at a time, the ct should be empty at this point
+            
+      Paragraph descP=new Paragraph(theDescription,new Font(Font.HELVETICA,12,Font.BOLD));
+
+      ct.addText(descP);
+      
+      // every article has a description, so we can assume that:
+      int status = ColumnText.NO_MORE_COLUMN;
+      
+      int descriptionLineHeight=16;
+      
+      while ((status & ColumnText.NO_MORE_TEXT) == 0){
+       //there is still text left in the description.
+       logger.error("adding a line to the description");
+       
+       //but is there room on the page?
+       if (! enoughY(descriptionLineHeight)){
+         newPage();
+       }
+       
+       //now we are set to add a line of descriptive text
+       toYPosition = currentYPosition - descriptionLineHeight;
+       float[] leftDescCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+       float[] rightDescCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+       ct.setColumns(leftDescCols,rightDescCols);
+       ct.setYLine(currentYPosition);
+       ct.setAlignment(Element.ALIGN_JUSTIFIED);
+       status=ct.go();
+       currentYPosition = toYPosition;
+      }
+      
+      // ok, now on to the meat of the job ahead
+      
+      int contentLineHeight=16;
+
+      //let's go ahead and add in all the body text
+      Paragraph contentP=new Paragraph(theContent,new Font(Font.HELVETICA,10));
+      ct.addText(contentP);
+      //and assume we have at least one line of text in the content
+      status = ColumnText.NO_MORE_COLUMN;
+
+      int maxImageHeight=250;
+      int maxImageWidth=250;
+
+      
+      // let's add a little bit of text, like a couple of lines
+      int x = 0;
+      while (((status & ColumnText.NO_MORE_TEXT) == 0) && x<3){
+       //in case we have some text left
+       
+       logger.error("adding a line to the content");
+
+       //but is there room on the page?
+       if (! enoughY(contentLineHeight)){
+         newPage();
+       }
+       
+       //now we are set to add a line of content text
+       toYPosition = currentYPosition - contentLineHeight;
+       float[] leftContentCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+       float[] rightContentCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+       ct.setColumns(leftContentCols,rightContentCols);
+       ct.setYLine(currentYPosition);
+       ct.setAlignment(Element.ALIGN_JUSTIFIED);
+       status=ct.go();
+       currentYPosition = toYPosition;
+       x++;
+      }
+
+
+
+      while (images.hasNext()){
+       
+       EntityImages currentImage=(EntityImages) images.next();
+       float img_width=(new Float(currentImage.getValue("img_width"))).floatValue();
+       float img_height=(new Float(currentImage.getValue("img_height"))).floatValue();
+       if (img_height>maxImageHeight){
+         img_width=(new Float((new Float(img_width*(maxImageHeight/img_height))).intValue())).floatValue();
+         img_height=maxImageHeight;
+       }
+       if (img_width>maxImageWidth){
+         img_height=(new Float((new Float(img_height*(maxImageWidth/img_width))).intValue())).floatValue();
+         img_width=maxImageWidth;
+       }
+
+       String img_title=currentImage.getValue("title");
+       String img_path=currentImage.getValue("publish_path");
+       
+         
+       
+
+       if ((status & ColumnText.NO_MORE_TEXT) == 0){ 
+         // there is still text, so add an image which will have text wrapped around it, then add the text which 
+         // will be on the left or the right of the image
+
+         float templateMinimumHeight = img_height+20;
+         float templateWidth = img_width+10;
+         
+         float templateHeight = templateMinimumHeight+contentLineHeight-(templateMinimumHeight % contentLineHeight);
+         
+         
+         PdfTemplate template = cb.createTemplate(templateWidth,templateHeight); 
+       
+         
+         //here we need a page check
+         if (! enoughY((new Float(templateHeight)).intValue())){
+           //ok, well just fill text to the bottom then
+           toYPosition = bottomEdge+footerHeight;
+           float[] leftBottomCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+           float[] rightBottomCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+           ct.setColumns(leftBottomCols,rightBottomCols);
+           ct.setYLine(currentYPosition);
+           ct.setAlignment(Element.ALIGN_JUSTIFIED);
+           status=ct.go();
+           newPage();
+         }
+
+         toYPosition=currentYPosition - templateHeight;
+         
+         Image theImage = Image.getInstance(localImageDir+img_path);
+         theImage.scaleAbsolute(img_width,img_height);
+         theImage.setAbsolutePosition(5,13); 
+         template.addImage(theImage);
+         template.beginText();
+         BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
+         template.setFontAndSize(bf, 8);
+         template.setTextMatrix(5, 3);
+         template.showText(img_title);
+         template.endText();
+         
+         
+         float leftImageTextEdge=leftEdge;
+         float rightImageTextEdge=rightEdge;
+         
+
+         if (addImageOnLeft){
+           cb.addTemplate(template,leftEdge,toYPosition);
+           leftImageTextEdge=leftEdge+templateWidth+5;
+           addImageOnLeft = false;
+         }         
+         else {
+           cb.addTemplate(template,rightEdge-templateWidth,toYPosition);
+           rightImageTextEdge = rightEdge-templateWidth-5;
+           addImageOnLeft = true;
+         }
+
+         logger.error("adding template at " + leftEdge + "," + toYPosition);
+         
+         //and fill some text while we are at it
+         
+         float[] leftBottomCols = {leftImageTextEdge,currentYPosition,leftImageTextEdge,toYPosition};
+         float[] rightBottomCols = {rightImageTextEdge,currentYPosition,rightImageTextEdge,toYPosition};
+         ct.setColumns(leftBottomCols,rightBottomCols);
+         ct.setYLine(currentYPosition);
+         ct.setAlignment(Element.ALIGN_JUSTIFIED);
+         status=ct.go();
+         
+         currentYPosition=toYPosition;
+         
+         
+         }
+       else { 
+         //add an image on the left with a big caption to the right
+         currentYPosition = currentYPosition - 10;
+         float templateMinimumHeight = img_height;
+         float templateWidth = img_width;
+         float templateHeight = templateMinimumHeight+contentLineHeight-(templateMinimumHeight % contentLineHeight);
+         PdfTemplate template = cb.createTemplate(templateWidth,templateHeight); 
+         if (! enoughY((new Float(templateHeight)).intValue())){
+           newPage();
+         }
+         toYPosition=currentYPosition - templateHeight;
+         Image theImage = Image.getInstance(localImageDir+img_path);
+         theImage.setAbsolutePosition(0,13); 
+         theImage.scaleAbsolute(img_width,img_height);
+         template.addImage(theImage);
+         
+         cb.addTemplate(template,leftEdge,toYPosition);
+         
+         // add a big caption
+         ColumnText cct = new ColumnText(cb);   
+         float[] leftCaptionCols = {leftEdge+templateWidth+5,currentYPosition-5,leftEdge+templateWidth+5,toYPosition};
+         float[] rightCaptionCols = {rightEdge,currentYPosition-5,rightEdge,toYPosition};
+         
+         Paragraph captionP=new Paragraph(img_title,new Font(Font.HELVETICA,16,Font.BOLD));
+         cct.addText(captionP);
+         cct.setColumns(leftCaptionCols,rightCaptionCols);
+         cct.setYLine(currentYPosition-5);
+         cct.setAlignment(Element.ALIGN_LEFT);
+         cct.go();
+
+         
+
+         currentYPosition=toYPosition;
+         
+
+       }
+       
+      }
+
+      
+      while ((status & ColumnText.NO_MORE_TEXT) == 0){
+       //in case we have some text left
+       
+       logger.error("adding a line to the content");
+
+       //but is there room on the page?
+       if (! enoughY(contentLineHeight)){
+         newPage();
+       }
+       
+       //now we are set to add a line of content text
+       toYPosition = currentYPosition - contentLineHeight;
+       float[] leftContentCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+       float[] rightContentCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+       ct.setColumns(leftContentCols,rightContentCols);
+       ct.setYLine(currentYPosition);
+       ct.setAlignment(Element.ALIGN_JUSTIFIED);
+       status=ct.go();
+       currentYPosition = toYPosition;
+
+      }
+      
+      // and add the source link 
+      
+      toYPosition = currentYPosition - contentLineHeight;
+      float[] leftSourceCols = {leftEdge,currentYPosition,leftEdge,toYPosition};
+      float[] rightSourceCols = {rightEdge,currentYPosition,rightEdge,toYPosition};
+      ct.setColumns(leftSourceCols,rightSourceCols);
+      Paragraph sourceP = new Paragraph(theSource,new Font(Font.COURIER,12,Font.BOLD));
+      ct.addText(sourceP);
+      ct.setYLine(currentYPosition);
+      ct.setAlignment(Element.ALIGN_RIGHT);
+      status=ct.go();
+      currentYPosition = toYPosition;
+
+
+      
+      
+      
+    }
+    catch(DocumentException de) {
+      logger.error(de.getMessage());
+    }
+    catch(MalformedURLException de) {
+      logger.error(de.getMessage());
+    }
+    catch(IOException de) {
+      logger.error(de.getMessage());
+    }
+    /*    while(images.hasNext()){
+      
+     EntityImages currentImage=(EntityImages) images.next();
+     float img_width=(new Float(currentImage.getValue("img_width"))).floatValue();
+     float img_height=(new Float(currentImage.getValue("img_height"))).floatValue();
+      if (img_width>250){
+       img_height=(new Float((new Float(img_height*(250.0F/img_width))).intValue())).floatValue();
+       img_width=250.0F;
+      }
+      String img_title=currentImage.getValue("title");
+      String img_path=currentImage.getValue("publish_path");
+
+      PdfTemplate template = cb.createTemplate(img_width+10, img_height+20); 
+      try{
+       Image theImage = Image.getInstance(localImageDir+img_path);
+       theImage.setAbsolutePosition(5,13); 
+       template.addImage(theImage);
+       template.beginText();
+       BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
+       template.setFontAndSize(bf, 8);
+       template.setTextMatrix(5, 3);
+       template.showText(img_title);
+       template.endText();
+       ImgTemplate it = new ImgTemplate(template);
+       it.setAlignment(Image.RIGHT | Image.TEXTWRAP);
+       document.add(it);
+       
+       document.add(new Paragraph("this is a test of adding some text to see if we bump down a line when there is some text"));
+       
+      }
+      catch(DocumentException de) {
+       System.err.println(de.getMessage());
+      }
+      catch(IOException ioe) {
+       System.err.println(ioe.getMessage());
+      }
+      } */
+
+    /*
+    try { 
+
+      
+      Paragraph p=new Paragraph(theContent,new Font(Font.HELVETICA,11));
+      p.setAlignment(Paragraph.ALIGN_JUSTIFIED);
+      
+      document.add(p);
+    }
+    catch(DocumentException de) {
+      System.err.println(de.getMessage());
+    }
+
+    */
+
+  }
+
+}
+
+