Merge branch 'master' of github.com:ZUGFeRD/mustangproject

# Conflicts:
#	src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDExporter.java
#	src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterEdgeTest.java
#	src/test/java/org/mustangproject/ZUGFeRD/MustangReaderWriterTest.java
This commit is contained in:
Jochen Stärk
2017-06-05 21:19:10 +02:00
9 changed files with 211 additions and 179 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ PDFA*.pdf
target/
pom.xml.*
bin/
/.gradle/

View File

@@ -1,8 +1,7 @@
PDFA3
Mustangproject
=====
Some samples how to create PDF/A3 files and PDF/A3 files with embedded files using Apache PDFBox and
the source code for the [Mustang project](http://www.mustangproject.org/).
Source code repository for the [Mustang project](http://www.mustangproject.org/) open source java PDF invoice metadata library in ZUGFeRD format.
License
-----
@@ -26,7 +25,7 @@ If you setup a Maven project, you can grab the artifacts from this maven reposit
<repositories>
<repository>
<id>mustang-mvn-repo</id>
<url>https://raw.github.com/Rayman2200/PDFA3/mvn-repo/</url>
<url>https://raw.github.com/ZUGFeRD/mustangproject/mvn-repo/</url>
</repository>
</repositories>
```
@@ -37,7 +36,13 @@ As dependency use this
<dependency>
<groupId>org.mustangproject.ZUGFeRD</groupId>
<artifactId>mustang</artifactId>
<version>1.3.0</version>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
```

View File

@@ -1,6 +1,11 @@
package org.mustangproject.ZUGFeRD;
public class ZUGFeRDExportException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public ZUGFeRDExportException() {
}

View File

@@ -44,7 +44,45 @@ import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
import org.mustangproject.ZUGFeRD.model.*;
import org.mustangproject.ZUGFeRD.model.AmountType;
import org.mustangproject.ZUGFeRD.model.CodeType;
import org.mustangproject.ZUGFeRD.model.CountryIDType;
import org.mustangproject.ZUGFeRD.model.CreditorFinancialAccountType;
import org.mustangproject.ZUGFeRD.model.CreditorFinancialInstitutionType;
import org.mustangproject.ZUGFeRD.model.CrossIndustryDocumentType;
import org.mustangproject.ZUGFeRD.model.DateTimeType;
import org.mustangproject.ZUGFeRD.model.DocumentCodeType;
import org.mustangproject.ZUGFeRD.model.DocumentContextParameterType;
import org.mustangproject.ZUGFeRD.model.DocumentLineDocumentType;
import org.mustangproject.ZUGFeRD.model.ExchangedDocumentContextType;
import org.mustangproject.ZUGFeRD.model.ExchangedDocumentType;
import org.mustangproject.ZUGFeRD.model.IDType;
import org.mustangproject.ZUGFeRD.model.IndicatorType;
import org.mustangproject.ZUGFeRD.model.LogisticsServiceChargeType;
import org.mustangproject.ZUGFeRD.model.NoteType;
import org.mustangproject.ZUGFeRD.model.ObjectFactory;
import org.mustangproject.ZUGFeRD.model.PaymentMeansCodeType;
import org.mustangproject.ZUGFeRD.model.PercentType;
import org.mustangproject.ZUGFeRD.model.QuantityType;
import org.mustangproject.ZUGFeRD.model.SupplyChainEventType;
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeAgreementType;
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeDeliveryType;
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeLineItemType;
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeSettlementType;
import org.mustangproject.ZUGFeRD.model.SupplyChainTradeTransactionType;
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeType;
import org.mustangproject.ZUGFeRD.model.TaxRegistrationType;
import org.mustangproject.ZUGFeRD.model.TaxTypeCodeType;
import org.mustangproject.ZUGFeRD.model.TextType;
import org.mustangproject.ZUGFeRD.model.TradeAddressType;
import org.mustangproject.ZUGFeRD.model.TradeAllowanceChargeType;
import org.mustangproject.ZUGFeRD.model.TradePartyType;
import org.mustangproject.ZUGFeRD.model.TradePaymentTermsType;
import org.mustangproject.ZUGFeRD.model.TradePriceType;
import org.mustangproject.ZUGFeRD.model.TradeProductType;
import org.mustangproject.ZUGFeRD.model.TradeSettlementMonetarySummationType;
import org.mustangproject.ZUGFeRD.model.TradeSettlementPaymentMeansType;
import org.mustangproject.ZUGFeRD.model.TradeTaxType;
public class ZUGFeRDExporter implements Closeable {
@@ -433,6 +471,7 @@ public class ZUGFeRDExporter implements Closeable {
.setConformanceLevel(conformanceLevel);
}
@Override
public void close() throws IOException {
if (doc != null) {
doc.close();
@@ -447,10 +486,10 @@ public class ZUGFeRDExporter implements Closeable {
private Totals totals;
private String createZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans) {
this.trans = trans;
private String createZugferdXMLForTransaction(IZUGFeRDExportableTransaction trans1) {
this.trans = trans1;
this.totals = new Totals();
currency = trans.getCurrency();
currency = trans1.getCurrency();
CrossIndustryDocumentType invoice = xmlFactory
.createCrossIndustryDocumentType();
@@ -1284,7 +1323,7 @@ public class ZUGFeRDExporter implements Closeable {
* data should hav ebeen set via
* <code>setZUGFeRDXMLData(byte[] zugferdData)</code>
*/
public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans)
public void PDFattachZugferdFile(IZUGFeRDExportableTransaction trans1)
throws IOException {
if (zugferdData == null) // XML ZUGFeRD data not set externally, needs
@@ -1293,7 +1332,7 @@ public class ZUGFeRDExporter implements Closeable {
// create a dummy file stream, this would probably normally be a
// FileInputStream
byte[] zugferdRaw = createZugferdXMLForTransaction(trans).getBytes(); //$NON-NLS-1$
byte[] zugferdRaw = createZugferdXMLForTransaction(trans1).getBytes(); //$NON-NLS-1$
if ((zugferdRaw[0] == (byte) 0xEF)
&& (zugferdRaw[1] == (byte) 0xBB)
@@ -1336,7 +1375,7 @@ public class ZUGFeRDExporter implements Closeable {
* the binary data of the file/attachment
* @throws java.io.IOException
*/
public void PDFAttachGenericFile(PDDocument doc, String filename,
public void PDFAttachGenericFile(PDDocument doc1, String filename,
String relationship, String description, String subType, byte[] data)
throws IOException {
PDComplexFileSpecification fs = new PDComplexFileSpecification();
@@ -1349,7 +1388,7 @@ public class ZUGFeRDExporter implements Closeable {
dict.setString("Desc", description);
ByteArrayInputStream fakeFile = new ByteArrayInputStream(data);
PDEmbeddedFile ef = new PDEmbeddedFile(doc, fakeFile);
PDEmbeddedFile ef = new PDEmbeddedFile(doc1, fakeFile);
ef.setSubtype(subType);
ef.setSize(data.length);
ef.setCreationDate(new GregorianCalendar());
@@ -1367,7 +1406,7 @@ public class ZUGFeRDExporter implements Closeable {
// now add the entry to the embedded file tree and set in the document.
PDDocumentNameDictionary names = new PDDocumentNameDictionary(
doc.getDocumentCatalog());
doc1.getDocumentCatalog());
PDEmbeddedFilesNameTreeNode efTree = names.getEmbeddedFiles();
if (efTree == null) {
efTree = new PDEmbeddedFilesNameTreeNode();
@@ -1385,20 +1424,20 @@ public class ZUGFeRDExporter implements Closeable {
efTree.setNames(namesMap);
names.setEmbeddedFiles(efTree);
doc.getDocumentCatalog().setNames(names);
doc1.getDocumentCatalog().setNames(names);
// AF entry (Array) in catalog with the FileSpec
COSArray cosArray = (COSArray) doc.getDocumentCatalog()
COSArray cosArray = (COSArray) doc1.getDocumentCatalog()
.getCOSObject().getItem("AF");
if (cosArray == null) {
cosArray = new COSArray();
}
cosArray.add(fs);
COSDictionary dict2 = doc.getDocumentCatalog().getCOSObject();
COSDictionary dict2 = doc1.getDocumentCatalog().getCOSObject();
COSArray array = new COSArray();
array.add(fs.getCOSObject()); // see below
dict2.setItem("AF",array);
doc.getDocumentCatalog().getCOSObject().setItem("AF", cosArray);
doc1.getDocumentCatalog().getCOSObject().setItem("AF", cosArray);
}
/**

View File

@@ -9,6 +9,7 @@ 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.pdfbox.util.Version;
import org.apache.xmpbox.XMPMetadata;
import org.apache.xmpbox.schema.AdobePDFSchema;
import org.apache.xmpbox.schema.DublinCoreSchema;
@@ -44,9 +45,13 @@ public class ZUGFeRDExporterFromA1Factory {
public ZUGFeRDExporter loadFromPDFA1(String pdfFilename) throws IOException {
ensurePDFIsValidA1(new FileDataSource(pdfFilename));
PDDocument doc = PDDocument.load(new File(pdfFilename));
ZUGFeRDExporter zugFeRDExporter = null;
try(PDDocument doc = PDDocument.load(new File(pdfFilename))) {
makePDFA3compliant(doc);
return new ZUGFeRDExporter(doc);
zugFeRDExporter = new ZUGFeRDExporter(doc);
}
return zugFeRDExporter;
}
/**
@@ -55,12 +60,16 @@ public class ZUGFeRDExporterFromA1Factory {
*
* @param pdfBinary binary of a PDF/A1 compliant document
*/
public ZUGFeRDExporter loadFromPDFA1(byte[] pdfBinary) throws IOException, TransformerException {
public ZUGFeRDExporter loadFromPDFA1(byte[] pdfBinary) throws IOException {
ensurePDFIsValidA1(new ByteArrayDataSource(new ByteArrayInputStream(pdfBinary)));
PDDocument doc = PDDocument.load(pdfBinary);
ZUGFeRDExporter zugFeRDExporter;
try (PDDocument doc = PDDocument.load(pdfBinary)) {
makePDFA3compliant(doc);
return new ZUGFeRDExporter(doc);
zugFeRDExporter = new ZUGFeRDExporter(doc);
}
return zugFeRDExporter;
}
/**
@@ -69,7 +78,7 @@ public class ZUGFeRDExporterFromA1Factory {
*
* @param pdfSource source to read a PDF/A1 compliant document from
*/
public ZUGFeRDExporter loadFromPDFA1(InputStream pdfSource) throws IOException, TransformerException {
public ZUGFeRDExporter loadFromPDFA1(InputStream pdfSource) throws IOException {
return loadFromPDFA1(readAllBytes(pdfSource));
}
@@ -86,7 +95,7 @@ public class ZUGFeRDExporterFromA1Factory {
}
private void makePDFA3compliant(PDDocument doc) throws IOException {
String fullProducer = producer + " (via mustangproject.org " + Version.VERSION + ")";
String fullProducer = producer + " (via mustangproject.org " + Version.getVersion() + ")";
PDDocumentCatalog cat = doc.getDocumentCatalog();
PDMetadata metadata = new PDMetadata(doc);
@@ -197,9 +206,6 @@ public class ZUGFeRDExporterFromA1Factory {
}
private static boolean getA1ParserValidationResult(PreflightParser parser) throws IOException {
PreflightDocument document = null;
try {
/*
* Parse the PDF file with PreflightParser that inherits from the
* NonSequentialParser. Some additional controls are present to
@@ -208,12 +214,14 @@ public class ZUGFeRDExporterFromA1Factory {
*/
parser.parse();
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 = parser.getPreflightDocument();
document.validate();
// Get validation result
@@ -225,10 +233,6 @@ public class ZUGFeRDExporterFromA1Factory {
* instance of ValidationResult
*/
return false;
} finally {
if (document != null) {
document.close();
}
}
}

View File

@@ -8,14 +8,13 @@ package org.mustangproject.ZUGFeRD;
* @author jstaerk
* */
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.Map;
import javax.management.RuntimeErrorException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -23,7 +22,6 @@ import javax.xml.parsers.ParserConfigurationException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDDocumentNameDictionary;
import org.apache.pdfbox.pdmodel.PDEmbeddedFilesNameTreeNode;
import org.apache.pdfbox.pdmodel.common.COSObjectable;
import org.apache.pdfbox.pdmodel.common.filespecification.PDComplexFileSpecification;
import org.apache.pdfbox.pdmodel.common.filespecification.PDEmbeddedFile;
import org.w3c.dom.Document;
@@ -62,13 +60,10 @@ public class ZUGFeRDImporter {
* Extracts a ZUGFeRD invoice from a PDF document represented by a file name.
* Errors are just logged to STDOUT.
*/
public void extract(String pdfFilename)
{
try
{
extractLowLevel(new BufferedInputStream(new FileInputStream(pdfFilename)));
} catch (IOException ioe)
{
public void extract(String pdfFilename) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFilename))) {
extractLowLevel(bis);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
@@ -78,18 +73,15 @@ public class ZUGFeRDImporter {
* Errors are reported via exception handling.
*/
public void extractLowLevel(InputStream pdfStream) throws IOException {
PDDocument doc = null;
try {
doc = PDDocument.load(pdfStream);
// PDDocumentInformation info = doc.getDocumentInformation();
PDDocumentNameDictionary names = new PDDocumentNameDictionary(
doc.getDocumentCatalog());
PDEmbeddedFilesNameTreeNode etn;
try (PDDocument doc = PDDocument.load(pdfStream)) {
// PDDocumentInformation info = doc.getDocumentInformation();
PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
etn = names.getEmbeddedFiles();
if (etn == null) {
doc.close();
return;
}
Map<String, PDComplexFileSpecification> efMap = etn.getNames();
// String filePath = "/tmp/";
for (String filename : efMap.keySet()) {
@@ -100,8 +92,7 @@ public class ZUGFeRDImporter {
if (filename.equals("ZUGFeRD-invoice.xml")) { //$NON-NLS-1$
containsMeta = true;
PDComplexFileSpecification fileSpec = (PDComplexFileSpecification) efMap
.get(filename);
PDComplexFileSpecification fileSpec = efMap.get(filename);
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
// String embeddedFilename = filePath + filename;
// File file = new File(filePath + filename);
@@ -117,18 +108,7 @@ public class ZUGFeRDImporter {
// fos.close();
}
}
} catch (IOException e1) {
throw e1;
}
finally {
try {
if(doc!=null) {
doc.close();
}
} catch (IOException e) {}
}
}
public void parse() {
@@ -421,9 +401,9 @@ public class ZUGFeRDImporter {
public String getMeta() {
if (rawXML==null){
return null;
} else {
return new String(rawXML);
}
return new String(rawXML);
}

View File

@@ -11,7 +11,6 @@ package org.mustangproject.ZUGFeRD.model;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;

View File

@@ -401,9 +401,7 @@ public class MustangReaderWriterEdgeTest extends TestCase implements IZUGFeRDExp
public void testZExport() throws Exception
{
final InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505newEdge.pdf";
// the writing part
ZUGFeRDExporter ze = null;
try {

View File

@@ -10,14 +10,13 @@ import java.util.GregorianCalendar;
import javax.xml.transform.TransformerException;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExportableTransaction
{
@@ -326,7 +325,7 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta
public void setVATPercent(BigDecimal VATPercent)
{
VATPercent = VATPercent;
this.VATPercent = VATPercent;
}
}
@@ -363,8 +362,10 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta
public void testAImport() throws IOException
{
ZUGFeRDImporter zi = new ZUGFeRDImporter();
InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf");
try (InputStream inputStream = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505.pdf")) {
zi.extractLowLevel(inputStream);
}
// Reading ZUGFeRD
String amount = null;
@@ -400,7 +401,7 @@ public class MustangReaderWriterTest extends TestCase implements IZUGFeRDExporta
*/
public void testZExport() throws Exception
{
final InputStream SOURCE_PDF = this.getClass().getResourceAsStream("/MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
final String TARGET_PDF = "./target/testout-MustangGnuaccountingBeispielRE-20170509_505new.pdf";
// the writing part