From commits-return-14135-archive-asf-public=cust-asf.ponee.io@pdfbox.apache.org Sun Jan 27 10:36:14 2019 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id 6F4AD180600 for ; Sun, 27 Jan 2019 10:36:13 +0100 (CET) Received: (qmail 41614 invoked by uid 500); 27 Jan 2019 09:36:12 -0000 Mailing-List: contact commits-help@pdfbox.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@pdfbox.apache.org Delivered-To: mailing list commits@pdfbox.apache.org Received: (qmail 41605 invoked by uid 99); 27 Jan 2019 09:36:12 -0000 Received: from Unknown (HELO svn01-us-west.apache.org) (209.188.14.144) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 27 Jan 2019 09:36:12 +0000 Received: from svn01-us-west.apache.org (localhost [127.0.0.1]) by svn01-us-west.apache.org (ASF Mail Server at svn01-us-west.apache.org) with ESMTP id 07A0C3A0069 for ; Sun, 27 Jan 2019 09:36:07 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1852275 - in /pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf: FDFAnnotationStamp.java FDFStampAnnotationAppearance.java Date: Sun, 27 Jan 2019 09:36:07 -0000 To: commits@pdfbox.apache.org From: tilman@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20190127093607.07A0C3A0069@svn01-us-west.apache.org> Author: tilman Date: Sun Jan 27 09:36:06 2019 New Revision: 1852275 URL: http://svn.apache.org/viewvc?rev=1852275&view=rev Log: PDFBOX-4437: refactor xml into main class Removed: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFStampAnnotationAppearance.java Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStamp.java Modified: pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStamp.java URL: http://svn.apache.org/viewvc/pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStamp.java?rev=1852275&r1=1852274&r2=1852275&view=diff ============================================================================== --- pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStamp.java (original) +++ pdfbox/branches/2.0/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fdf/FDFAnnotationStamp.java Sun Jan 27 09:36:06 2019 @@ -18,6 +18,7 @@ package org.apache.pdfbox.pdmodel.fdf; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.OutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -28,13 +29,18 @@ import javax.xml.xpath.XPathFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSDictionary; +import org.apache.pdfbox.cos.COSFloat; import org.apache.pdfbox.cos.COSName; +import org.apache.pdfbox.cos.COSStream; import org.apache.pdfbox.util.Hex; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.xml.sax.SAXException; /** @@ -123,7 +129,7 @@ public class FDFAnnotationStamp extends + "root should be 'dict' and not '" + appearanceEl.getNodeName() + "'"); } LOG.debug("Generate and set the appearance dictionary to the stamp annotation"); - annot.setItem(COSName.AP, new FDFStampAnnotationAppearance(appearanceEl)); + annot.setItem(COSName.AP, parseStampAnnotationAppearanceXML(appearanceEl)); } } @@ -151,4 +157,224 @@ public class FDFAnnotationStamp extends throw new IOException(ex); } } + + /** + * This will create an Appearance dictionary from an appearance XML document. + * + * @param fdfXML The XML document that contains the appearance data. + */ + private COSDictionary parseStampAnnotationAppearanceXML(Element appearanceXML) throws IOException + { + COSDictionary dictionary = new COSDictionary(); + // the N entry is required. + dictionary.setItem(COSName.N, new COSStream()); + LOG.debug("Build dictionary for Appearance based on the appearanceXML"); + + NodeList nodeList = appearanceXML.getChildNodes(); + String parentAttrKey = appearanceXML.getAttribute("KEY"); + LOG.debug("Appearance Root - tag: " + appearanceXML.getTagName() + ", name: " + + appearanceXML.getNodeName() + ", key: " + parentAttrKey + ", children: " + + nodeList.getLength()); + + // Currently only handles Appearance dictionary (AP key on the root) + if (!"AP".equals(appearanceXML.getAttribute("KEY"))) + { + LOG.warn(parentAttrKey + " => Not handling element: " + appearanceXML.getTagName() + + " with key: " + appearanceXML.getAttribute("KEY")); + return dictionary; + } + for (int i = 0; i < nodeList.getLength(); i++) + { + Node node = nodeList.item(i); + if (node instanceof Element) + { + Element child = (Element) node; + if ("STREAM".equalsIgnoreCase(child.getTagName())) + { + LOG.debug(parentAttrKey + + " => Process " + child.getAttribute("KEY") + + " item in the dictionary after processing the " + + child.getTagName()); + dictionary.setItem(child.getAttribute("KEY"), parseStreamElement(child)); + LOG.debug(parentAttrKey + " => Set " + child.getAttribute("KEY")); + } + else + { + LOG.warn(parentAttrKey + " => Not handling element: " + child.getTagName()); + } + } + } + return dictionary; + } + + private COSStream parseStreamElement(Element streamEl) throws IOException + { + COSStream stream = new COSStream(); + + NodeList nodeList = streamEl.getChildNodes(); + String parentAttrKey = streamEl.getAttribute("KEY"); + + for (int i = 0; i < nodeList.getLength(); i++) + { + Node node = nodeList.item(i); + if (node instanceof Element) + { + Element child = (Element) node; + String childAttrKey = child.getAttribute("KEY"); + String childAttrVal = child.getAttribute("VAL"); + LOG.debug(parentAttrKey + " => reading child: " + child.getTagName() + + " with key: " + childAttrKey); + if ("INT".equalsIgnoreCase(child.getTagName())) + { + if (!"Length".equals(childAttrKey)) + { + stream.setInt(COSName.getPDFName(childAttrKey), Integer.parseInt(childAttrVal)); + LOG.debug(parentAttrKey + " => Set " + childAttrKey + ": " + childAttrVal); + } + } + else if ("NAME".equalsIgnoreCase(child.getTagName())) + { + stream.setName(COSName.getPDFName(childAttrKey), childAttrVal); + LOG.debug(parentAttrKey + " => Set " + childAttrKey + ": " + childAttrVal); + } + else if ("BOOL".equalsIgnoreCase(child.getTagName())) + { + stream.setBoolean(COSName.getPDFName(childAttrKey), Boolean.parseBoolean(childAttrVal)); + LOG.debug(parentAttrKey + " => Set Interpolate: " + childAttrVal); + } + else if ("ARRAY".equalsIgnoreCase(child.getTagName())) + { + stream.setItem(COSName.getPDFName(childAttrKey), parseArrayElement(child)); + LOG.debug(parentAttrKey + " => Set " + childAttrKey); + } + else if ("DICT".equalsIgnoreCase(child.getTagName())) + { + stream.setItem(COSName.getPDFName(childAttrKey), parseDictElement(child)); + LOG.debug(parentAttrKey + " => Set " + childAttrKey); + } + else if ("STREAM".equalsIgnoreCase(child.getTagName())) + { + stream.setItem(COSName.getPDFName(childAttrKey), parseStreamElement(child)); + LOG.debug(parentAttrKey + " => Set " + childAttrKey); + } + else if ("DATA".equalsIgnoreCase(child.getTagName())) + { + LOG.debug(parentAttrKey + " => Handling DATA with encoding: " + + child.getAttribute("ENCODING")); + if ("HEX".equals(child.getAttribute("ENCODING"))) + { + OutputStream os = null; + try + { + os = stream.createRawOutputStream(); + os.write(Hex.decodeHex(child.getTextContent())); + LOG.debug(parentAttrKey + " => Data was streamed"); + } + finally + { + if (os != null) + { + os.close(); + } + } + } + else + { + LOG.warn(parentAttrKey + " => Not handling element DATA encoding: " + + child.getAttribute("ENCODING")); + } + } + else + { + LOG.warn(parentAttrKey + " => Not handling child element: " + child.getTagName()); + } + } + } + + return stream; + } + + private COSArray parseArrayElement(Element arrayEl) throws IOException + { + LOG.debug("Parse " + arrayEl.getAttribute("KEY") + " Array"); + COSArray array = new COSArray(); + NodeList nodeList = arrayEl.getElementsByTagName("FIXED"); + String elAttrKey = arrayEl.getAttribute("KEY"); + + if ("BBox".equals(elAttrKey)) + { + if (nodeList.getLength() < 4) + { + throw new IOException("BBox does not have enough coordinates, only has: " + + nodeList.getLength()); + } + } + else if ("Matrix".equals(elAttrKey)) + { + if (nodeList.getLength() < 6) + { + throw new IOException("Matrix does not have enough coordinates, only has: " + + nodeList.getLength()); + } + } + + LOG.debug("There are " + nodeList.getLength() + " FIXED elements"); + + for (int i = 0; i < nodeList.getLength(); i++) + { + Node node = nodeList.item(i); + if (node instanceof Element) + { + Element el = (Element) node; + LOG.debug(elAttrKey + " value(" + i + "): " + el.getAttribute("VAL")); + array.add(new COSFloat(el.getAttribute("VAL"))); + } + } + + return array; + } + + private COSDictionary parseDictElement(Element dictEl) throws IOException + { + LOG.debug("Parse " + dictEl.getAttribute("KEY") + " Dictionary"); + COSDictionary dict = new COSDictionary(); + + NodeList nodeList = dictEl.getChildNodes(); + String parentAttrKey = dictEl.getAttribute("KEY"); + + for (int i = 0; i < nodeList.getLength(); i++) + { + Node node = nodeList.item(i); + if (node instanceof Element) + { + Element child = (Element) node; + String childAttrKey = child.getAttribute("KEY"); + String childAttrVal = child.getAttribute("VAL"); + + if ("DICT".equals(child.getTagName())) + { + LOG.debug(parentAttrKey + " => Handling DICT element with key: " + childAttrKey); + dict.setItem(COSName.getPDFName(childAttrKey), parseDictElement(child)); + LOG.debug(parentAttrKey + " => Set " + childAttrKey); + } + else if ("STREAM".equals(child.getTagName())) + { + LOG.debug(parentAttrKey + " => Handling STREAM element with key: " + childAttrKey); + dict.setItem(COSName.getPDFName(childAttrKey), parseStreamElement(child)); + } + else if ("NAME".equals(child.getTagName())) + { + LOG.debug(parentAttrKey + " => Handling NAME element with key: " + childAttrKey); + dict.setName(COSName.getPDFName(childAttrKey), childAttrVal); + LOG.debug(parentAttrKey + " => Set " + childAttrKey + ": " + childAttrVal); + } + else + { + LOG.warn(parentAttrKey + " => NOT handling child element: " + child.getTagName()); + } + } + } + + return dict; + } }