From e6db5791c4c38626c88953a3f9060655bc8b9ab9 Mon Sep 17 00:00:00 2001 From: Yannik Hampe Date: Mon, 29 May 2017 19:08:24 +0200 Subject: [PATCH 1/2] Deleted code which is now duplicated in the ZUGFeRDExporterFromA1Factory due to merge conflicts and mark old API as deprecated --- .../ZUGFeRD/ZUGFeRDExporter.java | 252 +++++------------- .../ZUGFeRD/ZUGFeRDExporterFromA1Factory.java | 3 +- .../ZUGFeRD/model/PDFAConformanceLevel.java | 15 -- 3 files changed, 68 insertions(+), 202 deletions(-) delete mode 100644 src/main/java/org/mustangproject/ZUGFeRD/model/PDFAConformanceLevel.java diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java index f8561001..87af9afa 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java @@ -13,7 +13,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; @@ -28,7 +27,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.activation.FileDataSource; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; @@ -36,30 +34,16 @@ import javax.xml.bind.Marshaller; import javax.xml.transform.TransformerException; -import org.apache.xmpbox.XMPMetadata; -import org.apache.xmpbox.schema.XMPBasicSchema; -import org.apache.xmpbox.schema.DublinCoreSchema; -import org.apache.xmpbox.schema.AdobePDFSchema; -import org.apache.xmpbox.schema.PDFAIdentificationSchema; import org.apache.pdfbox.cos.COSArray; import org.apache.pdfbox.cos.COSBase; import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentCatalog; -import org.apache.pdfbox.pdmodel.PDDocumentInformation; import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary; import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode; -import org.apache.pdfbox.pdmodel.common.PDMetadata; import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; -import org.apache.pdfbox.preflight.PreflightDocument; -import org.apache.pdfbox.preflight.ValidationResult; -import org.apache.pdfbox.preflight.exception.ValidationException; -import org.apache.pdfbox.preflight.parser.PreflightParser; -import org.apache.pdfbox.preflight.utils.ByteArrayDataSource; -import org.apache.xmpbox.type.BadFieldValueException; -import org.apache.xmpbox.xml.XmpSerializer; import org.mustangproject.ZUGFeRD.model.*; public class ZUGFeRDExporter implements Closeable { @@ -90,9 +74,11 @@ public class ZUGFeRDExporter implements Closeable { * doc.save(PDFfilename); * * @author jstaerk - * @throws ZUGFeRDExportException if the exporter could not be initialized + * @deprecated Use the factory methods {@link #createFromPDFA3(String)}, {@link #createFromPDFA3(InputStream)} or + * the {@link ZUGFeRDExporterFromA1Factory} instead * */ + @Deprecated public ZUGFeRDExporter() { init(); } @@ -236,9 +222,11 @@ public class ZUGFeRDExporter implements Closeable { } // // MAIN CLASS + @Deprecated private PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; // BASIC, COMFORT etc - may be set from outside. + @Deprecated private ZUGFeRDConformanceLevel zUGFeRDConformanceLevel = ZUGFeRDConformanceLevel.EXTENDED; /** @@ -250,6 +238,7 @@ public class ZUGFeRDExporter implements Closeable { byte[] zugferdData = null; private boolean isTest; IZUGFeRDExportableTransaction trans = null; + @Deprecated private boolean ignoreA1Errors; private PDDocument doc; private String currency = "EUR"; @@ -326,8 +315,9 @@ public class ZUGFeRDExporter implements Closeable { * * Feel free to pass "A" as new level if you know what you are doing :-) * - * + * @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead */ + @Deprecated public void setConformanceLevel(PDFAConformanceLevel newLevel) { if (newLevel == null) { throw new NullPointerException("pdf conformance level"); @@ -362,176 +352,85 @@ public class ZUGFeRDExporter implements Closeable { isTest = true; } + /** + * @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead + */ + @Deprecated public void ignoreA1Errors() { ignoreA1Errors = true; } - private boolean getA1ParserValidationResult(PreflightParser parser) throws IOException { - ValidationResult result = null; - - try { - - /* - * Parse the PDF file with PreflightParser that inherits from the - * NonSequentialParser. Some additional controls are present to - * check a set of PDF/A requirements. (Stream length consistency, - * EOL after some Keyword...) - */ - parser.parse(); - - /* - * Once the syntax validation is done, the parser can provide a - * PreflightDocument (that inherits from PDDocument) This document - * process the end of PDF/A validation. - */ - PreflightDocument document = parser.getPreflightDocument(); - document.validate(); - - // Get validation result - result = document.getResult(); - document.close(); - - } catch (ValidationException e) { - /* - * the parse method can throw a SyntaxValidationException if the PDF - * file can't be parsed. In this case, the exception contains an - * instance of ValidationResult - */ - return false; - } - // display validation result - return result.isValid(); + /** + * @deprecated Use the factory method {@link #createFromPDFA3(String)} instead + */ + @Deprecated + public void loadPDFA3(String filename) throws IOException { + doc = PDDocument.load(new File(filename)); + } + public static ZUGFeRDExporter createFromPDFA3(String filename) throws IOException { + return new ZUGFeRDExporter(PDDocument.load(new File(filename))); } - - /*** - * Will return a boolean if the inputstream is valid PDF/A-1 and close the input stream - * @param file - * @return boolean - */ - public boolean isValidA1(InputStream file) throws IOException { - return getA1ParserValidationResult(new PreflightParser(new ByteArrayDataSource(file))); - } - - public void loadPDFA3(String filename) throws IOException { - doc = PDDocument.load(new File(filename)); - } - + /** + * @deprecated Use the factory method {@link #createFromPDFA3(InputStream)} instead + */ + @Deprecated public void loadPDFA3(InputStream file) throws IOException { - doc = PDDocument.load(file); + doc = PDDocument.load(file); + } + + public static ZUGFeRDExporter createFromPDFA3(InputStream pdfSource) throws IOException { + return new ZUGFeRDExporter(PDDocument.load(pdfSource)); } /** * Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on * the metadata level, this will not e.g. convert graphics to JPG-2000) + * + * @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead * */ + @Deprecated public PDDocumentCatalog PDFmakeA3compliant(String filename, - String producer, String creator, boolean attachZugferdHeaders) + String producer, String creator, boolean attachZugferdHeaders) throws IOException, TransformerException { - - if (!ignoreA1Errors && !isValidA1(new FileInputStream(filename))) { - throw new IOException("File is not a valid PDF/A-1 input file"); - } - loadPDFA3(filename); - return makeDocPDFA3compliant(producer, creator, attachZugferdHeaders); + doc = createPDFA1Factory() + .setProducer(producer) + .setCreator(creator) + .setAttachZugferdHeaders(attachZugferdHeaders) + .loadFromPDFA1(filename) + .doc; + + return doc.getDocumentCatalog(); } + /** + * @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead + */ + @Deprecated public PDDocumentCatalog PDFmakeA3compliant(InputStream file, - String producer, String creator, boolean attachZugferdHeaders) - throws IOException, TransformerException { - /* cache the file content in memory, unfortunately the next step, isValidA1, - * will close the input stream but the step thereafter (loadPDFA3) needs - * and open one*/ - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[1024]; - int n = 0; - while ((n = file.read(buf)) >= 0) - baos.write(buf, 0, n); - byte[] content = baos.toByteArray(); + String producer, String creator, boolean attachZugferdHeaders) throws IOException, TransformerException { - InputStream is1 = new ByteArrayInputStream(content); - if (!ignoreA1Errors && !isValidA1(is1)) { - throw new IOException("File is not a valid PDF/A-1 input file"); + doc = createPDFA1Factory() + .setProducer(producer) + .setCreator(creator) + .setAttachZugferdHeaders(attachZugferdHeaders) + .loadFromPDFA1(file) + .doc; + + return doc.getDocumentCatalog(); + } + + private ZUGFeRDExporterFromA1Factory createPDFA1Factory() { + ZUGFeRDExporterFromA1Factory factory = new ZUGFeRDExporterFromA1Factory(); + if (ignoreA1Errors) { + factory.ignoreA1Errors(); } - InputStream is2 = new ByteArrayInputStream(content); - loadPDFA3(is2); - - return makeDocPDFA3compliant(producer, creator, attachZugferdHeaders); - } - private PDDocumentCatalog makeDocPDFA3compliant(String producer, - String creator, boolean attachZugferdHeaders) throws IOException, - TransformerException { - String fullProducer = producer + " (via mustangproject.org " - + Version.VERSION + ")"; - - PDDocumentCatalog cat = doc.getDocumentCatalog(); - PDMetadata metadata = new PDMetadata(doc); - cat.setMetadata(metadata); - XMPMetadata xmp = XMPMetadata.createXMPMetadata(); - - - PDFAIdentificationSchema pdfaid = new PDFAIdentificationSchema(xmp); - - xmp.addSchema(pdfaid); - - DublinCoreSchema dc = xmp.createAndAddDublinCoreSchema(); - - dc.addCreator(creator); - - XMPBasicSchema xsb = xmp.createAndAddXMPBasicSchema(); - - xsb.setCreatorTool(creator); - xsb.setCreateDate(GregorianCalendar.getInstance()); - // PDDocumentInformation pdi=doc.getDocumentInformation(); - PDDocumentInformation pdi = new PDDocumentInformation(); - pdi.setProducer(fullProducer); - pdi.setAuthor(creator); - doc.setDocumentInformation(pdi); - - AdobePDFSchema pdf = xmp.createAndAddAdobePDFSchema(); - pdf.setProducer(fullProducer); - - /* - * // Mandatory: PDF/A3-a is tagged PDF which has to be expressed using - * a // MarkInfo dictionary (PDF A/3 Standard sec. 6.7.2.2) PDMarkInfo - * markinfo = new PDMarkInfo(); markinfo.setMarked(true); - * doc.getDocumentCatalog().setMarkInfo(markinfo); - */ - /* - * - * To be on the safe side, we use level B without Markinfo because we - * can not guarantee that the user correctly tagged the templates for - * the PDF. - */ - try { - pdfaid.setConformance(conformanceLevel.getLetter());//$NON-NLS-1$ //$NON-NLS-1$ - } catch (BadFieldValueException ex) { - // This should be impossible, because it would occur only if an illegal conformance level is - // supplied, however the enum enforces that the conformance level is valid. - throw new Error(ex); - } - - pdfaid.setPart(3); - - if (attachZugferdHeaders) { - addZugferdXMP(xmp); /* - * this is the only line where we do something - * Zugferd-specific, i.e. add PDF metadata - * specifically for Zugferd, not generically for - * a embedded file - */ - - } - - XmpSerializer serializer = new XmpSerializer(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - serializer.serialize(xmp, baos, false); - metadata.importXMPMetadata( baos.toByteArray() ); - - return cat; + return factory + .setZugferdConformanceLevel(zUGFeRDConformanceLevel) + .setConformanceLevel(conformanceLevel); } public void close() throws IOException { @@ -1519,7 +1418,10 @@ public class ZUGFeRDExporter implements Closeable { * * @param zUGFeRDConformanceLevel * the new conformance level + * + * @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead */ + @Deprecated public void setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel zUGFeRDConformanceLevel) { if (zUGFeRDConformanceLevel == null) { throw new NullPointerException("ZUGFeRD conformance level"); @@ -1540,26 +1442,6 @@ public class ZUGFeRDExporter implements Closeable { this.zUGFeRDConformanceLevel = ZUGFeRDConformanceLevel.valueOf(zUGFeRDConformanceLevel); } - /** - * * This will add both the RDF-indication which embedded file is Zugferd - * and the neccessary PDF/A schema extension description to be able to add - * this information to RDF - * - * @param metadata - */ - private void addZugferdXMP(XMPMetadata metadata) { - - XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, - this.zUGFeRDConformanceLevel); - - metadata.addSchema(zf); - - XMPSchemaPDFAExtensions pdfaex = new XMPSchemaPDFAExtensions(metadata); - - metadata.addSchema(pdfaex); - - } - /**** * Returns the PDFBox PDF Document * diff --git a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java index 9eb39d7d..75707e15 100644 --- a/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java +++ b/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java @@ -16,7 +16,6 @@ import org.apache.xmpbox.schema.PDFAIdentificationSchema; import org.apache.xmpbox.schema.XMPBasicSchema; import org.apache.xmpbox.type.BadFieldValueException; import org.apache.xmpbox.xml.XmpSerializer; -import org.mustangproject.ZUGFeRD.model.PDFAConformanceLevel; import javax.activation.DataSource; import javax.activation.FileDataSource; @@ -31,7 +30,7 @@ import java.util.GregorianCalendar; public class ZUGFeRDExporterFromA1Factory { private boolean ignoreA1Errors = false; private ZUGFeRDConformanceLevel zugferdConformanceLevel = ZUGFeRDConformanceLevel.EXTENDED; - private PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.U; + private PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; private String producer = "mustangproject"; private String creator = "mustangproject"; private boolean attachZugferdHeaders = true; diff --git a/src/main/java/org/mustangproject/ZUGFeRD/model/PDFAConformanceLevel.java b/src/main/java/org/mustangproject/ZUGFeRD/model/PDFAConformanceLevel.java deleted file mode 100644 index af58d66f..00000000 --- a/src/main/java/org/mustangproject/ZUGFeRD/model/PDFAConformanceLevel.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.mustangproject.ZUGFeRD.model; - -public enum PDFAConformanceLevel { - ACCESSIBLE("A"), BASIC("B"), U("U"); - - private final String letter; - - PDFAConformanceLevel(final String letter) { - this.letter = letter; - } - - public String getLetter() { - return letter; - } -} From 72e69bece86461737d07566b2612dfae93dba159 Mon Sep 17 00:00:00 2001 From: Yannik Hampe Date: Mon, 29 May 2017 19:19:18 +0200 Subject: [PATCH 2/2] Replaced usage of deprecated methods in unit tests with current API and close exporter after use --- .../ZUGFeRD/MustangReaderWriterEdgeTest.java | 29 ++++++++----------- .../ZUGFeRD/MustangReaderWriterTest.java | 29 ++++++++----------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java index 8a12c9a0..4918d9e0 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java @@ -398,32 +398,27 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp * It would not make sense to have it run before the less complex importer test (which is probably redundant) * --> as only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export */ - public void testZExport() + public void testZExport() throws Exception { final InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505newEdge.pdf"; // the writing part - try - { + ZUGFeRDExporter ze = null; + try { // automatically add Zugferd to all outgoing invoices - ZUGFeRDExporter ze = new ZUGFeRDExporter(); - ze.PDFmakeA3compliant(SOURCE_PDF, "My Application", System.getProperty("user.name"), true); + ze = new ZUGFeRDExporterFromA1Factory() + .setProducer("My Application") + .setCreator(System.getProperty("user.name")) + .loadFromPDFA1(SOURCE_PDF); + ze.PDFattachZugferdFile(this); ze.export(TARGET_PDF); - } - catch (IOException e) - { - e.printStackTrace(); - } - catch (TransformerException e) - { - e.printStackTrace(); - } - catch (Exception e) - { - e.printStackTrace(); + } finally { + if (ze != null) { + ze.close(); + } } // now check the contents (like MustangReaderTest) diff --git a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java index 7f371f75..1da06c7d 100644 --- a/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java +++ b/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java @@ -398,31 +398,26 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta * It would not make sense to have it run before the less complex importer test (which is probably redundant) * --> as only Name Ascending is supported for Test Unit sequence, I renamed the Exporter Test test-Z-Export */ - public void testZExport() + public void testZExport() throws Exception { final InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505new.pdf"; // the writing part - try - { + ZUGFeRDExporter ze = null; + try { // automatically add Zugferd to all outgoing invoices - ZUGFeRDExporter ze = new ZUGFeRDExporter(); - ze.PDFmakeA3compliant(SOURCE_PDF, "My Application", System.getProperty("user.name"), true); + ze = new ZUGFeRDExporterFromA1Factory() + .setProducer("My Application") + .setCreator(System.getProperty("user.name")) + .loadFromPDFA1(SOURCE_PDF); + ze.PDFattachZugferdFile(this); ze.export(TARGET_PDF); - } - catch (IOException e) - { - e.printStackTrace(); - } - catch (TransformerException e) - { - e.printStackTrace(); - } - catch (Exception e) - { - e.printStackTrace(); + } finally { + if (ze != null) { + ze.close(); + } } // now check the contents (like MustangReaderTest)