coparing arrays for beginners

This commit is contained in:
jstaerk
2024-05-06 15:24:43 +02:00
parent ed97bb9d12
commit bdb47ce100

View File

@@ -23,12 +23,7 @@ import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -82,9 +77,9 @@ public class ZUGFeRDImporter {
protected ZUGFeRDImporter() { protected ZUGFeRDImporter() {
//constructor for extending classes //constructor for extending classes
} }
public ZUGFeRDImporter(String pdfFilename) { public ZUGFeRDImporter(String pdfFilename) {
try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) { try (InputStream bis = Files.newInputStream(Paths.get(pdfFilename), StandardOpenOption.READ)) {
extractLowLevel(bis); extractLowLevel(bis);
@@ -111,48 +106,48 @@ public class ZUGFeRDImporter {
* @param inStream a inputstream of a pdf file * @param inStream a inputstream of a pdf file
*/ */
private void extractLowLevel(InputStream inStream) throws IOException { private void extractLowLevel(InputStream inStream) throws IOException {
BufferedInputStream pdfStream=new BufferedInputStream(inStream); BufferedInputStream pdfStream = new BufferedInputStream(inStream);
byte[] pad = new byte[4]; byte[] pad = new byte[4];
pdfStream.mark(0); pdfStream.mark(0);
pdfStream.read(pad); pdfStream.read(pad);
pdfStream.reset(); pdfStream.reset();
byte[] pdfSignature = { '%', 'P', 'D', 'F' }; byte[] pdfSignature = {'%', 'P', 'D', 'F'};
if (pad.equals(pdfSignature)) { // we have a pdf if (Arrays.equals(pad, pdfSignature)) { // we have a pdf
try (PDDocument doc = PDDocument.load(pdfStream)) { try (PDDocument doc = PDDocument.load(pdfStream)) {
// PDDocumentInformation info = doc.getDocumentInformation(); // PDDocumentInformation info = doc.getDocumentInformation();
final PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog()); final PDDocumentNameDictionary names = new PDDocumentNameDictionary(doc.getDocumentCatalog());
//start //start
if (doc.getDocumentCatalog() == null || doc.getDocumentCatalog().getMetadata() == null) { if (doc.getDocumentCatalog() == null || doc.getDocumentCatalog().getMetadata() == null) {
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.INFO, "no-xmlpart"); Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.INFO, "no-xmlpart");
return; return;
} }
final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata(); final InputStream XMP = doc.getDocumentCatalog().getMetadata().exportXMPMetadata();
xmpString = convertStreamToString(XMP); xmpString = convertStreamToString(XMP);
final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles(); final PDEmbeddedFilesNameTreeNode etn = names.getEmbeddedFiles();
if (etn == null) { if (etn == null) {
return; return;
} }
final Map<String, PDComplexFileSpecification> efMap = etn.getNames(); final Map<String, PDComplexFileSpecification> efMap = etn.getNames();
// String filePath = "/tmp/"; // String filePath = "/tmp/";
if (efMap != null) { if (efMap != null) {
extractFiles(efMap); // see extractFiles(efMap); // see
// https://memorynotfound.com/apache-pdfbox-extract-embedded-file-pdf-document/ // https://memorynotfound.com/apache-pdfbox-extract-embedded-file-pdf-document/
} else { } else {
final List<PDNameTreeNode<PDComplexFileSpecification>> kids = etn.getKids(); final List<PDNameTreeNode<PDComplexFileSpecification>> kids = etn.getKids();
for (final PDNameTreeNode<PDComplexFileSpecification> node : kids) { for (final PDNameTreeNode<PDComplexFileSpecification> node : kids) {
final Map<String, PDComplexFileSpecification> namesL = node.getNames(); final Map<String, PDComplexFileSpecification> namesL = node.getNames();
extractFiles(namesL); extractFiles(namesL);
}
} }
} }
}
} else { } else {
// no PDF probably XML // no PDF probably XML
containsMeta = true; containsMeta = true;
@@ -204,7 +199,7 @@ public class ZUGFeRDImporter {
xmlFact.setNamespaceAware(true); xmlFact.setNamespaceAware(true);
final DocumentBuilder builder = xmlFact.newDocumentBuilder(); final DocumentBuilder builder = xmlFact.newDocumentBuilder();
final ByteArrayInputStream is = new ByteArrayInputStream(rawXML); final ByteArrayInputStream is = new ByteArrayInputStream(rawXML);
/// is.skip(guessBOMSize(is)); /// is.skip(guessBOMSize(is));
document = builder.parse(is); document = builder.parse(is);
} }
@@ -221,8 +216,6 @@ public class ZUGFeRDImporter {
} }
protected String extractString(String xpathStr) { protected String extractString(String xpathStr) {
if (!containsMeta) { if (!containsMeta) {
throw new ZUGFeRDExportException("No suitable data/ZUGFeRD file could be found."); throw new ZUGFeRDExportException("No suitable data/ZUGFeRD file could be found.");
@@ -279,9 +272,9 @@ public class ZUGFeRDImporter {
case "urn:ferd:CrossIndustryDocument:invoice:1p0:extended": case "urn:ferd:CrossIndustryDocument:invoice:1p0:extended":
case "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended": case "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended":
return "EXTENDED"; return "EXTENDED";
default: default:
return ""; return "";
} }
} }
/** /**
@@ -315,7 +308,7 @@ public class ZUGFeRDImporter {
return extractIssuerAssignedID("SellerOrderReferencedDocument"); return extractIssuerAssignedID("SellerOrderReferencedDocument");
} }
/** /**
* @return the IssuerAssigned ID * @return the IssuerAssigned ID
*/ */
public String getContractOrderReferencedDocumentIssuerAssignedID() { public String getContractOrderReferencedDocumentIssuerAssignedID() {
@@ -357,21 +350,22 @@ public class ZUGFeRDImporter {
return ""; return "";
} }
} }
public Date getDetailedDeliveryPeriodFrom(){ public Date getDetailedDeliveryPeriodFrom() {
final String toParse = extractString( final String toParse = extractString(
"//*[local-name() = 'ApplicableHeaderTradeSettlement']" + "//*[local-name() = 'ApplicableHeaderTradeSettlement']" +
"//*[local-name() = 'BillingSpecifiedPeriod']" + "//*[local-name() = 'BillingSpecifiedPeriod']" +
"//*[local-name() = 'StartDateTime']//*[local-name() = 'DateTimeString']"); "//*[local-name() = 'StartDateTime']//*[local-name() = 'DateTimeString']");
return tryDate(toParse); return tryDate(toParse);
} }
public Date getDetailedDeliveryPeriodTo(){
final String toParse = extractString( public Date getDetailedDeliveryPeriodTo() {
"//*[local-name() = 'ApplicableHeaderTradeSettlement']" + final String toParse = extractString(
"//*[local-name() = 'BillingSpecifiedPeriod']" + "//*[local-name() = 'ApplicableHeaderTradeSettlement']" +
"//*[local-name() = 'EndDateTime']//*[local-name() = 'DateTimeString']"); "//*[local-name() = 'BillingSpecifiedPeriod']" +
return tryDate(toParse); "//*[local-name() = 'EndDateTime']//*[local-name() = 'DateTimeString']");
} return tryDate(toParse);
}
/** /**
* @return the TaxBasisTotalAmount * @return the TaxBasisTotalAmount
@@ -480,7 +474,9 @@ public class ZUGFeRDImporter {
*/ */
public String getBuyerTradePartyName() { public String getBuyerTradePartyName() {
return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'Name']"); return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'Name']");
} /** }
/**
* @return the BuyerTradeParty Name * @return the BuyerTradeParty Name
*/ */
public String getDeliveryTradePartyName() { public String getDeliveryTradePartyName() {
@@ -488,7 +484,6 @@ public class ZUGFeRDImporter {
} }
/** /**
* @return the line Total Amount * @return the line Total Amount
*/ */
@@ -545,7 +540,6 @@ public class ZUGFeRDImporter {
} }
/** /**
* @return the document code * @return the document code
*/ */
@@ -617,7 +611,7 @@ public class ZUGFeRDImporter {
if (result == null || result.isEmpty()) { if (result == null || result.isEmpty()) {
/* fx/zf would be SpecifiedTradeSettlementMonetarySummation /* fx/zf would be SpecifiedTradeSettlementMonetarySummation
* but ox is SpecifiedTradeSettlementHeaderMonetarySummation...*/ * but ox is SpecifiedTradeSettlementHeaderMonetarySummation...*/
result = extractString("//*[local-name() = 'GrandTotalAmount']"); result = extractString("//*[local-name() = 'GrandTotalAmount']");
} }
return result; return result;
@@ -681,7 +675,7 @@ public class ZUGFeRDImporter {
throw new Exception("Not yet parsed"); throw new Exception("Not yet parsed");
} }
final String head = getUTF8(); final String head = getUTF8();
String rootNode=extractString("local-name(/*)"); String rootNode = extractString("local-name(/*)");
if (rootNode.equals("CrossIndustryDocument")) { if (rootNode.equals("CrossIndustryDocument")) {
return EStandard.zugferd; return EStandard.zugferd;
} else if (rootNode.equals("Invoice")) { } else if (rootNode.equals("Invoice")) {
@@ -697,26 +691,26 @@ public class ZUGFeRDImporter {
throw new Exception("ZUGFeRD version could not be determined"); throw new Exception("ZUGFeRD version could not be determined");
} }
public int getVersion() throws Exception { public int getVersion() throws Exception {
if (!containsMeta) { if (!containsMeta) {
throw new Exception("Not yet parsed"); throw new Exception("Not yet parsed");
} }
if (version != null) { if (version != null) {
return version; return version;
} }
final String head = getUTF8(); final String head = getUTF8();
if (head.contains("<rsm:CrossIndustryDocument") // if (head.contains("<rsm:CrossIndustryDocument") //
|| head.contains("<CrossIndustryDocument") // || head.contains("<CrossIndustryDocument") //
|| head.contains("<SCRDMCCBDACIDAMessageStructure") // || head.contains("<SCRDMCCBDACIDAMessageStructure") //
|| head.contains("<rsm:SCRDMCCBDACIOMessageStructure")) { // || head.contains("<rsm:SCRDMCCBDACIOMessageStructure")) { //
version = 1; version = 1;
} else if (head.contains("<rsm:CrossIndustryInvoice")) { } else if (head.contains("<rsm:CrossIndustryInvoice")) {
version = 2; version = 2;
} else {
throw new Exception("ZUGFeRD version could not be determined");
} }
else {
throw new Exception("ZUGFeRD version could not be determined");
}
return version; return version;
} }
@@ -736,12 +730,12 @@ public class ZUGFeRDImporter {
final byte[] bomlessData; final byte[] bomlessData;
if ((rawXML[0] == (byte) 0xEF) if ((rawXML[0] == (byte) 0xEF)
&& (rawXML[1] == (byte) 0xBB) && (rawXML[1] == (byte) 0xBB)
&& (rawXML[2] == (byte) 0xBF)) { && (rawXML[2] == (byte) 0xBF)) {
// I don't like BOMs, lets remove it // I don't like BOMs, lets remove it
bomlessData = new byte[rawXML.length - 3]; bomlessData = new byte[rawXML.length - 3];
System.arraycopy(rawXML, 3, bomlessData, 0, System.arraycopy(rawXML, 3, bomlessData, 0,
rawXML.length - 3); rawXML.length - 3);
} else { } else {
bomlessData = rawXML; bomlessData = rawXML;
} }
@@ -771,7 +765,7 @@ public class ZUGFeRDImporter {
// indication if zugferd is present - better than just invoice // indication if zugferd is present - better than just invoice
final String meta = getMeta(); final String meta = getMeta();
return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext") return (meta != null) && (meta.length() > 0) && ((meta.contains("SpecifiedExchangedDocumentContext")
/* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */)); /* ZF1 */ || meta.contains("ExchangedDocumentContext") /* ZF2 */));
} }
@@ -784,6 +778,7 @@ public class ZUGFeRDImporter {
/** /**
* returns an instance of PostalTradeAddress for SellerTradeParty section * returns an instance of PostalTradeAddress for SellerTradeParty section
*
* @return an instance of PostalTradeAddress * @return an instance of PostalTradeAddress
*/ */
public PostalTradeAddress getBuyerTradePartyAddress() { public PostalTradeAddress getBuyerTradePartyAddress() {
@@ -806,6 +801,7 @@ public class ZUGFeRDImporter {
/** /**
* returns an instance of PostalTradeAddress for SellerTradeParty section * returns an instance of PostalTradeAddress for SellerTradeParty section
*
* @return an instance of PostalTradeAddress * @return an instance of PostalTradeAddress
*/ */
public PostalTradeAddress getSellerTradePartyAddress() { public PostalTradeAddress getSellerTradePartyAddress() {
@@ -823,10 +819,11 @@ public class ZUGFeRDImporter {
} }
return getAddressFromNodeList(nl); return getAddressFromNodeList(nl);
} }
/** /**
* returns an instance of PostalTradeAddress for ShipToTradeParty section * returns an instance of PostalTradeAddress for ShipToTradeParty section
*
* @return an instance of PostalTradeAddress * @return an instance of PostalTradeAddress
*/ */
public PostalTradeAddress getDeliveryTradePartyAddress() { public PostalTradeAddress getDeliveryTradePartyAddress() {
@@ -856,7 +853,7 @@ public class ZUGFeRDImporter {
for (int j = 0; j < nodes.getLength(); j++) { for (int j = 0; j < nodes.getLength(); j++) {
n = nodes.item(j); n = nodes.item(j);
final short nodeType = n.getNodeType(); final short nodeType = n.getNodeType();
if ((nodeType==Node.ELEMENT_NODE)&&(n.getLocalName()!=null)){ if ((nodeType == Node.ELEMENT_NODE) && (n.getLocalName() != null)) {
switch (n.getLocalName()) { switch (n.getLocalName()) {
case "PostcodeCode": case "PostcodeCode":
address.setPostCodeCode(""); address.setPostCodeCode("");
@@ -910,21 +907,22 @@ public class ZUGFeRDImporter {
/** /**
* returns a list of LineItems * returns a list of LineItems
*
* @return a List of LineItem instances * @return a List of LineItem instances
*/ */
public List<Item> getLineItemList() { public List<Item> getLineItemList() {
final List<Node> nodeList = getLineItemNodes(); final List<Node> nodeList = getLineItemNodes();
final List<Item> lineItemList = new ArrayList<>(); final List<Item> lineItemList = new ArrayList<>();
for (final Node n: nodeList) { for (final Node n : nodeList) {
final Item lineItem = new Item(null, null, null); final Item lineItem = new Item(null, null, null);
lineItem.setProduct(new Product(null,null,null,null)); lineItem.setProduct(new Product(null, null, null, null));
final NodeList nl = n.getChildNodes(); final NodeList nl = n.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) { for (int i = 0; i < nl.getLength(); i++) {
final Node nn = nl.item(i); final Node nn = nl.item(i);
Node node = null; Node node = null;
if (nn.getLocalName()!=null) { if (nn.getLocalName() != null) {
switch (nn.getLocalName()) { switch (nn.getLocalName()) {
case "SpecifiedLineTradeAgreement": case "SpecifiedLineTradeAgreement":
case "SpecifiedSupplyChainTradeAgreement": case "SpecifiedSupplyChainTradeAgreement":
@@ -992,17 +990,17 @@ public class ZUGFeRDImporter {
node = getNodeByName(nn.getChildNodes(), "BillingSpecifiedPeriod"); node = getNodeByName(nn.getChildNodes(), "BillingSpecifiedPeriod");
if (node != null) { if (node != null) {
final Node start = getNodeByName(node.getChildNodes(), "StartDateTime"); final Node start = getNodeByName(node.getChildNodes(), "StartDateTime");
Node dateTimeStart = null; Node dateTimeStart = null;
if(start != null) { if (start != null) {
dateTimeStart = getNodeByName(start.getChildNodes(), "DateTimeString"); dateTimeStart = getNodeByName(start.getChildNodes(), "DateTimeString");
} }
final Node end = getNodeByName(node.getChildNodes(), "EndDateTime"); final Node end = getNodeByName(node.getChildNodes(), "EndDateTime");
Node dateTimeEnd = null; Node dateTimeEnd = null;
if(end != null) { if (end != null) {
dateTimeEnd = getNodeByName(end.getChildNodes(), "DateTimeString"); dateTimeEnd = getNodeByName(end.getChildNodes(), "DateTimeString");
} }
lineItem.setDetailedDeliveryPeriod(tryDate(dateTimeStart), tryDate(dateTimeEnd)); lineItem.setDetailedDeliveryPeriod(tryDate(dateTimeStart), tryDate(dateTimeEnd));
} }
node = getNodeByName(nn.getChildNodes(), "SpecifiedTradeSettlementLineMonetarySummation"); node = getNodeByName(nn.getChildNodes(), "SpecifiedTradeSettlementLineMonetarySummation");
if (node != null) { if (node != null) {
@@ -1041,13 +1039,14 @@ public class ZUGFeRDImporter {
/** /**
* returns a List of LineItem Nodes from ZUGFeRD XML * returns a List of LineItem Nodes from ZUGFeRD XML
*
* @return a List of Node instances * @return a List of Node instances
*/ */
public List<Node> getLineItemNodes() { public List<Node> getLineItemNodes() {
final List<Node> lineItemNodes = new ArrayList<>(); final List<Node> lineItemNodes = new ArrayList<>();
NodeList nl = null; NodeList nl = null;
try { try {
nl = getNodeListByPath("//*[local-name() = 'IncludedSupplyChainTradeLineItem']"); nl = getNodeListByPath("//*[local-name() = 'IncludedSupplyChainTradeLineItem']");
} catch (final Exception e) { } catch (final Exception e) {
Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e); Logger.getLogger(ZUGFeRDImporter.class.getName()).log(Level.SEVERE, null, e);
@@ -1062,13 +1061,14 @@ public class ZUGFeRDImporter {
/** /**
* Returns a node, found by name. If more nodes with the same name are present, the first occurence will be returned * Returns a node, found by name. If more nodes with the same name are present, the first occurence will be returned
* @param nl - A NodeList which may contains the searched node *
* @param nl - A NodeList which may contains the searched node
* @param name The nodes name * @param name The nodes name
* @return a Node or null, if nothing is found * @return a Node or null, if nothing is found
*/ */
private Node getNodeByName(NodeList nl, String name) { private Node getNodeByName(NodeList nl, String name) {
for (int i = 0; i < nl.getLength(); i++) { for (int i = 0; i < nl.getLength(); i++) {
if ((nl.item(i).getLocalName()!=null)&&(nl.item(i).getLocalName().equals(name))) { if ((nl.item(i).getLocalName() != null) && (nl.item(i).getLocalName().equals(name))) {
return nl.item(i); return nl.item(i);
} else if (nl.item(i).getChildNodes().getLength() > 0) { } else if (nl.item(i).getChildNodes().getLength() > 0) {
final Node node = getNodeByName(nl.item(i).getChildNodes(), name); final Node node = getNodeByName(nl.item(i).getChildNodes(), name);
@@ -1082,6 +1082,7 @@ public class ZUGFeRDImporter {
/** /**
* Get a NodeList by providing an path * Get a NodeList by providing an path
*
* @param path a compliable Path * @param path a compliable Path
* @return a Nodelist or null, if an error occurs * @return a Nodelist or null, if an error occurs
*/ */
@@ -1102,18 +1103,20 @@ public class ZUGFeRDImporter {
/** /**
* returns the value of an node * returns the value of an node
*
* @param node the Node to get the value from * @param node the Node to get the value from
* @return A String or empty String, if no value was found * @return A String or empty String, if no value was found
*/ */
private String getNodeValue(Node node) { private String getNodeValue(Node node) {
if (node != null && node.getFirstChild() != null) { if (node != null && node.getFirstChild() != null) {
return node.getFirstChild().getNodeValue(); return node.getFirstChild().getNodeValue();
} }
return ""; return "";
} }
/** /**
* tries to convert an String to BigDecimal. * tries to convert an String to BigDecimal.
*
* @param nodeValue The value as String * @param nodeValue The value as String
* @return a BigDecimal with the value provides as String or a BigDecimal with value 0.00 if an error occurs * @return a BigDecimal with the value provides as String or a BigDecimal with value 0.00 if an error occurs
*/ */
@@ -1128,20 +1131,21 @@ public class ZUGFeRDImporter {
} }
} }
} }
private Date tryDate(Node node) {
final String nodeValue = getNodeValue(node);
if (nodeValue.isEmpty()) {
return null;
}
return tryDate(nodeValue);
}
private static Date tryDate(String toParse) { private Date tryDate(Node node) {
final SimpleDateFormat formatter = ZUGFeRDDateFormat.DATE.getFormatter(); final String nodeValue = getNodeValue(node);
try { if (nodeValue.isEmpty()) {
return formatter.parse(toParse); return null;
} catch (final Exception e) {
return null;
} }
} return tryDate(nodeValue);
}
private static Date tryDate(String toParse) {
final SimpleDateFormat formatter = ZUGFeRDDateFormat.DATE.getFormatter();
try {
return formatter.parse(toParse);
} catch (final Exception e) {
return null;
}
}
} }