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- * 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
+ *
- * 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 ListsetZUGFeRDXMLData(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