prepare document as late as possible

This commit is contained in:
Jochen Stärk
2017-11-30 14:58:29 +01:00
parent 50f9fe5f65
commit 4b4450410d
7 changed files with 197 additions and 180 deletions

View File

@@ -1,22 +1,26 @@
1.5.0 1.5.0
===== =====
<date> 2017-11-30
Now using factory. Export is now also possible on OutputStream.
Further dev improvements: no more need to call PDFattachZugferdFile(null) or exporter close();
toecount now has options to combine documents and upgrade xml file from ZF1 to ZF2
More unit tests, e.g. for custom xml export, PDF/A Schema extensions.
Toecount is now integrated and the main class so "java -jar mustang-1.5.0.jar" should suffice
Support for ZUGFeRD 2.0 "public review" part 1.
Now using factories to create/configure ZUGFeRDExporter.
Export is now also possible on OutputStream.
Removed need to call PDFattachZugferdFile(null) or exporter close();
More unit tests, e.g. for custom xml export, PDF/A Schema extensions.
The command line utility "toecount" is now integrated and the main class so "java -jar mustang-1.5.0.jar" should suffice.
It now also features options to combine PDF with XML and upgrade XML files from ZF1 to ZF2.
First attempts be able to start with a PDF/A-3 in the first place and better error messages for non-PDF/A-conformance.
Further changes: Further changes:
be able to specify profile #50 * be able to specify profile #50
close pdf files automatically after export #49 * close pdf files automatically after export #49
ZUGFeRDimporter does not close #48 * ZUGFeRDimporter does not close #48
command line option -e does not work on all-in-one jar #47 * command line option -e does not work on all-in-one jar #47
invoices have wrong namespaces #45 * invoices have wrong namespaces #45
invalid a3 #44 * invalid a3 #44
warn on export #39 * warn on export #39
1.4.0 1.4.0

Binary file not shown.

Binary file not shown.

View File

@@ -3,7 +3,6 @@ package org.mustangproject.ZUGFeRD;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.xmpbox.XMPMetadata; import org.apache.xmpbox.XMPMetadata;
public interface IExporterFactory { public interface IExporterFactory {
@@ -25,8 +24,6 @@ public interface IExporterFactory {
* @throws IOException * @throws IOException
*/ */
public ZUGFeRDExporter load(InputStream pdfSource) throws IOException; public ZUGFeRDExporter load(InputStream pdfSource) throws IOException;
public void prepareDocument(PDDocument doc) throws IOException;
public void addXMP(XMPMetadata metadata);
public IExporterFactory setCreator(String creator); public IExporterFactory setCreator(String creator);
public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel); public IExporterFactory setConformanceLevel(PDFAConformanceLevel newLevel);
@@ -34,6 +31,5 @@ public interface IExporterFactory {
public IExporterFactory setZUGFeRDVersion(int version); public IExporterFactory setZUGFeRDVersion(int version);
public IExporterFactory ignorePDFAErrors(); public IExporterFactory ignorePDFAErrors();
public IExporterFactory setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel zugferdConformanceLevel); public IExporterFactory setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel zugferdConformanceLevel);
public IExporterFactory setAttachZUGFeRDHeaders(final boolean attachZugferdHeaders);
} }

View File

