diff --git a/library/src/main/java/org/mustangproject/Invoice.java b/library/src/main/java/org/mustangproject/Invoice.java index ba4602f8..a99752e4 100644 --- a/library/src/main/java/org/mustangproject/Invoice.java +++ b/library/src/main/java/org/mustangproject/Invoice.java @@ -46,13 +46,18 @@ public class Invoice implements IExportableTransaction { protected Date detailedDeliveryDateStart = null; protected Date detailedDeliveryPeriodEnd = null; - protected ArrayList Allowances = new ArrayList(), - Charges = new ArrayList(), LogisticsServiceCharges = new ArrayList(); + protected ArrayList Allowances = new ArrayList<>(), + Charges = new ArrayList<>(), LogisticsServiceCharges = new ArrayList<>(); protected IZUGFeRDPaymentTerms paymentTerms = null; + private Date invoiceReferencedIssueDate; + private String specifiedProcuringProjectID = null; + + + private String specifiedProcuringProjectName = null; public Invoice() { - ZFItems = new ArrayList(); + ZFItems = new ArrayList<>(); setCurrency("EUR"); } @@ -246,7 +251,17 @@ public class Invoice implements IExportableTransaction { return invoiceReferencedDocumentID; } - @Override + @Override + public Date getInvoiceReferencedIssueDate() { + return invoiceReferencedIssueDate; + } + + public Invoice setInvoiceReferencedIssueDate(Date issueDate) { + this.invoiceReferencedIssueDate = issueDate; + return this; + } + + @Override public String getBuyerOrderReferencedDocumentIssueDateTime() { return buyerOrderReferencedDocumentIssueDateTime; } @@ -637,4 +652,23 @@ public class Invoice implements IExportableTransaction { return this; } + @Override + public String getSpecifiedProcuringProjectID() { + return specifiedProcuringProjectID; + } + + public Invoice setSpecifiedProcuringProjectID(String specifiedProcuringProjectID) { + this.specifiedProcuringProjectID = specifiedProcuringProjectID; + return this; + } + + @Override + public String getSpecifiedProcuringProjectName() { + return specifiedProcuringProjectName; + } + + public Invoice setSpecifiedProcuringProjectName(String specifiedProcuringProjectName) { + this.specifiedProcuringProjectName = specifiedProcuringProjectName; + return this; + } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java index 8f1f12c3..1ce056e6 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/IExportableTransaction.java @@ -416,7 +416,7 @@ public interface IExportableTransaction { } /** - * get the ID of the prceding invoice, which is e.g. to be corrected if this is a correction + * get the ID of the preceding invoice, which is e.g. to be corrected if this is a correction * * @return the ID of the document */ @@ -424,6 +424,7 @@ public interface IExportableTransaction { return null; } + default Date getInvoiceReferencedIssueDate(){return null;} /** * get the issue timestamp of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement * @@ -488,4 +489,12 @@ public interface IExportableTransaction { default String[] getNotes() { return null; } + + default String getSpecifiedProcuringProjectName(){ + return null; + } + + default String getSpecifiedProcuringProjectID(){ + return null; + } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java index a3d89bbf..2a8b8eb4 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java @@ -20,6 +20,7 @@ */ package org.mustangproject.ZUGFeRD; +import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE; import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON; import java.io.IOException; @@ -46,8 +47,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr protected byte[] zugferdData; private String paymentTermsDescription; - SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); - protected Profile profile = Profiles.getByName("COMFORT", 1); + protected Profile profile = Profiles.getByName("COMFORT", 1); /** @@ -169,8 +169,8 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" + " RECHNUNG\n" + " " + typecode + "\n" - + " " - + zugferdDateFormat.format(trans.getIssueDate()) + "\n" // date + + " " + + DATE.udtFormat(trans.getIssueDate()) + "\n" // date // format // was // 20130605 @@ -225,8 +225,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr + " "; if (trans.getDeliveryDate() != null) { - xml += "" + zugferdDateFormat.format(trans.getDeliveryDate()) - + ""; + xml += DATE.udtFormat(trans.getDeliveryDate()); } else { throw new IllegalStateException("No delivery date provided"); } @@ -292,9 +291,9 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr } if (hasDueDate && (trans.getDueDate() != null)) { - xml = xml + " " // $NON-NLS-2$ - + zugferdDateFormat.format(trans.getDueDate()) - + "\n";// 20130704 + xml = xml + " " // $NON-NLS-2$ + + DATE.udtFormat(trans.getDueDate()) + + "\n";// 20130704 } xml = xml + " \n"; @@ -440,8 +439,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr paymentTermsXml += "" + paymentTerms.getDescription() + ""; if (dueDate != null) { paymentTermsXml += ""; - paymentTermsXml += "" - + zugferdDateFormat.format(dueDate.getDate()) + ""; + paymentTermsXml += DATE.udtFormat(dueDate) ; paymentTermsXml += ""; } @@ -456,7 +454,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr if (discountTerms.getBaseDate() != null) { final Date baseDate = discountTerms.getBaseDate(); paymentTermsXml += ""; - paymentTermsXml += "" + zugferdDateFormat.format(baseDate) + ""; + paymentTermsXml += DATE.udtFormat(baseDate) ; paymentTermsXml += ""; paymentTermsXml += "" diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java index 978afb76..32eabf2d 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java @@ -20,6 +20,7 @@ */ package org.mustangproject.ZUGFeRD; +import static org.mustangproject.ZUGFeRD.ZUGFeRDDateFormat.DATE; import static org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE; import static org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants.CATEGORY_CODES_WITH_EXEMPTION_REASON; @@ -44,9 +45,7 @@ import org.mustangproject.XMLTools; public class ZUGFeRD2PullProvider implements IXMLProvider { - //// MAIN CLASS - protected SimpleDateFormat zugferdDateFormat = new SimpleDateFormat("yyyyMMdd"); - protected byte[] zugferdData; + protected byte[] zugferdData; protected IExportableTransaction trans; protected TransactionCalculator calc; private String paymentTermsDescription; @@ -278,7 +277,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { // xsi:schemaLocation=\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100 // ../Schema/ZUGFeRD1p0.xsd\"" + " xmlns:ram=\"urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100\"" - + " xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\">\n" + + " xmlns:udt=\"urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100\"" + + " xmlns:qdt=\"urn:un:unece:uncefact:data:standard:QualifiedDataType:100\">\n" + " \n" // + " // "+testBooleanStr+"\n" @@ -292,8 +292,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { // + " RECHNUNG\n" // + " 380\n" + " " + typecode + "\n" - + " " - + zugferdDateFormat.format(trans.getIssueDate()) + "\n" // date + + " " + + DATE.udtFormat(trans.getIssueDate()) + "\n" // date + notes + subjectNote + rebateAgreement @@ -405,10 +405,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) { xml = xml + ""; if (currentItem.getDetailedDeliveryPeriodFrom() != null) { - xml = xml + "" + zugferdDateFormat.format(currentItem.getDetailedDeliveryPeriodFrom()) + ""; + xml = xml + "" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodFrom()) + ""; } if (currentItem.getDetailedDeliveryPeriodTo() != null) { - xml = xml + "" + zugferdDateFormat.format(currentItem.getDetailedDeliveryPeriodTo()) + ""; + xml = xml + "" + DATE.udtFormat(currentItem.getDetailedDeliveryPeriodTo()) + ""; } xml = xml + ""; @@ -475,6 +475,15 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } } + if (trans.getSpecifiedProcuringProjectID() != null) { + xml = xml + " \n" + + " " + + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectID()) + "\n"; + if(trans.getSpecifiedProcuringProjectName()!= null) { + xml += " " + XMLTools.encodeXML(trans.getSpecifiedProcuringProjectName()) + "\n"; + } + xml += " \n"; + } xml = xml + " \n" + " \n"; if (this.trans.getDeliveryAddress() != null) { @@ -487,8 +496,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { + " "; if (trans.getDeliveryDate() != null) { - xml += "" + zugferdDateFormat.format(trans.getDeliveryDate()) - + ""; + xml += DATE.udtFormat(trans.getDeliveryDate()); } else { throw new IllegalStateException("No delivery date provided"); } @@ -546,10 +554,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if ((trans.getDetailedDeliveryPeriodFrom() != null) || (trans.getDetailedDeliveryPeriodTo() != null)) { xml = xml + ""; if (trans.getDetailedDeliveryPeriodFrom() != null) { - xml = xml + "" + zugferdDateFormat.format(trans.getDetailedDeliveryPeriodFrom()) + ""; + xml = xml + "" + DATE.udtFormat(trans.getDetailedDeliveryPeriodFrom()) + ""; } if (trans.getDetailedDeliveryPeriodTo() != null) { - xml = xml + "" + zugferdDateFormat.format(trans.getDetailedDeliveryPeriodTo()) + ""; + xml = xml + "" + DATE.udtFormat(trans.getDetailedDeliveryPeriodTo()) + ""; } xml = xml + ""; @@ -616,9 +624,9 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { } if (hasDueDate && (trans.getDueDate() != null)) { - xml = xml + " " // $NON-NLS-2$ - + zugferdDateFormat.format(trans.getDueDate()) - + "\n";// 20130704 + xml = xml + " " // $NON-NLS-2$ + + DATE.udtFormat(trans.getDueDate()) + + "\n";// 20130704 } xml = xml + " \n"; @@ -649,8 +657,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if (trans.getInvoiceReferencedDocumentID() != null) { xml = xml + " \n" + " " - + XMLTools.encodeXML(trans.getInvoiceReferencedDocumentID()) + "\n" - + " \n"; + + XMLTools.encodeXML(trans.getInvoiceReferencedDocumentID()) + "\n"; + if(trans.getInvoiceReferencedIssueDate()!= null){ + xml += "" + + DATE.qdtFormat(trans.getInvoiceReferencedIssueDate()) + + "\n"; + } + xml += " \n"; } xml = xml + " \n"; @@ -698,8 +711,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { paymentTermsXml += "" + paymentTerms.getDescription() + ""; if (dueDate != null) { paymentTermsXml += ""; - paymentTermsXml += "" - + zugferdDateFormat.format(dueDate) + ""; + paymentTermsXml += DATE.udtFormat(dueDate) ; paymentTermsXml += ""; } @@ -714,7 +726,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider { if (discountTerms.getBaseDate() != null) { final Date baseDate = discountTerms.getBaseDate(); paymentTermsXml += ""; - paymentTermsXml += "" + zugferdDateFormat.format(baseDate) + ""; + paymentTermsXml += DATE.udtFormat(baseDate); paymentTermsXml += ""; paymentTermsXml += "" diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDDateFormat.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDDateFormat.java index 3457fe18..d5003577 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDDateFormat.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRDDateFormat.java @@ -1,6 +1,7 @@ package org.mustangproject.ZUGFeRD; import java.text.SimpleDateFormat; +import java.util.Date; import org.mustangproject.ZUGFeRD.model.DateTimeTypeConstants; @@ -12,6 +13,8 @@ public enum ZUGFeRDDateFormat { private String dateTimeType; private SimpleDateFormat formatter; + private static final String QDT_FORMAT = "%s"; + private static final String UDT_FORMAT = "%s"; private ZUGFeRDDateFormat(String dateTimeType, SimpleDateFormat formatter) { this.dateTimeType = dateTimeType; @@ -25,4 +28,14 @@ public enum ZUGFeRDDateFormat { public SimpleDateFormat getFormatter() { return formatter; } + + public String simpleFormat(Date date){ + return getFormatter().format(date); + } + public String qdtFormat(Date date){ + return String.format(QDT_FORMAT, getDateTimeType(), getFormatter().format(date)); + } + public String udtFormat(Date date){ + return String.format(UDT_FORMAT, getDateTimeType(), getFormatter().format(date)); + } } diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentCodeTypeConstants.java b/library/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentCodeTypeConstants.java index bbc2a7ac..74fac56a 100644 --- a/library/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentCodeTypeConstants.java +++ b/library/src/main/java/org/mustangproject/ZUGFeRD/model/DocumentCodeTypeConstants.java @@ -23,4 +23,5 @@ public class DocumentCodeTypeConstants { public static final String CREDITNOTE = "381"; public static final String DEBITNOTE = "84"; public static final String CORRECTEDINVOICE = "384"; + public static final String PARTIAL_BILLING = "326"; } diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java index 00b20dd1..cb02923c 100644 --- a/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java +++ b/library/src/test/java/org/mustangproject/ZUGFeRD/UBLTest.java @@ -21,32 +21,32 @@ */ package org.mustangproject.ZUGFeRD; -import org.junit.FixMethodOrder; -import org.junit.runners.MethodSorters; -import org.mustangproject.CII.CIIToUBL; - import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import org.mustangproject.CII.CIIToUBL; + @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class UBLTest extends ResourceCase { public void testUBLBasic() { // the writing part - CIIToUBL c2u = new CIIToUBL(); - String sourceFilename = "factur-x.xml"; - File input = getResourceAsFile(sourceFilename); - File expectedFile = getResourceAsFile("ubl-conv-ubl-output-factur-x.xml"); + final CIIToUBL c2u = new CIIToUBL(); + final String sourceFilename = "factur-x.xml"; + final File input = getResourceAsFile(sourceFilename); + final File expectedFile = getResourceAsFile("ubl-conv-ubl-output-factur-x.xml"); String expected = null; String result = null; try { - File tempFile = File.createTempFile("ZUGFeRD-UBL-", "-test"); + final File tempFile = File.createTempFile("ZUGFeRD-UBL-", "-test"); c2u.convert(input, tempFile); expected = ResourceUtilities.readFile(StandardCharsets.UTF_8, expectedFile.getAbsolutePath()); - result = ResourceUtilities.readFile(StandardCharsets.UTF_8, tempFile.getAbsolutePath()); - } catch (IOException e) { + result = ResourceUtilities.readFile(StandardCharsets.UTF_8, tempFile.getAbsolutePath()).replaceAll("\r\n", "\n"); + } catch (final IOException e) { fail("Exception should not happen: "+e.getMessage()); } diff --git a/validator/src/main/java/org/mustangproject/validator/PDFValidator.java b/validator/src/main/java/org/mustangproject/validator/PDFValidator.java index 69499167..a459fb81 100644 --- a/validator/src/main/java/org/mustangproject/validator/PDFValidator.java +++ b/validator/src/main/java/org/mustangproject/validator/PDFValidator.java @@ -1,6 +1,5 @@ package org.mustangproject.validator; -import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; @@ -8,7 +7,6 @@ import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.io.UnsupportedEncodingException; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -16,14 +14,9 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.List; -import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; @@ -75,46 +68,47 @@ public class PDFValidator extends Validator { return Arrays.asList(arr).contains(targetValue); } - public void validate() throws IrrecoverableValidationError { + @Override + public void validate() throws IrrecoverableValidationError { zfXML = null; - File file = new File(pdfFilename); + final File file = new File(pdfFilename); // file existence must have been checked before - BigFileSearcher searcher = new BigFileSearcher(); + final BigFileSearcher searcher = new BigFileSearcher(); - byte[] pdfSignature = { '%', 'P', 'D', 'F' }; + final byte[] pdfSignature = { '%', 'P', 'D', 'F' }; if (searcher.indexOf(file, pdfSignature) != 0) { context.addResultItem( new ValidationResultItem(ESeverity.fatal, "Not a PDF file "+pdfFilename).setSection(20).setPart(EPart.pdf)); } - long startPDFTime = Calendar.getInstance().getTimeInMillis(); + final long startPDFTime = Calendar.getInstance().getTimeInMillis(); // Step 1 Validate PDF VeraGreenfieldFoundryProvider.initialise(); // Default validator config - ValidatorConfig validatorConfig = ValidatorFactory.defaultConfig(); + final ValidatorConfig validatorConfig = ValidatorFactory.defaultConfig(); // Default features config - FeatureExtractorConfig featureConfig = FeatureFactory.defaultConfig(); + final FeatureExtractorConfig featureConfig = FeatureFactory.defaultConfig(); // Default plugins config - PluginsCollectionConfig pluginsConfig = PluginsCollectionConfig.defaultConfig(); + final PluginsCollectionConfig pluginsConfig = PluginsCollectionConfig.defaultConfig(); // Default fixer config - MetadataFixerConfig fixerConfig = FixerFactory.defaultConfig(); + final MetadataFixerConfig fixerConfig = FixerFactory.defaultConfig(); // Tasks configuring - EnumSet tasks = EnumSet.noneOf(TaskType.class); + final EnumSet tasks = EnumSet.noneOf(TaskType.class); tasks.add(TaskType.VALIDATE); // tasks.add(TaskType.EXTRACT_FEATURES); // tasks.add(TaskType.FIX_METADATA); // Creating processor config - ProcessorConfig processorConfig = ProcessorFactory.fromValues(validatorConfig, featureConfig, pluginsConfig, + final ProcessorConfig processorConfig = ProcessorFactory.fromValues(validatorConfig, featureConfig, pluginsConfig, fixerConfig, tasks); // Creating processor and output stream. - ByteArrayOutputStream reportStream = new ByteArrayOutputStream(); + final ByteArrayOutputStream reportStream = new ByteArrayOutputStream(); try (BatchProcessor processor = ProcessorFactory.fileBatchProcessor(processorConfig)) { // Generating list of files for processing - List files = new ArrayList<>(); + final List files = new ArrayList<>(); files.add(new File(pdfFilename)); // starting the processor processor.process(files, ProcessorFactory.getHandler(FormatOption.MRR, true, reportStream, 100, @@ -122,25 +116,25 @@ public class PDFValidator extends Validator { pdfReport = reportStream.toString("utf-8").replaceAll("<\\?xml version=\"1\\.0\" encoding=\"utf-8\"\\?>", ""); - } catch (VeraPDFException e) { - ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(6) + } catch (final VeraPDFException e) { + final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(6) .setPart(EPart.pdf); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); vri.setStacktrace(sw.toString()); context.addResultItem(vri); - } catch (IOException excep) { + } catch (final IOException excep) { context.addResultItem(new ValidationResultItem(ESeverity.exception, excep.getMessage()).setSection(7) .setPart(EPart.pdf).setStacktrace(excep.getStackTrace().toString())); } // step 2 validate XMP - ZUGFeRDImporter zi = new ZUGFeRDImporter(pdfFilename); - String xmp = zi.getXMP(); + final ZUGFeRDImporter zi = new ZUGFeRDImporter(pdfFilename); + final String xmp = zi.getXMP(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - Document docXMP; + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + final Document docXMP; if (xmp.length() == 0) { context.addResultItem(new ValidationResultItem(ESeverity.error, "Invalid XMP Metadata not found") @@ -153,15 +147,15 @@ public class PDFValidator extends Validator { * 1.0 */ try { - DocumentBuilder builder = factory.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(xmp)); + final DocumentBuilder builder = factory.newDocumentBuilder(); + final InputSource is = new InputSource(new StringReader(xmp)); docXMP = builder.parse(is); - XPathFactory xpathFactory = XPathFactory.newInstance(); + final XPathFactory xpathFactory = XPathFactory.newInstance(); // Create XPath object XPath xpath = xpathFactory.newXPath(); XPathExpression - XPath xpath = xpathFactory.newXPath(); + final XPath xpath = xpathFactory.newXPath(); // xpath.compile("//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/[local-name()=\"ID\"]"); // evaluate expression result on XML document ndList = (NodeList) @@ -179,7 +173,7 @@ public class PDFValidator extends Validator { boolean conformanceLevelValid=false; for (int i = 0; i < nodes.getLength(); i++) { - String[] valueArray = { "BASIC WL", "BASIC", "MINIMUM", "EN 16931", "COMFORT", "CIUS", "EXTENDED", "XRECHNUNG" }; + final String[] valueArray = { "BASIC WL", "BASIC", "MINIMUM", "EN 16931", "COMFORT", "CIUS", "EXTENDED", "XRECHNUNG" }; if (stringArrayContains(valueArray, nodes.item(i).getTextContent())) { conformanceLevelValid=true; } @@ -220,7 +214,7 @@ public class PDFValidator extends Validator { } boolean documentFilenameValid=false; for (int i = 0; i < nodes.getLength(); i++) { - String[] valueArray = { "factur-x.xml", "ZUGFeRD-invoice.xml", "zugferd-invoice.xml", "xrechnung.xml" , "order-x.xml" }; + final String[] valueArray = { "factur-x.xml", "ZUGFeRD-invoice.xml", "zugferd-invoice.xml", "xrechnung.xml" , "order-x.xml" }; if (stringArrayContains(valueArray, nodes.item(i).getTextContent())) { documentFilenameValid=true; } @@ -246,7 +240,7 @@ public class PDFValidator extends Validator { boolean versionValid=false; for (int i = 0; i < nodes.getLength(); i++) { - String[] valueArray = { "1.0", "2p0", "1.2", "2.0" }; //1.2 and 2.0 are for xrechnung 1.2, 2p0 can be ZF 2.0, 2.1, 2.1.1 + final String[] valueArray = { "1.0", "2p0", "1.2", "2.0" }; //1.2 and 2.0 are for xrechnung 1.2, 2p0 can be ZF 2.0, 2.1, 2.1.1 if (stringArrayContains(valueArray, nodes.item(i).getTextContent())) { versionValid=true; } // e.g. 1.0 @@ -258,26 +252,26 @@ public class PDFValidator extends Validator { } - } catch (SAXException e) { + } catch (final SAXException e) { LOGGER.error(e.getMessage(), e); - } catch (IOException e) { + } catch (final IOException e) { LOGGER.error(e.getMessage(), e); - } catch (ParserConfigurationException e) { + } catch (final ParserConfigurationException e) { LOGGER.error(e.getMessage(), e); - } catch (XPathExpressionException e) { + } catch (final XPathExpressionException e) { LOGGER.error(e.getMessage(), e); } zfXML = zi.getUTF8(); // step 3 find signatures try { - byte[] symtraxSignature = "Symtrax".getBytes("UTF-8"); - byte[] mustangSignature = "via mustangproject".getBytes("UTF-8"); - byte[] facturxpythonSignature = "by Alexis de Lattre".getBytes("UTF-8"); - byte[] intarsysSignature = "intarsys ".getBytes("UTF-8"); - byte[] konikSignature = "Konik".getBytes("UTF-8"); - byte[] pdfMachineSignature = "pdfMachine from Broadgun Software".getBytes("UTF-8"); - byte[] ghostscriptSignature = "%%Invocation:".getBytes("UTF-8"); + final byte[] symtraxSignature = "Symtrax".getBytes("UTF-8"); + final byte[] mustangSignature = "via mustangproject".getBytes("UTF-8"); + final byte[] facturxpythonSignature = "by Alexis de Lattre".getBytes("UTF-8"); + final byte[] intarsysSignature = "intarsys ".getBytes("UTF-8"); + final byte[] konikSignature = "Konik".getBytes("UTF-8"); + final byte[] pdfMachineSignature = "pdfMachine from Broadgun Software".getBytes("UTF-8"); + final byte[] ghostscriptSignature = "%%Invocation:".getBytes("UTF-8"); if (searcher.indexOf(file, symtraxSignature) != -1) { Signature = "Symtrax"; @@ -297,13 +291,13 @@ public class PDFValidator extends Validator { context.setSignature(Signature); - } catch (UnsupportedEncodingException e) { + } catch (final UnsupportedEncodingException e) { LOGGER.error(e.getMessage(), e); } // step 4:validate additional data - HashMap additionalData=zi.getAdditionalData(); - for (String filename : additionalData.keySet()) { + final HashMap additionalData=zi.getAdditionalData(); + for (final String filename : additionalData.keySet()) { // validating xml in byte[] additionalData.get(filename) LOGGER.info("validating additionalData " + filename); validateSchema(additionalData.get(filename), "ad/basic/additional_data_base_schema.xsd", 2, EPart.pdf); @@ -312,7 +306,7 @@ public class PDFValidator extends Validator { //end - long endTime = Calendar.getInstance().getTimeInMillis(); + final long endTime = Calendar.getInstance().getTimeInMillis(); if (!pdfReport.contains("validationReports compliant=\"1\"")) { context.setInvalid(); } @@ -323,7 +317,7 @@ public class PDFValidator extends Validator { } context.addCustomXML(pdfReport + "" + ((context.getSignature() != null) ? context.getSignature() : "unknown") - + "" + (endTime - startPDFTime) + ""); + + "" + (endTime - startPDFTime) + ""); } diff --git a/validator/src/main/java/org/mustangproject/validator/ValidationContext.java b/validator/src/main/java/org/mustangproject/validator/ValidationContext.java index ab9fd8ae..0aaf3033 100644 --- a/validator/src/main/java/org/mustangproject/validator/ValidationContext.java +++ b/validator/src/main/java/org/mustangproject/validator/ValidationContext.java @@ -18,7 +18,7 @@ public class ValidationContext { public ValidationContext(Logger log) { logger = log; - results = new Vector(); + results = new Vector<>(); } public void addResultItem(ValidationResultItem vr) throws IrrecoverableValidationError { @@ -110,14 +110,14 @@ public class ValidationContext { res += ""; } - for (ValidationResultItem validationResultItem : results) { + for (final ValidationResultItem validationResultItem : results) { // xml and pdf are handled in their respective sections res += validationResultItem.getXMLOnce() + "\n"; } if (results.size() > 0) { res += ""; } - res += ""; + res += ""; return res; } @@ -126,9 +126,9 @@ public class ValidationContext { * @return the unique error types as comma separated string */ public String getCSVResult() { - ArrayList errorcodes = new ArrayList(); - for (ValidationResultItem validationResultItem : results) { - String errorCodeStr=Integer.toString(validationResultItem.getSection()); + final ArrayList errorcodes = new ArrayList<>(); + for (final ValidationResultItem validationResultItem : results) { + final String errorCodeStr=Integer.toString(validationResultItem.getSection()); errorcodes.add(errorCodeStr); } return String.join(",", errorcodes); diff --git a/validator/src/main/java/org/mustangproject/validator/XMLValidator.java b/validator/src/main/java/org/mustangproject/validator/XMLValidator.java index 22a3aaac..0221a410 100644 --- a/validator/src/main/java/org/mustangproject/validator/XMLValidator.java +++ b/validator/src/main/java/org/mustangproject/validator/XMLValidator.java @@ -1,6 +1,9 @@ package org.mustangproject.validator; -import java.io.*; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringReader; +import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; @@ -22,13 +25,14 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import com.helger.schematron.ISchematronResource; +import com.helger.schematron.svrl.SVRLHelper; import com.helger.schematron.svrl.jaxb.FailedAssert; import com.helger.schematron.svrl.jaxb.FiredRule; import com.helger.schematron.svrl.jaxb.SchematronOutputType; -import com.helger.schematron.ISchematronResource; import com.helger.schematron.xslt.SchematronResourceXSLT; -import com.helger.schematron.svrl.SVRLHelper; -import org.xml.sax.InputSource; public class XMLValidator extends Validator { @@ -54,18 +58,19 @@ public class XMLValidator extends Validator { * @param name the absolute filename of an xml file to validate * @throws IrrecoverableValidationError */ - public void setFilename(String name) throws IrrecoverableValidationError { // from XML Filename + @Override + public void setFilename(String name) throws IrrecoverableValidationError { // from XML Filename filename = name; // file existence must have been checked before try { zfXML = new String(XMLTools.removeBOM(Files.readAllBytes(Paths.get(name))), StandardCharsets.UTF_8); - } catch (IOException e) { + } catch (final IOException e) { - ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(9) + final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(9) .setPart(EPart.fx); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); vri.setStacktrace(sw.toString()); context.addResultItem(vri); @@ -105,13 +110,13 @@ public class XMLValidator extends Validator { */ @Override public void validate() throws IrrecoverableValidationError { - long startXMLTime = Calendar.getInstance().getTimeInMillis(); + final long startXMLTime = Calendar.getInstance().getTimeInMillis(); firedRules = 0; failedRules = 0; if (zfXML.isEmpty()) { - ValidationResultItem res = new ValidationResultItem(ESeverity.exception, + final ValidationResultItem res = new ValidationResultItem(ESeverity.exception, "XML data not found in " + filename + ": did you specify a pdf or xml file and does the xml file contain an embedded XML file?") .setSection(3); @@ -136,33 +141,33 @@ public class XMLValidator extends Validator { * */ - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); // otherwise we can not act namespace independently, i.e. use // document.getElementsByTagNameNS("*",... - DocumentBuilder db = dbf.newDocumentBuilder(); - InputSource is = new InputSource(new StringReader(zfXML)); - Document doc = db.parse(is); + final DocumentBuilder db = dbf.newDocumentBuilder(); + final InputSource is = new InputSource(new StringReader(zfXML)); + final Document doc = db.parse(is); - Element root = doc.getDocumentElement(); + final Element root = doc.getDocumentElement(); - NodeList ndList; + final NodeList ndList; // rootNode = document.getDocumentElement(); // ApplicableSupplyChainTradeSettlement // Create XPathFactory object - XPathFactory xpathFactory = XPathFactory.newInstance(); + final XPathFactory xpathFactory = XPathFactory.newInstance(); // Create XPath object - XPath xpath = xpathFactory.newXPath(); - XPathExpression expr = xpath.compile( + final XPath xpath = xpathFactory.newXPath(); + final XPathExpression expr = xpath.compile( "//*[local-name()=\"GuidelineSpecifiedDocumentContextParameter\"]/*[local-name()=\"ID\"]/text()"); // evaluate expression result on XML document ndList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (int bookingIndex = 0; bookingIndex < ndList.getLength(); bookingIndex++) { - Node booking = ndList.item(bookingIndex); + final Node booking = ndList.item(bookingIndex); // if there is a attribute in the tag number:value // urn:ferd:CrossIndustryDocument:invoice:1p0:extended // setForeignReference(booking.getTextContent()); @@ -324,24 +329,24 @@ public class XMLValidator extends Validator { } - } catch (IrrecoverableValidationError er) { + } catch (final IrrecoverableValidationError er) { throw er; - } catch (Exception e) { - ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(22) + } catch (final Exception e) { + final ValidationResultItem vri = new ValidationResultItem(ESeverity.exception, e.getMessage()).setSection(22) .setPart(EPart.fx); - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); + final StringWriter sw = new StringWriter(); + final PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); vri.setStacktrace(sw.toString()); context.addResultItem(vri); } } - long endTime = Calendar.getInstance().getTimeInMillis(); + final long endTime = Calendar.getInstance().getTimeInMillis(); context.addCustomXML("" + ((context.getGeneration() != null) ? context.getGeneration() : "invalid") + "" + ((context.getProfile() != null) ? context.getProfile() : "invalid") + - "" + firedRules + "" + failedRules + "" + "" + (endTime - startXMLTime) + ""); + "" + firedRules + "" + failedRules + "" + "" + (endTime - startXMLTime) + ""); } @@ -377,20 +382,20 @@ public class XMLValidator extends Validator { throw new IllegalArgumentException(xsltFilename + " is invalid Schematron!"); } - SchematronOutputType sout; + final SchematronOutputType sout; try { sout = aResSCH .applySchematronValidationToSVRL(new StreamSource(new StringReader(xml))); - } catch (Exception e) { + } catch (final Exception e) { throw new IrrecoverableValidationError(e.getMessage()); } - List failedAsserts = sout.getActivePatternAndFiredRuleAndFailedAssert(); + final List failedAsserts = sout.getActivePatternAndFiredRuleAndFailedAssert(); if (failedAsserts.size() > 0) { - for (Object object : failedAsserts) { + for (final Object object : failedAsserts) { if (object instanceof FailedAssert) { - FailedAssert failedAssert = (FailedAssert) object; + final FailedAssert failedAssert = (FailedAssert) object; LOGGER.info("FailedAssert ", failedAssert); context.addResultItem(new ValidationResultItem(severity, SVRLHelper.getAsString(failedAssert.getText())) diff --git a/validator/src/test/java/org/mustangproject/validator/PDFValidatorTest.java b/validator/src/test/java/org/mustangproject/validator/PDFValidatorTest.java index c2e38cd2..f1376f0e 100644 --- a/validator/src/test/java/org/mustangproject/validator/PDFValidatorTest.java +++ b/validator/src/test/java/org/mustangproject/validator/PDFValidatorTest.java @@ -9,8 +9,8 @@ public class PDFValidatorTest extends ResourceCase { private static final Logger LOGGER = LoggerFactory.getLogger(ZUGFeRDValidator.class.getCanonicalName()); // log public void testPDFValidation() { - ValidationContext vc = new ValidationContext(null); - PDFValidator pv = new PDFValidator(vc); + final ValidationContext vc = new ValidationContext(null); + final PDFValidator pv = new PDFValidator(vc); try { @@ -25,10 +25,10 @@ public class PDFValidatorTest extends ResourceCase { pv.setFilename(tempFile.getAbsolutePath()); pv.validate(); String actual = pv.getXMLResult(); - assertEquals(true, actual.contains("summary status='valid")); - assertEquals(false, actual.contains("summary status='invalid")); + assertEquals(true, actual.contains("summary status=\"valid")); + assertEquals(false, actual.contains("summary status=\"invalid")); - XMLValidator xv = new XMLValidator(vc); + final XMLValidator xv = new XMLValidator(vc); xv.setStringContent(pv.getRawXML()); xv.validate(); actual = vc.getXMLResult(); @@ -58,16 +58,16 @@ public class PDFValidatorTest extends ResourceCase { actual.contains("validationReports compliant=\"1\" nonCompliant=\"0\" failedJobs=\"0\">")); assertEquals(false, actual.contains("