Merge branch 'master' of github.com:ZUGFeRD/mustangproject
This commit is contained in:
@@ -115,7 +115,7 @@ corrections
|
||||
- support parsing of BT-90 CreditorReferenceID
|
||||
- #871 schema validation does not ignore external entities
|
||||
- #868 Fix wrong version in History.md
|
||||
- #729 Updates about SpecifiedTradeSettlementHeaderMonetarySummation and SpecifiedTradeSettlementPaymentMeans
|
||||
- #729 Updates about SpecifiedTradeSettlementHeaderMonetarySummation and SpecifiedTradeSettlementPaymentMeans. **Breaking Change:** The hardcoded values of ram:TypeCode (58) and ram:Information ("SEPA credit transfer") in the getSettlementXML() method of the IZUGFeRDTradeSettlementPayment interface have been removed. Starting with this version, any code utilizing this interface must explicitly set the corresponding attributes.
|
||||
- #863 LineCalculator throws NPE if product is null (since 2.17.0)
|
||||
- #731 Got a broken translation key when visualizing XML into PDF (xr:Business_process_type)
|
||||
- #865 Add sevdesk signature to PDF creators
|
||||
|
||||
@@ -136,6 +136,7 @@ public class DXExporterFromA1 extends DXExporterFromA3 {
|
||||
public DXExporterFromA1 setConformanceLevel(PDFAConformanceLevel newLevel) {
|
||||
return (DXExporterFromA1) super.setConformanceLevel(newLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DXExporterFromA1 setProducer(String producer){
|
||||
return (DXExporterFromA1) super.setProducer(producer);
|
||||
|
||||
@@ -71,6 +71,7 @@ import jakarta.activation.FileDataSource;
|
||||
public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
|
||||
protected PDFAConformanceLevel conformanceLevel = PDFAConformanceLevel.UNICODE;
|
||||
protected boolean compressionEnabled = false;
|
||||
protected ArrayList<FileAttachment> fileAttachments = new ArrayList<>();
|
||||
|
||||
/**
|
||||
@@ -296,8 +297,8 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
dict.setString("Desc", description);
|
||||
|
||||
ByteArrayInputStream fakeFile = new ByteArrayInputStream(data);
|
||||
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile);
|
||||
// ef.addCompression();
|
||||
COSName filter = compressionEnabled ? COSName.FLATE_DECODE : null;
|
||||
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile, filter);
|
||||
ef.setSubtype(subType);
|
||||
ef.setSize(data.length);
|
||||
ef.setCreationDate(new GregorianCalendar());
|
||||
@@ -417,7 +418,6 @@ public class DXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DXExporterFromA3 setCreator(String creator) {
|
||||
this.creator = creator;
|
||||
|
||||
@@ -56,6 +56,7 @@ public interface IZUGFeRDExporter extends Closeable, IExporter {
|
||||
public IZUGFeRDExporter load(InputStream pdfSource) throws IOException;
|
||||
public IZUGFeRDExporter setCreator(String creator);
|
||||
public IZUGFeRDExporter setConformanceLevel(PDFAConformanceLevel newLevel);
|
||||
public IZUGFeRDExporter setEnablePDFAttachmentCompression(boolean enablePDFAttachmentCompression);
|
||||
public IZUGFeRDExporter setProducer(String producer);
|
||||
public IZUGFeRDExporter setZUGFeRDVersion(int version);
|
||||
public boolean ensurePDFIsValid(final DataSource dataSource) throws IOException;
|
||||
|
||||
@@ -129,6 +129,9 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
|
||||
private boolean attachZUGFeRDHeaders = true;
|
||||
|
||||
/** Defines whether attachments to the PDF should be using FLATE compression */
|
||||
private boolean compressionEnabled = 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)
|
||||
@@ -296,8 +299,8 @@ public class OXExporterFromA3 extends ZUGFeRDExporterFromA3 {
|
||||
dict.setString("Desc", description);
|
||||
|
||||
ByteArrayInputStream fakeFile = new ByteArrayInputStream(data);
|
||||
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile);
|
||||
// ef.addCompression();
|
||||
COSName filter = compressionEnabled ? COSName.FLATE_DECODE : null;
|
||||
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile, filter);
|
||||
ef.setSubtype(subType);
|
||||
ef.setSize(data.length);
|
||||
ef.setCreationDate(new GregorianCalendar());
|
||||
|
||||
@@ -861,7 +861,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
||||
}
|
||||
|
||||
if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) {
|
||||
if (profile == Profiles.getByName("XRechnung")) {
|
||||
if ((profile == Profiles.getByName("XRechnung")) || (profile == Profiles.getByName("EN16931")) || (profile == Profiles.getByName("EXTENDED"))) {
|
||||
for (IZUGFeRDAllowanceCharge allowance : trans.getZFAllowances()) {
|
||||
xml += "<ram:SpecifiedTradeAllowanceCharge>" +
|
||||
"<ram:ChargeIndicator>" +
|
||||
|
||||
@@ -104,6 +104,9 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
private Profile profile = null;
|
||||
protected boolean documentPrepared = false;
|
||||
|
||||
/** Defines whether attachments to the PDF should be using FLATE compression */
|
||||
private boolean compressionEnabled = false;
|
||||
|
||||
/**
|
||||
* Data (XML invoice) to be added to the ZUGFeRD PDF. It may be externally set,
|
||||
* in which case passing a IZUGFeRDExportableTransaction is not necessary. By
|
||||
@@ -395,7 +398,8 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
dict.setString("Desc", description);
|
||||
|
||||
ByteArrayInputStream fakeFile = new ByteArrayInputStream(data);
|
||||
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile);
|
||||
COSName filter = compressionEnabled ? COSName.FLATE_DECODE : null;
|
||||
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile, filter);
|
||||
// ef.addCompression();
|
||||
ef.setSubtype(subType);
|
||||
ef.setSize(data.length);
|
||||
@@ -506,6 +510,12 @@ public class ZUGFeRDExporterFromA3 extends XRExporter implements IZUGFeRDExporte
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IZUGFeRDExporter setEnablePDFAttachmentCompression(boolean compressionEnabled) {
|
||||
this.compressionEnabled = compressionEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ZUGFeRDExporterFromA3 setCreator(String creator) {
|
||||
this.creator = creator;
|
||||
|
||||
@@ -188,6 +188,10 @@ public class ZUGFeRDExporterFromPDFA implements IZUGFeRDExporter {
|
||||
return getExporter().setConformanceLevel(newLevel);
|
||||
}
|
||||
|
||||
public IZUGFeRDExporter setEnablePDFAttachmentCompression(boolean compressionEnabled) {
|
||||
return getExporter().setEnablePDFAttachmentCompression(compressionEnabled);
|
||||
}
|
||||
|
||||
public IZUGFeRDExporter setProducer(String producer) {
|
||||
|
||||
return getExporter().setProducer(producer);
|
||||
|
||||
@@ -23,7 +23,11 @@ import junit.framework.TestSuite;
|
||||
|
||||
import org.apache.pdfbox.Loader;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
|
||||
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
|
||||
import org.apache.pdfbox.pdmodel.common.PDMetadata;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
|
||||
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
|
||||
import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException;
|
||||
import org.apache.xmpbox.XMPMetadata;
|
||||
import org.apache.xmpbox.schema.PDFAIdentificationSchema;
|
||||
@@ -413,10 +417,11 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.BASIC) >= 0);
|
||||
assertFalse(pdfContent.indexOf(DocumentContextParameterTypeConstants.EXTENDED) >= 0);
|
||||
assertTrue(pdfContent.indexOf(DocumentContextParameterTypeConstants.COMFORT) >= 0);
|
||||
byte[] targetBytes = baos.toByteArray();
|
||||
String xmlContent = readEmbeddedXmlFromPdf(targetBytes, "ZUGFeRD-invoice.xml");
|
||||
assertFalse(xmlContent.contains(DocumentContextParameterTypeConstants.BASIC));
|
||||
assertFalse(xmlContent.contains(DocumentContextParameterTypeConstants.EXTENDED));
|
||||
assertTrue(xmlContent.contains(DocumentContextParameterTypeConstants.COMFORT));
|
||||
|
||||
} catch (IOException e) {
|
||||
fail("IOException should not happen in testZExport");
|
||||
@@ -440,7 +445,8 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
result.write(buffer, 0, length);
|
||||
}
|
||||
|
||||
ze.addAdditionalFile("test.pdf", result.toByteArray());
|
||||
var bytes = result.toByteArray();
|
||||
ze.addAdditionalFile("test.pdf", bytes);
|
||||
|
||||
ze.setTransaction(this);
|
||||
ze.disableAutoClose(true);
|
||||
@@ -449,12 +455,14 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ze.export(baos);
|
||||
ze.close();
|
||||
String pdfContent = baos.toString(StandardCharsets.UTF_8);
|
||||
assertFalse(pdfContent.indexOf("(via mustangproject.org") == -1);
|
||||
byte[] targetBytes = baos.toByteArray();
|
||||
String pdfContent = new String(targetBytes, StandardCharsets.UTF_8);
|
||||
String xmlContent = readEmbeddedXmlFromPdf(targetBytes, "factur-x.xml");
|
||||
assertTrue(pdfContent.contains("(via mustangproject.org"));
|
||||
// check for pdf-a schema extension
|
||||
assertFalse(pdfContent.indexOf("<fx:ConformanceLevel>EN 16931</fx:ConformanceLevel>") == -1);
|
||||
assertFalse(pdfContent.indexOf("<pdfaSchema:prefix>fx</pdfaSchema:prefix>") == -1);
|
||||
assertFalse(pdfContent.indexOf("urn:cen.eu:en16931:2017") == -1);
|
||||
assertTrue(pdfContent.contains("<fx:ConformanceLevel>EN 16931</fx:ConformanceLevel>"));
|
||||
assertTrue(pdfContent.contains("<pdfaSchema:prefix>fx</pdfaSchema:prefix>"));
|
||||
assertTrue(xmlContent.contains("urn:cen.eu:en16931:2017"));
|
||||
}
|
||||
|
||||
// now check the contents (like MustangReaderTest)
|
||||
@@ -468,6 +476,27 @@ public class MustangReaderWriterTest extends MustangReaderTestCase {
|
||||
assertEquals(getNumber(), zi.getForeignReference());
|
||||
}
|
||||
|
||||
private static String readEmbeddedXmlFromPdf(byte[] targetBytes, String xmlFilename) throws IOException {
|
||||
// Read attached (compressed) XML file
|
||||
try (PDDocument pdDocument = Loader.loadPDF(targetBytes)) {
|
||||
PDDocumentNameDictionary names = new PDDocumentNameDictionary(pdDocument.getDocumentCatalog());
|
||||
|
||||
PDEmbeddedFilesNameTreeNode embeddedFiles = names.getEmbeddedFiles();
|
||||
Map<String, PDComplexFileSpecification> fileMap = embeddedFiles.getNames();
|
||||
|
||||
|
||||
PDComplexFileSpecification fileSpec = fileMap.get(xmlFilename);
|
||||
if (fileSpec == null) {
|
||||
fail("Files does not contain a file named " + xmlFilename);
|
||||
return null;
|
||||
}
|
||||
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
||||
String xmlContent = new String(embeddedFile.toByteArray(), StandardCharsets.UTF_8);
|
||||
System.out.println(xmlContent);
|
||||
return xmlContent;
|
||||
}
|
||||
}
|
||||
|
||||
public void testExceptionOnPDF14() {
|
||||
|
||||
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505new.pdf";
|
||||
|
||||
Reference in New Issue
Block a user