@@ -16,18 +16,29 @@ import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog; import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary; import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode; import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
import org.apache.pdfbox.pdmodel.common.PDMetadata;
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification; import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile; import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
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.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -59,7 +70,7 @@ public class ZUGFeRDExporter implements Closeable {
// BASIC, COMFORT etc - may be set from outside. // BASIC, COMFORT etc - may be set from outside.
@Deprecated @Deprecated
private ZUGFeRDConformanceLevel zUGFeRDConformanceLevel = ZUGFeRDConformanceLevel.EXTENDED; private ZUGFeRDConformanceLevel profile = ZUGFeRDConformanceLevel.EXTENDED;
/** /**
* Data (XML invoice) to be added to the ZUGFeRD PDF. It may be externally set, * Data (XML invoice) to be added to the ZUGFeRD PDF. It may be externally set,
@@ -68,14 +79,22 @@ public class ZUGFeRDExporter implements Closeable {
* IZUGFeRDExportableTransaction for the XML to be populated. * IZUGFeRDExportableTransaction for the XML to be populated.
*/ */
IXMLProvider xmlProvider; IXMLProvider xmlProvider;
protected PDMetadata metadata = null;
protected PDFAIdentificationSchema pdfaid = null;
protected XMPMetadata xmp = null;
protected String producer = "mustangproject";
protected String creator = "mustangproject";
@Deprecated @Deprecated
private boolean ignoreA1Errors; private boolean ignoreA1Errors;
protected boolean ensurePDFisUpgraded = true;
private PDDocument doc; private PDDocument doc;
int ZFVersion; int ZFVersion;
private boolean disableAutoClose; private boolean disableAutoClose;
private boolean fileAttached=false; private boolean fileAttached = false;
protected boolean attachZUGFeRDHeaders = true;
public ZUGFeRDExporter() { public ZUGFeRDExporter() {
init(); init();
@@ -116,7 +135,7 @@ public class ZUGFeRDExporter implements Closeable {
} }
} }
@Deprecated @Deprecated
public void setZUGFeRDVersion(int ver) { public void setZUGFeRDVersion(int ver) {
if (ver == 1) { if (ver == 1) {
ZUGFeRD1PullProvider z1p = new ZUGFeRD1PullProvider(); ZUGFeRD1PullProvider z1p = new ZUGFeRD1PullProvider();
@@ -129,7 +148,7 @@ public class ZUGFeRDExporter implements Closeable {
} }
ZFVersion = ver; ZFVersion = ver;
} }
public IXMLProvider getProvider() { public IXMLProvider getProvider() {
return xmlProvider; return xmlProvider;
} }
@@ -233,8 +252,7 @@ public class ZUGFeRDExporter implements Closeable {
public PDDocumentCatalog PDFmakeA3compliant(String filename, String producer, String creator, public PDDocumentCatalog PDFmakeA3compliant(String filename, String producer, String creator,
boolean attachZugferdHeaders) throws IOException, TransformerException { boolean attachZugferdHeaders) throws IOException, TransformerException {
doc = createPDFA1Factory().setProducer(producer).setCreator(creator) doc = createPDFA1Factory().setProducer(producer).setCreator(creator).load(filename).doc;
.setAttachZUGFeRDHeaders(attachZugferdHeaders).load(filename).doc;
return doc.getDocumentCatalog(); return doc.getDocumentCatalog();
} }
@@ -246,8 +264,7 @@ public class ZUGFeRDExporter implements Closeable {
public PDDocumentCatalog PDFmakeA3compliant(InputStream file, String producer, String creator, public PDDocumentCatalog PDFmakeA3compliant(InputStream file, String producer, String creator,
boolean attachZugferdHeaders) throws IOException, TransformerException { boolean attachZugferdHeaders) throws IOException, TransformerException {
doc = createPDFA1Factory().setProducer(producer).setCreator(creator) doc = createPDFA1Factory().setProducer(producer).setCreator(creator).load(file).doc;
.setAttachZUGFeRDHeaders(attachZugferdHeaders).load(file).doc;
return doc.getDocumentCatalog(); return doc.getDocumentCatalog();
} }
@@ -257,7 +274,7 @@ public class ZUGFeRDExporter implements Closeable {
if (ignoreA1Errors) { if (ignoreA1Errors) {
factory.ignorePDFAErrors(); factory.ignorePDFAErrors();
} }
return factory.setZUGFeRDConformanceLevel(zUGFeRDConformanceLevel).setConformanceLevel(conformanceLevel); return factory.setZUGFeRDConformanceLevel(profile).setConformanceLevel(conformanceLevel);
} }
@Override @Override
@@ -277,6 +294,8 @@ public class ZUGFeRDExporter implements Closeable {
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code> * <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
*/ */
public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException { public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans) throws IOException {
prepareDocument(doc);
xmlProvider.generateXML(trans); xmlProvider.generateXML(trans);
String filename = getFilenameForVersion(ZFVersion); String filename = getFilenameForVersion(ZFVersion);
PDFAttachGenericFile(doc, filename, "Alternative", PDFAttachGenericFile(doc, filename, "Alternative",
@@ -286,7 +305,8 @@ public class ZUGFeRDExporter implements Closeable {
public void export(String ZUGFeRDfilename) throws IOException { public void export(String ZUGFeRDfilename) throws IOException {
if (!fileAttached) { if (!fileAttached) {
throw new IOException("File must be attached (usually with PDFattachZugferdFile) before perfoming this operation"); throw new IOException(
"File must be attached (usually with PDFattachZugferdFile) before perfoming this operation");
} }
doc.save(ZUGFeRDfilename); doc.save(ZUGFeRDfilename);
if (!disableAutoClose) { if (!disableAutoClose) {
@@ -296,15 +316,15 @@ public class ZUGFeRDExporter implements Closeable {
public void export(OutputStream output) throws IOException { public void export(OutputStream output) throws IOException {
if (!fileAttached) { if (!fileAttached) {
throw new IOException("File must be attached (usually with PDFattachZugferdFile) before perfoming this operation"); throw new IOException(
"File must be attached (usually with PDFattachZugferdFile) before perfoming this operation");
} }
doc.save(output); doc.save(output);
if (!disableAutoClose) { if (!disableAutoClose) {
close(); close();
} }
} }
/** /**
* Embeds an external file (generic - any type allowed) in the PDF. * Embeds an external file (generic - any type allowed) in the PDF.
* *
@@ -324,7 +344,7 @@ public class ZUGFeRDExporter implements Closeable {
*/ */
public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description, public void PDFAttachGenericFile(PDDocument doc, String filename, String relationship, String description,
String subType, byte[] data) throws IOException { String subType, byte[] data) throws IOException {
fileAttached=true; fileAttached = true;
PDComplexFileSpecification fs = new PDComplexFileSpecification(); PDComplexFileSpecification fs = new PDComplexFileSpecification();
fs.setFile(filename); fs.setFile(filename);
@@ -412,7 +432,7 @@ public class ZUGFeRDExporter implements Closeable {
if (zUGFeRDConformanceLevel == null) { if (zUGFeRDConformanceLevel == null) {
throw new NullPointerException("ZUGFeRD conformance level"); throw new NullPointerException("ZUGFeRD conformance level");
} }
this.zUGFeRDConformanceLevel = zUGFeRDConformanceLevel; this.profile = zUGFeRDConformanceLevel;
} }
/** /**
@@ -425,7 +445,7 @@ public class ZUGFeRDExporter implements Closeable {
*/ */
@Deprecated @Deprecated
public void setZUGFeRDConformanceLevel(String zUGFeRDConformanceLevel) { public void setZUGFeRDConformanceLevel(String zUGFeRDConformanceLevel) {
this.zUGFeRDConformanceLevel = ZUGFeRDConformanceLevel.valueOf(zUGFeRDConformanceLevel); this.profile = ZUGFeRDConformanceLevel.valueOf(zUGFeRDConformanceLevel);
} }
/**** /****
@@ -437,6 +457,107 @@ public class ZUGFeRDExporter implements Closeable {
return doc; return doc;
} }
/**
* This will add both the RDF-indication which embedded file is Zugferd and the
* neccessary PDF/A schema extension description to be able to add this
* information to RDF
*
* @param metadata
*/
protected void addXMP(XMPMetadata metadata) {
if (attachZUGFeRDHeaders) {
XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, profile,
ZUGFeRDExporter.getNamespaceForVersion(ZFVersion), ZUGFeRDExporter.getPrefixForVersion(ZFVersion),
ZUGFeRDExporter.getFilenameForVersion(ZFVersion));
metadata.addSchema(zf);
}
XMPSchemaPDFAExtensions pdfaex = new XMPSchemaPDFAExtensions(metadata, ZFVersion, attachZUGFeRDHeaders);
pdfaex.setZUGFeRDVersion(ZFVersion);
metadata.addSchema(pdfaex);
}
protected byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException {
XmpSerializer serializer = new XmpSerializer();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
String prefix = "<?xpacket begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>";
String suffix = "<?xpacket end=\"w\"?>";
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) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return buffer.toByteArray();
}
protected void prepareDocument(PDDocument doc) throws IOException {
String fullProducer = producer + " (via mustangproject.org " + org.mustangproject.ZUGFeRD.Version.VERSION + ")";
PDDocumentCatalog cat = doc.getDocumentCatalog();
metadata = new PDMetadata(doc);
cat.setMetadata(metadata);
xmp = XMPMetadata.createXMPMetadata();
pdfaid = new PDFAIdentificationSchema(xmp);
xmp.addSchema(pdfaid);
DublinCoreSchema dc = xmp.createAndAddDublinCoreSchema();
dc.addCreator(creator);
XMPBasicSchema xsb = xmp.createAndAddXMPBasicSchema();
xsb.setCreatorTool(creator);
xsb.setCreateDate(GregorianCalendar.getInstance());
// PDDocumentInformation pdi=doc.getDocumentInformation();
PDDocumentInformation pdi = new PDDocumentInformation();
pdi.setProducer(fullProducer);
pdi.setAuthor(creator);
doc.setDocumentInformation(pdi);
AdobePDFSchema pdf = xmp.createAndAddAdobePDFSchema();
pdf.setProducer(fullProducer);
if (ensurePDFisUpgraded) {
try {
pdfaid.setConformance(conformanceLevel.getLetter());// $NON-NLS-1$ //$NON-NLS-1$
} catch (BadFieldValueException ex) {
// This should be impossible, because it would occur only if an illegal
// conformance level is supplied,
// however the enum enforces that the conformance level is valid.
throw new Error(ex);
}
pdfaid.setPart(3);
}
if (attachZUGFeRDHeaders) {
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
*/
}
try {
metadata.importXMPMetadata(serializeXmpMetadata(xmp));
} catch (TransformerException e) {
throw new ZUGFeRDExportException("Could not export XmpMetadata", e);
}
}
public boolean isAutoCloseDisabled() { public boolean isAutoCloseDisabled() {
return disableAutoClose; return disableAutoClose;
} }
@@ -445,4 +566,22 @@ public class ZUGFeRDExporter implements Closeable {
this.disableAutoClose = disableAutoClose; this.disableAutoClose = disableAutoClose;
} }
@Deprecated
public void setCreator(String creator) {
this.creator = creator;
}
@Deprecated
public void setProducer(String producer) {
this.producer = producer;
}
public void setPDFA3(boolean ensurePDFisUpgraded) {
this.ensurePDFisUpgraded = ensurePDFisUpgraded;
}
public void setAttachZUGFeRDHeaders(boolean attachZUGFeRDHeaders) {
this.attachZUGFeRDHeaders=attachZUGFeRDHeaders;
}
} }

View File

@@ -1,55 +1,10 @@
package org.mustangproject.ZUGFeRD; package org.mustangproject.ZUGFeRD;
import java.io.IOException;
import javax.xml.transform.TransformerException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.xmpbox.type.BadFieldValueException;
public class ZUGFeRDExporterFromA1Factory extends ZUGFeRDExporterFromA3Factory implements IExporterFactory { public class ZUGFeRDExporterFromA1Factory extends ZUGFeRDExporterFromA3Factory implements IExporterFactory {
public ZUGFeRDExporterFromA1Factory() {
/** ensurePDFisUpgraded=true;
* Make a PDF A/3 from the PDF A/1
*/
public void prepareDocument(PDDocument doc) throws IOException {
super.prepareDocument(doc);
/*
* // Mandatory: PDF/A3-a is tagged PDF which has to be expressed using a //
* MarkInfo dictionary (PDF A/3 Standard sec. 6.7.2.2) PDMarkInfo markinfo = new
* PDMarkInfo(); markinfo.setMarked(true);
* doc.getDocumentCatalog().setMarkInfo(markinfo);
*/
/*
*
* To be on the safe side, we use level B without Markinfo because we can not
* guarantee that the user correctly tagged the templates for the PDF.
*/
try {
pdfaid.setConformance(conformanceLevel.getLetter());// $NON-NLS-1$ //$NON-NLS-1$
} catch (BadFieldValueException ex) {
// This should be impossible, because it would occur only if an illegal
// conformance level is supplied,
// however the enum enforces that the conformance level is valid.
throw new Error(ex);
}
pdfaid.setPart(3);
if (attachZugferdHeaders) {
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
*/
}
try {
metadata.importXMPMetadata(serializeXmpMetadata(xmp));
} catch (TransformerException e) {
throw new ZUGFeRDExportException("Could not export XmpMetadata", e);
}
} }
} }

View File

@@ -2,31 +2,19 @@ package org.mustangproject.ZUGFeRD;
import org.apache.pdfbox.io.IOUtils; import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentCatalog;
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.common.PDMetadata;
import org.apache.pdfbox.preflight.PreflightDocument; import org.apache.pdfbox.preflight.PreflightDocument;
import org.apache.pdfbox.preflight.exception.ValidationException; import org.apache.pdfbox.preflight.exception.ValidationException;
import org.apache.pdfbox.preflight.parser.PreflightParser; import org.apache.pdfbox.preflight.parser.PreflightParser;
import org.apache.pdfbox.preflight.utils.ByteArrayDataSource; 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.xml.XmpSerializer;
import javax.activation.DataSource; import javax.activation.DataSource;
import javax.activation.FileDataSource; import javax.activation.FileDataSource;
import javax.xml.transform.TransformerException;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.GregorianCalendar;
import java.util.zip.ZipFile;
public class ZUGFeRDExporterFromA3Factory implements IExporterFactory { public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
protected boolean ignorePDFAErrors = false; protected boolean ignorePDFAErrors = false;
@@ -34,13 +22,10 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE; protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE;
protected String producer = "mustangproject"; protected String producer = "mustangproject";
protected String creator = "mustangproject"; protected String creator = "mustangproject";
protected boolean attachZugferdHeaders = true;
protected PDMetadata metadata = null;
protected PDFAIdentificationSchema pdfaid = null;
protected XMPMetadata xmp = null;
protected int ZFVersion=ZUGFeRDExporter.DefaultZUGFeRDVersion; 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 * 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) * metadata level, this will not e.g. convert graphics to JPG-2000)
@@ -53,46 +38,18 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
ensurePDFIsValidPDFA(new FileDataSource(pdfFilename)); ensurePDFIsValidPDFA(new FileDataSource(pdfFilename));
ZUGFeRDExporter zugFeRDExporter; ZUGFeRDExporter zugFeRDExporter;
PDDocument doc = PDDocument.load(new File(pdfFilename)); PDDocument doc = PDDocument.load(new File(pdfFilename));
prepareDocument(doc);
zugFeRDExporter = new ZUGFeRDExporter(doc); zugFeRDExporter = new ZUGFeRDExporter(doc);
zugFeRDExporter.setZUGFeRDVersion(ZFVersion); zugFeRDExporter.setZUGFeRDVersion(ZFVersion);
zugFeRDExporter.setZUGFeRDConformanceLevel(zugferdConformanceLevel); zugFeRDExporter.setZUGFeRDConformanceLevel(zugferdConformanceLevel);
zugFeRDExporter.setCreator(creator);
zugFeRDExporter.setProducer(producer);
zugFeRDExporter.setAttachZUGFeRDHeaders(attachZUGFeRDHeaders);
zugFeRDExporter.setPDFA3(ensurePDFisUpgraded);
return zugFeRDExporter; return zugFeRDExporter;
} }
public void prepareDocument(PDDocument doc) throws IOException {
String fullProducer = producer + " (via mustangproject.org " + org.mustangproject.ZUGFeRD.Version.VERSION + ")";
PDDocumentCatalog cat = doc.getDocumentCatalog();
metadata = new PDMetadata(doc);
cat.setMetadata(metadata);
xmp = XMPMetadata.createXMPMetadata();
pdfaid = new PDFAIdentificationSchema(xmp);
xmp.addSchema(pdfaid);
DublinCoreSchema dc = xmp.createAndAddDublinCoreSchema();
dc.addCreator(creator);
XMPBasicSchema xsb = xmp.createAndAddXMPBasicSchema();
xsb.setCreatorTool(creator);
xsb.setCreateDate(GregorianCalendar.getInstance());
// PDDocumentInformation pdi=doc.getDocumentInformation();
PDDocumentInformation pdi = new PDDocumentInformation();
pdi.setProducer(fullProducer);
pdi.setAuthor(creator);
doc.setDocumentInformation(pdi);
AdobePDFSchema pdf = xmp.createAndAddAdobePDFSchema();
pdf.setProducer(fullProducer);
}
/** /**
@@ -106,12 +63,21 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
ensurePDFIsValidPDFA(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary))); ensurePDFIsValidPDFA(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary)));
ZUGFeRDExporter zugFeRDExporter; ZUGFeRDExporter zugFeRDExporter;
PDDocument doc = PDDocument.load(pdfBinary); PDDocument doc = PDDocument.load(pdfBinary);
prepareDocument(doc);
zugFeRDExporter = new ZUGFeRDExporter(doc); zugFeRDExporter = new ZUGFeRDExporter(doc);
zugFeRDExporter.setZUGFeRDVersion(ZFVersion); zugFeRDExporter.setZUGFeRDVersion(ZFVersion);
zugFeRDExporter.setZUGFeRDConformanceLevel(zugferdConformanceLevel); zugFeRDExporter.setZUGFeRDConformanceLevel(zugferdConformanceLevel);
zugFeRDExporter.setCreator(creator);
zugFeRDExporter.setProducer(producer);
zugFeRDExporter.setAttachZUGFeRDHeaders(attachZUGFeRDHeaders);
zugFeRDExporter.setPDFA3(ensurePDFisUpgraded);
return zugFeRDExporter; return zugFeRDExporter;
} }
public ZUGFeRDExporterFromA3Factory () {
ensurePDFisUpgraded=false;
}
/** /**
* Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the * Makes A PDF/A3a-compliant document from a PDF-A1 compliant document (on the
@@ -135,53 +101,10 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
IOUtils.copy(in, buffer); IOUtils.copy(in, buffer);
return buffer.toByteArray(); return buffer.toByteArray();
} }
private static boolean isValidA1(DataSource dataSource) throws IOException {
public byte[] serializeXmpMetadata(XMPMetadata xmpMetadata) throws TransformerException {
XmpSerializer serializer = new XmpSerializer();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
String prefix="<?xpacket begin=\"\uFEFF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>";
String suffix="<?xpacket end=\"w\"?>";
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) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return buffer.toByteArray();
}
private static boolean isValidA1(DataSource dataSource) throws IOException {
return getPDFAParserValidationResult(new PreflightParser(dataSource)); return getPDFAParserValidationResult(new PreflightParser(dataSource));
} }
/**
* This will add both the RDF-indication which embedded file is Zugferd and the
* neccessary PDF/A schema extension description to be able to add this
* information to RDF
*
* @param metadata
*/
public void addXMP(XMPMetadata metadata) {
if (attachZugferdHeaders) {
XMPSchemaZugferd zf = new XMPSchemaZugferd(metadata, zugferdConformanceLevel, ZUGFeRDExporter.getNamespaceForVersion(ZFVersion), ZUGFeRDExporter.getPrefixForVersion(ZFVersion), ZUGFeRDExporter.getFilenameForVersion(ZFVersion) );
metadata.addSchema(zf);
}
XMPSchemaPDFAExtensions pdfaex = new XMPSchemaPDFAExtensions(metadata, ZFVersion, attachZugferdHeaders);
pdfaex.setZUGFeRDVersion(ZFVersion);
metadata.addSchema(pdfaex);
}
/** /**
* Sets the ZUGFeRD conformance level (override). * Sets the ZUGFeRD conformance level (override).
* *
@@ -246,10 +169,6 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
return this; return this;
} }
public IExporterFactory setAttachZUGFeRDHeaders(final boolean attachZugferdHeaders) {
this.attachZugferdHeaders = attachZugferdHeaders;
return this;
}
public IExporterFactory setCreator(String creator) { public IExporterFactory setCreator(String creator) {
this.creator = creator; this.creator = creator;
@@ -260,6 +179,10 @@ public class ZUGFeRDExporterFromA3Factory implements IExporterFactory {
this.producer = producer; this.producer = producer;
return this; return this;
} }
public IExporterFactory setAttachZUGFeRDHeaders(boolean attachHeaders) {
this.attachZUGFeRDHeaders = attachHeaders;
return this;
}
@Override @Override