diff --git a/History.md b/History.md index bc2328a3..23062454 100644 --- a/History.md +++ b/History.md @@ -1,9 +1,7 @@ 2.0 todo - verapdf as prevalidation - visualization? zugferdvisualizer? -- factory for xrechnung - new sample invoice -- complete or discard read into push provider - validate as library doc - javadoc export - prompt for source file for validation has to be pdf @@ -13,12 +11,16 @@ - xmp errors may not show correctly in log - switch for no log and no notices - merge readmes and history.md s +- homepage to be updated accordingly +- confirm correct generation from pdf/a3 files zf2edgetest done - remove jaxb - 2.1 now default - pushprovider - new xrechnung profile - german bank account numbers can no longer be specified (dropped in favor of IBAN and BIC) +- factory for xrechnung +- complete or discard read into push provider - integrates validator - validator now additionally supports xrechnung - integrates mustangserver @@ -33,6 +35,9 @@ done - upgraded to verapdf 1.16.1 - added Ghostscript signature - removal of izugferddate/IZUGFeRDPaymentTerms,IZUGFeRDPaymentDiscountTerms +switch +- change from ZUGFeRDExporter to IZUGFeRDExporter + 1.7.7 ===== 2020-05-26 diff --git a/Mustang-CLI/src/main/java/org/mustangproject/commandline/Main.java b/Mustang-CLI/src/main/java/org/mustangproject/commandline/Main.java index 7d0a21bc..9d7755f4 100755 --- a/Mustang-CLI/src/main/java/org/mustangproject/commandline/Main.java +++ b/Mustang-CLI/src/main/java/org/mustangproject/commandline/Main.java @@ -20,10 +20,7 @@ package org.mustangproject.commandline; import com.sanityinc.jargs.CmdLineParser; import com.sanityinc.jargs.CmdLineParser.Option; -import org.mustangproject.ZUGFeRD.ZUGFeRDConformanceLevel; -import org.mustangproject.ZUGFeRD.ZUGFeRDExporter; -import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromA1Factory; -import org.mustangproject.ZUGFeRD.ZUGFeRDImporter; +import org.mustangproject.ZUGFeRD.*; import org.mustangproject.validator.Validator; import org.mustangproject.validator.ZUGFeRDValidator; @@ -34,24 +31,12 @@ import java.io.InputStreamReader; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.xml.transform.TransformerException; - -import org.mustangproject.ZUGFeRD.ZUGFeRDConformanceLevel; -import org.mustangproject.ZUGFeRD.ZUGFeRDExporter; -import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromA1Factory; -import org.mustangproject.ZUGFeRD.ZUGFeRDImporter; -import org.mustangproject.validator.ZUGFeRDValidator; /*** * This is the command line interface to mustangproject * */ -import com.sanityinc.jargs.CmdLineParser; -import com.sanityinc.jargs.CmdLineParser.Option; import org.slf4j.LoggerFactory; public class Main { @@ -392,7 +377,7 @@ public class Main { ensureFileNotExists(outName); // All params are good! continue... - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setAttachZUGFeRDHeaders(false).load(pdfName); + ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().convertOnly().load(pdfName); ze.export(outName); System.out.println("Written to " + outName); @@ -435,8 +420,8 @@ public class Main { * .loadFromPDFA1("invoice.pdf"); */ try { - int zfIntVersion = ZUGFeRDExporter.DefaultZUGFeRDVersion; - ZUGFeRDConformanceLevel zfConformanceLevelProfile = ZUGFeRDConformanceLevel.EXTENDED; + int zfIntVersion = ZUGFeRDExporterFromA3.DefaultZUGFeRDVersion; + Profiles zfConformanceLevelProfile = Profiles.EXTENDED; if (pdfName == null) { pdfName = getFilenameFromUser("Source PDF", "invoice.pdf", "pdf", true, false); @@ -468,7 +453,7 @@ public class Main { if (zfVersion == null) { try { - zfVersion = getStringFromUser("Version (1 or 2)", Integer.toString(ZUGFeRDExporter.DefaultZUGFeRDVersion), "1|2"); + zfVersion = getStringFromUser("Version (1 or 2)", Integer.toString(ZUGFeRDExporterFromA3.DefaultZUGFeRDVersion), "1|2"); } catch (Exception e) { LOGGER.error(e.getMessage(), e); } @@ -505,29 +490,29 @@ public class Main { if ((format.equals("zf")) && (zfIntVersion == 1)) { if (zfProfile.equals("b")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.BASIC; + zfConformanceLevelProfile = Profiles.BASIC; } else if (zfProfile.equals("c")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.COMFORT; + zfConformanceLevelProfile = Profiles.COMFORT; } else if (zfProfile.equals("e")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.EXTENDED; + zfConformanceLevelProfile = Profiles.EXTENDED; } else { throw new Exception(String.format("Unknown ZUGFeRD profile '%s'", zfProfile)); } } else if (((format.equals("zf")) && (zfIntVersion == 2)) || (format.equals("fx"))) { if (zfProfile.equals("m")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.MINIMUM; + zfConformanceLevelProfile = Profiles.MINIMUM; } else if (zfProfile.equals("w")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.BASICWL; + zfConformanceLevelProfile = Profiles.BASICWL; } else if (zfProfile.equals("b")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.BASIC; + zfConformanceLevelProfile = Profiles.BASIC; } else if (zfProfile.equals("c")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.CIUS; + zfConformanceLevelProfile = Profiles.CIUS; } else if (zfProfile.equals("e")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.EN16931; + zfConformanceLevelProfile = Profiles.EN16931; } else if (zfProfile.equals("t")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.EXTENDED; + zfConformanceLevelProfile = Profiles.EXTENDED; } else if (zfProfile.equals("x")) { - zfConformanceLevelProfile = ZUGFeRDConformanceLevel.XRECHNUNG; + zfConformanceLevelProfile = Profiles.XRECHNUNG; } else { throw new Exception(String.format("Unknown ZUGFeRD profile '%s'", zfProfile)); } @@ -536,20 +521,20 @@ public class Main { } // All params are good! continue... - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setProducer("Mustang-cli") + ZUGFeRDExporterFromA1 ze = (ZUGFeRDExporterFromA1) new ZUGFeRDExporterFromA1().setProducer("Mustang-cli") .setZUGFeRDVersion(zfIntVersion) - .setCreator(System.getProperty("user.name")).setZUGFeRDConformanceLevel(zfConformanceLevelProfile) + .setCreator(System.getProperty("user.name")).setProfile(zfConformanceLevelProfile) .load(pdfName); if (ignoreInputErrors) { - ze.ignoreA1Errors(); + ze.ignorePDFAErrors(); } - if (format.equals("fx")) { - ze.setFacturX(); + if (!format.equals("fx")) { + ze.disableFacturX(); } - ze.setZUGFeRDXMLData(Files.readAllBytes(Paths.get(xmlName))); + ze.setXML(Files.readAllBytes(Paths.get(xmlName))); ze.export(outName); diff --git a/library/src/main/java/org/mustangproject/Contact.java b/library/src/main/java/org/mustangproject/Contact.java index dbe470fb..55889a25 100644 --- a/library/src/main/java/org/mustangproject/Contact.java +++ b/library/src/main/java/org/mustangproject/Contact.java @@ -1,4 +1,4 @@ -package library.src.main.java.org.mustangproject; +package org.mustangproject; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableContact; diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index 7c9f2c36..3e90490e 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -18,7 +18,7 @@ *

* ********************************************************************** */ -package library.src.main.java.org.mustangproject; +package org.mustangproject; import org.mustangproject.ZUGFeRD.*; @@ -26,7 +26,7 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; -public class Invoice implements IZUGFeRDExportableTransaction { +public class Invoice implements IExportableTransaction { protected String documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownTaxID = null, ownVATID = null, ownForeignOrganisationID = null, ownOrganisationName = null, ownStreet = null, ownZIP = null, ownLocation = null, ownCountry = null, currency = null, paymentTermDescription = null; protected Date issueDate = null, dueDate = null, deliveryDate = null; diff --git a/library/src/main/java/org/mustangproject/Item.java b/library/src/main/java/org/mustangproject/Item.java index 4e291287..ba3a784e 100644 --- a/library/src/main/java/org/mustangproject/Item.java +++ b/library/src/main/java/org/mustangproject/Item.java @@ -1,4 +1,4 @@ -package library.src.main.java.org.mustangproject; +package org.mustangproject; import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem; diff --git a/library/src/main/java/org/mustangproject/Product.java b/library/src/main/java/org/mustangproject/Product.java index 4e2af2fd..9f5aa734 100644 --- a/library/src/main/java/org/mustangproject/Product.java +++ b/library/src/main/java/org/mustangproject/Product.java @@ -1,4 +1,4 @@ -package library.src.main.java.org.mustangproject; +package org.mustangproject; import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java index 0b03bd69..98a90698 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/CustomXMLProvider.java @@ -37,7 +37,7 @@ public class CustomXMLProvider implements IXMLProvider, IProfileProvider { } @Override - public void generateXML(IZUGFeRDExportableTransaction trans) { + public void generateXML(IExportableTransaction trans) { // TODO Auto-generated method stub } @@ -55,7 +55,7 @@ public class CustomXMLProvider implements IXMLProvider, IProfileProvider { } @Override - public void setProfile(ZUGFeRDConformanceLevel level) { + public void setProfile(Profiles level) { // TODO Auto-generated method stub } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java similarity index 99% rename from library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java rename to library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java index 89ee515a..48e9a3d5 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransaction.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java @@ -32,7 +32,7 @@ import java.util.Date; import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants; -public interface IZUGFeRDExportableTransaction { +public interface IExportableTransaction { /** * appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExporter.java similarity index 71% rename from library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java rename to library/src/main/java/org/mustangproject/ZUGFeRD/IExporter.java index 7e61b8c3..095037a4 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1Factory.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExporter.java @@ -18,11 +18,14 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; +import java.io.Closeable; +import java.io.IOException; +import java.io.OutputStream; -public class ZUGFeRDExporterFromA1Factory extends ZUGFeRDExporterFromA3Factory implements IExporterFactory { - public ZUGFeRDExporterFromA1Factory() { - ensurePDFisUpgraded = true; +public interface IExporter { - } + public IExporter setTransaction(IExportableTransaction trans) throws IOException; + public void export(String ZUGFeRDfilename) throws IOException; + public void export(OutputStream output) throws IOException; } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java index d4469edb..de4e5a21 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IProfileProvider.java @@ -22,6 +22,6 @@ public interface IProfileProvider { public String getProfile(); - public void setProfile(ZUGFeRDConformanceLevel level); + public void setProfile(Profiles level); } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IXMLProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IXMLProvider.java index e24feef5..ab30ec89 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IXMLProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IXMLProvider.java @@ -24,6 +24,6 @@ public interface IXMLProvider { public void setTest(); - public void generateXML(IZUGFeRDExportableTransaction trans); + public void generateXML(IExportableTransaction trans); } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExporter.java similarity index 63% rename from library/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java rename to library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExporter.java index 6822d744..e93a60ab 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IExporterFactory.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IZUGFeRDExporter.java @@ -18,10 +18,12 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; +import javax.activation.DataSource; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; -public interface IExporterFactory { +public interface IZUGFeRDExporter extends Closeable, IExporter { /** * factory: loads a PDF file and returns an appropriate exporter * @@ -29,7 +31,7 @@ public interface IExporterFactory { * @return the generated exporter * @throws IOException if anything is wrong with filename */ - public ZUGFeRDExporter load(String pdfFilename) throws IOException; + public IZUGFeRDExporter load(String pdfFilename) throws IOException; /** * Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the @@ -39,7 +41,7 @@ public interface IExporterFactory { * @return the generated exporter * @throws IOException (should not happen at all) */ - public ZUGFeRDExporter load(byte[] pdfBinary) throws IOException; + public IZUGFeRDExporter load(byte[] pdfBinary) throws IOException; /** * Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the @@ -49,18 +51,18 @@ public interface IExporterFactory { * @throws IOException if anything is wrong with inputstream * @return the generated ZUGFeRDExporter */ - public ZUGFeRDExporter load(InputStream pdfSource) throws IOException; - - public IExporterFactory setCreator(String creator); - - public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel); - - public IExporterFactory setProducer(String producer); - - public IExporterFactory setZUGFeRDVersion(int version); - - public IExporterFactory ignorePDFAErrors(); - - public IExporterFactory setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel zugferdConformanceLevel); + public IZUGFeRDExporter load(InputStream pdfSource) throws IOException; + public IZUGFeRDExporter setCreator(String creator); + public IZUGFeRDExporter setConformanceLevel(PDFAConformanceLevel newLevel); + public IZUGFeRDExporter setProducer(String producer); + public IZUGFeRDExporter setZUGFeRDVersion(int version); + public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException; + public IZUGFeRDExporter setXML(byte[] zugferdData) throws IOException; + public IZUGFeRDExporter disableFacturX(); + public IZUGFeRDExporter setProfile(Profiles zugferdConformanceLevel); + public String getNamespaceForVersion(int ver); + public String getPrefixForVersion(int ver) ; + public IZUGFeRDExporter disableAutoClose(boolean disableAutoClose); + public IXMLProvider getProvider(); } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDConformanceLevel.java b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java similarity index 96% rename from library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDConformanceLevel.java rename to library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java index b4d9f186..a14a2cb8 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDConformanceLevel.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/Profiles.java @@ -18,6 +18,6 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; -public enum ZUGFeRDConformanceLevel { +public enum Profiles { BASIC, COMFORT, EXTENDED, EN16931/*=Comfort*/, MINIMUM, BASICWL /*basic without lines, less than basic*/, CIUS, XRECHNUNG } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java b/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java index 3e0dca57..6b658699 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaPDFAExtensions.java @@ -53,7 +53,7 @@ public class XMPSchemaPDFAExtensions extends PDFAExtensionSchema { public String namespace = null; public String prefix = null; - protected ZUGFeRDExporter exporter; + protected IZUGFeRDExporter exporter; protected void setZUGFeRDVersion(int ver) { @@ -89,14 +89,14 @@ public class XMPSchemaPDFAExtensions extends PDFAExtensionSchema { return li; } - public XMPSchemaPDFAExtensions(ZUGFeRDExporter ze, XMPMetadata metadata, int ZFVersion) { + public XMPSchemaPDFAExtensions(IZUGFeRDExporter ze, XMPMetadata metadata, int ZFVersion) { super(metadata); exporter=ze; setZUGFeRDVersion(ZFVersion); attachExtensions(metadata, true); } - public XMPSchemaPDFAExtensions(ZUGFeRDExporter ze, XMPMetadata metadata, int ZFVersion, boolean withZF) { + public XMPSchemaPDFAExtensions(IZUGFeRDExporter ze, XMPMetadata metadata, int ZFVersion, boolean withZF) { super(metadata); exporter=ze; setZUGFeRDVersion(ZFVersion); diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java b/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java index 04d19c21..598f15c6 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/XMPSchemaZugferd.java @@ -41,7 +41,7 @@ public class XMPSchemaZugferd extends XMPSchema { * @param prefix the xml namespace prefix for the XMP, zf for ZUGFeRD, fx for Factur-X * @param filename the filename of the invoice */ - public XMPSchemaZugferd(XMPMetadata metadata, int zfVersion, boolean isFacturX, ZUGFeRDConformanceLevel conformanceLevel, String URN, String prefix, String filename) { + public XMPSchemaZugferd(XMPMetadata metadata, int zfVersion, boolean isFacturX, Profiles conformanceLevel, String URN, String prefix, String filename) { super(metadata, URN, prefix, "ZUGFeRD Schema"); setAboutAsSimple(""); diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/XRExporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/XRExporter.java new file mode 100644 index 00000000..24c2a8be --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/XRExporter.java @@ -0,0 +1,75 @@ +/** + * ********************************************************************* + *

+ * Copyright 2018 Jochen Staerk + *

+ * Use is subject to license terms. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0. + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *

+ * See the License for the specific language governing permissions and + * limitations under the License. + *

+ * ********************************************************************** + */ +package org.mustangproject.ZUGFeRD; + +import org.apache.pdfbox.cos.*; +import org.apache.pdfbox.io.IOUtils; +import org.apache.pdfbox.pdmodel.*; +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.exception.ValidationException; +import org.apache.pdfbox.preflight.parser.PreflightParser; +import org.apache.pdfbox.preflight.utils.ByteArrayDataSource; +import org.apache.xmpbox.XMPMetadata; +import org.apache.xmpbox.schema.AdobePDFSchema; +import org.apache.xmpbox.schema.DublinCoreSchema; +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 javax.activation.DataSource; +import javax.activation.FileDataSource; +import javax.xml.transform.TransformerException; +import java.io.*; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Map; + +public class XRExporter implements IExporter { + IXMLProvider xmlProvider; + IExportableTransaction trans; + + public XRExporter() { + } + + + @Override + public IExporter setTransaction(IExportableTransaction trans) throws IOException { + this.trans=trans; + return this; + } + + @Override + public void export(String ZUGFeRDfilename) throws IOException { + export(new FileOutputStream(new File(ZUGFeRDfilename))); + + } + + @Override + public void export(OutputStream output) throws IOException { + xmlProvider.generateXML(trans); + byte[] bytes=xmlProvider.getXML(); + output.write(bytes, 0, bytes.length); + } +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index 38760bc3..053555c7 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -24,13 +24,11 @@ import org.dom4j.DocumentHelper; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter; import org.mustangproject.XMLTools; -import org.mustangproject.ZUGFeRD.*; import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; -import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; @@ -43,13 +41,13 @@ public class ZUGFeRD1PullProvider implements IXMLProvider, IProfileProvider { //// MAIN CLASS protected byte[] zugferdData; - private IZUGFeRDExportableTransaction trans; - private ZUGFeRDConformanceLevel level; + private IExportableTransaction trans; + private Profiles level; private String paymentTermsDescription; SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); @Override - public void setProfile(ZUGFeRDConformanceLevel level) { + public void setProfile(Profiles level) { this.level = level; } @@ -189,7 +187,7 @@ public class ZUGFeRD1PullProvider implements IXMLProvider, IProfileProvider { } @Override - public void generateXML(IZUGFeRDExportableTransaction trans) { + public void generateXML(IExportableTransaction trans) { this.trans = trans; boolean hasDueDate=false; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 35a1ef42..d1873546 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; -import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; @@ -41,12 +40,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { //// MAIN CLASS protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); protected byte[] zugferdData; - private IZUGFeRDExportableTransaction trans; - private ZUGFeRDConformanceLevel level; + private IExportableTransaction trans; + private Profiles level; private String paymentTermsDescription; @Override - public void setProfile(ZUGFeRDConformanceLevel level) { + public void setProfile(Profiles level) { this.level = level; } @@ -188,7 +187,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider, IProfileProvider { } @Override - public void generateXML(IZUGFeRDExportableTransaction trans) { + public void generateXML(IExportableTransaction trans) { this.trans = trans; boolean hasDueDate=false; diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1.java new file mode 100644 index 00000000..a4d0d51d --- /dev/null +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA1.java @@ -0,0 +1,119 @@ +/** ********************************************************************** + * + * Copyright 2018 Jochen Staerk + * + * Use is subject to license terms. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + *********************************************************************** */ +package org.mustangproject.ZUGFeRD; + + +import org.apache.pdfbox.preflight.PreflightDocument; +import org.apache.pdfbox.preflight.exception.ValidationException; +import org.apache.pdfbox.preflight.parser.PreflightParser; + +import javax.activation.DataSource; +import java.io.IOException; +import java.io.InputStream; + +public class ZUGFeRDExporterFromA1 extends ZUGFeRDExporterFromA3 implements IZUGFeRDExporter { + protected boolean ignorePDFAErrors = false; + + public ZUGFeRDExporterFromA1 ignorePDFAErrors() { + this.ignorePDFAErrors = true; + return this; + } + + private static boolean isValidA1(DataSource dataSource) throws IOException { + return getPDFAParserValidationResult(new PreflightParser(dataSource)); + } + + private static boolean getPDFAParserValidationResult(PreflightParser parser) throws IOException { + /* + * 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();// might add a Format.PDF_A1A as parameter and iterate through A1 and A3 + + try (PreflightDocument document = parser.getPreflightDocument()) { + /* + * 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. + */ + + document.validate(); + + // Get validation result + return document.getResult().isValid(); + } 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; + } + } + + public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException { + if (!ignorePDFAErrors && !isValidA1(dataSource)) { + throw new IOException("File is not a valid PDF/A input file"); + } + return true; + } + + public ZUGFeRDExporterFromA1() { + ensurePDFisUpgraded = true; + + } + + public ZUGFeRDExporterFromA1 load(String pdfFilename) throws IOException { + return (ZUGFeRDExporterFromA1) super.load(pdfFilename); + } + public ZUGFeRDExporterFromA1 load(byte[] pdfBinary) throws IOException { + return (ZUGFeRDExporterFromA1) super.load(pdfBinary); + } + public ZUGFeRDExporterFromA1 load(InputStream pdfSource) throws IOException{ + return (ZUGFeRDExporterFromA1) super.load(pdfSource); + } + public ZUGFeRDExporterFromA1 setCreator(String creator) { + return (ZUGFeRDExporterFromA1) super.setCreator(creator); + } + public ZUGFeRDExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) { + return (ZUGFeRDExporterFromA1) super.setConformanceLevel(newLevel); + } + public ZUGFeRDExporterFromA1 setProducer(String producer){ + return (ZUGFeRDExporterFromA1) super.setProducer(producer); + } + public ZUGFeRDExporterFromA1 setZUGFeRDVersion(int version){ + return (ZUGFeRDExporterFromA1) super.setZUGFeRDVersion(version); + } + public ZUGFeRDExporterFromA1 setXML(byte[] zugferdData) throws IOException{ + return (ZUGFeRDExporterFromA1) super.setXML(zugferdData); + } + + public ZUGFeRDExporterFromA1 setProfile(Profiles zugferdConformanceLevel){ + return (ZUGFeRDExporterFromA1) super.setProfile(zugferdConformanceLevel); + } + public ZUGFeRDExporterFromA1 disableAutoClose(boolean disableAutoClose){ + return (ZUGFeRDExporterFromA1) super.disableAutoClose(disableAutoClose); + } + public ZUGFeRDExporterFromA1 convertOnly() { + setAttachZUGFeRDHeaders(false); + return this; + } + +} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3.java similarity index 55% rename from library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java rename to library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3.java index 55f03cf3..b73a8d52 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3.java @@ -1,43 +1,35 @@ - -/** ********************************************************************** - * +/** + * ********************************************************************* + *

* Copyright 2018 Jochen Staerk - * + *

* Use is subject to license terms. - * + *

* Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0. - * + *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * + *

* See the License for the specific language governing permissions and * limitations under the License. - * - *********************************************************************** */ + *

+ * ********************************************************************** + */ package org.mustangproject.ZUGFeRD; -/* - * Mustangproject's ZUGFeRD implementation ZUGFeRD exporter Licensed under the - * APLv2 - * - * @date 2014-07-12 - * @version 1.2.0 - * @author jstaerk - * - */ - -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.cos.COSObject; +import org.apache.pdfbox.cos.*; +import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.pdmodel.*; 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.exception.ValidationException; +import org.apache.pdfbox.preflight.parser.PreflightParser; +import org.apache.pdfbox.preflight.utils.ByteArrayDataSource; import org.apache.xmpbox.XMPMetadata; import org.apache.xmpbox.schema.AdobePDFSchema; import org.apache.xmpbox.schema.DublinCoreSchema; @@ -46,41 +38,32 @@ import org.apache.xmpbox.schema.XMPBasicSchema; import org.apache.xmpbox.type.BadFieldValueException; import org.apache.xmpbox.xml.XmpSerializer; +import javax.activation.DataSource; +import javax.activation.FileDataSource; import javax.xml.transform.TransformerException; import java.io.*; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Map; -public class ZUGFeRDExporter implements Closeable { +public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporter, IExporter, Closeable { + private boolean isFacturX = true; public static final int DefaultZUGFeRDVersion = 2; - private boolean isFacturX = true; + protected Profiles profile = Profiles.EXTENDED; + protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; - /** - * To use the ZUGFeRD exporter, implement IZUGFeRDExportableTransaction in - * yourTransaction (which will require you to implement Product, Item and - * Contact) then call doc = PDDocument.load(PDFfilename); // automatically add - * Zugferd to all outgoing invoices ZUGFeRDExporter ze = new ZUGFeRDExporter(); - * ze.PDFmakeA3compliant(doc, "Your application name", - * System.getProperty("user.name"), true); ze.PDFattachZugferdFile(doc, - * yourTransaction); - *

- * doc.save(PDFfilename); - * - * @author jstaerk - * @deprecated Use the factory methods {@link #createFromPDFA3(String)}, - * {@link #createFromPDFA3(InputStream)} or the - * {@link ZUGFeRDExporterFromA1Factory} instead - */ - // // MAIN CLASS - @Deprecated - private PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; - // BASIC, COMFORT etc - may be set from outside. - @Deprecated - private ZUGFeRDConformanceLevel profile = ZUGFeRDConformanceLevel.EN16931; + protected boolean ensurePDFisUpgraded = true; + + private HashMap additionalFiles = new HashMap(); + + + private boolean disableAutoClose; + private boolean fileAttached = false; + + private boolean documentPrepared = false; /** * Data (XML invoice) to be added to the ZUGFeRD PDF. It may be externally set, @@ -88,7 +71,6 @@ public class ZUGFeRDExporter implements Closeable { * default it is null meaning the caller needs to pass a * IZUGFeRDExportableTransaction for the XML to be populated. */ - IXMLProvider xmlProvider; protected PDMetadata metadata = null; protected PDFAIdentificationSchema pdfaid = null; protected XMPMetadata xmp = null; @@ -105,41 +87,33 @@ public class ZUGFeRDExporter implements Closeable { */ protected String creatorTool = "mustangproject"; - @Deprecated - private boolean ignoreA1Errors; - protected boolean ensurePDFisUpgraded = true; private PDDocument doc; - int ZFVersion; - private HashMap additionalFiles = new HashMap(); + private HashMap additionalXMLs = new HashMap(); - private boolean disableAutoClose; - - private boolean fileAttached = false; - protected boolean attachZUGFeRDHeaders = true; - - private boolean documentPrepared = false; - - public ZUGFeRDExporter() { - init(); - } - - public ZUGFeRDExporter(PDDocument doc2) { - doc = doc2; - init(); - } + protected int ZFVersion = DefaultZUGFeRDVersion; + private boolean attachZUGFeRDHeaders = true; /** - * Adds additional file attachments into the ZF - * @param filename the name of the attachment - * @param filecontent the bytearray with the file contents + * 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) + * + * @param pdfFilename filename of an PDF/A1 compliant document */ - public void addAdditionalFile(String filename, byte[] filecontent) { - additionalFiles.put(filename, filecontent); + public ZUGFeRDExporterFromA3 load(String pdfFilename) throws IOException { + ensurePDFIsValid(new FileDataSource(pdfFilename)); + try (FileInputStream pdf = new FileInputStream(pdfFilename)) { + return load(readAllBytes(pdf)); + } } + public IXMLProvider getProvider() { + return xmlProvider; + } + + /*** * internal helper function: get namespace for given zugferd or factur-x version * @param ver the ZUGFeRD version @@ -147,12 +121,12 @@ public class ZUGFeRDExporter implements Closeable { */ public String getNamespaceForVersion(int ver) { if (isFacturX) { - return "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#"; + return "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#"; } else if (ver == 1) { return "urn:ferd:pdfa:CrossIndustryDocument:invoice:1p0#"; } else if (ver == 2) { return "urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#"; - + } else { throw new IllegalArgumentException("Version not supported"); } @@ -176,14 +150,14 @@ public class ZUGFeRDExporter implements Closeable { * @param ver the zf/fx version * @return the filename of the file to be embedded */ - public String getFilenameForVersion(int ver, ZUGFeRDConformanceLevel profile) { + public String getFilenameForVersion(int ver, Profiles profile) { if (isFacturX) { return "factur-x.xml"; } else { - if (ver==1) { - return "ZUGFeRD-invoice.xml"; + if (ver == 1) { + return "ZUGFeRD-invoice.xml"; } else { - if (profile==ZUGFeRDConformanceLevel.XRECHNUNG) { + if (profile == Profiles.XRECHNUNG) { return "xrechnung.xml"; } else { return "zugferd-invoice.xml"; @@ -192,229 +166,44 @@ public class ZUGFeRDExporter implements Closeable { } } - @Deprecated - public void setZUGFeRDVersion(int ver) { - if (ver == 1) { - ZUGFeRD1PullProvider z1p = new ZUGFeRD1PullProvider(); - disableFacturX(); - this.xmlProvider = z1p; - } else if (ver == 2) { - ZUGFeRD2PullProvider z2p = new ZUGFeRD2PullProvider(); - this.xmlProvider = z2p; - } else { - throw new IllegalArgumentException("Version not supported"); - } - ZFVersion = ver; - } - - public IXMLProvider getProvider() { - return xmlProvider; - } - - private void init() { - setZUGFeRDVersion(DefaultZUGFeRDVersion); - } /** * Factur-X is now set by default since ZF 2.1, you have to disable it if you dont wont it * Generate ZF2.1 files with filename factur-x.xml + * * @deprecated - * */ - public void setFacturX() { + */ + public ZUGFeRDExporterFromA3 setFacturX() { isFacturX = true; + return this; } /*** * Generate ZF2.0/2.1 files with filename zugferd-invoice.xml instead of factur-x.xml */ - public void disableFacturX() { + public IZUGFeRDExporter disableFacturX() { isFacturX = false; - } - /** - * All files are PDF/A-3, setConformance refers to the level conformance. - * - * PDF/A-3 has three conformance levels, called "A", "U" and "B". - *

- * PDF/A-3-B where B means only visually preservable, U -standard for Mustang- - * means visually and unicode preservable and A means full compliance, i.e. - * visually, unicode and structurally preservable and tagged PDF, i.e. useful - * metainformation for blind people. - *

- * Feel free to pass "A" as new level if you know what you are doing :-) - * @param newLevel "A", "U" or "B" - * - * @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead - */ - @Deprecated - public void setConformanceLevel(PDFAConformanceLevel newLevel) { - if (newLevel == null) { - throw new NullPointerException("pdf conformance level"); - } - conformanceLevel = newLevel; - } - - /** - * All files are PDF/A-3, setConformance refers to the level conformance. - *

- * PDF/A-3 has three conformance levels, called "A", "U" and "B". - *

- * PDF/A-3-B where B means only visually preservable, U -standard for Mustang- - * means visually and unicode preservable and A means full compliance, i.e. - * visually, unicode and structurally preservable and tagged PDF, i.e. useful - * metainformation for blind people. - *

- * Feel free to pass "A" as new level if you know what you are doing :-) - * - * @param newLevel "A", "U" or "B" - * @deprecated Use - * {@link #setConformanceLevel(org.mustangproject.ZUGFeRD.PDFAConformanceLevel)} - * instead - */ - @Deprecated - public void setConformanceLevel(String newLevel) { - conformanceLevel = PDFAConformanceLevel.findByLetter(newLevel); - } - - /** - * enables the flag to indicate a test invoice in the XML structure - */ - public void setTest() { - xmlProvider.setTest(); - } - - /** - * @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead - */ - @Deprecated - public void ignoreA1Errors() { - ignoreA1Errors = true; - } - - /*** - * load from a pdf which is already A/3 - * @param filename the PDF - * @throws IOException if anything is wrong with filename - * @deprecated Use the factory method {@link #createFromPDFA3(String)} instead - */ - @Deprecated - public void loadPDFA3(String filename) throws IOException { - doc = PDDocument.load(new File(filename)); - } - - /*** - * factory create a ZUGFeRD exporter for a PDF/A-3 pdf file - * @param filename of the pdf - * @return the created ZUGFeRDExporter - * @throws IOException if something is wrong with filename - */ - public static ZUGFeRDExporter createFromPDFA3(String filename) throws IOException { - return new ZUGFeRDExporter(PDDocument.load(new File(filename))); - } - - /** - * load from a pdf which is already A/3 from filestream - * @param file InputStream to load pdf from - * @deprecated Use the factory method {@link #createFromPDFA3(InputStream)} instead - * @throws IOException in case anything is wrong with file - * - */ - @Deprecated - public void loadPDFA3(InputStream file) throws IOException { - doc = PDDocument.load(file); - } - - /*** - * factory create a ZUGFeRD exporter for a PDF/A-3 inputstream - * @param pdfSource the InputStream of the pdf - * @return the created ZUGFeRDExporter - * @throws IOException (should not happen) - */ - public static ZUGFeRDExporter createFromPDFA3(InputStream pdfSource) throws IOException { - return new ZUGFeRDExporter(PDDocument.load(pdfSource)); + return this; } /** * 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) - * @param filename the pdf - * @param producer the name of the xmp producer (app) - * @param creator the name of the xmp creator (user) - * @param attachZugferdHeaders whether to attach XMP ZUGFeRD headers - * @return the created PDFbox PDDocumentCatalog - * @throws IOException if anything is wrong with file - * @throws TransformerException in case of xml (XMP) parsing issues - * @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead - */ - @Deprecated - public PDDocumentCatalog PDFmakeA3compliant(String filename, String producer, String creator, - boolean attachZugferdHeaders) throws IOException, TransformerException { - - doc = createPDFA1Factory().setProducer(producer).setCreator(creator).load(filename).doc; - - return doc.getDocumentCatalog(); - } - - /*** - * - * 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) - - * @param file the InputStream of the pdf - * @param producer the name of the xmp producer (app) - * @param creator the name of the xmp creator (user) - * @param attachZugferdHeaders whether to attach XMP ZUGFeRD headers - * @return the created PDFbox PDDocumentCatalog - * @throws IOException if anything is wrong with file - * @throws TransformerException in case of xml (XMP) parsing issues - * @deprecated use the {@link ZUGFeRDExporterFromA1Factory} instead - */ - @Deprecated - public PDDocumentCatalog PDFmakeA3compliant(InputStream file, String producer, String creator, - boolean attachZugferdHeaders) throws IOException, TransformerException { - - doc = createPDFA1Factory().setProducer(producer).setCreator(creator).load(file).doc; - - return doc.getDocumentCatalog(); - } - - - private IExporterFactory createPDFA1Factory() { - ZUGFeRDExporterFromA1Factory factory = new ZUGFeRDExporterFromA1Factory(); - if (ignoreA1Errors) { - factory.ignorePDFAErrors(); - } - return factory.setZUGFeRDConformanceLevel(profile).setConformanceLevel(conformanceLevel); - } - - @Override - public void close() throws IOException { - if (doc != null) { - doc.close(); - } - } - - /** - * Embeds the Zugferd XML structure in a file named ZUGFeRD-invoice.xml. * - * @param trans a IZUGFeRDExportableTransaction that provides the data-model to - * populate the XML. This parameter may be null, if so the XML data - * should hav ebeen set via - * setZUGFeRDXMLData(byte[] zugferdData) - * @throws IOException if anything is wrong with already loaded PDF + * @param pdfBinary binary of a PDF/A1 compliant document */ - public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException { - prepareDocument(); - ((IProfileProvider) xmlProvider).setProfile(profile); - xmlProvider.generateXML(trans); - String filename = getFilenameForVersion(ZFVersion, profile); - PDFAttachGenericFile(doc, filename, "Alternative", - "Invoice metadata conforming to ZUGFeRD standard (http://www.ferd-net.de/front_content.php?idcat=231&lang=4)", - "text/xml", xmlProvider.getXML()); - for (String filenameAdditional : additionalFiles.keySet()) { - PDFAttachGenericFile(doc, filenameAdditional, "Supplement", "ZUGFeRD extension/additional data", "text/xml", additionalFiles.get(filenameAdditional)); - } + public ZUGFeRDExporterFromA3 load(byte[] pdfBinary) throws IOException { + ensurePDFIsValid(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary))); + doc = PDDocument.load(pdfBinary); + return this; } + public ZUGFeRDExporterFromA3() { + + ensurePDFisUpgraded = false; + } + + /*** * Perform the final export to a now ZUGFeRD-enriched PDF file * @param ZUGFeRDfilename the pdf file name @@ -434,6 +223,13 @@ public class ZUGFeRDExporter implements Closeable { } } + @Override + public void close() throws IOException { + if (doc != null) { + doc.close(); + } + } + /*** * Perform the final export to a now ZUGFeRD-enriched PDF file as OutputStream @@ -516,27 +312,23 @@ public class ZUGFeRDExporter implements Closeable { doc.getDocumentCatalog().setNames(names); // AF entry (Array) in catalog with the FileSpec - COSBase AFEntry = (COSBase)doc.getDocumentCatalog().getCOSObject().getItem("AF"); - if ((AFEntry == null)) - { - COSArray cosArray = new COSArray(); - cosArray.add(fs); - doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); - } else if (AFEntry instanceof COSArray) - { - COSArray cosArray = (COSArray)AFEntry; - cosArray.add(fs); - doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); - } else if ((AFEntry instanceof COSObject) && - ((COSObject)AFEntry).getObject() instanceof COSArray) - { - COSArray cosArray = (COSArray)((COSObject)AFEntry).getObject(); - cosArray.add(fs); - } else - { - throw new IOException("Unexpected object type for PDFDocument/Catalog/COSDictionary/Item(AF)"); - } - } + COSBase AFEntry = (COSBase) doc.getDocumentCatalog().getCOSObject().getItem("AF"); + if ((AFEntry == null)) { + COSArray cosArray = new COSArray(); + cosArray.add(fs); + doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); + } else if (AFEntry instanceof COSArray) { + COSArray cosArray = (COSArray) AFEntry; + cosArray.add(fs); + doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray); + } else if ((AFEntry instanceof COSObject) && + ((COSObject) AFEntry).getObject() instanceof COSArray) { + COSArray cosArray = (COSArray) ((COSObject) AFEntry).getObject(); + cosArray.add(fs); + } else { + throw new IOException("Unexpected object type for PDFDocument/Catalog/COSDictionary/Item(AF)"); + } + } /** * Sets the ZUGFeRD XML data to be attached as a single byte array. This is @@ -546,49 +338,84 @@ public class ZUGFeRDExporter implements Closeable { * @param zugferdData XML data to be set as a byte array (XML file in raw form). * @throws IOException (should not happen) */ - public void setZUGFeRDXMLData(byte[] zugferdData) throws IOException { + public ZUGFeRDExporterFromA3 setXML(byte[] zugferdData) throws IOException { CustomXMLProvider cus = new CustomXMLProvider(); cus.setXML(zugferdData); this.xmlProvider = cus; - PDFattachZugferdFile(null); + setTransaction(null); + return this; + } + + /** + * 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) + * + * @param pdfSource source to read a PDF/A1 compliant document from + */ + public ZUGFeRDExporterFromA3 load(InputStream pdfSource) throws IOException { + return load(readAllBytes(pdfSource)); + } + + public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException { + return true; + } + + private static byte[] readAllBytes(InputStream in) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + IOUtils.copy(in, buffer); + return buffer.toByteArray(); } /** - * Sets the ZUGFeRD profile. + * Sets the ZUGFeRD conformance level (override). * - * @param zUGFeRDConformanceLevel the new conformance level - * @deprecated Use {@link ZUGFeRDExporterFromA1Factory} instead + * @param zugferdConformanceLevel the new conformance level */ - @Deprecated - public void setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel zUGFeRDConformanceLevel) { - if (zUGFeRDConformanceLevel == null) { - throw new NullPointerException("ZUGFeRD conformance level"); - } - this.profile = zUGFeRDConformanceLevel; + public ZUGFeRDExporterFromA3 setProfile(Profiles zugferdConformanceLevel) { + this.profile = zugferdConformanceLevel; + return this; } /** - * Sets the ZUGFeRD profile. - * - * @param zUGFeRDConformanceLevel the new conformance level - * @deprecated Use {@link #setConformanceLevel(PDFAConformanceLevel)} instead + * All files are PDF/A-3, setConformance refers to the level conformance. + *

+ * PDF/A-3 has three coformance levels, called "A", "U" and "B". + *

+ * PDF/A-3-B where B means only visually preservable, U -standard for Mustang- + * means visually and unicode preservable and A means full compliance, i.e. + * visually, unicode and structurally preservable and tagged PDF, i.e. useful + * metainformation for blind people. + *

+ * Feel free to pass "A" as new level if you know what you are doing :-) */ - @Deprecated - public void setZUGFeRDConformanceLevel(String zUGFeRDConformanceLevel) { - this.profile = ZUGFeRDConformanceLevel.valueOf(zUGFeRDConformanceLevel); + public ZUGFeRDExporterFromA3 setConformanceLevel(PDFAConformanceLevel newLevel) { + conformanceLevel = newLevel; + return this; } - /** - * * - * Returns the PDFBox PDF Document - * - * @return PDDocument the PDFBox PDF - */ - public PDDocument getDoc() { - return doc; + + public ZUGFeRDExporterFromA3 setCreator(String creator) { + this.creator = creator; + return this; } + public ZUGFeRDExporterFromA3 setCreatorTool(String creatorTool) { + this.creatorTool = creatorTool; + return this; + } + + public ZUGFeRDExporterFromA3 setProducer(String producer) { + this.producer = producer; + return this; + } + + protected ZUGFeRDExporterFromA3 setAttachZUGFeRDHeaders(boolean attachHeaders) { + this.attachZUGFeRDHeaders = attachHeaders; + return this; + } + + /** * 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 @@ -611,27 +438,6 @@ public class ZUGFeRDExporter implements Closeable { metadata.addSchema(pdfaex); } - protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException { - XmpSerializer serializer = new XmpSerializer(); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - String prefix = ""; - String suffix = ""; - - try { - buffer.write(prefix.getBytes("UTF-8")); // see https://github.com/ZUGFeRD/mustangproject/issues/44 - serializer.serialize(xmpMetadata, buffer, false); - buffer.write(suffix.getBytes("UTF-8")); - } catch (UnsupportedEncodingException e) - { - throw new TransformerException(e); - } catch (IOException e) - { - throw new TransformerException(e); - } - return buffer.toByteArray(); - } - protected void prepareDocument() throws IOException { String fullProducer = producer + " (via mustangproject.org " + org.mustangproject.ZUGFeRD.Version.VERSION + ")"; @@ -674,9 +480,9 @@ public class ZUGFeRDExporter implements Closeable { pdfaid.setPart(3); } addXMP(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 - */ + * 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 + */ try { @@ -688,6 +494,50 @@ public class ZUGFeRDExporter implements Closeable { documentPrepared = true; } + /** + * Embeds the Zugferd XML structure in a file named ZUGFeRD-invoice.xml. + * + * @param trans a IZUGFeRDExportableTransaction that provides the data-model to + * populate the XML. This parameter may be null, if so the XML data + * should hav ebeen set via + * setZUGFeRDXMLData(byte[] zugferdData) + * @throws IOException if anything is wrong with already loaded PDF + */ + public IExporter setTransaction(IExportableTransaction trans) throws IOException { + this.trans = trans; + prepareDocument(); + ((IProfileProvider) xmlProvider).setProfile(profile); + xmlProvider.generateXML(trans); + String filename = getFilenameForVersion(ZFVersion, profile); + PDFAttachGenericFile(doc, filename, "Alternative", + "Invoice metadata conforming to ZUGFeRD standard (http://www.ferd-net.de/front_content.php?idcat=231&lang=4)", + "text/xml", xmlProvider.getXML()); + for (String filenameAdditional : additionalFiles.keySet()) { + PDFAttachGenericFile(doc, filenameAdditional, "Supplement", "ZUGFeRD extension/additional data", "text/xml", additionalFiles.get(filenameAdditional)); + } + return this; + } + + protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException { + XmpSerializer serializer = new XmpSerializer(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + String prefix = ""; + String suffix = ""; + + try { + buffer.write(prefix.getBytes("UTF-8")); // see https://github.com/ZUGFeRD/mustangproject/issues/44 + serializer.serialize(xmpMetadata, buffer, false); + buffer.write(suffix.getBytes("UTF-8")); + } catch (UnsupportedEncodingException e) { + throw new TransformerException(e); + } catch (IOException e) { + throw new TransformerException(e); + } + return buffer.toByteArray(); + } + + /** * @return if pdf file will be automatically closed after adding ZF */ @@ -698,64 +548,25 @@ public class ZUGFeRDExporter implements Closeable { /** * @param disableAutoClose prevent PDF file from being closed after adding ZF */ - public void disableAutoClose(boolean disableAutoClose) { + public ZUGFeRDExporterFromA3 disableAutoClose(boolean disableAutoClose) { this.disableAutoClose = disableAutoClose; + return this; } - /** - * the human author (use factory method instead) - * - * @param creator the (human) name who created the PDF - */ - @Deprecated - public void setCreator(String creator) { - this.creator = creator; - } + @Override + public ZUGFeRDExporterFromA3 setZUGFeRDVersion(int version) { + this.ZFVersion = version; + if (version == 1) { + ZUGFeRD1PullProvider z1p = new ZUGFeRD1PullProvider(); + disableFacturX(); + this.xmlProvider = z1p; + } else if (version == 2) { + ZUGFeRD2PullProvider z2p = new ZUGFeRD2PullProvider(); + this.xmlProvider = z2p; + } else { + throw new IllegalArgumentException("Version not supported"); + } - /** - * the CreatorTool attribute for the PDF - * - * @param creatorTool the application which created the PDF - */ - protected void setCreatorTool(String creatorTool) { - this.creatorTool = creatorTool; - } - - /** - * the authoring software (use factory method instead) - * - * @param producer the authoring software - */ - @Deprecated - public void setProducer(String producer) { - this.producer = producer; - } - - /** - * @param ensurePDFisUpgraded if not set the PDF/A won't be relabelled A/3, e.g. if it already is one - */ - public void setPDFA3(boolean ensurePDFisUpgraded) { - this.ensurePDFisUpgraded = ensurePDFisUpgraded; - } - - /** - * @param attachZUGFeRDHeaders if false the ZUGFeRD XMP metadata won't be added, e.g. if it's not the first file - */ - public void setAttachZUGFeRDHeaders(boolean attachZUGFeRDHeaders) { - this.attachZUGFeRDHeaders = attachZUGFeRDHeaders; - } - - /** - * encapsulate the deprecated setters - * @param zfVersion 1 or 2 - * @param zugferdConformanceLevel BASIC, COMFORT, EN16931, etc. - * @param creator PDF creator - * @param producer PDF producer - */ - public void configure(int zfVersion, ZUGFeRDConformanceLevel zugferdConformanceLevel, String creator, String producer) { - setZUGFeRDVersion(zfVersion); - setZUGFeRDConformanceLevel(zugferdConformanceLevel); - setCreator(creator); - setProducer(producer); + return this; } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java deleted file mode 100644 index 483f174f..00000000 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporterFromA3Factory.java +++ /dev/null @@ -1,208 +0,0 @@ -/** ********************************************************************** - * - * Copyright 2018 Jochen Staerk - * - * Use is subject to license terms. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * - * See the License for the specific language governing permissions and - * limitations under the License. - * - *********************************************************************** */ -package org.mustangproject.ZUGFeRD; - -import org.apache.pdfbox.io.IOUtils; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.preflight.PreflightDocument; -import org.apache.pdfbox.preflight.exception.ValidationException; -import org.apache.pdfbox.preflight.parser.PreflightParser; -import org.apache.pdfbox.preflight.utils.ByteArrayDataSource; - -import javax.activation.DataSource; -import javax.activation.FileDataSource; -import java.io.*; -import java.util.HashMap; - -public class ZUGFeRDExporterFromA3Factory implements IExporterFactory { - protected boolean ignorePDFAErrors = false; - protected ZUGFeRDConformanceLevel zugferdConformanceLevel = ZUGFeRDConformanceLevel.EXTENDED; - protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; - /** - * Producer (attribute for PDF - */ - protected String producer = "mustangproject"; - /** - * Human creator (attribute for PDF) - */ - protected String creator = "mustangproject"; - /** - * Creator tool (attribute for PDF) - */ - protected String creatorTool = null; - - private HashMap additionalXMLs = new HashMap(); - - - protected int ZFVersion = ZUGFeRDExporter.DefaultZUGFeRDVersion; - protected boolean ensurePDFisUpgraded = false; - private boolean attachZUGFeRDHeaders = true; - - /** - * 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) - * - * @param pdfFilename filename of an PDF/A1 compliant document - */ - public ZUGFeRDExporter load(String pdfFilename) throws IOException { - - ensurePDFIsValidPDFA(new FileDataSource(pdfFilename)); - try (FileInputStream pdf = new FileInputStream(pdfFilename)) { - return load(readAllBytes(pdf)); - } - } - - - /** - * 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) - * - * @param pdfBinary binary of a PDF/A1 compliant document - */ - public ZUGFeRDExporter load(byte[] pdfBinary) throws IOException { - ensurePDFIsValidPDFA(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary))); - PDDocument doc = PDDocument.load(pdfBinary); - ZUGFeRDExporter zugFeRDExporter = new ZUGFeRDExporter(doc); - zugFeRDExporter.configure(ZFVersion, zugferdConformanceLevel, creator, producer); - zugFeRDExporter.setAttachZUGFeRDHeaders(attachZUGFeRDHeaders); - zugFeRDExporter.setPDFA3(ensurePDFisUpgraded); - - return zugFeRDExporter; - } - - public ZUGFeRDExporterFromA3Factory() { - - ensurePDFisUpgraded = false; - } - - /** - * 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) - * - * @param pdfSource source to read a PDF/A1 compliant document from - */ - public ZUGFeRDExporter load(InputStream pdfSource) throws IOException { - return load(readAllBytes(pdfSource)); - } - - private void ensurePDFIsValidPDFA(final DataSource dataSource) throws IOException { - if (!ignorePDFAErrors && !isValidA1(dataSource)) { - throw new IOException("File is not a valid PDF/A input file"); - } - } - - private static byte[] readAllBytes(InputStream in) throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - IOUtils.copy(in, buffer); - return buffer.toByteArray(); - } - - private static boolean isValidA1(DataSource dataSource) throws IOException { - return getPDFAParserValidationResult(new PreflightParser(dataSource)); - } - - /** - * Sets the ZUGFeRD conformance level (override). - * - * @param zugferdConformanceLevel the new conformance level - */ - public IExporterFactory setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel zugferdConformanceLevel) { - this.zugferdConformanceLevel = zugferdConformanceLevel; - return this; - } - - private static boolean getPDFAParserValidationResult(PreflightParser parser) throws IOException { - /* - * 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();// might add a Format.PDF_A1A as parameter and iterate through A1 and A3 - - try (PreflightDocument document = parser.getPreflightDocument()) { - /* - * 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. - */ - - document.validate(); - - // Get validation result - return document.getResult().isValid(); - } 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; - } - } - - /** - * All files are PDF/A-3, setConformance refers to the level conformance. - *

- * PDF/A-3 has three coformance levels, called "A", "U" and "B". - *

- * PDF/A-3-B where B means only visually preservable, U -standard for Mustang- - * means visually and unicode preservable and A means full compliance, i.e. - * visually, unicode and structurally preservable and tagged PDF, i.e. useful - * metainformation for blind people. - *

- * Feel free to pass "A" as new level if you know what you are doing :-) - */ - public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel) { - conformanceLevel = newLevel; - return this; - } - - public IExporterFactory ignorePDFAErrors() { - this.ignorePDFAErrors = true; - return this; - } - - - public IExporterFactory setCreator(String creator) { - this.creator = creator; - return this; - } - - public IExporterFactory setCreatorTool(String creatorTool) { - this.creatorTool = creatorTool; - return this; - } - - public IExporterFactory setProducer(String producer) { - this.producer = producer; - return this; - } - - public IExporterFactory setAttachZUGFeRDHeaders(boolean attachHeaders) { - this.attachZUGFeRDHeaders = attachHeaders; - return this; - } - - - @Override - public IExporterFactory setZUGFeRDVersion(int version) { - this.ZFVersion = version; - return this; - } -} diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java index aff207d1..7d5750b1 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDImporter.java @@ -30,8 +30,8 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.*; -import library.src.main.java.org.mustangproject.Item; -import library.src.main.java.org.mustangproject.Product; +import org.mustangproject.Item; +import org.mustangproject.Product; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary; import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode; @@ -811,13 +811,13 @@ public class ZUGFeRDImporter { * returns a list of LineItems * @return a List of LineItem instances */ - public List getLineItemList() { + public List getLineItemList() { List nodeList = getLineItemNodes(); - List lineItemList = new ArrayList<>(); + List lineItemList = new ArrayList<>(); for (Node n: nodeList ) { - library.src.main.java.org.mustangproject.Item lineItem = new Item(null, null, null); + Item lineItem = new Item(null, null, null); lineItem.setProduct(new Product(null,null,null,null)); NodeList nl = n.getChildNodes(); diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java index 3337dc82..506845b0 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDInvoiceImporter.java @@ -1,9 +1,9 @@ package org.mustangproject.ZUGFeRD; -import library.src.main.java.org.mustangproject.Contact; -import library.src.main.java.org.mustangproject.Invoice; -import library.src.main.java.org.mustangproject.Item; -import library.src.main.java.org.mustangproject.Product; +import org.mustangproject.Contact; +import org.mustangproject.Invoice; +import org.mustangproject.Item; +import org.mustangproject.Product; import org.w3c.dom.Node; import org.w3c.dom.NodeList; diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java index f8fef6a9..4415fe65 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java @@ -34,7 +34,7 @@ import junit.framework.TestCase; * @author jstaerk * */ -public class BackwardCompatibilityTest extends TestCase implements IZUGFeRDExportableTransaction{ +public class BackwardCompatibilityTest extends TestCase implements IExportableTransaction { final String TARGET_PDF_ZF1 = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506zf1.pdf"; final String TARGET_PDF_ZF2 = "./target/testout-MustangGnuaccountingBeispielRE-20171118_506zf2.pdf"; @@ -55,9 +55,9 @@ public class BackwardCompatibilityTest extends TestCase implements IZUGFeRDExpor try (InputStream SOURCE_PDF = this.getClass() .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(1).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { + IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(1).setProfile(Profiles.EN16931).load(SOURCE_PDF)) { - ze.PDFattachZugferdFile(this); + ze.setTransaction(this); ze.disableAutoClose(true); ze.export(TARGET_PDF_ZF1); @@ -95,9 +95,9 @@ public class BackwardCompatibilityTest extends TestCase implements IZUGFeRDExpor try (InputStream SOURCE_PDF = this.getClass() .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(2).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { + IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(2).setProfile(Profiles.EN16931).load(SOURCE_PDF)) { - ze.PDFattachZugferdFile(this); + ze.setTransaction(this); ze.disableAutoClose(true); ze.export(TARGET_PDF_ZF2); @@ -133,10 +133,9 @@ public class BackwardCompatibilityTest extends TestCase implements IZUGFeRDExpor try (InputStream SOURCE_PDF = this.getClass() .getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDVersion(2).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) { + IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(2).setProfile(Profiles.EN16931).load(SOURCE_PDF)) { - ze.setFacturX(); - ze.PDFattachZugferdFile(this); + ze.setTransaction(this); ze.disableAutoClose(true); ze.export(TARGET_PDF_FX); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java b/library/src/test/java/org/mustangproject/ZUGFeRD/IExportableTransactionImpl.java similarity index 69% rename from library/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java rename to library/src/test/java/org/mustangproject/ZUGFeRD/IExportableTransactionImpl.java index 47f4b963..92d6a183 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/IZUGFeRDExportableTransactionImpl.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/IExportableTransactionImpl.java @@ -20,7 +20,7 @@ package org.mustangproject.ZUGFeRD; import java.util.Date; -public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTransaction { +public class IExportableTransactionImpl implements IExportableTransaction { private String number; private Date issueDate; @@ -150,107 +150,107 @@ public class IZUGFeRDExportableTransactionImpl implements IZUGFeRDExportableTran } - public IZUGFeRDExportableTransactionImpl setNumber(String number) { + public IExportableTransactionImpl setNumber(String number) { this.number = number; return this; } - public IZUGFeRDExportableTransactionImpl setIssueDate(Date issueDate) { + public IExportableTransactionImpl setIssueDate(Date issueDate) { this.issueDate = issueDate; return this; } - public IZUGFeRDExportableTransactionImpl setOwnOrganisationFullPlaintextInfo(String ownOrganisationFullPlaintextInfo) { + public IExportableTransactionImpl setOwnOrganisationFullPlaintextInfo(String ownOrganisationFullPlaintextInfo) { this.ownOrganisationFullPlaintextInfo = ownOrganisationFullPlaintextInfo; return this; } - public IZUGFeRDExportableTransactionImpl setDueDate(Date dueDate) { + public IExportableTransactionImpl setDueDate(Date dueDate) { this.dueDate = dueDate; return this; } - public IZUGFeRDExportableTransactionImpl setZFAllowances(IZUGFeRDAllowanceCharge... zFAllowances) { + public IExportableTransactionImpl setZFAllowances(IZUGFeRDAllowanceCharge... zFAllowances) { this.zFAllowances = zFAllowances; return this; } - public IZUGFeRDExportableTransactionImpl setZFCharges(IZUGFeRDAllowanceCharge... zFCharges) { + public IExportableTransactionImpl setZFCharges(IZUGFeRDAllowanceCharge... zFCharges) { this.zFCharges = zFCharges; return this; } - public IZUGFeRDExportableTransactionImpl setZFLogisticsServiceCharges(IZUGFeRDAllowanceCharge... zFLogisticsServiceCharges) { + public IExportableTransactionImpl setZFLogisticsServiceCharges(IZUGFeRDAllowanceCharge... zFLogisticsServiceCharges) { this.zFLogisticsServiceCharges = zFLogisticsServiceCharges; return this; } - public IZUGFeRDExportableTransactionImpl setZFItems(IZUGFeRDExportableItem... zFItems) { + public IExportableTransactionImpl setZFItems(IZUGFeRDExportableItem... zFItems) { this.zFItems = zFItems; return this; } - public IZUGFeRDExportableTransactionImpl setRecipient(IZUGFeRDExportableContact recipient) { + public IExportableTransactionImpl setRecipient(IZUGFeRDExportableContact recipient) { this.recipient = recipient; return this; } - public IZUGFeRDExportableTransactionImpl setOwnTaxID(String ownTaxID) { + public IExportableTransactionImpl setOwnTaxID(String ownTaxID) { this.ownTaxID = ownTaxID; return this; } - public IZUGFeRDExportableTransactionImpl setOwnVATID(String ownVATID) { + public IExportableTransactionImpl setOwnVATID(String ownVATID) { this.ownVATID = ownVATID; return this; } - public IZUGFeRDExportableTransactionImpl setOwnOrganisationName(String ownOrganisationName) { + public IExportableTransactionImpl setOwnOrganisationName(String ownOrganisationName) { this.ownOrganisationName = ownOrganisationName; return this; } - public IZUGFeRDExportableTransactionImpl setOwnStreet(String ownStreet) { + public IExportableTransactionImpl setOwnStreet(String ownStreet) { this.ownStreet = ownStreet; return this; } - public IZUGFeRDExportableTransactionImpl setOwnZIP(String ownZIP) { + public IExportableTransactionImpl setOwnZIP(String ownZIP) { this.ownZIP = ownZIP; return this; } - public IZUGFeRDExportableTransactionImpl setOwnLocation(String ownLocation) { + public IExportableTransactionImpl setOwnLocation(String ownLocation) { this.ownLocation = ownLocation; return this; } - public IZUGFeRDExportableTransactionImpl setOwnCountry(String ownCountry) { + public IExportableTransactionImpl setOwnCountry(String ownCountry) { this.ownCountry = ownCountry; return this; } - public IZUGFeRDExportableTransactionImpl setDeliveryDate(Date deliveryDate) { + public IExportableTransactionImpl setDeliveryDate(Date deliveryDate) { this.deliveryDate = deliveryDate; return this; } - public IZUGFeRDExportableTransactionImpl setCurrency(String currency) { + public IExportableTransactionImpl setCurrency(String currency) { this.currency = currency; return this; } - public IZUGFeRDExportableTransactionImpl setPaymentTermDescription(String paymentTermDescription) { + public IExportableTransactionImpl setPaymentTermDescription(String paymentTermDescription) { this.paymentTermDescription = paymentTermDescription; return this; } - public IZUGFeRDExportableTransactionImpl setReferenceNumber(String referenceNumber) { + public IExportableTransactionImpl setReferenceNumber(String referenceNumber) { this.referenceNumber = referenceNumber; return this; } - public IZUGFeRDExportableTransactionImpl setTradeSettlementPayment(IZUGFeRDTradeSettlementPayment... settlementPayments) { + public IExportableTransactionImpl setTradeSettlementPayment(IZUGFeRDTradeSettlementPayment... settlementPayments) { this.settlementPayments = settlementPayments; return this; } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java b/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java index 4252e2cb..c605ae63 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderTestCase.java @@ -22,9 +22,7 @@ import junit.framework.TestCase; import java.math.BigDecimal; -import org.mustangproject.ZUGFeRD.MustangReaderTestCase.Item; - -public abstract class MustangReaderTestCase extends TestCase implements IZUGFeRDExportableTransaction { +public abstract class MustangReaderTestCase extends TestCase implements IExportableTransaction { public MustangReaderTestCase(String testName) { super(testName); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java index d44fd848..95e06374 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterCustomXMLTest.java @@ -58,7 +58,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { try { InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); - ZUGFeRDExporter zea1 = new ZUGFeRDExporterFromA1Factory().setProducer("My Application").setCreator("Test").setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931) + IZUGFeRDExporter zea1 = new ZUGFeRDExporterFromA1().setProducer("My Application").setCreator("Test").setProfile(Profiles.EN16931) .load(SOURCE_PDF); final byte[] UTF8ByteOrderMark = new byte[]{(byte) 0xef, (byte) 0xbb, (byte) 0xbf}; @@ -256,7 +256,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { " \n" + " \n" + ""; - zea1.setZUGFeRDXMLData(ownZUGFeRDXML.getBytes("UTF-8")); + zea1.setXML(ownZUGFeRDXML.getBytes("UTF-8")); ByteArrayOutputStream baos = new ByteArrayOutputStream(); zea1.disableAutoClose(true); zea1.export(TARGET_PDF); @@ -297,11 +297,11 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { try { InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf"); - ZUGFeRDExporter zea1 = new ZUGFeRDExporterFromA1Factory() + IZUGFeRDExporter zea1 = new ZUGFeRDExporterFromA1() .setProducer("My Application") .setCreator("Test") .setZUGFeRDVersion(1) - .setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.BASIC) + .setProfile(Profiles.BASIC) .load(SOURCE_PDF); /* we have much more information than just in the basic profile (comfort or extended) but it's perfectly valid to provide more information, just not less. */ String ownZUGFeRDXML = "\n" @@ -437,7 +437,7 @@ public class MustangReaderWriterCustomXMLTest extends TestCase { + "Heiße Luft pro Liter\n" + "\n" + "\n" + "\n" + "\n" + ""; - zea1.setZUGFeRDXMLData(ownZUGFeRDXML.getBytes("UTF-8")); + zea1.setXML(ownZUGFeRDXML.getBytes("UTF-8")); ByteArrayOutputStream baos = new ByteArrayOutputStream(); zea1.disableAutoClose(true); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java index e4ea9b17..25042dea 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java @@ -202,19 +202,19 @@ public class MustangReaderWriterEdgeTest extends MustangReaderTestCase { try (InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505PDFA3.pdf"); - - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA3Factory() + ) { + IZUGFeRDExporter ze = new ZUGFeRDExporterFromA3() .setProducer("My Application") .setCreator(System.getProperty("user.name")) .setZUGFeRDVersion(1) - .ignorePDFAErrors() - .load(SOURCE_PDF)) { - ze.PDFattachZugferdFile(this); + .load(SOURCE_PDF); + ze.setTransaction(this); String theXML = new String(ze.getProvider().getXML()); assertTrue(theXML.contains(" * ********************************************************************** */ -package library.src.test.java.org.mustangproject.ZUGFeRD; +package org.mustangproject.ZUGFeRD; import junit.framework.TestCase; -import library.src.main.java.org.mustangproject.Contact; -import library.src.main.java.org.mustangproject.Invoice; -import library.src.main.java.org.mustangproject.Item; -import library.src.main.java.org.mustangproject.Product; +import org.mustangproject.Contact; +import org.mustangproject.Invoice; +import org.mustangproject.Item; +import org.mustangproject.Product; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; import org.mustangproject.ZUGFeRD.ZUGFeRD2PullProvider; -import org.mustangproject.ZUGFeRD.ZUGFeRDExporter; -import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromA3Factory; -import org.mustangproject.ZUGFeRD.ZUGFeRDImporter; - -import org.xmlunit.builder.Input; -import org.xmlunit.xpath.JAXPXPathEngine; -import org.xmlunit.xpath.XPathEngine; - - -import java.io.IOException; -import java.io.InputStream; import java.math.BigDecimal; import java.util.Date; diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java index abbcfcc3..67a201b1 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2EdgeTest.java @@ -30,13 +30,12 @@ import java.util.GregorianCalendar; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; -import org.mustangproject.ZUGFeRD.MustangReaderTestCase.Item; import junit.framework.Test; import junit.framework.TestSuite; @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class ZF2EdgeTest extends MustangReaderTestCase implements IZUGFeRDExportableTransaction { +public class ZF2EdgeTest extends MustangReaderTestCase implements IExportableTransaction { final String TARGET_PDF = "./target/testout-ZF2newEdge.pdf"; protected class EdgeProduct implements IZUGFeRDExportableProduct { @@ -266,12 +265,12 @@ public class ZF2EdgeTest extends MustangReaderTestCase implements IZUGFeRDExport // the writing part try (InputStream SOURCE_PDF = this.getClass() - .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505PDFA3.pdf"); + .getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf"); - ZUGFeRDExporter ze = new ZUGFeRDExporterFromA3Factory().setProducer("My Application") + ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application") .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors() .load(SOURCE_PDF)) { - ze.PDFattachZugferdFile(this); + ze.setTransaction(this); String theXML = new String(ze.getProvider().getXML()); assertTrue(theXML.contains(" li = zi.getLineItemList(); + List li = zi.getLineItemList(); assertEquals(zi.getLineItemList().get(0).getId().toString(), "1"); assertEquals(zi.getLineItemList().get(0).getProduct().getBuyerAssignedID(), ""); assertEquals(zi.getLineItemList().get(0).getProduct().getSellerAssignedID(), ""); diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java index ebc0de80..e3faf10c 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2ZInvoiceImporterTest.java @@ -19,7 +19,7 @@ *********************************************************************** */ package org.mustangproject.ZUGFeRD; -import library.src.main.java.org.mustangproject.Invoice; +import org.mustangproject.Invoice; import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters;