Take into account that PDEmbeddedFilesNameTreeNode can also be in efTree.getKids(). Closes #60
This commit is contained in:
@@ -31,7 +31,11 @@ import java.io.ByteArrayInputStream;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
@@ -43,6 +47,7 @@ import javax.xml.xpath.XPathFactory;
|
|||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
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.PDNameTreeNode;
|
||||||
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.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
@@ -74,14 +79,19 @@ public class ZUGFeRDImporter {
|
|||||||
private boolean amountFound;
|
private boolean amountFound;
|
||||||
private boolean extracted = false;
|
private boolean extracted = false;
|
||||||
private boolean parsed = false;
|
private boolean parsed = false;
|
||||||
|
private static final Logger LOG = Logger.getLogger(ZUGFeRDImporter.class.getName());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts a ZUGFeRD invoice from a PDF document represented by a file name.
|
* Extracts a ZUGFeRD invoice from a PDF document represented by a file name.
|
||||||
* Errors are just logged to STDOUT.
|
* Errors are just logged to STDOUT.
|
||||||
* @param pdfFilename the filename of the pdf
|
*
|
||||||
|
* @param pdfFilename
|
||||||
|
* the filename of the pdf
|
||||||
*/
|
*/
|
||||||
public void extract(String pdfFilename) {
|
public void extract(String pdfFilename) {
|
||||||
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFilename))) {
|
try {
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(pdfFilename));
|
||||||
|
|
||||||
extractLowLevel(bis);
|
extractLowLevel(bis);
|
||||||
bis.close();
|
bis.close();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@@ -93,10 +103,12 @@ public class ZUGFeRDImporter {
|
|||||||
* Extracts a ZUGFeRD invoice from a PDF document represented by an input
|
* Extracts a ZUGFeRD invoice from a PDF document represented by an input
|
||||||
* stream. Errors are reported via exception handling.
|
* stream. Errors are reported via exception handling.
|
||||||
*
|
*
|
||||||
* @param pdfStream a inputstream of a pdf file
|
* @param pdfStream
|
||||||
|
* a inputstream of a pdf file
|
||||||
*/
|
*/
|
||||||
public void extractLowLevel(InputStream pdfStream) throws IOException {
|
public void extractLowLevel(InputStream pdfStream) throws IOException {
|
||||||
PDEmbeddedFilesNameTreeNode etn;
|
PDEmbeddedFilesNameTreeNode etn;
|
||||||
|
|
||||||
try (PDDocument doc = PDDocument.load(pdfStream)) {
|
try (PDDocument doc = PDDocument.load(pdfStream)) {
|
||||||
// PDDocumentInformation info = doc.getDocumentInformation();
|
// PDDocumentInformation info = doc.getDocumentInformation();
|
||||||
PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
|
PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
|
||||||
@@ -107,29 +119,44 @@ public class ZUGFeRDImporter {
|
|||||||
|
|
||||||
Map<String, PDComplexFileSpecification> efMap = etn.getNames();
|
Map<String, PDComplexFileSpecification> efMap = etn.getNames();
|
||||||
// String filePath = "/tmp/";
|
// String filePath = "/tmp/";
|
||||||
for (String filename : efMap.keySet()) {
|
|
||||||
/**
|
|
||||||
* currently (in the release candidate of version 1) only one attached file with
|
|
||||||
* the name ZUGFeRD-invoice.xml is allowed
|
|
||||||
*/
|
|
||||||
if ((filename.equals("ZUGFeRD-invoice.xml") || filename.equals("factur-x.xml"))) { //$NON-NLS-1$
|
|
||||||
containsMeta = true;
|
|
||||||
|
|
||||||
PDComplexFileSpecification fileSpec = efMap.get(filename);
|
if (efMap!=null) {
|
||||||
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
extractFiles(efMap); // see https://memorynotfound.com/apache-pdfbox-extract-embedded-file-pdf-document/
|
||||||
// String embeddedFilename = filePath + filename;
|
} else {
|
||||||
// File file = new File(filePath + filename);
|
|
||||||
// System.out.println("Writing " + embeddedFilename);
|
|
||||||
// ByteArrayOutputStream fileBytes=new
|
|
||||||
// ByteArrayOutputStream();
|
|
||||||
// FileOutputStream fos = new FileOutputStream(file);
|
|
||||||
|
|
||||||
rawXML = embeddedFile.toByteArray();
|
List<PDNameTreeNode<PDComplexFileSpecification>> kids = etn.getKids();
|
||||||
setMeta(new String(rawXML));
|
for (PDNameTreeNode<PDComplexFileSpecification> node : kids) {
|
||||||
extracted = true;
|
Map<String, PDComplexFileSpecification> namesL = node.getNames();
|
||||||
// fos.write(embeddedFile.getByteArray());
|
extractFiles(namesL);
|
||||||
// fos.close();
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extractFiles(Map<String, PDComplexFileSpecification> names) throws IOException {
|
||||||
|
for (String filename : names.keySet()) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* currently (in the release candidate of version 1) only one attached file with
|
||||||
|
* the name ZUGFeRD-invoice.xml is allowed
|
||||||
|
*/
|
||||||
|
if ((filename.equals("ZUGFeRD-invoice.xml") || filename.equals("factur-x.xml"))) { //$NON-NLS-1$
|
||||||
|
containsMeta = true;
|
||||||
|
|
||||||
|
PDComplexFileSpecification fileSpec = names.get(filename);
|
||||||
|
PDEmbeddedFile embeddedFile = fileSpec.getEmbeddedFile();
|
||||||
|
// String embeddedFilename = filePath + filename;
|
||||||
|
// File file = new File(filePath + filename);
|
||||||
|
// System.out.println("Writing " + embeddedFilename);
|
||||||
|
// ByteArrayOutputStream fileBytes=new
|
||||||
|
// ByteArrayOutputStream();
|
||||||
|
// FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
|
||||||
|
rawXML = embeddedFile.toByteArray();
|
||||||
|
setMeta(new String(rawXML));
|
||||||
|
extracted = true;
|
||||||
|
// fos.write(embeddedFile.getByteArray());
|
||||||
|
// fos.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -200,19 +227,17 @@ public class ZUGFeRDImporter {
|
|||||||
* </ram:PayeeSpecifiedCreditorFinancialInstitution>
|
* </ram:PayeeSpecifiedCreditorFinancialInstitution>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/***
|
|
||||||
* we should switch to xpath like this
|
|
||||||
// Create XPathFactory object
|
|
||||||
XPathFactory xpathFactory = XPathFactory.newInstance();
|
|
||||||
|
|
||||||
// Create XPath object
|
/***
|
||||||
XPath xpath = xpathFactory.newXPath();
|
* we should switch to xpath like this // Create XPathFactory object
|
||||||
XPathExpression expr =
|
* XPathFactory xpathFactory = XPathFactory.newInstance();
|
||||||
xpath.compile("//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/[local-name()=\"ID\"]");
|
*
|
||||||
//evaluate expression result on XML document
|
* // Create XPath object XPath xpath = xpathFactory.newXPath(); XPathExpression
|
||||||
ndList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
|
* expr =
|
||||||
|
* xpath.compile("//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/[local-name()=\"ID\"]");
|
||||||
|
* //evaluate expression result on XML document ndList = (NodeList)
|
||||||
|
* expr.evaluate(doc, XPathConstants.NODESET);
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ndList = document.getElementsByTagNameNS("*", "PayeePartyCreditorFinancialAccount"); //$NON-NLS-1$
|
ndList = document.getElementsByTagNameNS("*", "PayeePartyCreditorFinancialAccount"); //$NON-NLS-1$
|
||||||
@@ -333,10 +358,10 @@ public class ZUGFeRDImporter {
|
|||||||
private void setForeignReference(String foreignReference) {
|
private void setForeignReference(String foreignReference) {
|
||||||
this.foreignReference = foreignReference;
|
this.foreignReference = foreignReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return the sender's bank's BIC code
|
* @return the sender's bank's BIC code
|
||||||
*/
|
*/
|
||||||
public String getBIC() {
|
public String getBIC() {
|
||||||
if (!parsed) {
|
if (!parsed) {
|
||||||
@@ -379,7 +404,6 @@ public class ZUGFeRDImporter {
|
|||||||
return bankName;
|
return bankName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void setIBAN(String IBAN) {
|
private void setIBAN(String IBAN) {
|
||||||
this.IBAN = IBAN;
|
this.IBAN = IBAN;
|
||||||
}
|
}
|
||||||
@@ -427,12 +451,13 @@ public class ZUGFeRDImporter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param meta raw XML to be set
|
* @param meta
|
||||||
|
* raw XML to be set
|
||||||
*/
|
*/
|
||||||
public void setMeta(String meta) {
|
public void setMeta(String meta) {
|
||||||
this.rawXML = meta.getBytes();
|
this.rawXML = meta.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return raw XML of the invoice
|
* @return raw XML of the invoice
|
||||||
@@ -455,6 +480,7 @@ public class ZUGFeRDImporter {
|
|||||||
/**
|
/**
|
||||||
* will return true if the metadata (just extract-ed or set with setMeta)
|
* will return true if the metadata (just extract-ed or set with setMeta)
|
||||||
* contains ZUGFeRD XML
|
* contains ZUGFeRD XML
|
||||||
|
*
|
||||||
* @return true if the invoice contains ZUGFeRD XML
|
* @return true if the invoice contains ZUGFeRD XML
|
||||||
*/
|
*/
|
||||||
public boolean canParse() {
|
public boolean canParse() {
|
||||||
@@ -463,6 +489,6 @@ public class ZUGFeRDImporter {
|
|||||||
// indication if zugferd is present - better than just invoice
|
// indication if zugferd is present - better than just invoice
|
||||||
String meta = getMeta();
|
String meta = getMeta();
|
||||||
return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext") //$NON-NLS-1$
|
return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext") //$NON-NLS-1$
|
||||||
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /*ZF2*/));
|
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user