new zf 2.2 xslts, schema, schematron, switch to apache commons cli

This commit is contained in:
jstaerk
2022-03-07 15:36:25 +01:00
parent 76af482fe6
commit 15ba24e6a7
46 changed files with 368627 additions and 123 deletions

View File

@@ -11,19 +11,6 @@
<name>e-invoices commandline tool, allowing to create(embed), split and validate Factur-X/ZUGFeRD files. Validation should also work for XRechnung/CII. </name>
<packaging>jar</packaging>
<version>2.4.1-SNAPSHOT</version>
<repositories>
<repository>
<!-- for jargs -->
<id>sonatype-oss-public</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@@ -36,12 +23,13 @@
mvn install:install-file -Dfile=mustang-1.5.4-SNAPSHOT.jar -DgroupId=org.mustangproject.ZUGFeRD -DartifactId=mustang -Dversion=1.5.4 -Dpackaging=jar -DgeneratePom=true
-->
</dependency>
<dependency>
<!-- for commandline options -->
<groupId>com.sanityinc</groupId>
<artifactId>jargs</artifactId>
<version>2.0-SNAPSHOT</version>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency><!-- apache commons cli to parse command line -->
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<groupId>org.riversun</groupId>
<artifactId>bigdoc</artifactId>

View File

@@ -1,4 +1,4 @@
/** **********************************************************************
/************************************************************************
*
* Copyright 2018 Jochen Staerk
*
@@ -18,21 +18,22 @@
*********************************************************************** */
package org.mustangproject.commandline;
import com.sanityinc.jargs.CmdLineParser;
import com.sanityinc.jargs.CmdLineParser.Option;
import org.apache.commons.cli.*;
import org.mustangproject.CII.CIIToUBL;
import org.mustangproject.EStandard;
import org.mustangproject.ZUGFeRD.*;
import org.mustangproject.validator.Validator;
import org.mustangproject.validator.ZUGFeRDValidator;
import org.mustangproject.FileAttachment;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
/***
/*
* This is the command line interface to mustangproject
*
*/
@@ -49,7 +50,7 @@ public class Main {
}
private static String getUsage() {
return "Usage: --action metrics|combine|extract|a3only|ubl|validate|visualize [-d,--directory] [-l,--listfromstdin] [-i,--ignore fileextension, PDF/A errors] | [-h,--help] \r\n"
return "Usage: --action metrics|combine|extract|a3only|ubl|validate|validateExpectInvalid|validateExpectValid|visualize [-d,--directory] [-l,--listfromstdin] [-i,--ignore fileextension, PDF/A errors] | [-h,--help] \r\n"
+ " --action=license display open source license and notice\n"
+ " --action=metrics\n"
+ " -d, --directory count ZUGFeRD files in directory to be scanned\n"
@@ -76,6 +77,9 @@ public class Main {
+ " [--profile <...>]: set ZUGFeRD profile\n"
+ " For ZUGFeRD v1: <B>ASIC, <C>OMFORT or EX<T>ENDED\n"
+ " For ZUGFeRD v2: <M>INIMUM, BASIC <W>L, <B>ASIC, <C>IUS, <E>N16931, <X>Rechnung, EX<T>ENDED \n"
+ " --action=ubl convert UN/CEFACT 2016b CII XML to UBL XML\n"
+ " [--source <filename>]: set input XML file\n"
+ " [--out <filename>]: set output XML file\n"
+ " --action=upgrade upgrade ZUGFeRD XML to ZUGFeRD 2 XML\n"
+ " Additional parameters (optional - user will be prompted if not defined)\n"
+ " [--source <filename>]: set input XML ZUGFeRD 1 file\n"
@@ -85,17 +89,14 @@ public class Main {
+ " [--logAppend=<text>]: text to be added to log line\n"
+ " Additional parameters (optional - user will be prompted if not defined)\n"
+ " [--source=<filename>]: input PDF or XML file\n"
+ " --action=validateExpectValid validate directory expecting positive results \n"
+ " [--no-notices]: refrain from reporting notices\n"
+ " Additional parameters (optional - user will be prompted if not defined)\n"
+ " -d, --directory to check recursively \n"
+ " --action=ubl convert UN/CEFACT 2016b CII XML to UBL XML\n"
+ " [--source <filename>]: set input XML file\n"
+ " [--out <filename>]: set output XML file\n"
+ " --action=validateExpectInvalid validate directory expecting negative results \n"
+ " [--no-notices]: refrain from reporting notices\n"
+ " Additional parameters (optional - user will be prompted if not defined)\n"
+ " -d, --directory to check recursively\n"
+ " --action=validateExpectValid validate directory expecting positive results \n"
+ " [--no-notices]: refrain from reporting notices\n"
+ " Additional parameters (optional - user will be prompted if not defined)\n"
+ " -d, --directory to check recursively \n"
+ " --action=visualize convert XML to HTML \n"
+ " [--source <filename>]: set input XML file\n"
+ " [--out <filename>]: set output HTML file\n"
@@ -132,7 +133,7 @@ public class Main {
// for a more sophisticated dialogue maybe https://github.com/mabe02/lanterna/
// could be taken into account
System.out.print(prompt + " (default: " + defaultValue + ")");
if (!firstInput) {
if ((!firstInput)&&(pattern.length()>0)) {
System.out.print("\n(allowed pattern: " + pattern + ")");
}
@@ -190,8 +191,9 @@ public class Main {
boolean hasCorrectExtension=false;
String[] expectedExtensions=expectedExtension.split("\\|");
for (String currentExtension: expectedExtensions) {
if (selectedName.toLowerCase().endsWith(expectedExtension.toLowerCase())) {
if (selectedName.toLowerCase().endsWith(currentExtension.toLowerCase())) {
hasCorrectExtension=true;
break;
}
}
// error cases
@@ -263,8 +265,8 @@ public class Main {
/***
* converts from CII to UBL
* @param xmlName
* @param outName
* @param xmlName the name of the xml file
* @param outName the name of the output file
* @throws IOException
* @throws TransformerException
*/
@@ -325,70 +327,55 @@ public class Main {
}
/***
* the main function of the commandline tool...
* @param args
* @param args the commandline args, see also https://www.mustangproject.org/commandline/#verbose
*/
public static void main(String[] args) {
try {
CmdLineParser parser = new CmdLineParser();
CommandLine cmd;
CommandLineParser parser = new BasicParser();
// create Options object
Options options = new Options();
// Option: Help
Option<Boolean> helpOption = parser.addBooleanOption('h', "help");
// Option: Action
Option<String> actionOption = parser.addStringOption('a', "action");
options.addOption(new Option("h", "help",false, "display usage"));
options.addOption(new Option("a", "action",true, "which action to perform"));
options.addOption(new Option("f", "format",true, "which format to output"));
options.addOption(new Option("", "version",true, "which version of the standard to use"));
options.addOption(new Option("", "profile",true, "which profile of the standard to use"));
Option attachmentOpt=new Option("", "attachment", true, "File attachments");
attachmentOpt.setValueSeparator(',');
attachmentOpt.setArgs(Option.UNLIMITED_VALUES);
options.addOption(new Option("", "source",true, "which source file to use"));
options.addOption(new Option("", "source-xml",true, "which source file to use"));
options.addOption(new Option("", "out",true, "which output file to write to"));
options.addOption(new Option("", "no-notices",false, "suppress non-fatal errors"));
options.addOption(new Option("", "logAppend",true, "freeform text to be appended to log messages"));
options.addOption(new Option("", "directory",true, "which directory to operate on"));
options.addOption(new Option("i", "ignorefileextension",false, "ignore non-matching file extensions"));
options.addOption(new Option("l", "listfromstdin",false, "take list of files from commandline"));
// Generic options available for multiple command
// --source: input file
Option<String> sourceOption = parser.addStringOption("source");
// --out: output file
Option<String> outOption = parser.addStringOption("out");
Option<Boolean> noNoticesOption = parser.addBooleanOption("no-notices");
Option<String> logAppendOption = parser.addStringOption("logAppend");
// Command: Combining PDF and XML
// --combine
// (--source: input PDF file)
// (--source-xml: input XML file)
// (--out: output PDF file)
// (--version: ZUGFeRD version)
// (--profile: ZUGFeRD profile)
Option<String> sourceXmlOption = parser.addStringOption("source-xml");
Option<String> formatOption = parser.addStringOption('f', "format");
Option<String> zugferdVersionOption = parser.addStringOption("version");
Option<String> zugferdProfileOption = parser.addStringOption("profile");
cmd = parser.parse(options, args);
// Command: Show metrics in dir
// --directory
// (--ignorefileextension)
Option<String> dirnameOption = parser.addStringOption('d', "directory");
Option<Boolean> ignoreFileExtOption = parser.addBooleanOption('i', "ignorefileextension");
// Command: Show metrics from list from stdin
// --listfromstdin
Option<Boolean> filesFromStdInOption = parser.addBooleanOption('l', "listfromstdin");
try {
parser.parse(args);
} catch (CmdLineParser.OptionException e) {
System.err.println(e.getMessage());
printUsage();
System.exit(2);
}
// Retrieve all options
String action = parser.getOptionValue(actionOption);
String directoryName = parser.getOptionValue(dirnameOption);
Boolean filesFromStdIn = parser.getOptionValue(filesFromStdInOption, Boolean.FALSE);
Boolean ignoreFileExt = parser.getOptionValue(ignoreFileExtOption, Boolean.FALSE);
Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE) || ((action!=null)&&(action.equals("help")));
String action = cmd.getOptionValue("action");
String directoryName = cmd.getOptionValue("directory");
Boolean filesFromStdIn = cmd.hasOption("listfromstdin");//((Number)cmdLine.getParsedOptionValue("integer-option")).intValue();
Boolean ignoreFileExt = cmd.hasOption("ignorefileextension");
Boolean helpRequested = cmd.hasOption("help") || ((action!=null)&&(action.equals("help")));
String sourceName = parser.getOptionValue(sourceOption);
String sourceXMLName = parser.getOptionValue(sourceXmlOption);
String outName = parser.getOptionValue(outOption);
String format = parser.getOptionValue(formatOption);
Boolean noNotices = parser.getOptionValue(noNoticesOption);
String sourceName = cmd.getOptionValue("source");
String sourceXMLName = cmd.getOptionValue("source-xml");
String outName = cmd.getOptionValue("out");
String format = cmd.getOptionValue("format");
Boolean noNotices = cmd.hasOption("no-notices");
String zugferdVersion = cmd.getOptionValue("version");
String zugferdProfile = cmd.getOptionValue("profile");
ArrayList<FileAttachment> attachments=new ArrayList <>();
String zugferdVersion = parser.getOptionValue(zugferdVersionOption);
String zugferdProfile = parser.getOptionValue(zugferdProfileOption);
boolean optionsRecognized=false;
if (helpRequested) {
printHelp();
@@ -400,7 +387,7 @@ public class Main {
performMetrics(directoryName, filesFromStdIn, ignoreFileExt);
optionsRecognized=true;
} else if ((action!=null)&&(action.equals("combine"))) {
performCombine(sourceName, sourceXMLName, outName, format, zugferdVersion, zugferdProfile, ignoreFileExt);
performCombine(sourceName, sourceXMLName, outName, format, zugferdVersion, zugferdProfile, ignoreFileExt, attachments);
optionsRecognized=true;
} else if ((action!=null)&&(action.equals("extract"))) {
performExtract(sourceName, outName);
@@ -418,12 +405,13 @@ public class Main {
performUBL(sourceName, outName);
optionsRecognized=true;
} else if ((action!=null)&&(action.equals("validate"))) {
optionsRecognized=performValidate(sourceName, noNotices!=null&&noNotices, parser.getOptionValue(logAppendOption));
optionsRecognized=performValidate(sourceName, noNotices!=null&&noNotices, cmd.getOptionValue("logAppend"));
} else if ((action!=null)&&(action.equals("validateExpectValid"))) {
optionsRecognized=performValidateExpect(true, directoryName);
} else if ((action!=null)&&(action.equals("validateExpectInvalid"))) {
optionsRecognized=performValidateExpect(false, directoryName);
} else {
}
if (!optionsRecognized){
// no argument or argument unknown
printUsage();
System.exit(2);
@@ -534,7 +522,7 @@ public class Main {
}
private static void performCombine(String pdfName, String xmlName, String outName, String format, String zfVersion,
String zfProfile, Boolean ignoreInputErrors) throws Exception {
String zfProfile, Boolean ignoreInputErrors, ArrayList <FileAttachment> attachments) throws Exception {
/*
* ZUGFeRDExporter ze= new ZUGFeRDExporterFromA1Factory()
* .setProducer("toecount") .setCreator(System.getProperty("user.name"))
@@ -557,11 +545,23 @@ public class Main {
}
if (outName == null) {
outName = getFilenameFromUser("Ouput PDF", "invoice.ZUGFeRD.pdf", "pdf", false, true);
outName = getFilenameFromUser("Output PDF", "invoice.ZUGFeRD.pdf", "pdf", false, true);
} else {
System.out.println("Output PDF set to " + outName);
}
byte attachmentContents[]=null;
String attachmentFilename, attachmentMime, attachmentDescription;
attachmentFilename = getFilenameFromUser("Attachment filename (empty for none)", "", "pdf", true, false);
if (attachmentFilename.length()!=0) {
attachmentContents=Files.readAllBytes(Paths.get(attachmentFilename));
attachmentMime= Files.probeContentType(Paths.get(attachmentFilename));
attachments.add(new FileAttachment(attachmentFilename, attachmentMime, "Data", attachmentContents));
}
if (format == null) {
try {
format = getStringFromUser("Format (fx=Factur-X, zf=ZUGFeRD, ox=Order-X)", "zf", "fx|zf|ox");
@@ -600,6 +600,8 @@ public class Main {
}
zfProfile = zfProfile.toLowerCase();
// Verify params
ensureFileExists(pdfName);
ensureFileExists(xmlName);
@@ -664,6 +666,9 @@ public class Main {
((ZUGFeRDExporterFromA1)ze).ignorePDFAErrors();
}
}
for (FileAttachment attachment: attachments) {
((ZUGFeRDExporterFromA3) ze).attachFile(attachment.getFilename(), attachment.getData(), attachment.getMimetype(), attachment.getRelation());
}
ze = ze.load(pdfName);