aboutsummaryrefslogtreecommitdiff
path: root/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java')
-rw-r--r--pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java618
1 files changed, 618 insertions, 0 deletions
diff --git a/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java
new file mode 100644
index 0000000..1145619
--- /dev/null
+++ b/pdf-as-lib/src/main/java/at/knowcenter/wag/egov/egiz/pdf/PDFSignatureObjectIText.java
@@ -0,0 +1,618 @@
+/**
+ * <copyright> Copyright 2006 by Know-Center, Graz, Austria </copyright>
+ * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a
+ * joint initiative of the Federal Chancellery Austria and Graz University of
+ * Technology.
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://www.osor.eu/eupl/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ *
+ * This product combines work with different licenses. See the "NOTICE" text
+ * file for details on the various modules and licenses.
+ * The "NOTICE" text file is part of the distribution. Any derivative works
+ * that you distribute must include a readable copy of the "NOTICE" text file.
+ *
+ * $Id: PDFSignatureObjectIText.java,v 1.5 2006/10/31 08:09:33 wprinz Exp $
+ */
+package at.knowcenter.wag.egov.egiz.pdf;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+
+import at.gv.egiz.pdfas.exceptions.ErrorCode;
+import at.knowcenter.wag.egov.egiz.cfg.ConfigLogger;
+import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
+import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException;
+import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
+import at.knowcenter.wag.egov.egiz.sig.SignatureObject;
+import at.knowcenter.wag.egov.egiz.table.Entry;
+import at.knowcenter.wag.egov.egiz.table.Style;
+import at.knowcenter.wag.egov.egiz.table.Table;
+
+import com.lowagie.text.BadElementException;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Element;
+import com.lowagie.text.Font;
+import com.lowagie.text.Image;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.pdf.BaseFont;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.SubsetLocal;
+
+/**
+ * This class is the IText implementation of the PDFSignatureObject interface.
+ * The class takes an abstract definition of a signature object and convert them
+ * into a pdf table that is used to sign a pdf document.
+ *
+ * @author wlackner
+ * @see at.knowcenter.wag.egov.egiz.sig.SignatureObject
+ * @see at.knowcenter.wag.egov.egiz.table.Table
+ * @see at.knowcenter.wag.egov.egiz.table.Entry
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ * @see com.lowagie.text.pdf.PdfPTable
+ * @see at.knowcenter.wag.egov.egiz.cfg.SettingsReader
+ */
+public class PDFSignatureObjectIText implements PDFSignatureObject
+{
+
+// 03.11.2010 changed by exthex to allow setting separate hAlign and vAlign for value and non-value cells.
+// If no value for valuevalign or valuehalign is set the values from valign and halign are taken.
+// Also fixed a minor bug which prevented proper style inheritment (Bug Nr. #534).
+// 04.11.2010 changed by exthex - allow setting separate hAlign and vAlign for image cells analog to value cells.
+
+ private static final String SIG_PDFA1_B_VALID = "SIG_PDFA1B_VALID";
+
+/**
+ * The default font definition
+ */
+ private static Font DEFAULT_FONT = new Font(Font.HELVETICA, 8, Font.NORMAL);
+
+ /**
+ * The abstract signature object
+ */
+ private SignatureObject sigObject_ = null;
+
+ /**
+ * The IText pdf table object
+ */
+ private PdfPTable pdfSigObject_ = null;
+
+ /**
+ * The SettingsReader instance
+ */
+ private SettingsReader settings_ = null;
+
+ /**
+ * The logger definition.
+ */
+ private static final Logger logger_ = ConfigLogger.getLogger(PDFSignatureObjectIText.class);
+
+ /**
+ * Map the style align definitions to IText's align statements
+ */
+ private static HashMap alignMap_ = new HashMap();
+
+ /**
+ * Map the font definitions to IText's font statements
+ */
+ private static HashMap fontMap_ = new HashMap();
+
+ /**
+ * The empty constructor. It loads the ui definitions from signature tables
+ * and init the align map.
+ *
+ * @throws PDFDocumentException
+ */
+ public PDFSignatureObjectIText() throws PDFDocumentException
+ {
+ loadSettings();
+ initStyleMaps();
+ }
+
+ /**
+ * load the class settings
+ *
+ * @throws PDFDocumentException
+ * @see SettingsReader
+ */
+ private void loadSettings() throws PDFDocumentException
+ {
+ if (settings_ == null)
+ {
+ try
+ {
+ settings_ = SettingsReader.getInstance();
+ }
+ catch (SettingsException e)
+ {
+ String log_message = "Can not load pdf signature settings. Cause:\n" + e.getMessage();
+ logger_.error(log_message);
+ throw new PDFDocumentException(101, log_message, e);
+ }
+ }
+ }
+
+ /**
+ * This method initialize the style maps. It maps the style style definitions
+ * to IText styles.
+ */
+ private void initStyleMaps()
+ {
+ alignMap_.put(Style.TOP, new Integer(Element.ALIGN_TOP));
+ alignMap_.put(Style.MIDDLE, new Integer(Element.ALIGN_MIDDLE));
+ alignMap_.put(Style.BOTTOM, new Integer(Element.ALIGN_BOTTOM));
+ alignMap_.put(Style.LEFT, new Integer(Element.ALIGN_LEFT));
+ alignMap_.put(Style.CENTER, new Integer(Element.ALIGN_CENTER));
+ alignMap_.put(Style.RIGHT, new Integer(Element.ALIGN_RIGHT));
+
+ fontMap_.put(Style.HELVETICA, new Integer(Font.HELVETICA));
+ fontMap_.put(Style.TIMES_ROMAN, new Integer(Font.TIMES_ROMAN));
+ fontMap_.put(Style.COURIER, new Integer(Font.COURIER));
+ fontMap_.put(Style.NORMAL, new Integer(Font.NORMAL));
+ fontMap_.put(Style.BOLD, new Integer(Font.BOLD));
+ fontMap_.put(Style.ITALIC, new Integer(Font.ITALIC));
+ fontMap_.put(Style.BOLDITALIC, new Integer(Font.BOLDITALIC));
+ fontMap_.put(Style.UNDERLINE, new Integer(Font.UNDERLINE));
+ fontMap_.put(Style.STRIKETHRU, new Integer(Font.STRIKETHRU));
+ }
+
+ /**
+ * Set the abstract signature definition.
+ *
+ * @param signatorObject
+ * the abstract signator object
+ * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#setSignatorObject(at.knowcenter.wag.egov.egiz.sig.SignatureObject)
+ */
+ public void setSignatorObject(SignatureObject signatorObject)
+ {
+ sigObject_ = signatorObject;
+ }
+
+ /**
+ * This method maps the table cell definitions to the pdfCell element.
+ *
+ * @param pdfCell
+ * the pdf cell to be styled
+ * @param cellStyle
+ * the abstract style definition
+ * @param type
+ * type of the cell to render - the appropriate style will be set
+ * @see com.lowagie.text.pdf.PdfPCell
+ * @see at.knowcenter.wag.egov.egiz.table.Style
+ */
+ private void setCellStyle(PdfPCell pdfCell, Style cellStyle, int type)
+ {
+ if (cellStyle != null)
+ {
+ if (cellStyle.getBgColor() != null)
+ {
+ pdfCell.setBackgroundColor(cellStyle.getBgColor());
+ }
+ pdfCell.setPadding(cellStyle.getPadding());
+ //exthex - fix for not exactly vertically centered text
+ pdfCell.setUseAscender(true);
+
+ if (cellStyle.getBorder() > 0)
+ {
+ pdfCell.setBorderWidth(cellStyle.getBorder());
+ }
+ else
+ {
+ pdfCell.setBorder(0);
+ }
+ int align = -1;
+ if (type == Entry.TYPE_VALUE && cellStyle.getValueVAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getValueVAlign())).intValue();
+ //Note: to change the default valign of images to those of values, change the if construct below
+ else if (type == Entry.TYPE_IMAGE && cellStyle.getImageVAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getImageVAlign())).intValue();
+ else if (cellStyle.getVAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getVAlign())).intValue();
+ if (align != -1)
+ pdfCell.setVerticalAlignment(align);
+
+ align = -1;
+ if (type == Entry.TYPE_VALUE && cellStyle.getValueHAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getValueHAlign())).intValue();
+ //Note: to change the default halign of images to those of values, change the if construct below
+ else if (type == Entry.TYPE_IMAGE && cellStyle.getImageHAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getImageHAlign())).intValue();
+ else if (cellStyle.getHAlign() != null)
+ align = ((Integer) alignMap_.get(cellStyle.getHAlign())).intValue();
+ if (align != -1)
+ pdfCell.setHorizontalAlignment(align);
+ }
+ }
+
+ /**
+ * This method maps the cell font definition to the iText Font Object
+ *
+ * @param fontString
+ * @return the corresponding iText Font Object
+ * @see com.lowagie.text.Font
+ */
+ private Font getCellFont(String fontString)
+ {
+ Font font = DEFAULT_FONT;
+ if (fontString == null)
+ {
+ return font;
+ }
+ Object cache_font = fontMap_.get(fontString);
+ if (cache_font != null)
+ {
+ return (Font) cache_font;
+ }
+ String[] font_arr = fontString.split(",");
+ if (font_arr.length != 3)
+ {
+ return font;
+ }
+ Object font_face = fontMap_.get(font_arr[0]);
+ if (font_face == null)
+ {
+ return font;
+ }
+ Object font_weight = fontMap_.get(font_arr[2]);
+ if (font_weight == null)
+ {
+ return font;
+ }
+ int face = ((Integer) font_face).intValue();
+ float height = Float.parseFloat(font_arr[1]);
+ int weight = ((Integer) font_weight).intValue();
+
+ font = new Font(face, height, weight);
+ fontMap_.put(fontString, font);
+ return font;
+ }
+
+ /**
+ * Creates a custom
+ * @param fontString
+ * @return
+ * @throws PDFDocumentException
+ */
+ private Font getCellTrueTypeFont(String fontString) throws PDFDocumentException {
+ float fontSize=8;
+ String fontName = fontString.replaceFirst("TTF:", "");
+ String[] split = fontName.split(",");
+ if(split.length>1)
+ {
+ fontName = split[0].trim();
+ try
+ {
+ fontSize = Float.parseFloat(split[1].trim());
+ }catch (NumberFormatException e)
+ {
+ logger_.error("Unable to parse fontsize:"+fontString);
+ }
+ }
+ logger_.debug("TrueType Font detected:"+fontName +" ("+fontSize+")");
+
+ try {
+ Font font = (Font) fontMap_.get(fontString);
+
+ if (font == null) {
+ logger_.debug("Font \"" + fontString + "\" not in cache. Instantiating font.");
+ String fontPath = SettingsReader.RESOURCES_PATH + "fonts" + File.separator + fontName;
+ logger_.debug("Instantiating \"" + fontPath + "\".");
+
+ font = new Font(BaseFont.createFont(fontPath, BaseFont.WINANSI, true), fontSize);
+ fontMap_.put(fontString, font);
+ }
+ return font;
+ } catch (DocumentException e) {
+ throw new PDFDocumentException(ErrorCode.FONT_NOT_FOUND, e.getMessage());
+ } catch (IOException e) {
+ throw new PDFDocumentException(ErrorCode.FONT_NOT_FOUND, e.getMessage());
+ }
+ }
+
+ /**
+ * This method visualize an abstract table cell into a corresponding pdf table
+ * cell. The new pdf table cell is redered and get the style information from
+ * the abstract cell. Following types can be rendered:
+ * <ul>
+ * <li>text statements</li>
+ * <li>images</li>
+ * <li>tables</li>
+ * </ul>
+ *
+ * @param abstractCell
+ * the abstract cell definition
+ * @return the new redererd pdf table cell
+ * @throws PDFDocumentException
+ * ErrorCode:220, 221, 222
+ * @see com.lowagie.text.pdf.PdfPCell
+ * @see at.knowcenter.wag.egov.egiz.table.Entry
+ */
+ private PdfPCell renderCell(Entry abstractCell) throws PDFDocumentException
+ {
+ boolean pdfaValid =false;
+ try
+ {
+ String profileid = sigObject_.getSignatureTypeDefinition().getType();
+ String pdfa = SettingsReader.getInstance().getSetting("sig_obj." +profileid+".key."+SIG_PDFA1_B_VALID, "default."+SIG_PDFA1_B_VALID, "false");
+ pdfaValid= "true".equalsIgnoreCase(pdfa);
+
+// exthex test
+ //SubsetLocal.set(!pdfaValid);
+
+// boolean forceSubset = true; // get this from config, default to false
+ //String
+
+ //SubsetLocal.set(true); // exthex
+
+ logger_.trace("Sign PDF/A compliant:"+pdfa);
+ } catch (SettingsException e1)
+ {
+ logger_.error(e1);
+ }
+
+ PdfPCell pdf_cell = null;
+ Style cell_style = abstractCell.getStyle();
+ boolean isValue = true;
+ switch (abstractCell.getType())
+ {
+ case Entry.TYPE_CAPTION:
+ isValue = false;
+ case Entry.TYPE_VALUE:
+ String text = (String) abstractCell.getValue();
+ if (text == null)
+ {
+ text = "";
+ }
+ String font_string = cell_style.getFont();
+ if (abstractCell.getType() == Entry.TYPE_VALUE && cell_style.getValueFont() != null)
+ {
+ font_string = cell_style.getValueFont();
+ }
+
+ logger_.trace("using cell font: "+font_string);
+
+ Font cell_font;
+ if(font_string.startsWith("TTF:"))
+ {
+ cell_font = getCellTrueTypeFont(font_string);
+ }
+ else
+ {
+ if (pdfaValid) {
+ throw new PDFDocumentException(ErrorCode.NO_EMBEDABLE_TTF_CONFIGURED_FOR_PDFA, "PDF/A modus requires an embedable true type font");
+ }
+ cell_font = getCellFont(font_string);
+
+ }
+ // exthex
+ if (pdfaValid && abstractCell.getType() == Entry.TYPE_VALUE) {
+ SubsetLocal.addNonSubsetFont(cell_font.getBaseFont());
+ }
+ Phrase text_phrase = new Phrase(text, cell_font);
+ pdf_cell = new PdfPCell(text_phrase);
+ setCellStyle(pdf_cell, cell_style, (isValue?Entry.TYPE_VALUE:Entry.TYPE_CAPTION));
+ break;
+ case Entry.TYPE_IMAGE:
+ try
+ {
+ String img_ref = (String) abstractCell.getValue();
+ // fixed by tknall start
+ File img_file = new File(img_ref);
+ if (!img_file.isAbsolute()) {
+ logger_.debug("Image file declaration is relative. Prepending path of resources directory.");
+ img_file = new File(SettingsReader.relocateFile(img_ref));
+ } else {
+ logger_.debug("Image file declaration is absolute. Skipping file relocation.");
+ }
+// String img_location = SettingsReader.relocateFile(img_ref);
+// File img_file = new File (img_location);
+ if (!img_file.exists())
+ {
+ logger_.debug("Image file \"" + img_file.getCanonicalPath() + "\" doesn't exist.");
+ throw new PDFDocumentException(220, "Image file \"" + img_file.getCanonicalPath() + "\" doesn't exist.");
+ }
+ Image image = Image.getInstance(img_file.getCanonicalPath());
+ logger_.debug("Using image file \"" + img_file.getCanonicalPath() + "\".");
+
+ image.scaleToFit(80.0f, 80.0f);
+ boolean fit = true;
+ Style.ImageScaleToFit istf = cell_style.getImageScaleToFit();
+ if (istf != null)
+ {
+ image.scaleToFit(istf.getWidth(), istf.getHeight());
+ fit = false;
+ }
+ pdf_cell = new PdfPCell(image, fit);
+ setCellStyle(pdf_cell, cell_style, Entry.TYPE_IMAGE);
+ }
+ catch (BadElementException e)
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("BadElementException:" + e.getMessage());
+ }
+ PDFDocumentException pde = new PDFDocumentException(220, "PDF table can not created");
+ throw pde;
+ }
+ catch (MalformedURLException e)
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("MalformedURLException:" + e.getMessage());
+ }
+ PDFDocumentException pde = new PDFDocumentException(221, "PDF table can not created");
+ throw pde;
+ }
+ catch (IOException e)
+ {
+ if (logger_.isEnabledFor(Level.ERROR))
+ {
+ logger_.error("Error Code: 222, IOException:" + e.getMessage());
+ }
+ PDFDocumentException pde = new PDFDocumentException(222, "PDF table can not created: Image can not loaded");
+ throw pde;
+ }
+ break;
+ case Entry.TYPE_TABLE:
+ Table table = (Table) abstractCell.getValue();
+ // inherit the style from the parent table
+ Style inherit_style = Style.doInherit(table.getStyle(), cell_style);
+ table.setStyle(inherit_style);
+ PdfPTable pdf_table = renderTable(table);
+ pdf_cell = new PdfPCell(pdf_table);
+ // The default new PdfPCell has a default border of 15.
+ // For blocks without border and subtables this results
+ // in a border to be drawn around the cell.
+ // ==> no border on default
+ pdf_cell.setBorder(0);
+ break;
+ }
+ return pdf_cell;
+ }
+
+ /**
+ * This method visualize an abstract table into a corresponding pdf table. The
+ * new pdf table is redered and get the style information from the abstract
+ * cell.
+ *
+ * @param abstractTable
+ * the abstract table definition
+ * @return the new redererd pdf table cell
+ * @throws PDFDocumentException
+ * ErrorCode:220, 221, 222, 223
+ * @see com.lowagie.text.pdf.PdfPTable
+ * @see at.knowcenter.wag.egov.egiz.table.Table
+ */
+ private PdfPTable renderTable(Table abstractTable) throws PDFDocumentException
+ {
+ if (abstractTable == null)
+ {
+ PDFDocumentException pde = new PDFDocumentException(223, "Table is not defined.");
+ throw pde;
+ }
+ PdfPTable pdf_table = null;
+ float[] cols = abstractTable.getColsRelativeWith();
+ int max_cols = abstractTable.getMaxCols();
+ if (cols == null)
+ {
+ cols = new float[max_cols];
+ // set the column ratio for all columns to 1
+ for (int cols_idx = 0; cols_idx < cols.length; cols_idx++)
+ {
+ cols[cols_idx] = 1;
+ }
+ }
+ pdf_table = new PdfPTable(cols);
+ pdf_table.setWidthPercentage(abstractTable.getWidth());
+ Style table_style = abstractTable.getStyle();
+ setCellStyle(pdf_table.getDefaultCell(), table_style, Entry.TYPE_TABLE);
+
+ ArrayList rows = abstractTable.getRows();
+ for (int row_idx = 0; row_idx < rows.size(); row_idx++)
+ {
+ ArrayList row = (ArrayList) rows.get(row_idx);
+ // logger_.debug("## Row:" + row_idx + " ## of table:" +
+ // abstractTable.getName());
+ for (int entry_idx = 0; entry_idx < row.size(); entry_idx++)
+ {
+ Entry cell = (Entry) row.get(entry_idx);
+ // 03.11.2010 changed by exthex - swapped the two params, was probably a bug
+ Style inherit_style = Style.doInherit(table_style, cell.getStyle());
+ cell.setStyle(inherit_style);
+ // logger_.debug(cell.toString());
+ PdfPCell pdf_cell = renderCell(cell);
+ if (cell.getColSpan() > 1)
+ {
+ pdf_cell.setColspan(cell.getColSpan());
+ }
+ if (cell.isNoWrap())
+ {
+ pdf_cell.setNoWrap(true);
+ }
+ // System.err.println("valign:" + pdf_cell.getVerticalAlignment() + "
+ // halign:" +
+ // pdf_cell.getHorizontalAlignment());
+ pdf_table.addCell(pdf_cell);
+ }
+ }
+ // logger_.debug("render table:" + abstractTable.getName());
+ return pdf_table;
+ }
+
+ /**
+ * This method creates the pdf table object. It takes the abstract table
+ * definition from the signature object and render the abstract table.
+ *
+ * @param sigObject
+ * the signature object, the base for the abstract table definition
+ * @return R
+ * @throws PDFDocumentException
+ * ErrorCode:220, 221, 222, 223
+ */
+ private PdfPTable createPDFSignatureObject(SignatureObject sigObject) throws PDFDocumentException
+ {
+ SubsetLocal.clear();
+ Table table = sigObject.getAbstractTable();
+ PdfPTable pdf_table = renderTable(table);
+ return pdf_table;
+ }
+
+ /*
+ * This method search for the table definitions in the settings file an init
+ * @param sigObject
+ */
+ /*
+ * private void initTableSettings(SignatureObject sigObject) { String sig_type =
+ * sigObject.getSignationType(); String table_key = SignatureObject.SIG_OBJ +
+ * sig_type + ".table."; ArrayList main_rows = settings_.getKeys(table_key +
+ * "main"); }
+ */
+
+ /**
+ * Converts the current abstract signature object in a pdf signature object
+ * implementation
+ *
+ * @return the converted pdf signature object
+ * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#getSignatureObject()
+ */
+ public Object getSignatureObject() throws PDFDocumentException
+ {
+ if (pdfSigObject_ == null)
+ {
+ pdfSigObject_ = (PdfPTable) getSignatureObject(sigObject_);
+ }
+ return pdfSigObject_;
+ }
+
+ /**
+ * Converts a abstract signature object in a pdf signature object
+ * implementation
+ *
+ * @param sigObject
+ * the abstract signatorObject to convert
+ * @return the converted pdf signature object
+ * @throws PDFDocumentException
+ * @see at.knowcenter.wag.egov.egiz.pdf.PDFSignatureObject#getSignatureObject(at.knowcenter.wag.egov.egiz.sig.SignatureObject)
+ */
+ public Object getSignatureObject(SignatureObject sigObject) throws PDFDocumentException
+ {
+ // initTableSettings(sigObject);
+ return createPDFSignatureObject(sigObject);
+ }
+} \ No newline at end of file