Merge branch 'issues/481-ubl-to-pdf'

This commit is contained in:
jstaerk
2024-10-01 21:20:07 +02:00
17 changed files with 2308 additions and 101 deletions

View File

@@ -1,6 +1,6 @@
package org.mustangproject;
public enum EStandard {
facturx, orderx, despatchadvice, ubldespatchadvice, zugferd, cii, ubl
facturx, orderx, despatchadvice, ubldespatchadvice, zugferd, cii, ubl, ubl_creditnote
}

View File

@@ -62,6 +62,7 @@ import org.apache.fop.configuration.ConfigurationException;
import org.apache.fop.configuration.DefaultConfigurationBuilder;
import org.apache.xmlgraphics.util.MimeConstants;
import org.mustangproject.ClasspathResolverURIAdapter;
import org.mustangproject.EStandard;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -107,14 +108,46 @@ public class ZUGFeRDVisualizer {
mFactory.setURIResolver(new ClasspathResourceURIResolver());
}
/***
* returns which standard is used, CII or UBL
* @param fis inputstream (will be consumed)
* @return (facturx = cii)
*/
public EStandard findOutStandardFromRootNode(InputStream fis) {
String zf1Signature = "CrossIndustryDocument";
String zf2Signature = "CrossIndustryInvoice";
String ublSignature = "Invoice";
String ublCreditNoteSignature = "CreditNote";
String cioSignature = "SCRDMCCBDACIOMessageStructure";
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(fis));
Element root = doc.getDocumentElement();
if (root.getLocalName().equals(zf1Signature)) {
return EStandard.zugferd;
} else if (root.getLocalName().equals(zf2Signature)) {
return EStandard.facturx;
} else if (root.getLocalName().equals(ublSignature)) {
return EStandard.ubl;
} else if (root.getLocalName().equals(ublCreditNoteSignature)) {
return EStandard.ubl_creditnote;
} else if (root.getLocalName().equals(cioSignature)) {
return EStandard.orderx;
}
} catch (Exception e) {
LOGGER.error("Failed to recognize standard", e);
}
return null;
}
public String visualize(String xmlFilename, Language lang)
throws FileNotFoundException, TransformerException, IOException, SAXException, ParserConfigurationException {
try {
if (mXsltXRTemplate == null) {
mXsltXRTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
}
if (mXsltPDFTemplate == null) {
mXsltPDFTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
@@ -148,35 +181,28 @@ public class ZUGFeRDVisualizer {
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String zf1Signature = "CrossIndustryDocument";
String zf2Signature = "CrossIndustryInvoice";
String ublSignature = "Invoice";
String ublCreditNoteSignature = "CreditNote";
String cioSignature = "SCRDMCCBDACIOMessageStructure" +
"";
boolean doPostProcessing = false;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(fis));
Element root = doc.getDocumentElement();
fis = new FileInputStream(xmlFilename); // fis wont reset() so re-read from beginning
if (root.getLocalName().equals(zf1Signature)) {
EStandard thestandard = findOutStandardFromRootNode(fis);
fis = new FileInputStream(xmlFilename); // fis wont reset() so re-read from beginning
if (thestandard == EStandard.zugferd) {
applyZF1XSLT(fis, baos);
} else if (root.getLocalName().equals(zf2Signature)) {
} else if (thestandard == EStandard.facturx) {
//zf2 or fx
applyZF2XSLT(fis, iaos);
doPostProcessing = true;
} else if (root.getLocalName().equals(ublSignature)) {
} else if (thestandard == EStandard.ubl) {
//zf2 or fx
applyUBL2XSLT(fis, iaos);
doPostProcessing = true;
} else if (root.getLocalName().equals(ublCreditNoteSignature)) {
} else if (thestandard == EStandard.ubl_creditnote) {
//zf2 or fx
applyUBLCreditNote2XSLT(fis, iaos);
doPostProcessing = true;
} else if (root.getLocalName().equals(cioSignature)) {
} else if (thestandard == EStandard.orderx) {
//zf2 or fx
applyCIO2XSLT(fis, iaos);
doPostProcessing = true;
@@ -219,11 +245,11 @@ public class ZUGFeRDVisualizer {
protected String toFOP(String xmlFilename)
throws FileNotFoundException, TransformerException {
FileInputStream fis = new FileInputStream(xmlFilename);
EStandard theStandard = findOutStandardFromRootNode(fis);
fis = new FileInputStream(xmlFilename);//rewind :-(
try {
if (mXsltXRTemplate == null) {
mXsltXRTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
}
if (mXsltPDFTemplate == null) {
mXsltPDFTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/xr-pdf.xsl")));
@@ -232,12 +258,18 @@ public class ZUGFeRDVisualizer {
LOGGER.error("Failed to init XSLT templates", ex);
}
FileInputStream fis = new FileInputStream(xmlFilename);
ByteArrayOutputStream iaos = new ByteArrayOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//zf2 or fx
applyZF2XSLT(fis, iaos);
if (theStandard == EStandard.facturx) {
applyZF2XSLT(fis, iaos);
} else if (theStandard == EStandard.ubl) {
applyUBL2XSLT(fis, iaos);
} else if (theStandard == EStandard.ubl_creditnote) {
applyUBLCreditNote2XSLT(fis, iaos);
}
PipedInputStream in = new PipedInputStream();
PipedOutputStream out;
@@ -272,7 +304,7 @@ public class ZUGFeRDVisualizer {
public void toPDF(String xmlFilename, String pdfFilename) {
// the writing part
File CIIinputFile = new File(xmlFilename);
File XMLinputFile = new File(xmlFilename);
String result = null;
@@ -280,7 +312,7 @@ public class ZUGFeRDVisualizer {
out from git with arbitrary options (which may include CSRF changes)
*/
try {
result = this.toFOP(CIIinputFile.getAbsolutePath());
result = this.toFOP(XMLinputFile.getAbsolutePath());
} catch (FileNotFoundException | TransformerException e) {
LOGGER.error("Failed to apply FOP", e);
}
@@ -330,8 +362,6 @@ public class ZUGFeRDVisualizer {
// Step 6: Start XSLT transformation and FOP processing
transformer.transform(src, res);
//Files.write(Paths.get("C:\\Users\\jstaerk\\temp\\fop.pdf"), res.toString().getBytes(StandardCharsets.UTF_8));
} catch (FOPException | IOException | TransformerException e) {
LOGGER.error("Failed to create PDF", e);
}
@@ -339,6 +369,11 @@ public class ZUGFeRDVisualizer {
protected void applyZF2XSLT(final InputStream xmlFile, final OutputStream HTMLOutstream)
throws TransformerException {
if (mXsltXRTemplate == null) {
mXsltXRTemplate = mFactory.newTemplates(
new StreamSource(CLASS_LOADER.getResourceAsStream(RESOURCE_PATH + "stylesheets/cii-xr.xsl")));
}
Transformer transformer = mXsltXRTemplate.newTransformer();
transformer.transform(new StreamSource(xmlFile), new StreamResult(HTMLOutstream));

View File

@@ -0,0 +1,56 @@
package org.mustangproject.util;
public final class ByteArraySearcher {
private ByteArraySearcher() {
}
public static int indexOf(byte[] haystack, byte[] needle) {
if (needle.length > haystack.length) {
return -1;
}
// Any needle to search?
if (needle.length == 0) {
return -1;
}
for (int i = 0; i <= haystack.length - needle.length; i++) {
boolean found = true;
for (int j = 0; j < needle.length; j++) {
if (haystack[i + j] != needle[j]) {
found = false;
break;
}
}
if (found) {
return i;
}
}
return -1;
}
public static boolean contains(byte[] haystack, byte[] needle) {
return indexOf(haystack, needle) >= 0;
}
public static boolean startsWith(byte[] haystack, byte[] needle) {
if (needle.length > haystack.length) {
return false;
}
// Any needle to search?
if (needle.length == 0) {
return false;
}
for (int j = 0; j < needle.length; j++) {
if (haystack[j] != needle[j]) {
return false;
}
}
return true;
}
}