From beeb104007a43de60f5512743d815f14c8a8131d Mon Sep 17 00:00:00 2001 From: apenski Date: Thu, 26 Oct 2017 09:50:58 +0200 Subject: [PATCH] Initial Implementation --- .gitignore | 34 + NOTICE | 5 + README.md | 104 + pom.xml | 334 + src/main/assembly/standalone-assembly.xml | 37 + .../de/kosit/validationtool/api/Check.java | 53 + .../api/CheckConfiguration.java | 68 + .../de/kosit/validationtool/api/Input.java | 45 + .../validationtool/api/InputFactory.java | 244 + .../cmd/CheckAssertionAction.java | 132 + .../cmd/CommandLineApplication.java | 290 + .../cmd/ExtractHtmlContentAction.java | 98 + .../validationtool/cmd/InternalCheck.java | 83 + .../validationtool/cmd/PrintReportAction.java | 57 + .../cmd/SerializeReportAction.java | 68 + .../impl/ClassPathResourceResolver.java | 118 + .../impl/CollectingErrorEventHandler.java | 168 + .../impl/ContentRepository.java | 175 + .../impl/ConversionService.java | 241 + .../validationtool/impl/DefaultCheck.java | 137 + .../validationtool/impl/ObjectFactory.java | 256 + .../impl/RelativeUriResolver.java | 85 + .../impl/ScenarioRepository.java | 173 + .../impl/model/BaseScenario.java | 187 + .../impl/model/BaseXMLSyntaxError.java | 82 + .../validationtool/impl/model/Result.java | 80 + .../impl/tasks/CheckAction.java | 120 + .../impl/tasks/CreateReportAction.java | 94 + .../impl/tasks/DocumentParseAction.java | 90 + .../impl/tasks/ScenarioSelectionAction.java | 60 + .../impl/tasks/SchemaValidationAction.java | 86 + .../tasks/SchematronValidationAction.java | 97 + .../impl/tasks/ValidateReportInputAction.java | 68 + src/main/model/binding/global.xjb | 55 + src/main/model/xsd/assertions.xsd | 71 + src/main/model/xsd/createReportInput.xsd | 153 + src/main/model/xsd/scenarios.xsd | 137 + src/main/resources/simplelogger.properties | 51 + .../validationtool/api/InputFactoryTest.java | 149 + .../cmd/CheckAssertionActionTest.java | 77 + .../kosit/validationtool/cmd/CommandLine.java | 130 + .../cmd/CommandlineApplicationTest.java | 178 + .../cmd/ExtractHtmlActionTest.java | 74 + .../cmd/PrintReportActionTest.java | 70 + .../cmd/SerializeReportActionTest.java | 78 + .../impl/ContentRepositoryTest.java | 111 + .../impl/ConversionServiceTest.java | 121 + .../validationtool/impl/DefaultCheckTest.java | 75 + .../impl/DocumentParserTest.java | 88 + .../de/kosit/validationtool/impl/Helper.java | 102 + .../impl/RelativeUriResolverTest.java | 74 + .../impl/SaxonSecurityTest.java | 76 + .../impl/ScenarioRepositoryTest.java | 101 + .../impl/SchemaValidatorActionTest.java | 115 + .../validationtool/impl/VersioningTest.java | 86 + src/test/resources/evil/evil1.xsl | 32 + src/test/resources/evil/evil2.xsl | 30 + src/test/resources/evil/evil3.xsl | 13 + src/test/resources/evil/evil4.xsl | 14 + src/test/resources/evil/evil5.xsl | 33 + src/test/resources/evil/ref.txt | 1 + ...LReady_EU_UBL-NL_20170102_FULL-invalid.xml | 301 + .../UBLReady_EU_UBL-NL_20170102_FULL.xml | 302 + .../examples/UBLReady/scenarios-1.xml | 55 + .../examples/UBLReady/scenarios-2.xml | 66 + .../examples/assertions/tests-xrechnung.xml | 45 + .../examples/assertions/ubl-0001-report.xml | 3426 +++++++++++ .../examples/assertions/ubl-0001.xml | 542 ++ .../examples/assertions/ubl-0002.xml | 542 ++ .../common/CCTS_CCT_SchemaModule-2.1.xsd | 769 +++ .../UBL-CommonAggregateComponents-2.1.xsd | 4166 +++++++++++++ .../common/UBL-CommonBasicComponents-2.1.xsd | 5394 +++++++++++++++++ .../UBL-CommonExtensionComponents-2.1.xsd | 235 + .../UBL-CommonSignatureComponents-2.1.xsd | 81 + .../UBL-CoreComponentParameters-2.1.xsd | 73 + .../UBL-ExtensionContentDataType-2.1.xsd | 99 + .../common/UBL-QualifiedDataTypes-2.1.xsd | 78 + .../UBL-SignatureAggregateComponents-2.1.xsd | 102 + .../UBL-SignatureBasicComponents-2.1.xsd | 83 + .../common/UBL-UnqualifiedDataTypes-2.1.xsd | 554 ++ .../xsdrt/common/UBL-XAdESv132-2.1.xsd | 499 ++ .../xsdrt/common/UBL-XAdESv141-2.1.xsd | 46 + .../common/UBL-xmldsig-core-schema-2.1.xsd | 332 + .../xsdrt/maindoc/UBL-CreditNote-2.1.xsd | 153 + .../UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd | 156 + .../UBL-2.1/xsl/BIIRULES-UBL-T10.xsl | 1383 +++++ .../UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl | 1243 ++++ .../resources/eRechnung/default-report.xsl | 756 +++ .../repository/resources/eRechnung/report.xsl | 607 ++ .../resources/examples/results/report.xml | 330 + .../examples/versioning/scenarios-base.xml | 66 + .../versioning/scenarios-increment.xml | 66 + .../versioning/scenarios-newfeature.xml | 60 + .../versioning/scenarios-newversion.xml | 60 + .../resources/invalid/scenarios-illformed.xml | 90 + .../resources/invalid/scenarios-invalid.xml | 87 + src/test/resources/valid/report.xml | 101 + src/test/resources/valid/scenarios.xml | 96 + 98 files changed, 29308 insertions(+) create mode 100644 .gitignore create mode 100644 NOTICE create mode 100644 README.md create mode 100644 pom.xml create mode 100644 src/main/assembly/standalone-assembly.xml create mode 100644 src/main/java/de/kosit/validationtool/api/Check.java create mode 100644 src/main/java/de/kosit/validationtool/api/CheckConfiguration.java create mode 100644 src/main/java/de/kosit/validationtool/api/Input.java create mode 100644 src/main/java/de/kosit/validationtool/api/InputFactory.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/InternalCheck.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java create mode 100644 src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java create mode 100644 src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java create mode 100644 src/main/java/de/kosit/validationtool/impl/ContentRepository.java create mode 100644 src/main/java/de/kosit/validationtool/impl/ConversionService.java create mode 100644 src/main/java/de/kosit/validationtool/impl/DefaultCheck.java create mode 100644 src/main/java/de/kosit/validationtool/impl/ObjectFactory.java create mode 100644 src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java create mode 100644 src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java create mode 100644 src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java create mode 100644 src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java create mode 100644 src/main/java/de/kosit/validationtool/impl/model/Result.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/DocumentParseAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java create mode 100644 src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java create mode 100644 src/main/model/binding/global.xjb create mode 100644 src/main/model/xsd/assertions.xsd create mode 100644 src/main/model/xsd/createReportInput.xsd create mode 100644 src/main/model/xsd/scenarios.xsd create mode 100644 src/main/resources/simplelogger.properties create mode 100644 src/test/java/de/kosit/validationtool/api/InputFactoryTest.java create mode 100644 src/test/java/de/kosit/validationtool/cmd/CheckAssertionActionTest.java create mode 100644 src/test/java/de/kosit/validationtool/cmd/CommandLine.java create mode 100644 src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java create mode 100644 src/test/java/de/kosit/validationtool/cmd/ExtractHtmlActionTest.java create mode 100644 src/test/java/de/kosit/validationtool/cmd/PrintReportActionTest.java create mode 100644 src/test/java/de/kosit/validationtool/cmd/SerializeReportActionTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/ContentRepositoryTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/DocumentParserTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/Helper.java create mode 100644 src/test/java/de/kosit/validationtool/impl/RelativeUriResolverTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/SaxonSecurityTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/SchemaValidatorActionTest.java create mode 100644 src/test/java/de/kosit/validationtool/impl/VersioningTest.java create mode 100644 src/test/resources/evil/evil1.xsl create mode 100644 src/test/resources/evil/evil2.xsl create mode 100644 src/test/resources/evil/evil3.xsl create mode 100644 src/test/resources/evil/evil4.xsl create mode 100644 src/test/resources/evil/evil5.xsl create mode 100644 src/test/resources/evil/ref.txt create mode 100644 src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL-invalid.xml create mode 100644 src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml create mode 100644 src/test/resources/examples/UBLReady/scenarios-1.xml create mode 100644 src/test/resources/examples/UBLReady/scenarios-2.xml create mode 100644 src/test/resources/examples/assertions/tests-xrechnung.xml create mode 100644 src/test/resources/examples/assertions/ubl-0001-report.xml create mode 100644 src/test/resources/examples/assertions/ubl-0001.xml create mode 100644 src/test/resources/examples/assertions/ubl-0002.xml create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/CCTS_CCT_SchemaModule-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonAggregateComponents-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonBasicComponents-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonExtensionComponents-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonSignatureComponents-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CoreComponentParameters-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-ExtensionContentDataType-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-QualifiedDataTypes-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureAggregateComponents-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureBasicComponents-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-UnqualifiedDataTypes-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv132-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv141-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-xmldsig-core-schema-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-CreditNote-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl create mode 100644 src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl create mode 100644 src/test/resources/examples/repository/resources/eRechnung/default-report.xsl create mode 100644 src/test/resources/examples/repository/resources/eRechnung/report.xsl create mode 100644 src/test/resources/examples/results/report.xml create mode 100644 src/test/resources/examples/versioning/scenarios-base.xml create mode 100644 src/test/resources/examples/versioning/scenarios-increment.xml create mode 100644 src/test/resources/examples/versioning/scenarios-newfeature.xml create mode 100644 src/test/resources/examples/versioning/scenarios-newversion.xml create mode 100644 src/test/resources/invalid/scenarios-illformed.xml create mode 100644 src/test/resources/invalid/scenarios-invalid.xml create mode 100644 src/test/resources/valid/report.xml create mode 100644 src/test/resources/valid/scenarios.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21d3671 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Created by .ignore support plugin (hsz.mobi) +### Java template +# Compiled class file +*.class + +# Log file +*.log +.idea +*.iml + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +src/test/generated + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +src/generated + +# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) +!/.mvn/wrapper/maven-wrapper.jar + diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..a6b2a58 --- /dev/null +++ b/NOTICE @@ -0,0 +1,5 @@ +KoSIT Prüf-Tool +Copyright 2017 Koordinierungsstelle für IT-Standards + +This product includes software developed by +Koordinierungsstelle für IT-Standards (http://www.kosit.de/). \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..32eb262 --- /dev/null +++ b/README.md @@ -0,0 +1,104 @@ +## Inhaltsverzeichnis + +- [Über das Prütool](#über-das-prüftool) +- [Status](#status) +- [Verwendung](#verwendung) +- [Build-Anweisungen](#build-anweisungen) +- [Konfiguration xRechnung](#konfiguration-xrechnung) + + +## Über das Prüftool + * macht die KoSIT +## Status + +## Verwendung +Das Prüftool steht in zwei Varianten zur Verfügung: +- als [**Standalone-Version**](#verwendung-als-anwendung), die von der Kommandozeile aus aufgerufen werden kann +- als [**Bibliothek**](#verwendung-als-bibliothek), die in eigene Anwendungen integriert werden kann + +### Verwendung als Standalone-Anwendung +```java -jar validationtool--standalone.jar -s [OPTIONS] [FILE]...``` + +Eine Liste der möglichen Optionen kann der Hilfe entnommen werden. Diese steht mit folgendem Projektaufruf zur Verfügung + +```java -jar validationtool--standalone.jar --help``` + +### Verwendung als Bibliothek +Daneben kann das Prüftool auch in eigene Anwendungen integriert werden. + +Die Bibliothek steht im Maven-Central-Repository zur Verfügung und kann mit kompatiblen Build-Tools genutzt werden. + +* Maven +``` + + de.kosit + validationtool + 1.0.0 + +``` +* Gradle +``` +dependencies { + compile group: 'de.kosit', name: 'validationtool', version: '1.0.0' +} +``` + +Voraussetzung für die Verwendung ist eine valide Prüfszenarien-Definition (xml-Datei) und das dazugehörige Repository +mit den von den definierten Szenarien benötigten Artefakten. Der folgende Quellcode zeigt die Erzeugung einer neuen Prüf-Instanz: + +```java +//Vorbereitung der Konfiguration +URI scenarios = URI.create("scenarios.xml"); +CheckConfiguration config = new CheckConfiguration(); +config.setScenarioDefinition(scenarios); + +//Instantiierung der DefaultCheck-Implementierung +Check check = new DefaultCheck(config); +``` + +Weitere Konfigurationsoption ist der Pfad zum Repository. Standardmäßig wird das Repository relativ zur Szenarien-Defintion +aufgelöst. + +Die so erzeugte Prüfinstanz initialisiert sämtliche Szenarien und deren Prüfartefakte. Ein etwaiger Konfigurationsfehler +wird frühzeitig mitgeteilt. + +Die eigentlich Prüfung erfolgt mit den beiden Methoden des `Check`-Interfaces: + +```java +... +Check pruefer = new DefaultCheck(config); + +//einzelne Datei prüfen +Input pruefKandidat = InputFactory.read(new File("rechnung.xml")); +Document report = pruefer.check(pruefKandidat); + +//Batch-Prüfung +List files = Files.list(Paths.get("rechnungen")).map(path -> path.toFile()).collect(Collectors.toList()); +List toCheck = files.stream().map(InputFactory::read).collect(Collectors.toList()); +List reports = pruefer.check(toCheck); + +``` + +Eine einmal initialisierte Prüfinstanz ist **threadsafe** und kann beliebig oft wieder verwendet +werden. XML-Artefakte wie Schema oder XSLT-Executables werden bei Instantiierung des `DefaultCheck` initialisiert und +wiederverwendet. Da diese Objekte relativ aufwändig zu Erzeugen sind, empfielt sich die Wiederverwendung der `Check`-Instanz. + +Die Batch-Verarbeitung erfolgt grundsätzlich seriell. Der `DefaultCheck` implementiert **keine Parallelverarbeitung**. + +Einziges Eingabeobjekt ist `Input`, welches sich mit den verschiedenen Methoden der `InputFactory` aus div. Eingabe-Resourcen +erzeugen lässt. Die InputFactory erzeugt für jedes Eingabe-Objekt eine Prüfsumme, die im Report mitgeführt wird. Der +verwendete Algorithmus ist über die `read`-Methoden der `InputFactory` definierbar. Standardmäßig wird _SHA-256_ des JDK +verwendet + +### Build-Anweisungen +Das Projekt wird mit Apache Maven gebaut. + +Mittels `mvn install` wird standardmäßig die Bibliotheks-Variante gebaut. Diese enthält nur die Klassen und +Komponenten für die Prüfung. Abhängigkeiten müssen durch die einbindende Anwendung aufgelöst werden (maven). + +Ein `mvn install -Pstandalone` baut die Standalone-Variante. Diese Variante enthält zusätzlich Klassen zur Verarbeitung +von Eingaben aus der Kommandozeile, sowie für Ausgabeoptionen für Ergebnisse. Darüberhinaus ist diese als sog. +Uber-Jar gebaut, sodass sämtliche Abhängigkeiten im Jar gebundlet sind und das Jar-File somit 'lauffähig' ist. + +### Konfiguration xRechnung + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f11e643 --- /dev/null +++ b/pom.xml @@ -0,0 +1,334 @@ + + + + + 4.0.0 + + 3.0 + + de.kosit + validationtool + 1.0.0 + KoSIT XML Prüftool + KoSIT XML Prüftool zur Prüfung von XML Dateien gegenüber definierten Szenarien. + + + andreas.penski + Andreas Penski + ]init[ AG + https://www.init.de + + + fabian.buettner + Fabian Büttner + KoSIT + http://www.kosit.de + + + + + + UTF-8 + 0.7.9 + 1.16.16 + 9.7.0-15 + 1.7.25 + + + + + + org.projectlombok + lombok + ${version.lombok} + provided + + + net.sf.saxon + Saxon-HE + ${version.saxon-he} + compile + + + org.slf4j + slf4j-api + ${version.slf4j} + + + commons-cli + commons-cli + 1.4 + + + + org.apache.commons + commons-lang3 + 3.5 + + + org.assertj + assertj-core + 3.8.0 + test + + + junit + junit + 4.12 + test + + + org.slf4j + slf4j-simple + 1.7.25 + test + + + org.apache.commons + commons-io + 1.3.2 + test + + + + + + + full-distribution + + + + maven-jar-plugin + 2.3.1 + + full + + + + + + + standalone + + + org.slf4j + slf4j-simple + 1.7.22 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + package + + single + + + + + + de.kosit.validationtool.cmd.CommandLineApplication + + + + + src/main/assembly/standalone-assembly.xml + + + + + + + + maven-jar-plugin + 2.3.1 + + + default-jar + none + + + + + + + + + + + + src/main/model + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + UTF-8 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.20 + + + always + + + + maven-jar-plugin + 2.3.1 + + + simplelogger.properties + de/kosit/validationtool/cmd/** + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 1.1 + + + add-source + generate-sources + + add-source + + + + src/generated/java + + + + + + + + + org.jvnet.jaxb2.maven2 + maven-jaxb2-plugin + 0.13.2 + + + + generate + + + + + true + src/main/model/xsd + src/main/model/binding + src/generated/java + false + + -Xinheritance + + + + org.jvnet.jaxb2_commons + jaxb2-basics + 0.11.1 + + + + + + + + org.jacoco + jacoco-maven-plugin + ${version.jacoco} + + + **/validationtool/model/** + **/validationtool/cmd/assertions/** + + + + + prepareJacocoJUnitArgLine + + prepare-agent + + + jacocoArgumentsJUnit + + + + generateJacocoReport + + report + + verify + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.10 + + + -Dfile.encoding=UTF-8 ${jacocoArgumentsJUnit} + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 + + v@{project.version} + + + + + + + \ No newline at end of file diff --git a/src/main/assembly/standalone-assembly.xml b/src/main/assembly/standalone-assembly.xml new file mode 100644 index 0000000..3a33cff --- /dev/null +++ b/src/main/assembly/standalone-assembly.xml @@ -0,0 +1,37 @@ + + + + standalone + + jar + + false + + + true + runtime + + + + + ${project.build.outputDirectory} + + + diff --git a/src/main/java/de/kosit/validationtool/api/Check.java b/src/main/java/de/kosit/validationtool/api/Check.java new file mode 100644 index 0000000..ae9d953 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/api/Check.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.api; + +import java.util.List; +import java.util.stream.Collectors; + +import org.w3c.dom.Document; + +/** + * Zentrale Schnittstellendefinition für das Prüf-Tool. + * + * @author Andreas Penski + */ +public interface Check { + + /** + * Führt die konfigurierte Prüfung für die übergebene Resource aus. + * + * @param input die Resource / XML-Datei, die geprüft werden soll. + * @return ein Ergebnis-{@link Document} + */ + Document check(Input input); + + + /** + * Führt eine Prüfung im Batch-Mode durch. Die Default-Implementierung führt die Prüfung sequentiell aus. + * + * @param input die Eingabe + * @return Liste mit Ergebnis-Dokumenten + */ + default List check(List input) { + return input.stream().map(i -> check(i)).collect(Collectors.toList()); + } + +} diff --git a/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java b/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java new file mode 100644 index 0000000..e5e4e67 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.api; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import java.net.URI; + +/** + * Zentrale Konfigration einer Prüf-Instanz. + * + * @author Andreas Penski + */ +@Getter +@Setter +@Slf4j +@RequiredArgsConstructor +public class CheckConfiguration { + + /** + * URL, die auf die scenerio.xml Datei zeigt. + */ + private final URI scenarioDefinition; + + /** + * Root-Ordner mit den von den einzelnen Szenarien benötigten Dateien + */ + private URI scenarioRepository; + + + /** + * Liefert das Repository mit den Artefakten der einzelnen Szenarien. + * + * @return uri die durch entsprechende resolver aufgelöst werden kann + */ + public URI getScenarioRepository() { + if (scenarioRepository == null) { + scenarioRepository = createDefaultRepository(); + } + return scenarioRepository; + } + + private URI createDefaultRepository() { + log.info("Creating default scenario repository (alongside scenario definition)"); + return scenarioDefinition.resolve("."); + } + +} diff --git a/src/main/java/de/kosit/validationtool/api/Input.java b/src/main/java/de/kosit/validationtool/api/Input.java new file mode 100644 index 0000000..db2dac5 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/api/Input.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.api; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Eine Datei in eingelesener Form. + * + * @author apenski + */ +@Getter +@RequiredArgsConstructor (access = AccessLevel.PACKAGE) +@AllArgsConstructor (access = AccessLevel.PACKAGE) +public class Input { + + private final byte[] content; + + private final String name; + + private byte[] hashCode; + + private String digestAlgorithm; + +} diff --git a/src/main/java/de/kosit/validationtool/api/InputFactory.java b/src/main/java/de/kosit/validationtool/api/InputFactory.java new file mode 100644 index 0000000..66d4c4e --- /dev/null +++ b/src/main/java/de/kosit/validationtool/api/InputFactory.java @@ -0,0 +1,244 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.api; + +import static org.apache.commons.lang3.StringUtils.isNotEmpty; + +import java.io.*; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.DigestInputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.xml.bind.DatatypeConverter; + +import org.apache.commons.lang3.StringUtils; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +/** + * Service zum Einlesen des Test-Objekts in den Speicher. Beim Einlesen wird gleichzeitig eine Prüfsumme ermittelt und + * mit dem Ergebnis mitgeführt. + * + * @author Andreas Penski + */ +@Slf4j +public class InputFactory { + + static final String DEFAULT_ALGORITH = "SHA-256"; + + private static final int EOF = -1; + + private static final int DEFAULT_BUFFER_SIZE = 4096; + + public static final String MESSAGE_OPEN_STREAM_ERROR = "Can not open stream from"; + + @Getter + private final String algorithm; + + InputFactory() { + this(null); + } + + InputFactory(String specifiedAlgorithm) { + this.algorithm = isNotEmpty(specifiedAlgorithm) ? specifiedAlgorithm : DEFAULT_ALGORITH; + createDigest(); + } + + /** + * Liest einen Prüfling von dem übergebenen Pfad. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der Prüfsumme + * genutzt. + * + * @param path der Prüflings + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(Path path) { + return read(path, DEFAULT_ALGORITH); + } + + /** + * Liest einen Prüfling von der übergebenen URL. Es wird ein definierter Algorithmis zur Ermittlung der Prüfsumme + * genutzt. + * + * @param path der Prüflings + * @param digestAlgorithm der Prüfsummenalgorithmus + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(Path path, String digestAlgorithm) { + checkNull(path); + try ( InputStream stream = Files.newInputStream(path) ) { + return read(stream, path.toString(), digestAlgorithm); + } catch (IOException e) { + throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + path, e); + } + } + + /** + * Liest einen Prüfling von der übergebenen Datei. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der + * Prüfsumme genutzt. + * + * @param file der Prüflings + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(File file) { + return read(file, DEFAULT_ALGORITH); + } + + /** + * Liest einen Prüfling von der übergebenen URL. Es wird der Default-Prüfsummenalgorithmus zur Ermittlung der Prüfsumme + * genutzt. + * + * @param url URL des Prüflings + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(URL url) { + return read(url, DEFAULT_ALGORITH); + } + + /** + * Liest einen Prüfling von der übergebenen URL. Es wird ein definierter Algorithmis zur Ermittlung der Prüfsumme + * genutzt. + * + * @param url URL des Prüflings + * @param digestAlgorithm der Prüfsummenalgorithmus + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(URL url, String digestAlgorithm) { + checkNull(url); + try { + return read(url.openStream(), url.getFile(), digestAlgorithm); + } catch (IOException e) { + throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + url, e); + } + } + + /** + * Liest einen Prüfling von der übergebenen URL. Es wird ein definierter Algorithmis zur Ermittlung der Prüfsumme + * genutzt. + * + * @param file der Prüflings + * @param digestAlgorithm der Prüfsummenalgorithmus + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(File file, String digestAlgorithm) { + checkNull(file); + try { + return read(file.toURI().toURL(), digestAlgorithm); + } catch (IOException e) { + throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + file, e); + } + } + + /** + * Liest einen Prüfling von der übergebenen byte-Sequenz. Es wird ein definierter Algorithmis zur Ermittlung der + * Prüfsumme genutzt. + * + * @param input URL des Prüflings + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(byte[] input, String name) { + checkNull(input); + return read(input, name, DEFAULT_ALGORITH); + } + + /** + * Liest einen Prüfling von der übergebenen byte-Sequenz. Es wird ein definierter Algorithmis zur Ermittlung der + * Prüfsumme genutzt. + * + * @param input URL des Prüflings + * @param digestAlgorithm der Prüfsummenalgorithmus + * @return ein Prüf-Eingabe-Objekt + */ + public static Input read(byte[] input, String name, String digestAlgorithm) { + checkNull(input); + return read(new ByteArrayInputStream(input), name, digestAlgorithm); + } + + private static void checkNull(Object input) { + if (input == null) { + throw new IllegalArgumentException("Input can not be null"); + } + } + + /** + * Liest einen Prüfling vom übergebenen {@link InputStream}. + * + * @param inputStream der {@link InputStream} + * @param name der Name/Bezeichner des Prüflings + * @return einen Prüfling in eingelesener Form + */ + public static Input read(InputStream inputStream, String name) { + return read(inputStream, name, DEFAULT_ALGORITH); + } + + /** + * Liest einen Prüfling vom übergebenen {@link InputStream}. + * + * @param inputStream der {@link InputStream} + * @param name der Name/Bezeichner des Prüflings + * @param digestAlgorithm der Prüfsummenalgorithmus + * @return einen Prüfling in eingelesener Form + */ + public static Input read(InputStream inputStream, String name, String digestAlgorithm) { + return new InputFactory(digestAlgorithm).readStream(inputStream, name); + } + + private Input readStream(InputStream inputStream, String name) { + if (StringUtils.isNotBlank(name)) { + log.debug("Generating hashcode for {} using {} algorithm", name, getAlgorithm()); + MessageDigest digest = createDigest(); + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + try ( BufferedInputStream bis = new BufferedInputStream(inputStream); + DigestInputStream dis = new DigestInputStream(bis, digest); + ByteArrayOutputStream out = new ByteArrayOutputStream() ) { + + // read the file and update the hash calculation + int n; + while (EOF != (n = dis.read(buffer))) { + out.write(buffer, 0, n); + } + // get the hash value as byte array + byte[] hash = digest.digest(); + log.debug("Generated hashcode for {} is {}", name, DatatypeConverter.printHexBinary(hash)); + out.flush(); + return new Input(out.toByteArray(), name, hash, digest.getAlgorithm()); + } catch (IOException e) { + throw new IllegalArgumentException(MESSAGE_OPEN_STREAM_ERROR + name, e); + } + } else { + throw new IllegalArgumentException("Must supply a valid name/identifier for the input"); + } + } + + private MessageDigest createDigest() { + try { + MessageDigest digest; + digest = MessageDigest.getInstance(getAlgorithm()); + return digest; + } catch (NoSuchAlgorithmException e) { + // should not happen + throw new IllegalStateException(String.format("Specified method %s is not available", getAlgorithm()), e); + } + } + +} diff --git a/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java b/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java new file mode 100644 index 0000000..006626d --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/CheckAssertionAction.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import de.kosit.validationtool.cmd.assertions.AssertionType; +import de.kosit.validationtool.cmd.assertions.Assertions; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.CheckAction; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.sf.saxon.s9api.*; +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.Document; + +import javax.xml.transform.dom.DOMSource; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Überprüft den Report mittels bereitgestellter Assertions. Diese {@link CheckAction} dient der Überprüfung der von der + * KoSIT bereitgestellten Prüfszenarien und den darin enthaltenen Artefakten. + * + * @author Andreas Penski + */ +@Slf4j +@RequiredArgsConstructor +public class CheckAssertionAction implements CheckAction { + + private final Assertions assertions; + + @Getter(AccessLevel.PRIVATE) + private final Processor processor; + + private Map> mappedAssertions; + + private static boolean matches(String key, String name) { + return key.startsWith(name) || (name + ".xml").endsWith(key); + } + + @Override + public void check(Bag results) { + log.info("Checking assertions for {}", results.getInput().getName()); + final List toCheck = findAssertions(results.getName()); + final List errors = new ArrayList<>(); + if (toCheck != null && !toCheck.isEmpty()) { + final XdmNode node = loadDocument(results.getReport()); + toCheck.forEach(a -> { + if (!check(node, a)) { + log.error("Assertion mismatch: {}", a.getValue()); + errors.add(a.getValue()); + } + }); + if (errors.isEmpty()) { + log.info("{} assertions successfully verified for {}", toCheck.size(), results.getName()); + } else { + log.warn("{} assertion of {} failed while checking {}", errors.size(), toCheck.size(), results.getName()); + } + results.setAssertionResult(new Result<>(toCheck.size(), errors)); + } else { + log.warn("Can not find assertions for {}", results.getName()); + } + } + + private List findAssertions(String name) { + return getMapped().entrySet().stream().filter(e -> matches(e.getKey(), name)).map(Map.Entry::getValue).findFirst().orElse(null); + } + + private XdmNode loadDocument(Document d) { + DocumentBuilder documentBuilder = getProcessor().newDocumentBuilder(); + try { + return documentBuilder.build(new DOMSource(d)); + } catch (SaxonApiException e) { + log.error("Can not load result document. Therefore can not run defined assertions", e); + } + return null; + } + + private boolean check(XdmNode document, AssertionType assertion) { + try { + final XPathSelector selector = createSelector(assertion); + selector.setContextItem(document); + return selector.effectiveBooleanValue(); + } catch (SaxonApiException e) { + log.error("Error evaluating assertion {} for {}", assertion.getTest(), assertion.getReportDoc(), e); + } + return false; + + } + + private XPathSelector createSelector(AssertionType assertion) throws SaxonApiException { + try { + final XPathCompiler compiler = getProcessor().newXPathCompiler(); + assertions.getNamespace().forEach(ns -> compiler.declareNamespace(ns.getPrefix(), ns.getValue())); + return compiler.compile(assertion.getTest()).load(); + } catch (SaxonApiException e) { + throw new IllegalStateException(String.format("Can not compile xpath match expression '%s'", + StringUtils.isNotBlank(assertion.getTest()) ? assertion.getTest() : "EMPTY EXPRESSION"), e); + } + } + + private Map> getMapped() { + if (mappedAssertions == null) { + mappedAssertions = new HashMap<>(); + for (AssertionType assertionType : assertions.getAssertion()) { + List list = mappedAssertions.computeIfAbsent(assertionType.getReportDoc(), k -> new ArrayList<>()); + list.add(assertionType); + } + } + return mappedAssertions; + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java new file mode 100644 index 0000000..eb89024 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java @@ -0,0 +1,290 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.cli.*; +import org.apache.commons.lang3.StringUtils; + +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.cmd.assertions.Assertions; +import de.kosit.validationtool.impl.ConversionService; +import de.kosit.validationtool.impl.ObjectFactory; + +/** + * Commandline Version des Prüftools. Parsed die Kommandozeile und führt die konfigurierten Aktionen aus. + * + * @author Andreas Penski + */ +@Slf4j +public class CommandLineApplication { + + private static final Option HELP = Option.builder("?").longOpt("help").argName("Help").desc("Displays this help").build(); + + private static final Option SCENARIOS = Option.builder("s").required().longOpt("scenarios").hasArg() + .desc("Location of scenarios.xml e.g.").build(); + + private static final Option REPOSITORY = Option.builder("r").longOpt("repository").hasArg() + .desc("Directory containing scenario content").build(); + + private static final Option PRINT = Option.builder("p").longOpt("print").desc("Prints the check result to stdout").build(); + + private static final Option OUTPUT = Option.builder("o").longOpt("output-directory") + .desc("Defines the out directory for results. Defaults to cwd").hasArg().build(); + + private static final Option EXTRACT_HTML = Option.builder("h").longOpt("html") + .desc("Extract and save any html content within result as a separate file ").build(); + + private static final Option DEBUG = Option.builder("d").longOpt("debug").desc("Prints some more debug information").build(); + + private static final Option CHECK_ASSERTIONS = Option.builder("c").longOpt("check-assertions").hasArg() + .desc("Check the result using defined assertions").argName("assertions-file").build(); + + private CommandLineApplication() { + // main class -> hide constructor + } + + /** + * Main-Funktion für die Kommandozeilen-Applikation. + * + * @param args die Eingabe-Argumente + */ + public static void main(String[] args) { + final int resultStatus = mainProgram(args); + System.exit(resultStatus); + } + + /** + * Hauptprogramm für die Kommandozeilen-Applikation. + * + * @param args die Eingabe-Argumente + */ + static int mainProgram(String[] args) { + Options options = createOptions(); + if (isHelpRequested(args)) { + printHelp(options); + } else { + try { + CommandLineParser parser = new DefaultParser(); + final CommandLine cmd = parser.parse(options, args); + if (cmd.getArgList().isEmpty()) { + printHelp(createOptions()); + } else { + return processActions(cmd); + } + } catch (ParseException e) { + log.error("Error processing command line arguments: " + e.getMessage()); + printHelp(options); + } + } + return 0; + } + + private static boolean isHelpRequested(String[] args) { + Options helpOptions = createHelpOptions(); + try { + CommandLineParser parser = new DefaultParser(); + CommandLine cmd = parser.parse(helpOptions, args, true); + if (cmd.hasOption(HELP.getOpt()) || args.length == 0) { + return true; + } + } catch (ParseException e) { + // we can ignore that, we just look for the help parameters + } + return false; + } + + private static int processActions(CommandLine cmd) { + try { + + long start = System.currentTimeMillis(); + CheckConfiguration d = new CheckConfiguration(determineDefinition(cmd)); + d.setScenarioRepository(determineRepository(cmd)); + InternalCheck check = new InternalCheck(d); + Path outputDirectory = determineOutputDirectory(cmd); + + if (cmd.hasOption(EXTRACT_HTML.getOpt())) { + check.getCheckSteps().add(new ExtractHtmlContentAction(check.getContentRepository(), outputDirectory)); + } + check.getCheckSteps().add(new SerializeReportAction(outputDirectory)); + if (cmd.hasOption(PRINT.getOpt())) { + check.getCheckSteps().add(new PrintReportAction()); + } + if (cmd.hasOption(CHECK_ASSERTIONS.getOpt())) { + Assertions assertions = loadAssertions(cmd.getOptionValue(CHECK_ASSERTIONS.getOpt())); + check.getCheckSteps().add(new CheckAssertionAction(assertions, ObjectFactory.createProcessor())); + } + + log.info("Setup completed in {}ms\n", System.currentTimeMillis() - start); + + final Collection targets = determineTestTargets(cmd); + start = System.currentTimeMillis(); + final List input = targets.stream().map(InputFactory::read).collect(Collectors.toList()); + boolean result = check.checkInput(input); + log.info("Processing {} object(s) completed in {}ms", input.size(), System.currentTimeMillis() - start); + return result ? 0 : 1; + + } catch (Exception e) { + if (cmd.hasOption(DEBUG.getOpt())) { + log.error(e.getMessage(), e); + } else { + log.error(e.getMessage()); + } + return -1; + } + } + + private static Assertions loadAssertions(String optionValue) { + Path p = Paths.get(optionValue); + Assertions a = null; + if (Files.exists(p)) { + ConversionService c = new ConversionService(); + c.initialize(de.kosit.validationtool.cmd.assertions.ObjectFactory.class.getPackage()); + a = c.readXml(p.toUri(), Assertions.class); + } + return a; + } + + private static Path determineOutputDirectory(CommandLine cmd) { + final String value = cmd.getOptionValue(OUTPUT.getOpt()); + Path fir; + if (StringUtils.isNotBlank(value)) { + fir = Paths.get(value); + if ((!Files.exists(fir) && !fir.toFile().mkdirs()) || !Files.isDirectory(fir)) { + throw new IllegalStateException(String.format("Invalid target directory %s specified", value)); + } + } else { + fir = Paths.get(""/* cwd */); + } + return fir; + } + + private static Collection determineTestTargets(CommandLine cmd) { + Collection targets = new ArrayList<>(); + if (!cmd.getArgList().isEmpty()) { + cmd.getArgList().forEach(e -> targets.addAll(determineTestTarget(e))); + } + if (targets.isEmpty()) { + throw new IllegalStateException("No test targets found. Nothing to check. Will quit now!"); + } + return targets; + } + + private static Collection determineTestTarget(String s) { + Path d = Paths.get(s); + if (Files.isDirectory(d)) { + return listDirectoryTargets(d); + } else if (Files.exists(d)) { + return Collections.singleton(d); + } + log.warn("The specified test target {} does not exist. Will be ignored", s); + return Collections.emptyList(); + + } + + private static Collection listDirectoryTargets(Path d) { + try { + return Files.list(d).filter(path -> path.toString().endsWith(".xml")).collect(Collectors.toList()); + } catch (IOException e) { + throw new IllegalStateException("IOException while liste directory content. Can not determine test targets.", e); + } + + } + + private static URI determineRepository(CommandLine cmd) throws MalformedURLException { + if (checkOptionWithValue(REPOSITORY, cmd)) { + Path d = Paths.get(cmd.getOptionValue(REPOSITORY.getOpt())); + if (Files.isDirectory(d)) { + return d.toUri(); + } else { + throw new IllegalArgumentException( + String.format("Not a valid path for scenario definition specified: '%s'", d.toAbsolutePath())); + } + } + return null; + } + + private static URI determineDefinition(CommandLine cmd) throws MalformedURLException { + checkOptionWithValue(SCENARIOS, cmd); + Path f = Paths.get(cmd.getOptionValue(SCENARIOS.getOpt())); + if (Files.isRegularFile(f)) { + return f.toAbsolutePath().toUri(); + } else { + throw new IllegalArgumentException( + String.format("Not a valid path for scenario definition specified: '%s'", f.toAbsolutePath())); + } + } + + private static boolean checkOptionWithValue(Option option, CommandLine cmd) { + String opt = option.getOpt(); + if (cmd.hasOption(opt)) { + String value = cmd.getOptionValue(opt); + if (StringUtils.isNoneBlank(value)) { + return true; + } else { + throw new IllegalArgumentException(String.format("Option value required for Option '%s'", option.getLongOpt())); + } + } else if (option.isRequired()) { + + throw new IllegalArgumentException(String.format("Option '%s' required ", option.getLongOpt())); + } + return false; + } + + private static void printHelp(Options options) { + // automatically generate the help statement + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("check-tool -s [OPTIONS] [FILE]... ", options, false); + } + + private static Options createHelpOptions() { + Options options = new Options(); + options.addOption(HELP); + return options; + } + + private static Options createOptions() { + Options options = new Options(); + options.addOption(HELP); + options.addOption(SCENARIOS); + options.addOption(REPOSITORY); + options.addOption(PRINT); + options.addOption(OUTPUT); + options.addOption(EXTRACT_HTML); + options.addOption(DEBUG); + options.addOption(CHECK_ASSERTIONS); + return options; + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java b/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java new file mode 100644 index 0000000..826e77c --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/ExtractHtmlContentAction.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.transform.dom.DOMSource; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.tasks.CheckAction; + +import net.sf.saxon.s9api.*; + +/** + * Extrahiert HTML-Dokumente aus dem Report und persistiert diese im konfigurierten Ausgabe-Verzeichnis. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +@Slf4j +public class ExtractHtmlContentAction implements CheckAction { + + private static final QName NAME_ATTRIBUTE = new QName("data-report-type"); + + private final ContentRepository repository; + + private final Path outputDirectory; + + private XPathExecutable executable; + + @Override + public void check(Bag results) { + try { + final XPathSelector selector = getSelector(); + DocumentBuilder documentBuilder = repository.getProcessor().newDocumentBuilder(); + + final XdmNode xdmSource = documentBuilder.build(new DOMSource(results.getReport())); + selector.setContextItem(xdmSource); + selector.forEach(m -> print(results.getName(), m)); + + } catch (SaxonApiException e) { + throw new IllegalStateException("Can not extract html content", e); + } + } + + private void print(String origName, XdmItem xdmItem) { + XdmNode node = (XdmNode) xdmItem; + final String name = origName + "-" + node.getAttributeValue(NAME_ATTRIBUTE); + final Path file = outputDirectory.resolve(name + ".html"); + final Serializer serializer = repository.getProcessor().newSerializer(file.toFile()); + try { + log.info("Writing report html '{}' to {}", name, file.toAbsolutePath()); + serializer.serializeNode(node); + } catch (SaxonApiException e) { + log.info("Error extracting html content to {}", file.toAbsolutePath(), e); + } + } + + private XPathSelector getSelector() { + if (executable == null) { + Map ns = new HashMap<>(); + ns.put("html", "http://www.w3.org/1999/xhtml"); + executable = repository.createXPath("//html:html", ns); + } + return executable.load(); + } + + @Override + public boolean isSkipped(Bag results) { + if (results.getReport() == null) { + log.warn("Can not extract html content. No report document found"); + return true; + } + return false; + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java b/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java new file mode 100644 index 0000000..471f7c7 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/InternalCheck.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.impl.DefaultCheck; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.CheckAction; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Simple Erweiterung der Klasse {@link DefaultCheck} um das Ergebnis der Assertion-Prüfung auszwerten und auszugeben. + * Diese Klasse stellt keine fachlicher Erweiterung des eigentlichen Prüfvorganges dar! + * + * @author Andreas Penski + */ +@Slf4j +class InternalCheck extends DefaultCheck { + + /** + * Erzeugt eine neue Instanz mit der angegebenen Konfiguration. + * + * @param configuration die Konfiguration + */ + public InternalCheck(CheckConfiguration configuration) { + super(configuration); + } + + /** + * Prüft die Prüflinge und gibt Informationen über etwaige Assertions aus. + * + * @param input die Prüflinge + * @return false wenn es Assertion-Fehler gibt, sonst true + */ + public boolean checkInput(List input) { + List results = new ArrayList<>(); + input.forEach(i -> { + CheckAction.Bag bag = new CheckAction.Bag(i, createReport()); + runCheckInternal(bag); + results.add(bag); + }); + + return printAndEvaluate(results); + + } + + private boolean printAndEvaluate(List results) { + final List> asserts = results.stream().filter(r -> r.getAssertionResult() != null) + .map(CheckAction.Bag::getAssertionResult).collect(Collectors.toList()); + int checkAssertions = asserts.stream().mapToInt(e -> e.getObject()).sum(); + int failedAssertions = asserts.stream().mapToInt(e -> e.getErrors().size()).sum(); + + if (failedAssertions > 0) { + log.error("Assertion check failed.\n\nAssertions run: {}, Assertions failed: {}\n", checkAssertions, failedAssertions); + } else if (checkAssertions > 0) { + log.info("Assertion check successful.\n\nAssertions run: {}, Assertions failed: {}\n", checkAssertions, failedAssertions); + } + return failedAssertions == 0; + } + +} diff --git a/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java b/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java new file mode 100644 index 0000000..435cfcd --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/PrintReportAction.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import java.io.StringWriter; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.tasks.CheckAction; + +/** + * Gibt das Ergebnis-Document auf std-out aus. + * + * @author Andreas Penski + */ +@Slf4j +public class PrintReportAction implements CheckAction { + + @Override + public void check(Bag results) { + try { + Transformer transformer = ObjectFactory.createTransformer(true); + final StringWriter writer = new StringWriter(); + Result output = new StreamResult(writer); + Source input = new DOMSource(results.getReport()); + transformer.transform(input, output); + System.out.print(writer.toString()); + } catch (TransformerException e) { + log.error("Error while printing result to stdout", e); + } + } +} diff --git a/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java b/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java new file mode 100644 index 0000000..8896db7 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/cmd/SerializeReportAction.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.tasks.CheckAction; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.nio.file.Path; + +/** + * Schreibt das Prüfergebnis als XML-Dokument an eine definierte Stelle. + * + * @author Andreas Penski + */ +@Slf4j +@RequiredArgsConstructor +public class SerializeReportAction implements CheckAction { + + private final Path outputDirectory; + + @Override + public void check(Bag results) { + final Path file = outputDirectory.resolve(results.getName() + "-report.xml"); + try { + log.info("Serializing result to {}", file.toAbsolutePath()); + Transformer transformer = ObjectFactory.createTransformer(true); + Result output = new StreamResult(file.toFile()); + Source input = new DOMSource(results.getReport()); + transformer.transform(input, output); + } catch (TransformerException e) { + log.error("Can not serialize result report to {}", file.toAbsolutePath(), e); + } + } + + @Override + public boolean isSkipped(Bag results) { + if (results.getReport() == null) { + log.warn("Can not serialize result report. No document found"); + return true; + } + return false; + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java b/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java new file mode 100644 index 0000000..1b53fe1 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/ClassPathResourceResolver.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.net.URI; +import java.net.URL; + +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +/** + * {@link LSResourceResolver} der objekte relativ zu einem Basis-Pfad aus dem Classpath der Anwendung laden kann. + * + * @author Andreas Penski + */ +@Slf4j +class ClassPathResourceResolver implements LSResourceResolver { + + private final URI base; + + /** + * Instantiiert einen neuen resolver mit angegebenen Basispfad + * + * @param basePath der Basispfad + */ + public ClassPathResourceResolver(String basePath) { + if (!StringUtils.startsWith(basePath, "/")) { + throw new IllegalArgumentException("Base path must start with a slash"); + } + base = URI.create(basePath + (basePath.endsWith("/") == basePath.length() > 1 ? "" : "/")); + } + + @Override + public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { + final URL resource = ClassPathResourceResolver.class.getResource(base.resolve(systemId).toASCIIString()); + if (resource != null) { + try { + InputStream in = resource.openStream(); + final LSInputImpl input = new LSInputImpl(publicId, systemId, baseURI); + input.setByteStream(in); + return input; + + } catch (IOException e) { + log.error("Error loading schema resource from {}", resource, e); + } + } + // not found + return null; + } + + /** + * Simple {@link LSInput}-Implementierung, die einen Stream liefern kann + */ + @Getter + @Setter + @RequiredArgsConstructor + private static class LSInputImpl implements LSInput { + + private Reader characterStream; + + private InputStream byteStream; + + private String systemId; + + private String publicId; + + private String baseURI; + + private String encoding; + + private boolean certifiedText; + + private String stringData; + + /** + * Instantiierung einer neue Instanz. + * @param publicId die publicId + * @param systemId die systemId + * @param baseURI die baseURI + */ + public LSInputImpl(String publicId, String systemId, String baseURI) { + this.publicId = publicId; + this.systemId = systemId; + this.baseURI = baseURI; + } + + @Override + public boolean getCertifiedText() { + return certifiedText; + } + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java new file mode 100644 index 0000000..580ffb1 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/CollectingErrorEventHandler.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.StringJoiner; + +import javax.xml.bind.ValidationEvent; +import javax.xml.bind.ValidationEventHandler; +import javax.xml.transform.ErrorListener; +import javax.xml.transform.SourceLocator; +import javax.xml.transform.TransformerException; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import lombok.Getter; + +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; +import de.kosit.validationtool.model.reportInput.XMLSyntaxErrorSeverity; + +import net.sf.saxon.s9api.MessageListener; +import net.sf.saxon.s9api.XdmNode; + +/** + * Sammelt Fehler-Ereignisinformation beim Schema-Validieren und weiteren XML-basierten Aktionen + * + * @author Andreas Penski + */ +@Getter +public class CollectingErrorEventHandler implements ValidationEventHandler, ErrorHandler, MessageListener, ErrorListener { + + private static final int DEFAULT_ABORT_COUNT = 50; + + private Collection errors = new ArrayList<>(); + + private int stopProcessCount = DEFAULT_ABORT_COUNT; + + private static XMLSyntaxError createError(XMLSyntaxErrorSeverity severity, String message) { + XMLSyntaxError e = new XMLSyntaxError(); + e.setSeverity(severity); + e.setMessage(message); + return e; + } + + private static XMLSyntaxError createError(XMLSyntaxErrorSeverity severity, SAXParseException exception) { + XMLSyntaxError e = createError(severity, exception.getMessage()); + e.setRowNumber(exception.getLineNumber()); + e.setColumnNumber(exception.getColumnNumber()); + return e; + } + + private static XMLSyntaxError createError(XMLSyntaxErrorSeverity severity, TransformerException exception) { + XMLSyntaxError e = createError(severity, exception.getMessage()); + if (exception.getLocator() != null) { + e.setRowNumber(exception.getLocator().getLineNumber()); + e.setColumnNumber(exception.getLocator().getColumnNumber()); + } + return e; + } + + private static XMLSyntaxErrorSeverity translateSeverity(int severity) { + switch (severity) { + case ValidationEvent.WARNING: + return XMLSyntaxErrorSeverity.SEVERITY_WARNING; + case ValidationEvent.ERROR: + return XMLSyntaxErrorSeverity.SEVERITY_ERROR; + case ValidationEvent.FATAL_ERROR: + return XMLSyntaxErrorSeverity.SEVERITY_FATAL_ERROR; + default: + throw new IllegalArgumentException("Unknown severity level " + severity); + } + } + + @Override + public boolean handleEvent(ValidationEvent event) { + XMLSyntaxError e = createError(translateSeverity(event.getSeverity()), event.getMessage()); + e.setColumnNumber(event.getLocator().getColumnNumber()); + e.setRowNumber(event.getLocator().getLineNumber()); + errors.add(e); + return stopProcessCount != errors.size(); + } + + /** + * Zeigt an, ob Validierungsfehler vorhanden sind. + * + * @return true wenn mindestens ein Fehler vorhanden ist. + */ + public boolean hasErrors() { + return hasEvents() && errors.stream().anyMatch(e -> e.getSeverity() != XMLSyntaxErrorSeverity.SEVERITY_WARNING); + } + + /** + * Zeigt an, ob es Validierungs-Ereignisse gab. + * + * @return true wenn mindestens ein Validierungsereignis aufgetreten ist + */ + public boolean hasEvents() { + return !errors.isEmpty(); + } + + @Override + public void warning(SAXParseException exception) throws SAXException { + errors.add(createError(XMLSyntaxErrorSeverity.SEVERITY_WARNING, exception)); + } + + @Override + public void error(SAXParseException exception) throws SAXException { + errors.add(createError(XMLSyntaxErrorSeverity.SEVERITY_ERROR, exception)); + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException { + errors.add(createError(XMLSyntaxErrorSeverity.SEVERITY_FATAL_ERROR, exception)); + } + + @Override + public void message(XdmNode content, boolean terminate, SourceLocator locator) { + XMLSyntaxError e = new XMLSyntaxError(); + if (locator != null) { + e.setColumnNumber(locator.getColumnNumber()); + e.setRowNumber(locator.getLineNumber()); + } + e.setMessage("Error procesing" + content.getStringValue()); + e.setSeverity(terminate ? XMLSyntaxErrorSeverity.SEVERITY_FATAL_ERROR : XMLSyntaxErrorSeverity.SEVERITY_WARNING); + } + + @Override + public void warning(TransformerException exception) throws TransformerException { + errors.add(createError(XMLSyntaxErrorSeverity.SEVERITY_WARNING, exception)); + } + + @Override + public void error(TransformerException exception) throws TransformerException { + errors.add(createError(XMLSyntaxErrorSeverity.SEVERITY_ERROR, exception)); + } + + @Override + public void fatalError(TransformerException exception) throws TransformerException { + errors.add(createError(XMLSyntaxErrorSeverity.SEVERITY_FATAL_ERROR, exception)); + } + + public String getErrorDescription() { + final StringJoiner joiner = new StringJoiner("\n"); + errors.forEach(e -> joiner + .add(e.getSeverity().value() + " " + e.getMessage() + " At row " + e.getRowNumber() + " at pos " + e.getColumnNumber())); + return joiner.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java new file mode 100644 index 0000000..d2a7be6 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.Collection; +import java.util.Map; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.apache.commons.lang3.StringUtils; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.SAXException; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import net.sf.saxon.s9api.*; + +/** + * Repository für verschiedene XML Artefakte zur Vearbeitung der Prüfszenarien. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +@Slf4j +public class ContentRepository { + + @Getter + private final Processor processor; + + private final URI repository; + + private Schema reportInputSchema; + + private static Source resolve(URL resource) { + try { + return new StreamSource(resource.openStream(), resource.toURI().getRawPath()); + } catch (IOException | URISyntaxException e) { + throw new IllegalStateException("Can not load schema for resource " + resource.getPath(), e); + } + } + + private static Schema createSchema(Source[] schemaSources, LSResourceResolver resourceResolver) { + try { + SchemaFactory sf = ObjectFactory.createSchemaFactory(); + sf.setResourceResolver(resourceResolver); + return sf.newSchema(schemaSources); + } catch (SAXException e) { + throw new IllegalArgumentException("Can not load schema from sources " + schemaSources[0].getSystemId(), e); + } + } + + private static Schema createSchema(Source[] schemaSources) { + return createSchema(schemaSources, null); + } + + /** + * Lädt ein XSL von der angegebenen URI + * + * @param uri die URI der XSL Definition + * @return ein XSLT Executable + */ + public XsltExecutable loadXsltScript(URI uri) { + log.info("Loading XSLT script from {}", uri); + final XsltCompiler xsltCompiler = getProcessor().newXsltCompiler(); + final CollectingErrorEventHandler listener = new CollectingErrorEventHandler(); + try { + xsltCompiler.setErrorListener(listener); + xsltCompiler.setURIResolver(new RelativeUriResolver(repository)); + + return xsltCompiler.compile(resolve(uri)); + } catch (SaxonApiException e) { + listener.getErrors().forEach(event -> event.log(log)); + throw new IllegalStateException("Can not compile xslt executable for uri " + uri, e); + } finally { + if (!listener.hasErrors() && listener.hasEvents()) { + log.warn("Received warnings while loading a xslt script {}", uri); + listener.getErrors().forEach(e -> e.log(log)); + } + } + } + + /** + * Erzeugt ein Schema-Objekt auf Basis der übergebenen URL. + * + * @param url die url + * @return das erzeugte Schema + */ + public Schema createSchema(URL url) { + log.info("Load schema from source {}", url.getPath()); + return createSchema(new Source[] { resolve(url) }); + } + + /** + * Liefert das definiert Schema für die Szenario-Konfiguration + * + * @return Scenario-Schema + */ + public Schema getScenarioSchema() { + return createSchema(ContentRepository.class.getResource("/xsd/scenarios.xsd")); + } + + /** + * Liefert das definierte Schema für die Validierung des [@link CreateReportInput} + * + * @return ReportInput-Schema + */ + public Schema getReportInputSchema() { + if (reportInputSchema == null) { + final Source source = resolve(ContentRepository.class.getResource("/xsd/createReportInput.xsd")); + reportInputSchema = createSchema(new Source[] { source }, new ClassPathResourceResolver("/xsd")); + } + return reportInputSchema; + } + + /** + * Erzeugt ein Schema auf Basis der übegebenen URIs + * + * @param uris die uris in String-Repräsentation + * @return das Schema + */ + public Schema createSchema(Collection uris) { + return createSchema(uris.stream().map(s -> resolve(URI.create(s))).toArray(Source[]::new)); + } + + private Source resolve(URI source) { + return new StreamSource(repository.resolve(source).toASCIIString()); + } + + /** + * Erzeugt einen [@link XPathExecutable} auf Basis der angegebenen Informationen. + * + * @param expression der XPATH-Ausdruck + * @param namespaces optionale Namespace-Mappings + * @return ein kompiliertes Executable + */ + public XPathExecutable createXPath(String expression, Map namespaces) { + try { + final XPathCompiler compiler = getProcessor().newXPathCompiler(); + if (namespaces != null) { + namespaces.entrySet().forEach(n -> compiler.declareNamespace(n.getKey(), n.getValue())); + } + return compiler.compile(expression); + } catch (SaxonApiException e) { + throw new IllegalStateException(String.format("Can not compile xpath match expression '%s'", + StringUtils.isNotBlank(expression) ? expression : "EMPTY EXPRESSION"), e); + } + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/ConversionService.java b/src/main/java/de/kosit/validationtool/impl/ConversionService.java new file mode 100644 index 0000000..eea4acc --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/ConversionService.java @@ -0,0 +1,241 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.io.IOException; +import java.io.StringWriter; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.StringJoiner; + +import javax.xml.bind.*; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.stream.*; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; + +import org.w3c.dom.Document; + +import lombok.extern.slf4j.Slf4j; + +/** + * JAXB Conversion Utility. + */ +@Slf4j +public class ConversionService { + + // context setup + private JAXBContext jaxbContext; + + private static QName createQName(final T model) { + return new QName(model.getClass().getSimpleName().toLowerCase()); + } + + private void checkInputEmpty(final URI xml) { + if (xml == null) { + throw new ConversionExeption("Can not unmarshal from empty input"); + } + } + + private void checkTypeEmpty(final Class type) { + if (type == null) { + throw new ConversionExeption("Can not unmarshal without type information. Need to specify a target type"); + } + } + + /** + * Initialisiert den default context; Alle Packages mit {@link XmlRegistry XmlRegistries}. + */ + public void initialize() { + Collection p = new ArrayList<>(); + p.add(de.kosit.validationtool.model.reportInput.ObjectFactory.class.getPackage()); + p.add(de.kosit.validationtool.model.scenarios.ObjectFactory.class.getPackage()); + initialize(p); + } + + public void initialize(final Package... context) { + initialize(Arrays.asList(context)); + } + /** + * Initialisiert den conversion service mit den angegegebenen Packages. + * + * @param context packages für den JAXB Kontext + */ + public void initialize(final Collection context) { + final String[] packages = context != null ? context.stream().map(Package::getName).toArray(String[]::new) : new String[0]; + StringJoiner joiner = new StringJoiner(":"); + Arrays.stream(packages).forEach(p -> joiner.add(p)); + initialize(joiner.toString()); + } + + /** + * Initialsiert den conversion service mit dem angegebenen Kontextpfad + * + * @param contextPath der Kontextpfad + */ + private void initialize(final String contextPath) { + try { + this.jaxbContext = JAXBContext.newInstance(contextPath); + } catch (final JAXBException e) { + throw new IllegalStateException(String.format("Can not create JAXB context for given context: %s", contextPath), e); + } + } + + private JAXBContext getJaxbContext() { + if (this.jaxbContext == null) { + initialize(); + } + return this.jaxbContext; + } + + /** + * Unmarshalls a specifc xml model into a defined java object. + * + * @param xml the xml + * @param type the expected type created + * @param type information + * @return the created object + */ + public T readXml(final URI xml, final Class type) { + return readXml(xml, type, null, null); + } + + public T readXml(final URI xml, final Class type, Schema schema) { + return readXml(xml, type, schema, null); + } + + public T readXml(final URI xml, final Class type, Schema schema, ValidationEventHandler handler) { + checkInputEmpty(xml); + checkTypeEmpty(type); + CollectingErrorEventHandler defaultHandler = null; + ValidationEventHandler handler2Use = handler; + if (schema != null && handler == null) { + defaultHandler = new CollectingErrorEventHandler(); + handler2Use = defaultHandler; + } + try { + final XMLInputFactory inputFactory = XMLInputFactory.newFactory(); + inputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false); + inputFactory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false); + inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + final XMLStreamReader xsr = inputFactory.createXMLStreamReader(new StreamSource(xml.toASCIIString())); + final Unmarshaller u = getJaxbContext().createUnmarshaller(); + u.setSchema(schema); + + u.setEventHandler(handler2Use); + final T value = u.unmarshal(xsr, type).getValue(); + if (defaultHandler != null && defaultHandler.hasErrors()) { + throw new ConversionExeption( + String.format("Schema errors while reading content from %s: %s", xml, defaultHandler.getErrorDescription())); + } + + return value; + } catch (final JAXBException | XMLStreamException e) { + throw new ConversionExeption(String.format("Can not unmarshal to type %s from %s", type.getSimpleName(), xml.toString()), e); + } + } + + /** + * Serializing an object to xml. + * + * @param model the object + * @param type of the object + * @return the serialized form. + */ + public String writeXml(final T model) { + return writeXml(model, null, null); + } + + public String writeXml(final T model, Schema schema, ValidationEventHandler handler) { + if (model == null) { + throw new ConversionExeption("Can not serialize null"); + } + try ( StringWriter w = new StringWriter() ) { + final JAXBIntrospector introspector = getJaxbContext().createJAXBIntrospector(); + final Marshaller marshaller = getJaxbContext().createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); + marshaller.setSchema(schema); + marshaller.setEventHandler(handler); + final XMLOutputFactory xof = XMLOutputFactory.newFactory(); + final XMLStreamWriter xmlStreamWriter = xof.createXMLStreamWriter(w); + if (null == introspector.getElementName(model)) { + final JAXBElement jaxbElement = new JAXBElement(createQName(model), model.getClass(), model); + marshaller.marshal(jaxbElement, xmlStreamWriter); + } else { + marshaller.marshal(model, xmlStreamWriter); + } + xmlStreamWriter.flush(); + return w.toString(); + } catch (JAXBException | IOException | XMLStreamException e) { + throw new ConversionExeption(String.format("Error serializing Object %s", model.getClass().getName()), e); + } + } + + public Document writeDocument(T input) { + if (input == null) { + throw new ConversionExeption("Can not serialize null"); + } + DocumentBuilder builder = ObjectFactory.createDocumentBuilder(false); + Document document = builder.newDocument(); + + // Marshal the Object to a Document + Marshaller marshaller = null; + try { + marshaller = getJaxbContext().createMarshaller(); + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + marshaller.marshal(input, document); + return document; + } catch (JAXBException e) { + throw new ConversionExeption(String.format("Error serializing Object %s to document", input.getClass().getName()), e); + } + } + + /** + * Exception while serializing/deserializing with jaxb. + */ + public class ConversionExeption extends RuntimeException { + + /** + * Constructor. + * + * @param message the message. + * @param cause the cause + */ + public ConversionExeption(final String message, final Exception cause) { + super(message, cause); + } + + /** + * Constructor. + * + * @param message the message. + */ + public ConversionExeption(final String message) { + super(message); + } + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java new file mode 100644 index 0000000..28e6325 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java @@ -0,0 +1,137 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import org.w3c.dom.Document; + +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.api.Check; +import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.impl.tasks.*; +import de.kosit.validationtool.model.reportInput.CreateReportInput; +import de.kosit.validationtool.model.reportInput.DocumentIdentificationType; +import de.kosit.validationtool.model.reportInput.EngineType; +import de.kosit.validationtool.model.reportInput.ProcessingError; + +import net.sf.saxon.s9api.Processor; + +/** + * Die Referenz-Implementierung für den Prüfprozess. Nach initialer Konfiguration ist diese Klasse threadsafe und kann + * in Server-Umgebungen eingesetzt werden + * + * @author Andreas Penski + */ +@Slf4j +public class DefaultCheck implements Check { + + private static final String ENGINE_NAME = "KoSIT Prüftool"; + + private static final String ENGINE_VERSION = "1.0.0"; + + private ScenarioRepository repository; + + @Getter + private ContentRepository contentRepository; + + private ConversionService conversionService; + + @Getter + private List checkSteps; + + /** + * Erzeugt eine neue Instanz mit der angegebenen Konfiguration. + * + * @param configuration die Konfiguration + */ + public DefaultCheck(CheckConfiguration configuration) { + Processor processor = ObjectFactory.createProcessor(); + conversionService = new ConversionService(); + contentRepository = new ContentRepository(processor, configuration.getScenarioRepository()); + repository = new ScenarioRepository(processor, contentRepository); + repository.initialize(configuration); + checkSteps = new ArrayList<>(); + checkSteps.add(this::createDocumentIdentification); + checkSteps.add(new DocumentParseAction()); + checkSteps.add(new ScenarioSelectionAction(repository)); + checkSteps.add(new SchemaValidationAction()); + checkSteps.add(new SchematronValidationAction(processor, configuration.getScenarioRepository())); + checkSteps.add(new ValidateReportInputAction(conversionService, contentRepository.getReportInputSchema())); + checkSteps.add(new CreateReportAction(processor, conversionService, repository, configuration.getScenarioRepository())); + } + + protected static CreateReportInput createReport() { + CreateReportInput type = new CreateReportInput(); + EngineType e = new EngineType(); + e.setName(ENGINE_NAME); + type.setEngine(e); + type.setTimestamp(ObjectFactory.createTimestamp()); + type.setFrameworkVersion(ENGINE_VERSION); + return type; + } + + @Override + public Document check(Input input) { + CheckAction.Bag t = new CheckAction.Bag(input, createReport()); + return runCheckInternal(t); + } + + protected Document runCheckInternal(CheckAction.Bag t) { + long started = System.currentTimeMillis(); + log.info("Checking content of {}", t.getInput().getName()); + Iterator it = checkSteps.iterator(); + + + while (it.hasNext()) { + final CheckAction action = it.next(); + if (!action.isSkipped(t)) { + action.check(t); + } + if (t.isStopped()) { + final ProcessingError processingError = t.getReportInput().getProcessingError(); + log.error("Error processing input {}: {}", t.getInput().getName(), + processingError != null ? processingError.getError().stream().collect(Collectors.joining("\n")) : ""); + break; + } + } + t.setFinished(true); + log.info("Finished check of {} in {}ms\n", t.getInput().getName(), System.currentTimeMillis() - started); + return t.getReport(); + } + + private boolean createDocumentIdentification(CheckAction.Bag transporter) { + DocumentIdentificationType i = new DocumentIdentificationType(); + DocumentIdentificationType.DocumentHash h = new DocumentIdentificationType.DocumentHash(); + h.setHashAlgorithm(transporter.getInput().getDigestAlgorithm()); + h.setHashValue(transporter.getInput().getHashCode()); + i.setDocumentHash(h); + i.setDocumentReference(transporter.getInput().getName()); + transporter.getReportInput().setDocumentIdentification(i); + return true; + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java b/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java new file mode 100644 index 0000000..5245e70 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java @@ -0,0 +1,256 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.GregorianCalendar; + +import javax.xml.XMLConstants; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.*; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; + +import lombok.extern.slf4j.Slf4j; + +import net.sf.saxon.Configuration; +import net.sf.saxon.expr.XPathContext; +import net.sf.saxon.lib.*; +import net.sf.saxon.s9api.Processor; +import net.sf.saxon.trans.XPathException; + +/** + * Eine Factory für häufig verwendete Objekte mit XML. Zentralisiert die XML Security Konfiguration. Die Konfiguration + * basiert auf den OWASP-Empfehlungen. + * + * Diese Klasse ist stark abhängig von der Verwendung eines Oracle JDK. Alternative JDKs haben u.U. eine andere SAX- / + * StAX- / XML-Implementierug und profitieren entsprechend NICHT von den hier getroffenen Einstellungen. + * + * @author Andreas Penski + */ +@Slf4j +public class ObjectFactory { + + private static final String ORACLE_XERCES_CLASS = "com.sun.org.apache.xerces.internal.impl.Constants"; + + private static final String DISSALLOW_DOCTYPE_DECL_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl"; + + private static final String LOAD_EXTERNAL_DTD_FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; + + private static final String FEATURE_SECURE_PROCESSING = "http://javax.xml.XMLConstants/feature/secure-processing"; + + private static Processor processor; + + static { + try { + Class.forName(ORACLE_XERCES_CLASS); + } catch (ClassNotFoundException e) { + log.warn("No oracle JDK version of XERCES found. Configured security features may not have any effect."); + log.warn("Please take care of XML security while checking your xml contents"); + } + } + + private ObjectFactory() { + // hide, it's a factory + } + + private static DocumentBuilderFactory createDocumentBuilderFactory(boolean validating) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + try { + dbf.setValidating(validating); + dbf.setNamespaceAware(true); + + // explicitly enable secure processing + dbf.setFeature(FEATURE_SECURE_PROCESSING, true); + + // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented + dbf.setFeature(DISSALLOW_DOCTYPE_DECL_FEATURE, true); + + // Disable external DTDs as well + dbf.setFeature(LOAD_EXTERNAL_DTD_FEATURE, false); + + // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks" + dbf.setXIncludeAware(false); + dbf.setExpandEntityReferences(false); + return dbf; + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Can not create DocumentBuilderFactory due to underlying configuration error", e); + } + + } + + /** + * Transformer für die Ausgabe. Nutzt nicht Saxon! + * + * @param prettyPrint pretty-printing der Ausgabe + * @return einen vorkonfigurierten Transformer + */ + public static Transformer createTransformer(boolean prettyPrint) { + Transformer transformer = null; + try { + transformer = TransformerFactory.newInstance().newTransformer(); + if (prettyPrint) { + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + } + return transformer; + } catch (TransformerConfigurationException e) { + throw new IllegalStateException("Can not create Transformer due to underlying configuration error", e); + } + } + + /** + * Erzeugt einen Zeitstempel zur Verwendung in XML-Objekten + * + * @return eine Instanz {@link XMLGregorianCalendar} + */ + public static XMLGregorianCalendar createTimestamp() { + try { + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(new Date()); + return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal); + + } catch (DatatypeConfigurationException e) { + throw new IllegalStateException("Can not create timestamp", e); + } + } + + public static DocumentBuilder createDocumentBuilder(boolean validating) { + try { + return createDocumentBuilderFactory(validating).newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new IllegalStateException("Can not create DocumentFactory due to underlying configuration error", e); + } + } + + private static String encode(String input) { + try { + return URLEncoder.encode(input, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("Error encoding property while initializing saxon", e); + } + } + + public static Processor createProcessor() { + if (processor == null) { + processor = new Processor(false); + //verhindere global im Prinzip alle resolving strategien + SecureUriResolver resolver = new SecureUriResolver(); + processor.getUnderlyingConfiguration().setCollectionFinder(resolver); + processor.getUnderlyingConfiguration().setOutputURIResolver(resolver); + //hier fehlt eigentlich noch der UriResolver für unparsed text, wird erst ab Saxon 9.8 unterstützt + + //grundsätzlich Feature-konfiguration: + processor.setConfigurationProperty(FeatureKeys.DTD_VALIDATION, false); + processor.setConfigurationProperty(FeatureKeys.ENTITY_RESOLVER_CLASS, ""); + processor.setConfigurationProperty(FeatureKeys.XINCLUDE, false); + processor.setConfigurationProperty(FeatureKeys.ALLOW_EXTERNAL_FUNCTIONS, false); + + // Konfiguration des zu verwendenden Parsers, wenn Saxon selbst einen erzeugen muss, bspw. beim XSL parsen + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(FEATURE_SECURE_PROCESSING), true); + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(DISSALLOW_DOCTYPE_DECL_FEATURE), false); + processor.setConfigurationProperty(FeatureKeys.XML_PARSER_FEATURE + encode(LOAD_EXTERNAL_DTD_FEATURE), false); + } + return processor; + } + + /** + * Erzeugt einen Validier für das angegebenen Schema. + * + * @param schema das Schema mit dem validiert werden soll + * @return einen vorkonfigurierten Validator + */ + public static Validator createValidator(Schema schema) { + final Validator validator = schema.newValidator(); + try { + validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + } catch (SAXNotRecognizedException | SAXNotSupportedException e) { + log.warn("Can not disable external DTD access. Maybe an unsupported JAXP implementation is used."); + log.debug(e.getMessage(), e); + } + try { + validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + } catch (SAXNotRecognizedException | SAXNotSupportedException e) { + log.warn("Can not disable external DTD access. Maybe an unsupported JAXP implementation is used."); + log.debug(e.getMessage(), e); + + } + return validator; + } + + public static SchemaFactory createSchemaFactory() { + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + try { + sf.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + sf.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "file"); + } catch (SAXException e) { + log.warn("Can not disable external DTD access, maybe an unsupported JAXP implementation is used", e); + } + return sf; + } + + private static class SecureUriResolver implements CollectionFinder, OutputURIResolver, UnparsedTextURIResolver { + + public static final String MESSAGE = "Configuration error. Resolving ist not allowed"; + + @Override + public OutputURIResolver newInstance() { + return this; + } + + @Override + public Result resolve(String href, String base) throws TransformerException { + throw new IllegalStateException(MESSAGE); + } + + @Override + public void close(Result result) throws TransformerException { + throw new IllegalStateException(MESSAGE); + } + + @Override + public Reader resolve(URI absoluteURI, String encoding, Configuration config) throws XPathException { + throw new IllegalStateException(MESSAGE); + } + + @Override + public ResourceCollection findCollection(XPathContext context, String collectionURI) throws XPathException { + throw new IllegalStateException(MESSAGE); + } + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java b/src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java new file mode 100644 index 0000000..0ff80fd --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/RelativeUriResolver.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URI; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; +import javax.xml.transform.stream.StreamSource; + +import lombok.RequiredArgsConstructor; + +import net.sf.saxon.Configuration; +import net.sf.saxon.lib.UnparsedTextURIResolver; +import net.sf.saxon.trans.XPathException; + +/** + * {@link URIResolver} that resolves artifacts relative to a given base uri. The resolved URI must be resolving as child + * e.g. the baseUri must be a parent of the resolved artifact. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +public class RelativeUriResolver implements URIResolver, UnparsedTextURIResolver { + + /** the base uri */ + private final URI baseUri; + + @Override + public Source resolve(final String href, final String base) throws TransformerException { + final URI resolved = URI.create(base).resolve(href); + if (isUnderBaseUri(resolved)) { + try { + return new StreamSource(resolved.toURL().openStream()); + } catch (final IOException e) { + + throw new IllegalStateException(String.format("Can not resolve required %s", href), e); + } + } else { + throw new IllegalStateException( + String.format("The resolved transformation artifact %s is not within the configured repository %s", resolved, baseUri)); + } + } + + private boolean isUnderBaseUri(URI resolved) { + String base = baseUri.toASCIIString().replaceAll("file:/+", ""); + String r = resolved.toASCIIString().replaceAll("file:/+", ""); + return r.startsWith(base); + } + + @Override + public Reader resolve(URI absoluteURI, String encoding, Configuration config) throws XPathException { + if (isUnderBaseUri(absoluteURI)) { + try { + return new InputStreamReader(absoluteURI.toURL().openStream(), encoding); + } catch (IOException e) { + throw new IllegalStateException(String.format("Can not resolve required %s", absoluteURI), e); + } + } else { + throw new IllegalStateException( + String.format("The resolved transformation artifact %s is not within the configured repository %s", absoluteURI, baseUri)); + } + } +} \ No newline at end of file diff --git a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java new file mode 100644 index 0000000..9234a8e --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java @@ -0,0 +1,173 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.net.MalformedURLException; +import java.net.URI; +import java.util.List; +import java.util.stream.Collectors; + +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.DocumentParseAction; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; +import de.kosit.validationtool.model.scenarios.ScenarioType; +import de.kosit.validationtool.model.scenarios.Scenarios; + +import net.sf.saxon.s9api.*; + +/** + * Repository for die aktiven Szenario einer Prüfinstanz. + * + * @author Andreas Penski + */ +@Slf4j +@RequiredArgsConstructor +public class ScenarioRepository { + + private static final String SUPPORTED_MAJOR_VERSION = "1"; + + private static final String SUPPORTED_MAJOR_VERSION_SCHEMA = "http://www.xoev.de/de/validator/framework/1/scenarios"; + + @Getter(value = AccessLevel.PRIVATE) + + private final Processor processor; + + @Getter(value = AccessLevel.PRIVATE) + private final ContentRepository repository; + + private XsltExecutable noScenarioReport; + + @Getter(value = AccessLevel.PACKAGE) + private Scenarios scenarios; + + private static boolean isSupportedDocument(Document doc) { + final Element root = doc.getDocumentElement(); + return root.hasAttribute("frameworkVersion") && root.getAttribute("frameworkVersion").startsWith(SUPPORTED_MAJOR_VERSION) + && doc.getDocumentElement().getNamespaceURI().equals(SUPPORTED_MAJOR_VERSION_SCHEMA); + } + + private static void checkVersion(URI scenarioDefinition) { + DocumentParseAction p = new DocumentParseAction(); + try { + final Result result = p.parseDocument(InputFactory.read(scenarioDefinition.toURL())); + if (result.isValid() && !isSupportedDocument(result.getObject())) { + throw new IllegalStateException(String.format( + "Specified scenario configuration %s is not supported.%nThis version only supports definitions of '%s'", + scenarioDefinition, SUPPORTED_MAJOR_VERSION_SCHEMA)); + + } + } catch (MalformedURLException e) { + throw new IllegalStateException("Error reading definition file"); + } + } + + public XsltExecutable getNoScenarioReport() { + if (noScenarioReport == null) { + noScenarioReport = repository.loadXsltScript(URI.create(scenarios.getNoScenarioReport().getResource().getLocation())); + } + return noScenarioReport; + } + + /** + * Initialisiert das Repository mit der angegebenen Konfiguration. + * + * @param config die Konfiguration + */ + public void initialize(CheckConfiguration config) { + ConversionService conversionService = new ConversionService(); + checkVersion(config.getScenarioDefinition()); + log.info("Loading scenarios from {}", config.getScenarioDefinition()); + CollectingErrorEventHandler handler = new CollectingErrorEventHandler(); + this.scenarios = conversionService.readXml(config.getScenarioDefinition(), Scenarios.class, repository.getScenarioSchema(), + handler); + if (!handler.hasErrors()) { + log.info("Loaded scenarios for {} by {} from {}. The following scenarios are available:\n\n{}", scenarios.getName(), + scenarios.getAuthor(), scenarios.getDate(), summarizeScenarios()); + log.info("Loading scenario content from {}", config.getScenarioRepository()); + getScenarios().getScenario().forEach(s -> s.initialize(repository, false)); + } else { + throw new IllegalStateException(String.format("Can not load scenarios from %s due to %s", config.getScenarioDefinition(), + handler.getErrorDescription())); + } + // initialize fallback report eager + getNoScenarioReport(); + + } + + private String summarizeScenarios() { + StringBuilder b = new StringBuilder(); + scenarios.getScenario().forEach(s -> { + b.append(s.getName()); + b.append("\n"); + }); + return b.toString(); + } + + /** + * Ermittelt für das angegebene Dokument das passende Szenario. + * + * @param document das Eingabedokument + * @return ein Ergebnis-Objekt zur weiteren Verarbeitung + */ + public Result selectScenario(Document document) { + Result result = new Result<>(); + final List collect = scenarios.getScenario().stream().filter(s -> match(document, s)).collect(Collectors.toList()); + if (collect.size() == 1) { + result = new Result<>(collect.get(0)); + } else if (collect.isEmpty()) { + result.getErrors().add("None of the loaded scenarios matches the specified document"); + } else { + result.getErrors().add("More than on scenario matches the specified document"); + } + return result; + + } + + private boolean match(Document document, ScenarioType scenario) { + try { + final XPathSelector selector = scenario.getSelector(); + DocumentBuilder documentBuilder = getProcessor().newDocumentBuilder(); + + final XdmNode xdmSource = documentBuilder.build(new DOMSource(document)); + selector.setContextItem(xdmSource); + return selector.effectiveBooleanValue(); + } catch (SaxonApiException e) { + log.error("Error evaluating xpath expression", e); + } + return false; + + } + + void initialize(Scenarios def) { + this.scenarios = def; + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java b/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java new file mode 100644 index 0000000..46e21bf --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.model; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.xml.validation.Schema; + +import org.apache.commons.lang3.NotImplementedException; +import org.w3c.dom.Document; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.ScenarioRepository; +import de.kosit.validationtool.model.scenarios.*; + +import net.sf.saxon.s9api.XPathExecutable; +import net.sf.saxon.s9api.XPathSelector; +import net.sf.saxon.s9api.XsltExecutable; + +/** + * Eine Basis-Klasse für Szenarien. Wiederverwendbare Objekte mit Bezug zum Szenario werden hier gecached. Die Klasse + * stellt im eigentlichen Sinne eine Erweiterung der durch JAXB generierten Strukturen dar. + * + * @author Andreas Penski + */ +public abstract class BaseScenario { + + private XPathExecutable xPathExecutable; + + private Schema schema; + + private List schematronValidations; + + private ContentRepository repository; + + private Transformation reportTransformation; + + /** + * Gibt eine Transformation zurück. + * @return initialisierte Transformation + */ + public Transformation getReportTransformation() { + if (reportTransformation == null) { + final ResourceType resource = getCreateReport().getResource(); + final XsltExecutable executable = repository.loadXsltScript(URI.create(resource.getLocation())); + reportTransformation = new Transformation(executable, resource); + } + return reportTransformation; + } + + /** + * Lieferrt das Schema zu diesem Szenario. + * @return das passende Schema + */ + public Schema getSchema() { + if (schema == null) { + final List schemaResources = getValidateWithXmlSchema().getResource().stream().map(r -> r.getLocation()) + .collect(Collectors.toList()); + schema = repository.createSchema(schemaResources); + } + return schema; + } + + + /** + * Initialisiert das Szenario auf Basis eines [@link ContentRepository} + * @param repository das Repository mit den Szenario-Artefakten + * @param lazy optionales lazy loading der XML-Artefakte + * @return true wenn erfolgreich + */ + public boolean initialize(ContentRepository repository, boolean lazy) { + this.repository = repository; + if (!lazy) { + getSchema(); + getSelector(); + getSchematronValidations(); + getReportTransformation(); + } + return true; + } + + /** + * Liefer eine Liste mit Schematron Validierungs-Transformationen + * @return liste mit initialisierten Transformationsinformationen + */ + public List getSchematronValidations() { + if (schematronValidations == null) { + schematronValidations = new ArrayList<>(); + getValidateWithSchematron().forEach(v -> { + if (v.isPsvi()) { + throw new NotImplementedException("This implemenation does not support PSVI usage"); + } + final XsltExecutable xsltExecutable = repository.loadXsltScript(URI.create(v.getResource().getLocation())); + schematronValidations.add(new Transformation(xsltExecutable, v.getResource())); + }); + } + return schematronValidations; + } + + /** + * Der XPath-Selector zur Identifikation des Scenarios. + * + * @return vorbereiteten selector + * @see {@link ScenarioRepository#selectScenario(Document)}. + */ + public XPathSelector getSelector() { + if (xPathExecutable == null) { + final Map namespaces = getNamespace().stream().collect(Collectors.toMap(NamespaceType::getPrefix, NamespaceType::getValue)); + xPathExecutable = repository.createXPath(getMatch(), namespaces); + } + return xPathExecutable.load(); + } + + /** + * Getter aus dem schema. + * + * @return xpath match + */ + public abstract String getMatch(); + + /** + * Getter aus dem schema. + * + * @return {@link List} of {@link NamespaceType} + */ + public abstract List getNamespace(); + + /** + * Getter aus dem schema. + * + * @return Validierungsanweisungen + */ + public abstract ValidateWithXmlSchema getValidateWithXmlSchema(); + + /** + * Getter aus dem schema. + * + * @return Validierungsanweisungne + */ + public abstract List getValidateWithSchematron(); + + /** + * Getter aus dem schema. + * + * @return report informationen + */ + public abstract CreateReportType getCreateReport(); + + /** + * Laufzeitinformationen über eine Transformation. + */ + @Getter + @Setter + @AllArgsConstructor + public class Transformation { + + private XsltExecutable executable; + + private ResourceType resourceType; + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java b/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java new file mode 100644 index 0000000..d248332 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/model/BaseXMLSyntaxError.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.model; + +import org.slf4j.Logger; + +import de.kosit.validationtool.model.reportInput.XMLSyntaxErrorSeverity; + +/** + * Basis-Klasse für Syntax-Error. Wird über die JAXB-generierte Klasse + * {@link de.kosit.validationtool.model.reportInput.XMLSyntaxError} erweitert. + * + * @author Andreas Penski + */ +public abstract class BaseXMLSyntaxError { + + /** + * Logged den Syntax-Fehler über einen definierten Logger. + * + * @param logger der Logger + */ + public void log(Logger logger) { + String msgTemplate = "{} At row {} at pos {}"; + Object[] params = { getMessage(), getRowNumber(), getColumnNumber() }; + if (getSeverity() == XMLSyntaxErrorSeverity.SEVERITY_WARNING) { + logger.warn(msgTemplate, params); + } else { + logger.error(msgTemplate, params); + } + + } + + @Override + public String toString() { + return String.format("%s At row %s at pos %s", getMessage(), getRowNumber(), getColumnNumber()); + } + + /** + * Getter aus dem schema + * + * @return Spalte des Fehlers + */ + public abstract Integer getColumnNumber(); + + /** + * Getter aus dem schema + * + * @return Zeile des Fehlers + */ + public abstract Integer getRowNumber(); + + /** + * Getter aus dem schema + * + * @return Fehlermeldung + */ + public abstract String getMessage(); + + /** + * Getter aus dem schema + * + * @return severity + */ + public abstract XMLSyntaxErrorSeverity getSeverity(); +} diff --git a/src/main/java/de/kosit/validationtool/impl/model/Result.java b/src/main/java/de/kosit/validationtool/impl/model/Result.java new file mode 100644 index 0000000..21cc704 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/model/Result.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * Ein Ergebnisobjekte, dass das eigentliche Ergebnis hält und optional auch verschiedene Fehlerobjekte. + * + * @param der Typ des Ergebnis-Objekts + * @param der Typ des Fehler-Objekts + */ +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class Result { + + private T object; + + private Collection errors = new ArrayList<>(); + + /** + * Erzeugt ein neues Ergebnis mit Fehler + * + * @param errors die Fehler + */ + public Result(Collection errors) { + this(null, errors); + } + + /** + * Erzeugt ein neues Ergebnis mit einem Ergebnisobjekt + * + * @param o + */ + public Result(T o) { + this(o, Collections.emptyList()); + } + + /** + * Zeigt an, ob das Ergebnis valide, also ohne Fehler ist. + * + * @return true wenn erfolgreich + */ + public boolean isValid() { + return object != null && errors.isEmpty(); + } + + /** + * Zeigt an, ob das Ergebnis nicht valide ist, als entsprechend Fehler gesammelt wurden. + * + * @return true wenn erfolgreich wenn Fehler vorhanden sind. + */ + public boolean isInvalid() { + return !isValid(); + } +} \ No newline at end of file diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java new file mode 100644 index 0000000..ee8c24f --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.model.reportInput.CreateReportInput; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; +import de.kosit.validationtool.model.scenarios.ScenarioType; +import lombok.Getter; +import lombok.Setter; +import org.w3c.dom.Document; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Interface, welches von allen Prüfschritten implementiert wird. Der Parameter vom Typ {@link Bag} dient dabei sowohl + * als Quellce für Eingabe Parameter als auch für die Aufnahme von Ergebnisse, die an weitere Schritte weitergeleitet + * werden sollen. + * + * @author Andreas Penski + */ +@FunctionalInterface +public interface CheckAction { + + /** + * Ausfürhung des Prüfschrittes und Erweiterung der gesammelten Informationen. + * + * @param results die Informationssammlung + */ + void check(Bag results); + + /** + * Ermittlung, ob ein Schritt u.U. ausgelassen werden kann. Die Funktion wird vor der eigentlichen Prüfaktion aufgerufen + * und kann somit eine Ausführung des Prüfschrittes verhindern. Entwickler können diese Funktion überschreiben, um den + * Prüfschritt bedingt auszuführen. + * + * @param results die bisher gesammelten Information + * @return true wenn der Schritt ausgelassen werden soll + */ + default boolean isSkipped(Bag results) { + return false; + } + + /** + * Transport-Klasse für Eingabe und Ausgabe-Objekte für die einzelnen Prüfschritte. + */ + @Getter + @Setter + class Bag { + + private Result scenarioSelectionResult; + + private CreateReportInput reportInput; + + /** Das finale Ergebnis */ + private Document report; + + private boolean finished; + + private boolean stopped; + + /** Das zu prüfende Dokument */ + private Input input; + + private Result parserResult; + + private Result assertionResult; + + private Result schemaValidationResult; + + public Bag(Input input) { + this(input, new CreateReportInput()); + } + + public Bag(Input input, CreateReportInput reportInput) { + this.input = input; + this.reportInput = reportInput; + } + + /** + * Signalisiert einen vorzeitigen Stop der Vearbeitung. + */ + public void stopProcessing() { + this.stopped = true; + } + + /** + * Gibt den Namen des Prüflings zurück, dabei werden etwaige Pfadinformationen abgeschnitten. + * + * @return der Name des Prüflings + */ + public String getName() { + final String fileName = getInput().getName().replaceAll(".*/|.*\\\\", ""); + final Matcher matcher = Pattern.compile("(.*)\\..+").matcher(fileName); + if (matcher.matches()) { + return matcher.group(1); + } + return fileName; + } + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java new file mode 100644 index 0000000..ed1b762 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import java.net.URI; + +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; + +import lombok.RequiredArgsConstructor; + +import de.kosit.validationtool.impl.*; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.model.scenarios.ScenarioType; + +import net.sf.saxon.s9api.*; + +/** + * Erzeugt den Report auf Basis der gesammelten Informationen über den Prüfling. Sollte kein Szenario identifiziert + * worden sein, so wird ein {@link ScenarioRepository#getNoScenarioReport() default report} erzeugt. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +public class CreateReportAction implements CheckAction { + + private final Processor processor; + + private final ConversionService conversionService; + + private final ScenarioRepository repository; + + private final URI contentRepository; + + private static XsltExecutable loadFromScenario(ScenarioType object) { + return object.getReportTransformation().getExecutable(); + } + + @Override + public void check(Bag results) { + final DocumentBuilder documentBuilder = processor.newDocumentBuilder(); + try { + + final Document inputDoc = results.getParserResult().isValid() ? results.getParserResult().getObject() + : ObjectFactory.createDocumentBuilder(true).newDocument(); + + final XdmNode parsedDocument = documentBuilder.build(new DOMSource(inputDoc)); + final Document reportInput = conversionService.writeDocument(results.getReportInput()); + final XdmNode root = documentBuilder.build(new DOMSource(reportInput)); + final XsltTransformer transformer = getTransformation(results).load(); + transformer.setInitialContextNode(root); + CollectingErrorEventHandler e = new CollectingErrorEventHandler(); + RelativeUriResolver resolver = new RelativeUriResolver(contentRepository); + transformer.setMessageListener(e); + transformer.setURIResolver(resolver); + transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver); + transformer.setParameter(new QName("input-document"), parsedDocument); + Document result = ObjectFactory.createDocumentBuilder(false).newDocument(); + transformer.setDestination(new DOMDestination(result)); + transformer.transform(); + results.setReport(result); + + } catch (SaxonApiException e) { + throw new IllegalStateException("Can not create final report", e); + } + } + + private XsltExecutable getTransformation(Bag results) { + final Result scenario = results.getScenarioSelectionResult(); + return scenario != null && scenario.isValid() ? loadFromScenario(scenario.getObject()) : loadFallback(); + } + + private XsltExecutable loadFallback() { + return repository.getNoScenarioReport(); + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/DocumentParseAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/DocumentParseAction.java new file mode 100644 index 0000000..874666c --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/DocumentParseAction.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.impl.CollectingErrorEventHandler; +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.model.reportInput.ValidationResultsWellformedness; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; +import de.kosit.validationtool.model.reportInput.XMLSyntaxErrorSeverity; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; + +/** + * Setzt Parsing-Funktionalitäten um. Prüft auf well-formedness + * + * @author Andreas Penski + */ +@Slf4j +@RequiredArgsConstructor +public class DocumentParseAction implements CheckAction { + + /** + * Parsed und überprüft ein übergebenes Dokument darauf ob es well-formed ist. Dies stellt den ersten + * Verarbeitungsschritt des Prüf-Tools dar. Diese Funktion verzichtet explizit auf das Validierung gegenüber ein Schema. + * + * @param content ein Dokument + * @return Ergebnis des Parsings inklusive etwaiger Fehler + */ + public Result parseDocument(Input content) { + if (content == null) { + throw new IllegalArgumentException("Url may not be null"); + } + Result result; + CollectingErrorEventHandler errorHandler = new CollectingErrorEventHandler(); + try ( InputStream input = new ByteArrayInputStream(content.getContent()) ) { + DocumentBuilder db = ObjectFactory.createDocumentBuilder(false); + db.setErrorHandler(errorHandler); + Document doc = db.parse(input); + result = new Result<>(doc, errorHandler.getErrors()); + } catch (SAXException e) { + log.debug("SAXException while parsing {}", content.getName(), e); + result = new Result<>(errorHandler.getErrors()); + } catch (IOException e) { + log.debug("IOException while parsing {}", content, e); + XMLSyntaxError error = new XMLSyntaxError(); + error.setSeverity(XMLSyntaxErrorSeverity.SEVERITY_FATAL_ERROR); + error.setMessage(String.format("IOException while reading resource %s", content.getName())); + result = new Result<>(Collections.singleton(error)); + } + + return result; + } + + @Override + public void check(Bag results) { + Result parserResult = parseDocument(results.getInput()); + ValidationResultsWellformedness v = new ValidationResultsWellformedness(); + results.setParserResult(parserResult); + v.getXmlSyntaxError().addAll(parserResult.getErrors()); + results.getReportInput().setValidationResultsWellformedness(v); + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java new file mode 100644 index 0000000..b43ef5b --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import lombok.RequiredArgsConstructor; + +import de.kosit.validationtool.impl.ScenarioRepository; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.model.reportInput.CreateReportInput; +import de.kosit.validationtool.model.reportInput.ProcessingError; +import de.kosit.validationtool.model.scenarios.ScenarioType; + +/** + * Identifiziert das der Eingabe entsprechende Szenario, sofern eines konfiguriert ist. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +public class ScenarioSelectionAction implements CheckAction { + + private final ScenarioRepository repository; + + @Override + public void check(Bag results) { + final CreateReportInput report = results.getReportInput(); + final Result scenarioTypeResult = repository.selectScenario(results.getParserResult().getObject()); + results.setScenarioSelectionResult(scenarioTypeResult); + if (scenarioTypeResult.isValid()) { + final ScenarioType scenario = scenarioTypeResult.getObject(); + report.setScenario(scenario); + } else { + if (report.getProcessingError() == null) { + report.setProcessingError(new ProcessingError()); + } + report.getProcessingError().getError().addAll(scenarioTypeResult.getErrors()); + } + } + + @Override + public boolean isSkipped(Bag results) { + return results.getParserResult().isInvalid(); + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java new file mode 100644 index 0000000..f43afbd --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Validator; + +import org.xml.sax.SAXException; + +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.impl.CollectingErrorEventHandler; +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.model.reportInput.CreateReportInput; +import de.kosit.validationtool.model.reportInput.ValidationResultsXmlSchema; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; +import de.kosit.validationtool.model.scenarios.ScenarioType; + +/** + * Schema-Validierung der Eingabe-Datei mittels Schema-Definition aus dem identifizierten Szenario. + * + * @author Andreas Penski + */ +@Slf4j +public class SchemaValidationAction implements CheckAction { + + private Result validate(byte[] document, ScenarioType scenarioType) { + log.debug("Validating document using scenario {}", scenarioType.getName()); + final CollectingErrorEventHandler errorHandler = new CollectingErrorEventHandler(); + try ( InputStream input = new ByteArrayInputStream(document) ) { + final Validator validator = ObjectFactory.createValidator(scenarioType.getSchema()); + validator.setErrorHandler(errorHandler); + validator.validate(new StreamSource(input)); + return new Result<>(!errorHandler.hasErrors(), errorHandler.getErrors()); + } catch (SAXException | IOException e) { + throw new IllegalStateException("Error validating document", e); + } + } + + @Override + public void check(Bag results) { + final CreateReportInput report = results.getReportInput(); + final ScenarioType scenario = results.getScenarioSelectionResult().getObject(); + final Result validateResult = validate(results.getInput().getContent(), scenario); + results.setSchemaValidationResult(validateResult); + ValidationResultsXmlSchema result = new ValidationResultsXmlSchema(); + report.setValidationResultsXmlSchema(result); + result.getResource().addAll(scenario.getValidateWithXmlSchema().getResource()); + if (!validateResult.isValid()) { + result.getXmlSyntaxError().addAll(validateResult.getErrors()); + } + } + + + + @Override + public boolean isSkipped(Bag results) { + return hasNoScenario(results); + } + + private static boolean hasNoScenario(Bag results) { + return results.getScenarioSelectionResult() == null || results.getScenarioSelectionResult().isInvalid(); + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java new file mode 100644 index 0000000..51002f1 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import java.net.URI; +import java.util.List; +import java.util.stream.Collectors; + +import javax.xml.transform.dom.DOMSource; + +import org.w3c.dom.Document; + +import lombok.RequiredArgsConstructor; + +import de.kosit.validationtool.impl.CollectingErrorEventHandler; +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.RelativeUriResolver; +import de.kosit.validationtool.impl.model.BaseScenario; +import de.kosit.validationtool.model.reportInput.CreateReportInput; +import de.kosit.validationtool.model.reportInput.ValidationResultsSchematron; +import de.kosit.validationtool.model.scenarios.ScenarioType; + +import net.sf.saxon.s9api.*; + +/** + * Ausführung von konfigurierten Schematron Validierungen eines Szenarios. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +public class SchematronValidationAction implements CheckAction { + + private final Processor processor; + + private final URI repository; + + private List validate(Document document, ScenarioType scenario) { + return scenario.getSchematronValidations().stream().map(v -> validate(document, v)).collect(Collectors.toList()); + } + + private ValidationResultsSchematron validate(Document document, BaseScenario.Transformation validation) { + final DocumentBuilder documentBuilder = processor.newDocumentBuilder(); + try { + final XdmNode root = documentBuilder.build(new DOMSource(document)); + final XsltTransformer transformer = validation.getExecutable().load(); + //resolving nur relative zum Repository + final RelativeUriResolver resolver = new RelativeUriResolver(repository); + transformer.setURIResolver(resolver); + CollectingErrorEventHandler e = new CollectingErrorEventHandler(); + transformer.setMessageListener(e); + + Document result = ObjectFactory.createDocumentBuilder(false).newDocument(); + transformer.setDestination(new DOMDestination(result)); + transformer.setInitialContextNode(root); + transformer.transform(); + ValidationResultsSchematron s = new ValidationResultsSchematron(); + s.setResource(validation.getResourceType()); + ValidationResultsSchematron.Results r = new ValidationResultsSchematron.Results(); + r.setAny(result.getDocumentElement()); + s.setResults(r); + return s; + + } catch (SaxonApiException e) { + throw new IllegalStateException("Can not run schematron validation", e); + } + } + + @Override + public void check(Bag results) { + final CreateReportInput report = results.getReportInput(); + final List bla = validate(results.getParserResult().getObject(), + results.getScenarioSelectionResult().getObject()); + report.getValidationResultsSchematron().addAll(bla); + } + + @Override + public boolean isSkipped(Bag results) { + return results.getSchemaValidationResult() == null || results.getSchemaValidationResult().isInvalid(); + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java new file mode 100644 index 0000000..57747d8 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl.tasks; + +import javax.xml.validation.Schema; + +import org.apache.commons.lang3.StringUtils; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.impl.CollectingErrorEventHandler; +import de.kosit.validationtool.impl.ConversionService; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; + +/** + * Validiert die gesammelten Informationen über den Prüfling. Zusätzlich Check. + * + * @author Andreas Penski + */ +@RequiredArgsConstructor +@Slf4j +public class ValidateReportInputAction implements CheckAction { + + private final ConversionService conversionService; + + private final Schema schema; + + @Override + public void check(Bag bag) { + final Result results = validate(bag.getReportInput()); + if (!results.isValid()) { + log.error("Report input has errors {}", results.getErrors()); + bag.stopProcessing(); + } + } + + /** + * Validatiert das gegebene JAXB-Objekt gegen das konfigurierte Schema + * + * @param object das JAXB-Objekt + * @param der Typ des Objekts + * @return ein Validierungsergebnis + */ + private Result validate(T object) { + CollectingErrorEventHandler h = new CollectingErrorEventHandler(); + final String result = conversionService.writeXml(object, schema, h); + return new Result<>(StringUtils.isNotBlank(result), h.getErrors()); + } +} diff --git a/src/main/model/binding/global.xjb b/src/main/model/binding/global.xjb new file mode 100644 index 0000000..1391881 --- /dev/null +++ b/src/main/model/binding/global.xjb @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + de.kosit.validationtool.impl.model.BaseXMLSyntaxError + + + + + + + + de.kosit.validationtool.impl.model.BaseScenario + + + + + + + + + \ No newline at end of file diff --git a/src/main/model/xsd/assertions.xsd b/src/main/model/xsd/assertions.xsd new file mode 100644 index 0000000..e7d5e73 --- /dev/null +++ b/src/main/model/xsd/assertions.xsd @@ -0,0 +1,71 @@ + + + + + + + + + In diesem Dokument werden zum Test einer Prüftoolkonfiguration Zusicherungen zu einzelnen + Prüfberichten beschrieben. Ein + solches Dokument kann der Kommandozeilenversion des Prüftools über --check-assertions übergeben werden. + + + + + + + + + + + + + Definition eines Präfix für einen Namensraum, zur Verwendung in nachfolgenden + assertion-Elementen. + + + + + + + + + + + + Zusicherung: für das in report-doc angegebene Dokument (relativ zum aktuellen + Ausgabeverzeichnis) hat der angebene + XPath-Test den "Effective Truth Value" true(). Im Textknoten kann eine textuelle Zusammenfassung des + Tests stehen. + + + + + + + + + + + diff --git a/src/main/model/xsd/createReportInput.xsd b/src/main/model/xsd/createReportInput.xsd new file mode 100644 index 0000000..0323008 --- /dev/null +++ b/src/main/model/xsd/createReportInput.xsd @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + In alignment with + http://docs.oracle.com/javase/8/docs/api/org/xml/sax/ErrorHandler.html and + http://docs.oracle.com/javase/8/docs/api/org/xml/sax/SAXParseException.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dient der eindeutigen Identifikation des geprüften Dokuments anhand seines Hashwertes, der durch eine Dokumentenreferenz + ergänzt werden kann. + + + + + Angaben zum Hashwert des geprüften Dokuments. + + + + + + Benennung eines Algorithmus zur Berechnung des Hashwerts. + + + + + Der Hashwert des geprüften Dokuments bei Anwendung des bezeichneten Algorithmus. + + + + + + + + Eine von der prüfenden Organisationseinheit festgelegte, möglichst eindeutige Referenz des geprüften + Dokuments. + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/model/xsd/scenarios.xsd b/src/main/model/xsd/scenarios.xsd new file mode 100644 index 0000000..9570334 --- /dev/null +++ b/src/main/model/xsd/scenarios.xsd @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/simplelogger.properties b/src/main/resources/simplelogger.properties new file mode 100644 index 0000000..a6fb5ba --- /dev/null +++ b/src/main/resources/simplelogger.properties @@ -0,0 +1,51 @@ +# +# Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under +# one or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. KoSIT licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# SLF4J's SimpleLogger configuration file for the command line client +# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err. + +# Default logging detail level for all instances of SimpleLogger. +# Must be one of ("trace", "debug", "info", "warn", or "error"). +# If not specified, defaults to "info". +org.slf4j.simpleLogger.defaultLogLevel=info + + +# Set to true if you want the current date and time to be included in output messages. +# Default is false, and will output the number of milliseconds elapsed since startup. +org.slf4j.simpleLogger.showDateTime=true + +# The date and time format to be used in the output messages. +# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat. +# If the format is not specified or is invalid, the default format is used. +# The default format is yyyy-MM-dd HH:mm:ss:SSS Z. +org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss + +# Set to true if you want to output the current thread name. +# Defaults to true. +org.slf4j.simpleLogger.showThreadName=false + +# Set to true if you want the Logger instance name to be included in output messages. +# Defaults to true. +org.slf4j.simpleLogger.showLogName=false + +# Set to true if you want the last component of the name to be included in output messages. +# Defaults to false. +org.slf4j.simpleLogger.showShortLogName=false + +org.slf4j.simpleLogger.levelInBrackets=true \ No newline at end of file diff --git a/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java b/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java new file mode 100644 index 0000000..f99d486 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/api/InputFactoryTest.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.api; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import de.kosit.validationtool.impl.ConversionServiceTest; + +/** + * Testet den Hashcode-Service. + * + * @author Andreas Penski + */ +public class InputFactoryTest { + + private static final URL CONTENT = ConversionServiceTest.class.getResource("/valid/scenarios.xml"); + + private static final URL OTHER_CONTENT = ConversionServiceTest.class.getResource("/valid/report.xml"); + + public static final String SOME_VALUE = "some value"; + + private static URL NOT_EXISTING; + + static { + try { + NOT_EXISTING = new URL("file://localhost/somefile.text"); + } catch (MalformedURLException e) { + // just ignore; + } + } + + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void testDefaultDigestAlgorithm() { + assertThat(new InputFactory().getAlgorithm()).isEqualTo(InputFactory.DEFAULT_ALGORITH); + assertThat(new InputFactory("").getAlgorithm()).isEqualTo(InputFactory.DEFAULT_ALGORITH); + } + + @Test + public void testSimple() { + final byte[] s1 = InputFactory.read(CONTENT).getHashCode(); + final byte[] s2 = InputFactory.read(CONTENT).getHashCode(); + final byte[] s3 = InputFactory.read(OTHER_CONTENT).getHashCode(); + assertThat(s1).isNotEmpty(); + assertThat(s1).isEqualTo(s2); + assertThat(s3).isNotEmpty(); + assertThat(s1).isNotEqualTo(s3); + } + + @Test + public void testWrongAlgorithm() { + expectedException.expect(IllegalStateException.class); + InputFactory service = new InputFactory("unknown"); + } + + @Test + public void testNullInputURL() { + expectedException.expect(IllegalArgumentException.class); + InputFactory.read((URL) null); + } + + @Test + public void testInputByte() { + final Input input = InputFactory.read(SOME_VALUE.getBytes(), SOME_VALUE); + assertThat(input).isNotNull(); + } + + @Test + public void testInputStream() { + final Input input = InputFactory.read(new ByteArrayInputStream(SOME_VALUE.getBytes()), SOME_VALUE); + assertThat(input).isNotNull(); + } + + @Test + public void testNullStream() { + expectedException.expect(IllegalArgumentException.class); + final Input input = InputFactory.read((InputStream)null, SOME_VALUE); + } + + @Test + public void testInputFile() throws URISyntaxException { + final Input input = InputFactory.read(new File(CONTENT.toURI())); + assertThat(input).isNotNull(); + } + + @Test + public void testInputPath() throws URISyntaxException { + final Input input = InputFactory.read(Paths.get(CONTENT.toURI())); + assertThat(input).isNotNull(); + } + + @Test + public void testNullInput() { + expectedException.expect(IllegalArgumentException.class); + InputFactory.read((byte[]) null, SOME_VALUE); + } + + @Test + public void testNullInputName() { + expectedException.expect(IllegalArgumentException.class); + InputFactory.read(SOME_VALUE.getBytes(), null); + } + + @Test + public void testEmptyInputName() { + expectedException.expect(IllegalArgumentException.class); + InputFactory.read(SOME_VALUE.getBytes(), ""); + } + + @Test + public void testUnexistingInput() { + expectedException.expect(IllegalArgumentException.class); + InputFactory.read(NOT_EXISTING); + } + + +} diff --git a/src/test/java/de/kosit/validationtool/cmd/CheckAssertionActionTest.java b/src/test/java/de/kosit/validationtool/cmd/CheckAssertionActionTest.java new file mode 100644 index 0000000..8292c76 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/cmd/CheckAssertionActionTest.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Test; + +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.cmd.assertions.Assertions; +import de.kosit.validationtool.impl.Helper; +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.tasks.CheckAction; +import de.kosit.validationtool.model.reportInput.CreateReportInput; + +/** + * Testet das Assertion-Feature. + * + * @author Andreas Penski + */ +public class CheckAssertionActionTest { + + private static final URL SAMPLE = CheckAssertionActionTest.class.getResource("/examples/assertions/ubl-0001.xml"); + + private static final URL SAMPLE_REPORT = CheckAssertionActionTest.class.getResource("/examples/assertions/ubl-0001-report.xml"); + + private static final URL SAMPLE_ASSERTIONS = CheckAssertionActionTest.class.getResource("/examples/assertions/tests-xrechnung.xml"); + + private CommandLine commandLine; + + @Before + public void setup() throws IOException { + commandLine = new CommandLine(); + commandLine.activate(); + } + + @Test + public void testEmptyInput() { + CheckAssertionAction a = new CheckAssertionAction(new Assertions(), ObjectFactory.createProcessor()); + a.check(new CheckAction.Bag(InputFactory.read(SAMPLE), new CreateReportInput())); + assertThat(commandLine.getErrorOutput()).contains("Can not find assertions for"); + } + + @Test + public void testSimple() throws URISyntaxException { + final CheckAction.Bag bag = new CheckAction.Bag(InputFactory.read(SAMPLE), new CreateReportInput()); + bag.setReport(Helper.load(SAMPLE_REPORT).getObject()); + + final Assertions assertions = Helper.load(SAMPLE_ASSERTIONS, Assertions.class); + CheckAssertionAction a = new CheckAssertionAction(assertions, ObjectFactory.createProcessor()); + a.check(bag); + + assertThat(commandLine.getErrorOutput()).contains("Assertion mismatch"); + } +} diff --git a/src/test/java/de/kosit/validationtool/cmd/CommandLine.java b/src/test/java/de/kosit/validationtool/cmd/CommandLine.java new file mode 100644 index 0000000..1412124 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/cmd/CommandLine.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import java.io.*; +import java.util.List; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.TeeOutputStream; + +import lombok.Getter; +import lombok.Setter; + +/** + * Helferlein um Ausgaben auf der Kommandozeile zu testen. + * + * @author Andreas Penski + */ +public class CommandLine { + + private static ReplaceableOutputStream out = new ReplaceableOutputStream<>(); + + private static ReplaceableOutputStream error = new ReplaceableOutputStream<>(); + + static { + // Initialisierung muss vor SL4J's SimpleLogger erfolgen, sonst sind logs nicht erfasst. + // deshalb darf diese Klasse kein Log haben + System.setOut(new PrintStream(new TeeOutputStream(System.out, out))); + System.setErr(new PrintStream(new TeeOutputStream(System.err, error))); + } + + public String getOutput() { + return new String(out.getOut().toByteArray()); + } + + + public String getErrorOutput() { + return new String(error.getOut().toByteArray()); + } + + public List getOutputLines() { + return readLines(out.getOut().toByteArray()); + } + + public List getErrorLines() { + return readLines(error.getOut().toByteArray()); + } + + private List readLines(byte[] bytes) { + try ( ByteArrayInputStream in = new ByteArrayInputStream(bytes); + Reader r = new InputStreamReader(in) ) { + + return IOUtils.readLines(r); + } catch (IOException e) { + throw new IllegalStateException("Can not read input"); + } + } + + public void activate() { + out.setOut(new ByteArrayOutputStream()); + error.setOut(new ByteArrayOutputStream()); + + } + + public void deactivate() { + out.setOut(null); + error.setOut(null); + } + + /** + * Simpler Proxy für {@link OutputStream}, dessen target ausgetauscht werden kann. + * + * @param Typ des eigentlichen {@link OutputStream} + */ + private static class ReplaceableOutputStream extends OutputStream { + + @Getter + @Setter + private O out; + + public void write(int idx) throws IOException { + if (out != null) { + this.out.write(idx); + } + } + + public void write(byte[] bts) throws IOException { + if (out != null) { + this.out.write(bts); + } + } + + public void write(byte[] bts, int st, int end) throws IOException { + if (out != null) { + this.out.write(bts, st, end); + } + } + + public void flush() throws IOException { + + if (out != null) { + this.out.flush(); + } + } + + public void close() throws IOException { + if (out != null) { + this.out.close(); + } + } + } + +} diff --git a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java new file mode 100644 index 0000000..23c2fad --- /dev/null +++ b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import static de.kosit.validationtool.impl.Helper.*; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Testet die Parameter des Kommandozeilen-Tools. + * + * @author Andreas Penski + */ +public class CommandlineApplicationTest { + + public static final String RESULT_OUTPUT = "Processing 1 object(s) completed"; + + private CommandLine commandLine; + + + @Before + public void setup() throws IOException { + commandLine = new CommandLine(); + commandLine.activate(); + } + + @Test + public void testHelp() { + String[] args = new String[] { "-?" }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).isEmpty(); + checkForHelp(commandLine.getOutputLines()); + } + + private void checkForHelp(List outputLines) { + assertThat(outputLines.size()).isGreaterThan(0); + outputLines.subList(1, outputLines.size() - 1).forEach(l -> assertThat(l.startsWith(" -") || l.startsWith(" "))); + } + + @Test + public void testRequiredScenarioFile() { + String[] args = new String[] { "-d", "arguments", "egal welche", "argument drin sind" }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).isNotEmpty(); + assertThat(commandLine.getErrorOutput()).contains("Missing required option: s"); + } + + @Test + public void testNotExistingScenarioFile() { + String[] args = new String[] { "-s", Paths.get(NOT_EXISTING).toString(), Paths.get(NOT_EXISTING).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).isNotEmpty(); + assertThat(commandLine.getErrorOutput()).contains("Not a valid path for scenario definition specified"); + } + + @Test + public void testIncorrectRepository() { + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), Paths.get(NOT_EXISTING).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).isNotEmpty(); + assertThat(commandLine.getErrorOutput()).contains("Can not load schema from sources"); + } + + @Test + public void testNotExistingTestTarget() { + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-r", Paths.get(REPOSITORY).toString(), + Paths.get(NOT_EXISTING).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).isNotEmpty(); + assertThat(commandLine.getErrorOutput()).contains("No test targets found"); + } + + @Test + public void testValidMinimalConfiguration() { + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-r", Paths.get(REPOSITORY).toString(), + Paths.get(SAMPLE).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains(RESULT_OUTPUT); + } + + @Test + public void testValidMultipleInput() { + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-r", Paths.get(REPOSITORY).toString(), + Paths.get(SAMPLE).toString(), Paths.get(SAMPLE2).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains("Processing 2 object(s) completed"); + } + + @Test + public void testValidDirectoryInput() { + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-r", Paths.get(REPOSITORY).toString(), + Paths.get(SAMPLE_DIR).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains("Processing 4 object(s) completed"); + } + + @Test + public void testValidOutputConfiguration() throws IOException { + Path output = Paths.get("output"); + // assertThat(output).doesNotExist(); + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-o", output.getFileName().toString(), "-r", + Paths.get(REPOSITORY).toString(), Paths.get(SAMPLE).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains(RESULT_OUTPUT); + assertThat(output).exists(); + assertThat(Files.list(output)).hasSize(1); + } + + @Test + public void testNoInput() { + // assertThat(output).doesNotExist(); + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-r", Paths.get(REPOSITORY).toString(), }; + CommandLineApplication.mainProgram(args); + checkForHelp(commandLine.getOutputLines()); + } + + @Test + public void testPrint() { + + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-p", "-r", Paths.get(REPOSITORY).toString(), + Paths.get(SAMPLE).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains(RESULT_OUTPUT); + assertThat(commandLine.getOutputLines()).contains(""); + } + + @Test + public void testHtmlExtraktion() throws IOException { + Path output = Files.createTempDirectory("pruef-tool-test"); + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-h", "-o", output.toAbsolutePath().toString(), "-r", + Paths.get(REPOSITORY).toString(), Paths.get(SAMPLE).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains(RESULT_OUTPUT); + assertThat(Files.list(output).filter(f -> f.toString().endsWith(".html")).count()).isGreaterThan(0); + } + + @Test + public void testAssertionsExtraktion() throws IOException { + String[] args = new String[] { "-d", "-s", Paths.get(SCENARIO_FILE).toString(), "-r", Paths.get(REPOSITORY).toString(), "-c", + Paths.get(ASSERTIONS).toString(), Paths.get(REPOSITORY).toString(), Paths.get(SAMPLE).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains(RESULT_OUTPUT); + assertThat(commandLine.getErrorOutput()).contains("Can not find assertions for "); + } + + @Test + public void testDebugFlag() throws IOException { + String[] args = new String[] { "-s", Paths.get(SCENARIO_FILE).toString(), "-r", "unknown", "-d", Paths.get(ASSERTIONS).toString() }; + CommandLineApplication.mainProgram(args); + assertThat(commandLine.getErrorOutput()).contains("at de.kosit.validationtool"); + } + +} diff --git a/src/test/java/de/kosit/validationtool/cmd/ExtractHtmlActionTest.java b/src/test/java/de/kosit/validationtool/cmd/ExtractHtmlActionTest.java new file mode 100644 index 0000000..7e94140 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/cmd/ExtractHtmlActionTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.stream.Collectors; + +import org.apache.commons.io.FileUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.impl.Helper; +import de.kosit.validationtool.impl.tasks.CheckAction; + +/** + * Testet die HTML-Extrkation des Kommondazeilenprogramms. + * + * @author Andreas Penski + */ +public class ExtractHtmlActionTest { + + private static final URL REPORT = SerializeReportActionTest.class.getResource("/examples/results/report.xml"); + + private ExtractHtmlContentAction action; + + private Path tmpDirectory; + + @Before + public void setup() throws IOException { + tmpDirectory = Files.createTempDirectory("checktool"); + action = new ExtractHtmlContentAction(Helper.loadTestRepository(), tmpDirectory); + } + + @After + public void tearDown() throws IOException { + FileUtils.deleteDirectory(tmpDirectory.toFile()); + } + + @Test + public void testSimple() throws IOException { + CheckAction.Bag b = new CheckAction.Bag(InputFactory.read(REPORT)); + assertThat(action.isSkipped(b)).isTrue(); + b.setReport(Helper.load(REPORT).getObject()); + action.check(b); + assertThat(action.isSkipped(b)).isFalse(); + action.check(b); + assertThat(b.isStopped()).isFalse(); + assertThat(Files.list(tmpDirectory).collect(Collectors.toList())).hasSize(1); + } +} diff --git a/src/test/java/de/kosit/validationtool/cmd/PrintReportActionTest.java b/src/test/java/de/kosit/validationtool/cmd/PrintReportActionTest.java new file mode 100644 index 0000000..c817ac6 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/cmd/PrintReportActionTest.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.cmd; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.net.URL; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.impl.Helper; +import de.kosit.validationtool.impl.tasks.CheckAction; + +/** + * @author Andreas Penski + */ +public class PrintReportActionTest { + + private static final URL REPORT = SerializeReportActionTest.class.getResource("/examples/results/report.xml"); + + private CommandLine commandLine; + + private PrintReportAction action; + + @Before + public void setup() throws IOException { + commandLine = new CommandLine(); + commandLine.activate(); + action = new PrintReportAction(); + } + + @After + public void tearDownd() throws IOException { + commandLine.deactivate(); + } + + @Test + public void testSimpleSerialize() { + CheckAction.Bag b = new CheckAction.Bag(InputFactory.read(REPORT)); + b.setReport(Helper.load(REPORT).getObject()); + assertThat(action.isSkipped(b)).isFalse(); + action.check(b); + assertThat(b.isStopped()).isFalse(); + assertThat(commandLine.getOutput()).isNotEmpty(); + assertThat(commandLine.getOutput()).startsWith(" namespace = new HashMap<>(); + namespace.put("html", "http://www.w3.org/1999/xhtml"); + xPath = repository.createXPath("//html:html", namespace ); + assertThat(xPath).isNotNull(); + } + + @Test + public void testXpathCreationWithoutNamespace(){ + exception.expect(IllegalStateException.class); + repository.createXPath("//html:html", null ); + } + + @Test + public void testIllegalXpath(){ + exception.expect(IllegalStateException.class); + repository.createXPath("kein Xpath Ausdruck", null ); + } +} diff --git a/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java b/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java new file mode 100644 index 0000000..eb4da25 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static org.assertj.core.api.Java6Assertions.assertThat; + +import java.io.File; +import java.io.Serializable; +import java.net.URISyntaxException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import de.kosit.validationtool.model.scenarios.Scenarios; + +/** + * Simple test for testing the jaxb conversion service. + * + * @author apenski + */ +public class ConversionServiceTest { + + private static final URL VALID_XML = ConversionServiceTest.class.getResource("/valid/scenarios.xml"); + + private static final URL INVALID_XML = ConversionServiceTest.class.getResource("/invalid/scenarios-invalid.xml"); + + private static final URL ILLFORMED_XML = ConversionServiceTest.class.getResource("/invalid/scenarios-illformed.xml"); + + private static final URL SCHEMA = ConversionServiceTest.class.getResource("/xsd/scenarios.xsd"); + + @Rule + public ExpectedException exception = ExpectedException.none(); + + private ConversionService service; + + private ContentRepository repository; + + @Before + public void setup() { + service = new ConversionService(); + repository = new ContentRepository(ObjectFactory.createProcessor(), new File("src/test/resources/examples/repository").toURI()); + } + + @Test + public void testMarshalNull() { + exception.expect(ConversionService.ConversionExeption.class); + service.writeXml(null); + } + + @Test + public void testMarshalUnknown() { + exception.expect(ConversionService.ConversionExeption.class); + service.writeXml(new Serializable() { + }); + } + + @Test + public void testUnmarshal() throws URISyntaxException { + final Scenarios s = service.readXml(VALID_XML.toURI(), Scenarios.class); + assertThat(s).isNotNull(); + assertThat(s.getName()).isEqualToIgnoringCase("XInneres"); + } + + @Test + public void testUnmarshalWithSchema() throws URISyntaxException { + final Scenarios s = service.readXml(VALID_XML.toURI(), Scenarios.class, repository.createSchema(SCHEMA)); + assertThat(s).isNotNull(); + assertThat(s.getName()).isEqualToIgnoringCase("XInneres"); + } + + @Test + public void testUnmarshalInvalidXml() throws URISyntaxException { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(INVALID_XML.toURI(), Scenarios.class, repository.createSchema(SCHEMA)); + } + + @Test + public void testUnmarshalIllFormed() throws URISyntaxException { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(ILLFORMED_XML.toURI(), Scenarios.class, repository.createSchema(SCHEMA)); + } + + @Test + public void testUnmarshalEmpty() { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(null, Scenarios.class); + } + + @Test + public void testUnmarshalUnknownType() throws URISyntaxException { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(VALID_XML.toURI(), ConversionService.class); + } + + @Test + public void testUnmarshalWithoutType() throws URISyntaxException { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(VALID_XML.toURI(), null); + } + +} diff --git a/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java b/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java new file mode 100644 index 0000000..f621163 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/DefaultCheckTest.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Input; +import org.junit.Before; +import org.junit.Test; +import org.w3c.dom.Document; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static de.kosit.validationtool.api.InputFactory.read; +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test das Check-Interface + * + * @author Andreas Penski + */ +public class DefaultCheckTest { + + private static final URL SCENARIO_DEFINITION = ScenarioRepositoryTest.class.getResource("/examples/UBLReady/scenarios-2.xml"); + + private static final URL VALID_EXAMPLE = ScenarioRepositoryTest.class + .getResource("/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml"); + + public static final int MULTI_COUNT = 5; + + private DefaultCheck implementation; + + @Before + public void setup() throws URISyntaxException { + CheckConfiguration d = new CheckConfiguration(SCENARIO_DEFINITION.toURI()); + d.setScenarioRepository(new File("src/test/resources/examples/repository").toURI()); + implementation = new DefaultCheck(d); + } + + @Test + public void testHappyCase() throws Exception { + final Document doc = implementation.check(read(VALID_EXAMPLE)); + assertThat(doc).isNotNull(); + } + + @Test + public void testMultipleCase() throws Exception { + final List input = IntStream.range(0, MULTI_COUNT).mapToObj(i -> read(VALID_EXAMPLE)).collect(Collectors.toList()); + final List docs = implementation.check(input); + assertThat(docs).isNotNull(); + assertThat(docs).hasSize(MULTI_COUNT); + } + +} diff --git a/src/test/java/de/kosit/validationtool/impl/DocumentParserTest.java b/src/test/java/de/kosit/validationtool/impl/DocumentParserTest.java new file mode 100644 index 0000000..f902bb7 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/DocumentParserTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static de.kosit.validationtool.api.InputFactory.read; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.IOException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.w3c.dom.Document; + +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.DocumentParseAction; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; + +/** + * @author Andreas Penski + */ +public class DocumentParserTest { + + private static final URL CONTENT = ConversionServiceTest.class.getResource("/valid/scenarios.xml"); + + private static final URL ILLFORMED = ConversionServiceTest.class.getResource("/invalid/scenarios-illformed.xml"); + + private static final URL NOT_EXISTING = ConversionServiceTest.class.getResource("/does not exist.xml"); + + + + @Rule + public ExpectedException exception = ExpectedException.none(); + + private DocumentParseAction parser; + + @Before + public void setup() { + parser = new DocumentParseAction(); + } + + @Test + public void testSimple() throws IOException { + final Result result = parser.parseDocument(read(CONTENT)); + assertThat(result).isNotNull(); + assertThat(result.getObject()).isNotNull(); + assertThat(result.getErrors()).isEmpty(); + assertThat(result.isValid()).isTrue(); + } + + + @Test + public void testIllformed() throws IOException { + final Result result = parser.parseDocument(read(ILLFORMED)); + assertThat(result).isNotNull(); + assertThat(result.getErrors()).isNotEmpty(); + assertThat(result.getObject()).isNull(); + assertThat(result.isValid()).isFalse(); + } + + @Test + public void testNullInput() { + exception.expect(IllegalArgumentException.class); + parser.parseDocument(null); + + } + + +} diff --git a/src/test/java/de/kosit/validationtool/impl/Helper.java b/src/test/java/de/kosit/validationtool/impl/Helper.java new file mode 100644 index 0000000..fb03a4e --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/Helper.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import java.io.File; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Paths; + +import org.w3c.dom.Document; + +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.CheckAction; +import de.kosit.validationtool.impl.tasks.DocumentParseAction; +import de.kosit.validationtool.model.reportInput.XMLSyntaxError; + +/** + * Helferlein für Test-Artefakte + * + * @author Andreas Penski + */ +public class Helper { + + public static final URI SOURCE_ROOT = Paths.get("src/main/resources").toUri(); + + public static final URI MODEL_ROOT = Paths.get("src/main/model").toUri(); + + public static final URI ASSERTION_SCHEMA = MODEL_ROOT.resolve("xsd/assertions.xsd"); + + public static final URI SCENARIO_SCHEMA = MODEL_ROOT.resolve("xsd/scenarios.xsd"); + + public static final URI TEST_ROOT = Paths.get("src/test/resources").toUri(); + + + + public static final URI EXAMPLES_DIR = TEST_ROOT.resolve("examples/"); + public static final URI ASSERTIONS = EXAMPLES_DIR.resolve("assertions/tests-xrechnung.xml"); + + public static final URI SCENARIO_FILE = EXAMPLES_DIR.resolve("UBLReady/scenarios-2.xml"); + + + public static final URI REPOSITORY = EXAMPLES_DIR.resolve("repository/"); + + public static final URI NOT_EXISTING = EXAMPLES_DIR.resolve("doesnotexist"); + + public static final URI SAMPLE_DIR = EXAMPLES_DIR.resolve("UBLReady/"); + public static final URI SAMPLE_XSLT = EXAMPLES_DIR.resolve("repository/resources/eRechnung/report.xsl"); + public static final URI SAMPLE = SAMPLE_DIR.resolve("UBLReady_EU_UBL-NL_20170102_FULL.xml"); + + public static final URI SAMPLE2 = SAMPLE_DIR.resolve("UBLReady_EU_UBL-NL_20170102_FULL-invalid.xml"); + + + /** + * Lädt ein XML-Dokument von der gegebenen URL + * + * @param url die url die geladen werden soll + * @return ein result objekt mit Dokument + */ + public static Result load(URL url) { + DocumentParseAction a = new DocumentParseAction(); + CheckAction.Bag b = new CheckAction.Bag(InputFactory.read(url)); + a.check(b); + return b.getParserResult(); + } + + public static T load(URL url, Class type) throws URISyntaxException { + ConversionService c = new ConversionService(); + c.initialize(de.kosit.validationtool.model.reportInput.ObjectFactory.class.getPackage(), + de.kosit.validationtool.cmd.assertions.ObjectFactory.class.getPackage(), + de.kosit.validationtool.model.scenarios.ObjectFactory.class.getPackage()); + return c.readXml(url.toURI(), type); + } + + /** + * Lädt das default test repository mit Artefacten für Unit-Tests + * + * @return ein {@link ContentRepository} + */ + public static ContentRepository loadTestRepository() { + return new ContentRepository(ObjectFactory.createProcessor(), new File("src/test/resources/examples/repository").toURI()); + } +} + diff --git a/src/test/java/de/kosit/validationtool/impl/RelativeUriResolverTest.java b/src/test/java/de/kosit/validationtool/impl/RelativeUriResolverTest.java new file mode 100644 index 0000000..e9202a9 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/RelativeUriResolverTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import java.net.URISyntaxException; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +/** + * Testet den Uri-Resolver der relative auflösen soll + * + * @author Andreas Penski + */ +public class RelativeUriResolverTest { + + private static final URI BASE; + + static { + try { + BASE = RelativeUriResolver.class.getResource("/examples/assertions/").toURI(); + } catch (URISyntaxException e) { + throw new IllegalStateException(e); + } + } + + @Rule + public ExpectedException exception = ExpectedException.none(); + + private URIResolver resolver = new RelativeUriResolver(BASE); + + @Test + public void testSucces() throws TransformerException { + final Source resource = resolver.resolve("ubl-0001.xml", BASE.toASCIIString()); + assertThat(resource).isNotNull(); + } + + @Test + public void testNotExisting() throws TransformerException { + exception.expect(IllegalStateException.class); + resolver.resolve("ubl-0001", BASE.toASCIIString()); + } + + @Test + public void testOutOfPath() throws TransformerException { + exception.expect(IllegalStateException.class); + resolver.resolve("../results/report.xml", BASE.toASCIIString()); + } +} diff --git a/src/test/java/de/kosit/validationtool/impl/SaxonSecurityTest.java b/src/test/java/de/kosit/validationtool/impl/SaxonSecurityTest.java new file mode 100644 index 0000000..6508788 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/SaxonSecurityTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.net.URL; + +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; +import org.w3c.dom.Document; + +import lombok.extern.slf4j.Slf4j; + +import net.sf.saxon.s9api.*; + +/** + * Testet verschiedene Saxon Security Einstellungen. + * + * @author Andreas Penski + */ +@Slf4j +public class SaxonSecurityTest { + + @Test + public void testEvilStylesheets() throws IOException { + Processor p = ObjectFactory.createProcessor(); + for (int i = 1; i <= 5; i++) { + try { + URL resource = SaxonSecurityTest.class.getResource(String.format("/evil/evil%s.xsl", i)); + final XsltCompiler compiler = p.newXsltCompiler(); + final RelativeUriResolver resolver = new RelativeUriResolver(Helper.REPOSITORY); + compiler.setURIResolver(resolver); + final XsltExecutable exetuable = compiler.compile(new StreamSource(resource.openStream())); + final XsltTransformer transformer = exetuable.load(); + final Document document = ObjectFactory.createDocumentBuilder(false).newDocument(); + document.createElement("root"); + Document result = ObjectFactory.createDocumentBuilder(false).newDocument(); + transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver); + transformer.setURIResolver(resolver); + transformer.setSource(new DOMSource(document)); + transformer.setDestination(new DOMDestination(result)); + transformer.transform(); + + // wenn der Punkt erreicht wird, sollte wenigstens, das Element evil nicht mit 'bösen' Inhalten gefüllt sein! + if (StringUtils.isNotBlank(result.getDocumentElement().getTextContent())) { + fail(String.format("Saxon configuration should prevent expansion within %s", resource)); + } + + } catch (SaxonApiException | RuntimeException e) { + log.info("Expected exception detected", e.getMessage()); + } + } + } +} diff --git a/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java b/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java new file mode 100644 index 0000000..76da77f --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static de.kosit.validationtool.api.InputFactory.read; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.w3c.dom.Document; + +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.DocumentParseAction; +import de.kosit.validationtool.model.scenarios.ScenarioType; +import de.kosit.validationtool.model.scenarios.Scenarios; + +/** + * Testet das {@link ScenarioRepository}. + * + * @author Andreas Penski + */ + +public class ScenarioRepositoryTest { + + private static final URL SAMPLE = ScenarioRepositoryTest.class.getResource("/valid/scenarios.xml"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + ContentRepository content; + + private ScenarioRepository repository; + + @Before + public void setup() { + content = new ContentRepository(ObjectFactory.createProcessor(), new File("src/test/resources/examples/repository").toURI()); + Scenarios def = new Scenarios(); + ScenarioType t = new ScenarioType(); + t.setMatch("//*:name"); + t.setName("Test"); + t.initialize(content, true); + def.getScenario().add(t); + repository = new ScenarioRepository(ObjectFactory.createProcessor(), content); + repository.initialize(def); + } + + @Test + public void testHappyCase() throws Exception { + final Result scenario = repository.selectScenario(load(SAMPLE)); + assertThat(scenario).isNotNull(); + assertThat(scenario.isValid()).isTrue(); + } + + @Test + public void testNonMatch() throws Exception { + repository.getScenarios().getScenario().clear(); + final Result scenario = repository.selectScenario(load(SAMPLE)); + assertThat(scenario).isNotNull(); + assertThat(scenario.isValid()).isFalse(); + } + + @Test + public void testMultiMatch() throws Exception { + ScenarioType t = new ScenarioType(); + t.setMatch("//*:name"); + t.setName("Test"); + t.initialize(content, true); + repository.getScenarios().getScenario().add(t); + final Result scenario = repository.selectScenario(load(SAMPLE)); + assertThat(scenario).isNotNull(); + assertThat(scenario.isValid()).isFalse(); + } + + private Document load(URL url) throws IOException { + DocumentParseAction p = new DocumentParseAction(); + return p.parseDocument(read(url)).getObject(); + } +} diff --git a/src/test/java/de/kosit/validationtool/impl/SchemaValidatorActionTest.java b/src/test/java/de/kosit/validationtool/impl/SchemaValidatorActionTest.java new file mode 100644 index 0000000..55134e9 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/SchemaValidatorActionTest.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.util.Collections; + +import javax.xml.validation.Schema; + +import org.junit.Before; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.impl.model.Result; +import de.kosit.validationtool.impl.tasks.CheckAction; +import de.kosit.validationtool.impl.tasks.SchemaValidationAction; +import de.kosit.validationtool.model.reportInput.CreateReportInput; +import de.kosit.validationtool.model.scenarios.ResourceType; +import de.kosit.validationtool.model.scenarios.ScenarioType; +import de.kosit.validationtool.model.scenarios.ValidateWithXmlSchema; + +/** + * Testet die {@linkSchemaValidatorAction}. + * + * @author Andreas Penski + */ +public class SchemaValidatorActionTest { + + private static final URL VALID_EXAMPLE = SchemaValidatorActionTest.class + .getResource("/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml"); + + private static final URI INVALID_EXAMPLE = Helper.TEST_ROOT.resolve("invalid/scenarios-invalid.xml"); + + public ExpectedException expectedException = ExpectedException.none(); + + private SchemaValidationAction service; + + private ContentRepository repository; + + @Before + public void setup() { + service = new SchemaValidationAction(); + repository = new ContentRepository(ObjectFactory.createProcessor(), Helper.REPOSITORY); + + } + + @Test + public void testSimple() { + CheckAction.Bag bag = new CheckAction.Bag(InputFactory.read(VALID_EXAMPLE), new CreateReportInput()); + bag.setParserResult(Helper.load(VALID_EXAMPLE)); + ScenarioType t = new ScenarioType(); + ValidateWithXmlSchema v = new ValidateWithXmlSchema(); + ResourceType r = new ResourceType(); + r.setLocation("resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd"); + r.setName("invoice"); + v.getResource().add(r); + t.setValidateWithXmlSchema(v); + t.initialize(repository, true); + bag.setScenarioSelectionResult(new Result<>(t, Collections.emptyList())); + service.check(bag); + assertThat(bag.getSchemaValidationResult().isValid()).isTrue(); + assertThat(bag.getSchemaValidationResult()).isNotNull(); + assertThat(bag.getSchemaValidationResult().isValid()).isTrue(); + } + + @Test + public void testValidationFailure() throws MalformedURLException { + CheckAction.Bag bag = new CheckAction.Bag(InputFactory.read(INVALID_EXAMPLE.toURL()), new CreateReportInput()); + bag.setParserResult(Helper.load(INVALID_EXAMPLE.toURL())); + ScenarioType t = new ScenarioType(); + ValidateWithXmlSchema v = new ValidateWithXmlSchema(); + ResourceType r = new ResourceType(); + r.setLocation(Helper.REPOSITORY.relativize(Helper.SCENARIO_SCHEMA).getRawPath()); + r.setName("invoice"); + v.getResource().add(r); + t.setValidateWithXmlSchema(v); + t.initialize(repository, true); + bag.setScenarioSelectionResult(new Result<>(t, Collections.emptyList())); + service.check(bag); + assertThat(bag.getSchemaValidationResult().isValid()).isFalse(); + bag.getSchemaValidationResult().getErrors().forEach(e->{ + assertThat(e.getRowNumber()).isGreaterThan(0); + assertThat(e.getColumnNumber()).isGreaterThan(0); + }); + } + + @Test + public void testSchemaReferences() { + final Schema reportInputSchema = repository.getReportInputSchema(); + assertThat(reportInputSchema).isNotNull(); + } + +} diff --git a/src/test/java/de/kosit/validationtool/impl/VersioningTest.java b/src/test/java/de/kosit/validationtool/impl/VersioningTest.java new file mode 100644 index 0000000..8e53959 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/impl/VersioningTest.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under + * one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. KoSIT licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package de.kosit.validationtool.impl; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import de.kosit.validationtool.model.scenarios.Scenarios; + +/** + * Testet die Versionierung von Scenario-Dateien aka Konfigurationsdaten. + * + * @author Andreas Penski + */ +public class VersioningTest { + + private static final URL BASE = VersioningTest.class.getResource("/examples/versioning/scenarios-base.xml"); + + private static final URL INCREMENT = VersioningTest.class.getResource("/examples/versioning/scenarios-increment.xml"); + + private static final URL NEW_FEATURE = VersioningTest.class.getResource("/examples/versioning/scenarios-newfeature.xml"); + + private static final URL NEW_VERSION = VersioningTest.class.getResource("/examples/versioning/scenarios-newVersion.xml"); + + @Rule + public ExpectedException exception = ExpectedException.none(); + + private ConversionService service; + + private ContentRepository repository; + + @Before + public void setup() { + service = new ConversionService(); + repository = new ContentRepository(ObjectFactory.createProcessor(), new File("src/test/resources/examples/repository").toURI()); + } + + @Test + public void testBase() throws URISyntaxException { + final Scenarios result = service.readXml(BASE.toURI(), Scenarios.class, repository.getScenarioSchema()); + assertThat(result).isNotNull(); + } + + @Test + public void testFrameworkIncrement() throws URISyntaxException { + final Scenarios result = service.readXml(INCREMENT.toURI(), Scenarios.class, repository.getScenarioSchema()); + assertThat(result).isNotNull(); + } + + @Test + public void testNewFeature() throws URISyntaxException { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(NEW_FEATURE.toURI(), Scenarios.class, repository.getScenarioSchema()); + } + + @Test + public void testNewVersion() throws URISyntaxException { + exception.expect(ConversionService.ConversionExeption.class); + service.readXml(NEW_VERSION.toURI(), Scenarios.class, repository.getScenarioSchema()); + } +} diff --git a/src/test/resources/evil/evil1.xsl b/src/test/resources/evil/evil1.xsl new file mode 100644 index 0000000..601ff6c --- /dev/null +++ b/src/test/resources/evil/evil1.xsl @@ -0,0 +1,32 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/evil/evil2.xsl b/src/test/resources/evil/evil2.xsl new file mode 100644 index 0000000..af7bb32 --- /dev/null +++ b/src/test/resources/evil/evil2.xsl @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/evil/evil3.xsl b/src/test/resources/evil/evil3.xsl new file mode 100644 index 0000000..8f0de2d --- /dev/null +++ b/src/test/resources/evil/evil3.xsl @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/evil/evil4.xsl b/src/test/resources/evil/evil4.xsl new file mode 100644 index 0000000..29a6322 --- /dev/null +++ b/src/test/resources/evil/evil4.xsl @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/evil/evil5.xsl b/src/test/resources/evil/evil5.xsl new file mode 100644 index 0000000..c66dc79 --- /dev/null +++ b/src/test/resources/evil/evil5.xsl @@ -0,0 +1,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/evil/ref.txt b/src/test/resources/evil/ref.txt new file mode 100644 index 0000000..ac46e7e --- /dev/null +++ b/src/test/resources/evil/ref.txt @@ -0,0 +1 @@ +this content should not appear in \ No newline at end of file diff --git a/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL-invalid.xml b/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL-invalid.xml new file mode 100644 index 0000000..9cf75ea --- /dev/null +++ b/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL-invalid.xml @@ -0,0 +1,301 @@ + + + + + + + urn:cen.eu:en16931:2017 + + urn:www.cenbii.eu:profile:bii04:ver2.0 + + 20170102 + 2017-02-16 + 2017-03-18 + 380 + 2017-02-16 + EUR + + RK20172013 + + 2017-02-14 + 2017-02-14 + + + + 20170205 + + + + + + UBL Platform + + + Readystreet 9a + Amsterdam + 9876 YZ + + NL + + + + + NL123456789B01 + + VAT + + + + UBL Ketentest BV + 12345678 + + + 06 987654321 + info@gbned.nl + + + + + + + + UBL Ready + + + Demostreet 1 + Arnhem + 1234 AB + + NL + + + + + + UBL Ready + + + John Doe + 070-1111111 + invoices@ublready.com + + + + + + 2017-02-16 + + + Stocklane 10 + Arnhem + 4321 BA + + NL + + + + + + + + 31 + + NL23ABNA0123456789 + + + ABNANL2A + + + + + + + Payments within 30 days. + + + + false + 64 + Invoice allowance (VAT low 6%) + 1 + 22 + 220 + + S + 6 + + VAT + + + + + false + 64 + Invoice allowance (VAT high 21%) + 1 + 18 + 180 + + S + 21 + + VAT + + + + + true + ZZZ + Handling costs + 10 + + S + 21 + + VAT + + + + + 48.00 + + 198 + 11.88 + + S + 6.00 + + VAT + + + + + 172 + 36.12 + + S + 21.00 + + VAT + + + + + + + 400.00 + 370.00 + 418.00 + 40.00 + 10.00 + 418.00 + + + + 5 + 1.00 + 50.00 + + Book The digital highway in Holland + The digital highway + + BK0232 + + + S + 6.00 + + VAT + + + + + 50.00 + 1.00 + + + + + 10 + 2.00 + 170.00 + + Book Coding UBL for orders and invoices + Coding UBL + + BK3025 + + + S + 6.00 + + VAT + + + + + 85.00 + 2.00 + + + + + 15 + 1.00 + 180.00 + + false + Price discount + 10 + 20.00 + 200 + + + Conversion softwarepackage to UBL + Conversion UBL + + SW4026 + + + S + 21.00 + + VAT + + + + + 200.00 + 1.00 + + + + diff --git a/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml b/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml new file mode 100644 index 0000000..fd4d1d3 --- /dev/null +++ b/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml @@ -0,0 +1,302 @@ + + + + + + + urn:cen.eu:en16931:2017 + + urn:www.cenbii.eu:profile:bii04:ver2.0 + + 20170102 + 2017-02-16 + 2017-03-18 + 380 + 2017-02-16 + EUR + + RK20172013 + + 2017-02-14 + 2017-02-14 + + + + 20170205 + + + + + + UBL Platform + + + Readystreet 9a + Amsterdam + 9876 YZ + + NL + + + + + NL123456789B01 + + VAT + + + + UBL Ketentest BV + 12345678 + + + 06 987654321 + info@gbned.nl + + + + + + + + UBL Ready + + + Demostreet 1 + Arnhem + 1234 AB + + NL + + + + + + UBL Ready + + + John Doe + 070-1111111 + invoices@ublready.com + + + + + + 2017-02-16 + + + Stocklane 10 + Arnhem + 4321 BA + + NL + + + + + + + + 31 + + NL23ABNA0123456789 + + + ABNANL2A + + + + + + + Payments within 30 days. + + + + false + 64 + Invoice allowance (VAT low 6%) + 1 + 22 + 220 + + S + 6 + + VAT + + + + + false + 64 + Invoice allowance (VAT high 21%) + 1 + 18 + 180 + + S + 21 + + VAT + + + + + true + ZZZ + Handling costs + 10 + + S + 21 + + VAT + + + + + 48.00 + + 198 + 11.88 + + S + 6.00 + + VAT + + + + + 172 + 36.12 + + S + 21.00 + + VAT + + + + + + + 400.00 + 370.00 + 418.00 + 40.00 + 10.00 + 418.00 + + + + 5 + 1.00 + 50.00 + + Book The digital highway in Holland + The digital highway + + BK0232 + + + S + 6.00 + + VAT + + + + + 50.00 + 1.00 + + + + + 10 + 2.00 + 170.00 + + Book Coding UBL for orders and invoices + Coding UBL + + BK3025 + + + S + 6.00 + + VAT + + + + + 85.00 + 2.00 + + + + + 15 + 1.00 + 180.00 + + false + Price discount + 10 + 20.00 + 200 + + + Conversion softwarepackage to UBL + Conversion UBL + + SW4026 + + + S + 21.00 + + VAT + + + + + 200.00 + 1.00 + + + + + diff --git a/src/test/resources/examples/UBLReady/scenarios-1.xml b/src/test/resources/examples/UBLReady/scenarios-1.xml new file mode 100644 index 0000000..e6b6678 --- /dev/null +++ b/src/test/resources/examples/UBLReady/scenarios-1.xml @@ -0,0 +1,55 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + Report für eRechnung + + does-not-exist.xsl + + + + + + default + resources/eRechnung/report.xsl + + + +
diff --git a/src/test/resources/examples/UBLReady/scenarios-2.xml b/src/test/resources/examples/UBLReady/scenarios-2.xml new file mode 100644 index 0000000..f2befec --- /dev/null +++ b/src/test/resources/examples/UBLReady/scenarios-2.xml @@ -0,0 +1,66 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + + + default + resources/eRechnung/default-report.xsl + + + +
diff --git a/src/test/resources/examples/assertions/tests-xrechnung.xml b/src/test/resources/examples/assertions/tests-xrechnung.xml new file mode 100644 index 0000000..2927700 --- /dev/null +++ b/src/test/resources/examples/assertions/tests-xrechnung.xml @@ -0,0 +1,45 @@ + + + + + + http://www.xoev.de/de/validator/varl/1 + + + Schema wurde validiert + + + Schematron wurde validiert + + Empfehlung zur Annahme + + Schema wurde validiert + + + Schematron wurde validiert + + Empfehlung zur Ablehnung + + + + diff --git a/src/test/resources/examples/assertions/ubl-0001-report.xml b/src/test/resources/examples/assertions/ubl-0001-report.xml new file mode 100644 index 0000000..4263206 --- /dev/null +++ b/src/test/resources/examples/assertions/ubl-0001-report.xml @@ -0,0 +1,3426 @@ + + + + + + KoSIT POC + + 2017-09-14T09:09:21.855+02:00 + + + SHA-256 + 8LK/pF4UR8Kf5QPs1gs1J+h8WGyVXwmGy+kZTgqGYgg= + + /C:/Developer/projects/prueftool/svn/trunk/test/tests-xrechnung/ubl-0001.xml + + + + + UBL 2.x Invoice (EN16931) + urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2 + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice[starts-with(cbc:CustomizationID, 'urn:cen.eu:en16931:2017')] + + + XML Schema UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + Schematron Rules for Invoice - UBL + resources/eRechnung/UBL-2.1/xsl/EN16931-UBL-validation.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + + + XML Schema UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + Schematron Rules for Invoice - UBL + resources/eRechnung/UBL-2.1/xsl/EN16931-UBL-validation.xsl + + + + + + + + + Prüfbericht + + + +

Prüfbericht

+ +

+ Konformitätsprüfung:Das geprüfte Dokument enthält weder Fehler noch Warnungen. Es ist + konform zu den formalen Vorgaben. +

+

Bewertung: Es wird empfohlen das Dokument anzunehmen und weiter zu + verarbeiten. +

+

Inhalt des Rechnungsdokuments:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
0001 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
0002 +
urn:cen.eu:en16931:2017
+
0003 +
12115118
+
0004 +
2015-01-09
+
0005 +
2015-01-09
+
0006 +
380
+
0007 +
Alle leveringen zijn franco. Alle prijzen zijn incl. BTW. + Betalingstermijn: 14 dagen netto. Prijswijzigingen voorbehouden. Op al onze + aanbiedingen, leveringen en overeenkomsten zijn van toepassing in de algemene + verkoop en leveringsvoorwaarden. Gedeponeerd bij de K.v.K. te Amsterdam + 25-04-'85##Delivery terms +
+
0008 +
EUR
+
0009 +
+
+
+
+
0010 +
+
+
+
+
+
+
+
+
0011 +
+
+
+
+
+
+
+
+
+
+
0012 +
Postbus 7l
+
0013 +
Velsen-Noord
+
0014 +
1950 AB
+
0015 +
+
+
+
+
0016 +
NL
+
0017 +
+
+
+
+
+
+
0018 +
NL8200.98.395.B.01
+
0019 +
+
+
+
+
0020 +
VAT
+
0021 +
+
+
+
+
+
+
0022 +
De Koksmaat
+
0023 +
57151520
+
0024 +
+
+
+
+
0025 +
+
+
+
+
+
+
+
+
+
+
0026 +
+
+
+
+
0027 +
10202
+
0028 +
+
+
+
+
+
+
+
+
+
+
0029 +
POSTBUS 367
+
0030 +
HEEMSKERK
+
0031 +
1960 AJ
+
0032 +
+
+
+
+
0033 +
NL
+
0034 +
+
+
+
+
0035 +
ODIN 59
+
0036 +
+
+
+
+
0037 +
Dhr. J BLOKKER
+
0038 +
+
+
+
+
+
+
+
+
0039 +
30
+
0040 +
Deb. 10202 / Fact. 12115118
+
0041 +
+
+
+
+
0042 +
NL57 RABO 0107307510
+
0043 +
+
+
+
+
+
+
+
+
0044 +
30
+
0045 +
Deb. 10202 / Fact. 12115118
+
0046 +
+
+
+
+
0047 +
NL03 INGB 0004489902
+
0048 +
+
+
+
+
+
+
+
+
0049 +
20.73
+
EUR
+
0050 +
+
+
+
+
+
+
+
+
0051 +
183.23
+
EUR
+
0052 +
10.99
+
EUR
+
0053 +
+
+
+
+
+
+
+
+
0054 +
S
+
0055 +
6
+
0056 +
+
+
+
+
0057 +
VAT
+
0058 +
+
+
+
+
+
+
+
+
0059 +
46.37
+
EUR
+
0060 +
9.74
+
EUR
+
0061 +
+
+
+
+
+
+
+
+
0062 +
S
+
0063 +
21
+
0064 +
+
+
+
+
0065 +
VAT
+
0066 +
+
+
+
+
+
+
+
+
+
+
0067 +
229.60
+
EUR
+
0068 +
229.60
+
EUR
+
0069 +
250.33
+
EUR
+
0070 +
250.33
+
EUR
+
0071 +
+
+
+
+
+
+
+
+
+
+
+
+
0072 +
1
+
0073 +
2
+
EA
+
0074 +
19.90
+
EUR
+
0075 +
+
+
+
+
+
+
+
+
0076 +
PATAT FRITES 10MM 10KG
+
0077 +
+
+
+
+
0078 +
166022
+
0079 +
+
+
+
+
+
+
+
+
0080 +
S
+
0081 +
6
+
0082 +
+
+
+
+
0083 +
VAT
+
0084 +
+
+
+
+
0085 +
9.95
+
EUR
+
0086 +
+
+
+
+
+
+
+
+
+
+
+
+
0087 +
2
+
0088 +
1
+
EA
+
0089 +
9.85
+
EUR
+
0090 +
+
+
+
+
+
+
+
+
0091 +
PKAAS 50PL. JONG BEL. 1KG
+
0092 +
+
+
+
+
0093 +
661813
+
0094 +
+
+
+
+
+
+
+
+
0095 +
S
+
0096 +
6
+
0097 +
+
+
+
+
0098 +
VAT
+
0099 +
+
+
+
+
0100 +
9.85
+
EUR
+
0101 +
+
+
+
+
+
+
+
+
+
+
+
+
0102 +
3
+
0103 +
1
+
EA
+
0104 +
8.29
+
EUR
+
0105 +
+
+
+
+
+
+
+
+
0106 +
POT KETCHUP 3 LT
+
0107 +
+
+
+
+
0108 +
438146
+
0109 +
+
+
+
+
+
+
+
+
0110 +
S
+
0111 +
6
+
0112 +
+
+
+
+
0113 +
VAT
+
0114 +
+
+
+
+
0115 +
8.29
+
EUR
+
0116 +
+
+
+
+
+
+
+
+
+
+
+
+
0117 +
4
+
0118 +
2
+
EA
+
0119 +
14.46
+
EUR
+
0120 +
+
+
+
+
+
+
+
+
0121 +
FRITESSAUS 3 LRR
+
0122 +
+
+
+
+
0123 +
438103
+
0124 +
+
+
+
+
+
+
+
+
0125 +
S
+
0126 +
6
+
0127 +
+
+
+
+
0128 +
VAT
+
0129 +
+
+
+
+
0130 +
7.23
+
EUR
+
0131 +
+
+
+
+
+
+
+
+
+
+
+
+
0132 +
5
+
0133 +
1
+
EA
+
0134 +
35.00
+
EUR
+
0135 +
+
+
+
+
+
+
+
+
0136 +
KOFFIE BLIK 3,5KG SNELF
+
0137 +
+
+
+
+
0138 +
666955
+
0139 +
+
+
+
+
+
+
+
+
0140 +
S
+
0141 +
6
+
0142 +
+
+
+
+
0143 +
VAT
+
0144 +
+
+
+
+
0145 +
35.00
+
EUR
+
0146 +
+
+
+
+
+
+
+
+
+
+
+
+
0147 +
6
+
0148 +
1
+
EA
+
0149 +
35.00
+
EUR
+
0150 +
+
+
+
+
+
+
+
+
0151 +
KOFFIE 3.5 KG BLIK STAND
+
0152 +
+
+
+
+
0153 +
664871
+
0154 +
+
+
+
+
+
+
+
+
0155 +
S
+
0156 +
6
+
0157 +
+
+
+
+
0158 +
VAT
+
0159 +
+
+
+
+
0160 +
35.00
+
EUR
+
0161 +
+
+
+
+
+
+
+
+
+
+
+
+
0162 +
7
+
0163 +
1
+
EA
+
0164 +
10.65
+
EUR
+
0165 +
+
+
+
+
+
+
+
+
0166 +
SUIKERKLONT
+
0167 +
+
+
+
+
0168 +
350257
+
0169 +
+
+
+
+
+
+
+
+
0170 +
S
+
0171 +
6
+
0172 +
+
+
+
+
0173 +
VAT
+
0174 +
+
+
+
+
0175 +
10.65
+
EUR
+
0176 +
+
+
+
+
+
+
+
+
+
+
+
+
0177 +
8
+
0178 +
1
+
EA
+
0179 +
1.55
+
EUR
+
0180 +
+
+
+
+
+
+
+
+
0181 +
1 KG UL BLOKJES
+
0182 +
+
+
+
+
0183 +
350258
+
0184 +
+
+
+
+
+
+
+
+
0185 +
S
+
0186 +
6
+
0187 +
+
+
+
+
0188 +
VAT
+
0189 +
+
+
+
+
0190 +
1.55
+
EUR
+
0191 +
+
+
+
+
+
+
+
+
+
+
+
+
0192 +
9
+
0193 +
3
+
EA
+
0194 +
14.37
+
EUR
+
0195 +
+
+
+
+
+
+
+
+
0196 +
BLOCKNOTE A5
+
0197 +
+
+
+
+
0198 +
999998
+
0199 +
+
+
+
+
+
+
+
+
0200 +
S
+
0201 +
6
+
0202 +
+
+
+
+
0203 +
VAT
+
0204 +
+
+
+
+
0205 +
4.79
+
EUR
+
0206 +
+
+
+
+
+
+
+
+
+
+
+
+
0207 +
10
+
0208 +
1
+
EA
+
0209 +
8.29
+
EUR
+
0210 +
+
+
+
+
+
+
+
+
0211 +
CHIPS NAT KLEIN ZAKJES
+
0212 +
+
+
+
+
0213 +
740810
+
0214 +
+
+
+
+
+
+
+
+
0215 +
S
+
0216 +
6
+
0217 +
+
+
+
+
0218 +
VAT
+
0219 +
+
+
+
+
0220 +
8.29
+
EUR
+
0221 +
+
+
+
+
+
+
+
+
+
+
+
+
0222 +
11
+
0223 +
2
+
EA
+
0224 +
16.58
+
EUR
+
0225 +
+
+
+
+
+
+
+
+
0226 +
CHIPS PAP KLEINE ZAKJES
+
0227 +
+
+
+
+
0228 +
740829
+
0229 +
+
+
+
+
+
+
+
+
0230 +
S
+
0231 +
6
+
0232 +
+
+
+
+
0233 +
VAT
+
0234 +
+
+
+
+
0235 +
8.29
+
EUR
+
0236 +
+
+
+
+
+
+
+
+
+
+
+
+
0237 +
12
+
0238 +
1
+
EA
+
0239 +
9.95
+
EUR
+
0240 +
+
+
+
+
+
+
+
+
0241 +
TR KL PAKJES APPELSAP
+
0242 +
+
+
+
+
0243 +
740828
+
0244 +
+
+
+
+
+
+
+
+
0245 +
S
+
0246 +
6
+
0247 +
+
+
+
+
0248 +
VAT
+
0249 +
+
+
+
+
0250 +
9.95
+
EUR
+
0251 +
+
+
+
+
+
+
+
+
+
+
+
+
0252 +
13
+
0253 +
2
+
EA
+
0254 +
3.30
+
EUR
+
0255 +
+
+
+
+
+
+
+
+
0256 +
PK CHOCOLADEMEL
+
0257 +
+
+
+
+
0258 +
740827
+
0259 +
+
+
+
+
+
+
+
+
0260 +
S
+
0261 +
6
+
0262 +
+
+
+
+
0263 +
VAT
+
0264 +
+
+
+
+
0265 +
1.65
+
EUR
+
0266 +
+
+
+
+
+
+
+
+
+
+
+
+
0267 +
14
+
0268 +
1
+
EA
+
0269 +
10.80
+
EUR
+
0270 +
+
+
+
+
+
+
+
+
0271 +
KRAT BIER
+
0272 +
+
+
+
+
0273 +
999996
+
0274 +
+
+
+
+
+
+
+
+
0275 +
S
+
0276 +
21
+
0277 +
+
+
+
+
0278 +
VAT
+
0279 +
+
+
+
+
0280 +
10.80
+
EUR
+
0281 +
+
+
+
+
+
+
+
+
+
+
+
+
0282 +
15
+
0283 +
1
+
EA
+
0284 +
3.90
+
EUR
+
0285 +
+
+
+
+
+
+
+
+
0286 +
STATIEGELD
+
0287 +
+
+
+
+
0288 +
999995
+
0289 +
+
+
+
+
+
+
+
+
0290 +
S
+
0291 +
6
+
0292 +
+
+
+
+
0293 +
VAT
+
0294 +
+
+
+
+
0295 +
3.90
+
EUR
+
0296 +
+
+
+
+
+
+
+
+
+
+
+
+
0297 +
16
+
0298 +
2
+
EA
+
0299 +
7.60
+
EUR
+
0300 +
+
+
+
+
+
+
+
+
0301 +
BLEEK 3 X 750 ML
+
0302 +
+
+
+
+
0303 +
102172
+
0304 +
+
+
+
+
+
+
+
+
0305 +
S
+
0306 +
21
+
0307 +
+
+
+
+
0308 +
VAT
+
0309 +
+
+
+
+
0310 +
3.80
+
EUR
+
0311 +
+
+
+
+
+
+
+
+
+
+
+
+
0312 +
17
+
0313 +
2
+
EA
+
0314 +
9.34
+
EUR
+
0315 +
+
+
+
+
+
+
+
+
0316 +
WC PAPIER
+
0317 +
+
+
+
+
0318 +
999994
+
0319 +
+
+
+
+
+
+
+
+
0320 +
S
+
0321 +
21
+
0322 +
+
+
+
+
0323 +
VAT
+
0324 +
+
+
+
+
0325 +
4.67
+
EUR
+
0326 +
+
+
+
+
+
+
+
+
+
+
+
+
0327 +
18
+
0328 +
1
+
EA
+
0329 +
18.63
+
EUR
+
0330 +
+
+
+
+
+
+
+
+
0331 +
BALPENNEN 50 ST BLAUW
+
0332 +
+
+
+
+
0333 +
999993
+
0334 +
+
+
+
+
+
+
+
+
0335 +
S
+
0336 +
21
+
0337 +
+
+
+
+
0338 +
VAT
+
0339 +
+
+
+
+
0340 +
18.63
+
EUR
+
0341 +
+
+
+
+
+
+
+
+
+
+
+
+
0342 +
19
+
0343 +
6
+
EA
+
0344 +
102.12
+
EUR
+
0345 +
+
+
+
+
+
+
+
+
0346 +
EM FRITUURVET
+
0347 +
+
+
+
+
0348 +
999992
+
0349 +
+
+
+
+
+
+
+
+
0350 +
S
+
0351 +
6
+
0352 +
+
+
+
+
0353 +
VAT
+
0354 +
+
+
+
+
0355 +
17.02
+
EUR
+
0356 +
+
+
+
+
+
+
+
+
+
+
+
+
0357 +
20
+
0358 +
6
+
EA
+
0359 +
-109.98
+
EUR
+
0360 +
+
+
+
+
+
+
+
+
0361 +
FRITUUR VET 10 KG RETOUR
+
0362 +
+
+
+
+
0363 +
175137
+
0364 +
+
+
+
+
+
+
+
+
0365 +
S
+
0366 +
6
+
0367 +
+
+
+
+
0368 +
VAT
+
0369 +
+
+
+
+
0370 +
18.33
+
EUR
+
+

Dieser Prüfbericht wurde erstellt mit KoSIT POC.

+ + +
+
+
+
diff --git a/src/test/resources/examples/assertions/ubl-0001.xml b/src/test/resources/examples/assertions/ubl-0001.xml new file mode 100644 index 0000000..a8b1736 --- /dev/null +++ b/src/test/resources/examples/assertions/ubl-0001.xml @@ -0,0 +1,542 @@ + + + + + urn:cen.eu:en16931:2017 + 12115118 + 2015-01-09 + 2015-01-09 + 380 + Alle leveringen zijn franco. Alle prijzen zijn incl. BTW. Betalingstermijn: 14 dagen netto. + Prijswijzigingen voorbehouden. Op al onze aanbiedingen, leveringen en overeenkomsten zijn van toepassing in de + algemene verkoop en leveringsvoorwaarden. Gedeponeerd bij de K.v.K. te Amsterdam 25-04-'85##Delivery terms + + EUR + + + + Postbus 7l + Velsen-Noord + 1950 AB + + NL + + + + NL8200.98.395.B.01 + + VAT + + + + De Koksmaat + 57151520 + + + + + + + 10202 + + + POSTBUS 367 + HEEMSKERK + 1960 AJ + + NL + + + + ODIN 59 + + + Dhr. J BLOKKER + + + + + 30 + Deb. 10202 / Fact. 12115118 + + NL57 RABO 0107307510 + + + + 30 + Deb. 10202 / Fact. 12115118 + + NL03 INGB 0004489902 + + + + 20.73 + + 183.23 + 10.99 + + S + 6 + + VAT + + + + + 46.37 + 9.74 + + S + 21 + + VAT + + + + + + 229.60 + 229.60 + 250.33 + 250.33 + + + 1 + 2 + 19.90 + + PATAT FRITES 10MM 10KG + + 166022 + + + S + 6 + + VAT + + + + + 9.95 + + + + 2 + 1 + 9.85 + + PKAAS 50PL. JONG BEL. 1KG + + 661813 + + + S + 6 + + VAT + + + + + 9.85 + + + + 3 + 1 + 8.29 + + POT KETCHUP 3 LT + + 438146 + + + S + 6 + + VAT + + + + + 8.29 + + + + 4 + 2 + 14.46 + + FRITESSAUS 3 LRR + + 438103 + + + S + 6 + + VAT + + + + + 7.23 + + + + 5 + 1 + 35.00 + + KOFFIE BLIK 3,5KG SNELF + + 666955 + + + S + 6 + + VAT + + + + + 35.00 + + + + 6 + 1 + 35.00 + + KOFFIE 3.5 KG BLIK STAND + + 664871 + + + S + 6 + + VAT + + + + + 35.00 + + + + 7 + 1 + 10.65 + + SUIKERKLONT + + 350257 + + + S + 6 + + VAT + + + + + 10.65 + + + + 8 + 1 + 1.55 + + 1 KG UL BLOKJES + + 350258 + + + S + 6 + + VAT + + + + + 1.55 + + + + 9 + 3 + 14.37 + + BLOCKNOTE A5 + + 999998 + + + S + 6 + + VAT + + + + + 4.79 + + + + 10 + 1 + 8.29 + + CHIPS NAT KLEIN ZAKJES + + 740810 + + + S + 6 + + VAT + + + + + 8.29 + + + + 11 + 2 + 16.58 + + CHIPS PAP KLEINE ZAKJES + + 740829 + + + S + 6 + + VAT + + + + + 8.29 + + + + 12 + 1 + 9.95 + + TR KL PAKJES APPELSAP + + 740828 + + + S + 6 + + VAT + + + + + 9.95 + + + + 13 + 2 + 3.30 + + PK CHOCOLADEMEL + + 740827 + + + S + 6 + + VAT + + + + + 1.65 + + + + 14 + 1 + 10.80 + + KRAT BIER + + 999996 + + + S + 21 + + VAT + + + + + 10.80 + + + + 15 + 1 + 3.90 + + STATIEGELD + + 999995 + + + S + 6 + + VAT + + + + + 3.90 + + + + 16 + 2 + 7.60 + + BLEEK 3 X 750 ML + + 102172 + + + S + 21 + + VAT + + + + + 3.80 + + + + 17 + 2 + 9.34 + + WC PAPIER + + 999994 + + + S + 21 + + VAT + + + + + 4.67 + + + + 18 + 1 + 18.63 + + BALPENNEN 50 ST BLAUW + + 999993 + + + S + 21 + + VAT + + + + + 18.63 + + + + 19 + 6 + 102.12 + + EM FRITUURVET + + 999992 + + + S + 6 + + VAT + + + + + 17.02 + + + + 20 + 6 + -109.98 + + FRITUUR VET 10 KG RETOUR + + 175137 + + + S + 6 + + VAT + + + + + 18.33 + + + diff --git a/src/test/resources/examples/assertions/ubl-0002.xml b/src/test/resources/examples/assertions/ubl-0002.xml new file mode 100644 index 0000000..a8b1736 --- /dev/null +++ b/src/test/resources/examples/assertions/ubl-0002.xml @@ -0,0 +1,542 @@ + + + + + urn:cen.eu:en16931:2017 + 12115118 + 2015-01-09 + 2015-01-09 + 380 + Alle leveringen zijn franco. Alle prijzen zijn incl. BTW. Betalingstermijn: 14 dagen netto. + Prijswijzigingen voorbehouden. Op al onze aanbiedingen, leveringen en overeenkomsten zijn van toepassing in de + algemene verkoop en leveringsvoorwaarden. Gedeponeerd bij de K.v.K. te Amsterdam 25-04-'85##Delivery terms + + EUR + + + + Postbus 7l + Velsen-Noord + 1950 AB + + NL + + + + NL8200.98.395.B.01 + + VAT + + + + De Koksmaat + 57151520 + + + + + + + 10202 + + + POSTBUS 367 + HEEMSKERK + 1960 AJ + + NL + + + + ODIN 59 + + + Dhr. J BLOKKER + + + + + 30 + Deb. 10202 / Fact. 12115118 + + NL57 RABO 0107307510 + + + + 30 + Deb. 10202 / Fact. 12115118 + + NL03 INGB 0004489902 + + + + 20.73 + + 183.23 + 10.99 + + S + 6 + + VAT + + + + + 46.37 + 9.74 + + S + 21 + + VAT + + + + + + 229.60 + 229.60 + 250.33 + 250.33 + + + 1 + 2 + 19.90 + + PATAT FRITES 10MM 10KG + + 166022 + + + S + 6 + + VAT + + + + + 9.95 + + + + 2 + 1 + 9.85 + + PKAAS 50PL. JONG BEL. 1KG + + 661813 + + + S + 6 + + VAT + + + + + 9.85 + + + + 3 + 1 + 8.29 + + POT KETCHUP 3 LT + + 438146 + + + S + 6 + + VAT + + + + + 8.29 + + + + 4 + 2 + 14.46 + + FRITESSAUS 3 LRR + + 438103 + + + S + 6 + + VAT + + + + + 7.23 + + + + 5 + 1 + 35.00 + + KOFFIE BLIK 3,5KG SNELF + + 666955 + + + S + 6 + + VAT + + + + + 35.00 + + + + 6 + 1 + 35.00 + + KOFFIE 3.5 KG BLIK STAND + + 664871 + + + S + 6 + + VAT + + + + + 35.00 + + + + 7 + 1 + 10.65 + + SUIKERKLONT + + 350257 + + + S + 6 + + VAT + + + + + 10.65 + + + + 8 + 1 + 1.55 + + 1 KG UL BLOKJES + + 350258 + + + S + 6 + + VAT + + + + + 1.55 + + + + 9 + 3 + 14.37 + + BLOCKNOTE A5 + + 999998 + + + S + 6 + + VAT + + + + + 4.79 + + + + 10 + 1 + 8.29 + + CHIPS NAT KLEIN ZAKJES + + 740810 + + + S + 6 + + VAT + + + + + 8.29 + + + + 11 + 2 + 16.58 + + CHIPS PAP KLEINE ZAKJES + + 740829 + + + S + 6 + + VAT + + + + + 8.29 + + + + 12 + 1 + 9.95 + + TR KL PAKJES APPELSAP + + 740828 + + + S + 6 + + VAT + + + + + 9.95 + + + + 13 + 2 + 3.30 + + PK CHOCOLADEMEL + + 740827 + + + S + 6 + + VAT + + + + + 1.65 + + + + 14 + 1 + 10.80 + + KRAT BIER + + 999996 + + + S + 21 + + VAT + + + + + 10.80 + + + + 15 + 1 + 3.90 + + STATIEGELD + + 999995 + + + S + 6 + + VAT + + + + + 3.90 + + + + 16 + 2 + 7.60 + + BLEEK 3 X 750 ML + + 102172 + + + S + 21 + + VAT + + + + + 3.80 + + + + 17 + 2 + 9.34 + + WC PAPIER + + 999994 + + + S + 21 + + VAT + + + + + 4.67 + + + + 18 + 1 + 18.63 + + BALPENNEN 50 ST BLAUW + + 999993 + + + S + 21 + + VAT + + + + + 18.63 + + + + 19 + 6 + 102.12 + + EM FRITUURVET + + 999992 + + + S + 6 + + VAT + + + + + 17.02 + + + + 20 + 6 + -109.98 + + FRITUUR VET 10 KG RETOUR + + 175137 + + + S + 6 + + VAT + + + + + 18.33 + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/CCTS_CCT_SchemaModule-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/CCTS_CCT_SchemaModule-2.1.xsd new file mode 100644 index 0000000..2bc034a --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/CCTS_CCT_SchemaModule-2.1.xsd @@ -0,0 +1,769 @@ + + + + + + + + + + + + + + + + UNDT000001 + CCT + Amount. Type + 1.0 + A number of monetary units specified in a currency where the unit of the currency is + explicit or implied. + + Amount + decimal + + + + + + + + UNDT000001-SC2 + SC + Amount Currency. Identifier + The currency of the amount. + Amount Currency + Identification + Identifier + string + Reference UNECE Rec 9, using 3-letter alphabetic codes. + + + + + + + UNDT000001-SC3 + SC + Amount Currency. Code List Version. Identifier + + The VersionID of the UN/ECE Rec9 code list. + Amount Currency + Code List Version + Identifier + string + + + + + + + + + + + + UNDT000002 + CCT + Binary Object. Type + 1.0 + A set of finite-length sequences of binary octets. + Binary Object + binary + + + + + + + + UNDT000002-SC2 + SC + Binary Object. Format. Text + The format of the binary content. + Binary Object + Format + Text + string + + + + + + + UNDT000002-SC3 + SC + Binary Object. Mime. Code + The mime type of the binary object. + Binary Object + Mime + Code + string + + + + + + + UNDT000002-SC4 + SC + Binary Object. Encoding. Code + Specifies the decoding algorithm of the binary object. + Binary Object + Encoding + Code + string + + + + + + + UNDT000002-SC5 + SC + Binary Object. Character Set. Code + The character set of the binary object if the mime type is text. + + Binary Object + Character Set + Code + string + + + + + + + UNDT000002-SC6 + SC + Binary Object. Uniform Resource. Identifier + + The Uniform Resource Identifier that identifies where the binary object is + located. + + Binary Object + Uniform Resource Identifier + Identifier + string + + + + + + + UNDT000002-SC7 + SC + Binary Object. Filename.Text + The filename of the binary object. + Binary Object + Filename + Text + string + + + + + + + + + + + + UNDT000007 + CCT + Code. Type + 1.0 + A character string (letters, figures, or symbols) that for brevity and/or languange + independence may be used to represent or replace a definitive value or text of an attribute together + with relevant supplementary information. + + Code + string + Should not be used if the character string identifies an instance of an object class or + an object in the real world, in which case the Identifier. Type should be used. + + + + + + + + + UNDT000007-SC2 + SC + Code List. Identifier + The identification of a list of codes. + Code List + Identification + Identifier + string + + + + + + + UNDT000007-SC3 + SC + Code List. Agency. Identifier + An agency that maintains one or more lists of codes. + Code List + Agency + Identifier + string + Defaults to the UN/EDIFACT data element 3055 code list. + + + + + + + UNDT000007-SC4 + SC + Code List. Agency Name. Text + The name of the agency that maintains the list of codes. + Code List + Agency Name + Text + string + + + + + + + UNDT000007-SC5 + SC + Code List. Name. Text + The name of a list of codes. + Code List + Name + Text + string + + + + + + + UNDT000007-SC6 + SC + Code List. Version. Identifier + The version of the list of codes. + Code List + Version + Identifier + string + + + + + + + UNDT000007-SC7 + SC + Code. Name. Text + The textual equivalent of the code content component. + Code + Name + Text + string + + + + + + + UNDT000007-SC8 + SC + Language. Identifier + The identifier of the language used in the code name. + Language + Identification + Identifier + string + + + + + + + UNDT000007-SC9 + SC + Code List. Uniform Resource. Identifier + The Uniform Resource Identifier that identifies where the code list is + located. + + Code List + Uniform Resource Identifier + Identifier + string + + + + + + + UNDT000007-SC10 + SC + Code List Scheme. Uniform Resource. Identifier + + The Uniform Resource Identifier that identifies where the code list scheme + is located. + + Code List Scheme + Uniform Resource Identifier + Identifier + string + + + + + + + + + + + + UNDT000008 + CCT + Date Time. Type + 1.0 + A particular point in the progression of time together with the relevant supplementary + information. + + Date Time + string + Can be used for a date and/or time. + + + + + + + + UNDT000008-SC1 + SC + Date Time. Format. Text + The format of the date time content + Date Time + Format + Text + string + + + + + + + + + + + + UNDT000011 + CCT + Identifier. Type + 1.0 + A character string to identify and distinguish uniquely, one instance of an object in + an identification scheme from all other objects in the same scheme together with relevant + supplementary information. + + Identifier + string + + + + + + + + UNDT000011-SC2 + SC + Identification Scheme. Identifier + The identification of the identification scheme. + Identification Scheme + Identification + Identifier + string + + + + + + + UNDT000011-SC3 + SC + Identification Scheme. Name. Text + The name of the identification scheme. + Identification Scheme + Name + Text + string + + + + + + + UNDT000011-SC4 + SC + Identification Scheme Agency. Identifier + + The identification of the agency that maintains the identification + scheme. + + Identification Scheme Agency + Identification + Identifier + string + Defaults to the UN/EDIFACT data element 3055 code list. + + + + + + + UNDT000011-SC5 + SC + Identification Scheme Agency. Name. Text + + The name of the agency that maintains the identification scheme. + + Identification Scheme Agency + Agency Name + Text + string + + + + + + + UNDT000011-SC6 + SC + Identification Scheme. Version. Identifier + + The version of the identification scheme. + Identification Scheme + Version + Identifier + string + + + + + + + UNDT000011-SC7 + SC + Identification Scheme Data. Uniform Resource. Identifier + + The Uniform Resource Identifier that identifies where the identification + scheme data is located. + + Identification Scheme Data + Uniform Resource Identifier + Identifier + string + + + + + + + UNDT000011-SC8 + SC + Identification Scheme. Uniform Resource. Identifier + + The Uniform Resource Identifier that identifies where the identification + scheme is located. + + Identification Scheme + Uniform Resource Identifier + Identifier + string + + + + + + + + + + + + UNDT000012 + CCT + Indicator. Type + 1.0 + A list of two mutually exclusive Boolean values that express the only possible states + of a Property. + + Indicator + string + + + + + + + + UNDT000012-SC2 + SC + Indicator. Format. Text + Whether the indicator is numeric, textual or binary. + Indicator + Format + Text + string + + + + + + + + + + + + UNDT000013 + CCT + Measure. Type + 1.0 + A numeric value determined by measuring an object along with the specified unit of + measure. + + Measure + decimal + + + + + + + + UNDT000013-SC2 + SC + Measure Unit. Code + The type of unit of measure. + Measure Unit + Code + Code + string + Reference UNECE Rec. 20 and X12 355 + + + + + + + UNDT000013-SC3 + SC + Measure Unit. Code List Version. Identifier + + The version of the measure unit code list. + Measure Unit + Code List Version + Identifier + string + + + + + + + + + + + + UNDT000014 + CCT + Numeric. Type + 1.0 + Numeric information that is assigned or is determined by calculation, counting, or + sequencing. It does not require a unit of quantity or unit of measure. + + Numeric + string + + + + + + + + UNDT000014-SC2 + SC + Numeric. Format. Text + Whether the number is an integer, decimal, real number or percentage. + + Numeric + Format + Text + string + + + + + + + + + + + + UNDT000018 + CCT + Quantity. Type + 1.0 + A counted number of non-monetary units possibly including fractions. + Quantity + decimal + + + + + + + + UNDT000018-SC2 + SC + Quantity. Unit. Code + The unit of the quantity + Quantity + Unit Code + Code + string + + + + + + + UNDT000018-SC3 + SC + Quantity Unit. Code List. Identifier + The quantity unit code list. + Quantity Unit + Code List + Identifier + string + + + + + + + UNDT000018-SC4 + SC + Quantity Unit. Code List Agency. Identifier + + The identification of the agency that maintains the quantity unit code + list + + Quantity Unit + Code List Agency + Identifier + string + Defaults to the UN/EDIFACT data element 3055 code list. + + + + + + + UNDT000018-SC5 + SC + Quantity Unit. Code List Agency Name. Text + + The name of the agency which maintains the quantity unit code list. + + Quantity Unit + Code List Agency Name + Text + string + + + + + + + + + + + + UNDT000019 + CCT + Text. Type + 1.0 + A character string (i.e. a finite set of characters) generally in the form of words of + a language. + + Text + string + + + + + + + + UNDT000019-SC2 + SC + Language. Identifier + The identifier of the language used in the content component. + + Language + Identification + Identifier + string + + + + + + + UNDT000019-SC3 + SC + Language. Locale. Identifier + The identification of the locale of the language. + Language + Locale + Identifier + string + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonAggregateComponents-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonAggregateComponents-2.1.xsd new file mode 100644 index 0000000..dc2e4c2 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonAggregateComponents-2.1.xsd @@ -0,0 +1,4166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonBasicComponents-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonBasicComponents-2.1.xsd new file mode 100644 index 0000000..435dd83 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonBasicComponents-2.1.xsd @@ -0,0 +1,5394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonExtensionComponents-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonExtensionComponents-2.1.xsd new file mode 100644 index 0000000..5ea3a39 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonExtensionComponents-2.1.xsd @@ -0,0 +1,235 @@ + + + + + + + + + + + + + A container for all extensions present in the document. + + + + + + + A container for all extensions present in the document. + + + + + + + A single extension for private use. + + + + + + + + + A single extension for private use. + + + + + + + A single extension for private use. + + + + + + + An identifier for the Extension assigned by the creator of the extension. + + + + + + + A name for the Extension assigned by the creator of the extension. + + + + + + + An agency that maintains one or more Extensions. + + + + + + + The name of the agency that maintains the Extension. + + + + + + + The version of the Extension. + + + + + + + A URI for the Agency that maintains the Extension. + + + + + + + A URI for the Extension. + + + + + + + A code for reason the Extension is being included. + + + + + + + A description of the reason for the Extension. + + + + + + + The definition of the extension content. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonSignatureComponents-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonSignatureComponents-2.1.xsd new file mode 100644 index 0000000..027ae35 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CommonSignatureComponents-2.1.xsd @@ -0,0 +1,81 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CoreComponentParameters-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CoreComponentParameters-2.1.xsd new file mode 100644 index 0000000..fbda5b8 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-CoreComponentParameters-2.1.xsd @@ -0,0 +1,73 @@ + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-ExtensionContentDataType-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-ExtensionContentDataType-2.1.xsd new file mode 100644 index 0000000..9df0f4d --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-ExtensionContentDataType-2.1.xsd @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + Any element in any namespace other than the UBL extension + namespace is allowed to be the apex element of an extension. + Only those elements found in the UBL schemas and in the + trees of schemas imported in this module are validated. + Any element for which there is no schema declaration in any + of the trees of schemas passes validation and is not + treated as a schema constraint violation. + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-QualifiedDataTypes-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-QualifiedDataTypes-2.1.xsd new file mode 100644 index 0000000..2d53c97 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-QualifiedDataTypes-2.1.xsd @@ -0,0 +1,78 @@ + + + + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureAggregateComponents-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureAggregateComponents-2.1.xsd new file mode 100644 index 0000000..bea5510 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureAggregateComponents-2.1.xsd @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + This is a single digital signature as defined by the W3C specification. + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureBasicComponents-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureBasicComponents-2.1.xsd new file mode 100644 index 0000000..0858978 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-SignatureBasicComponents-2.1.xsd @@ -0,0 +1,83 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-UnqualifiedDataTypes-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-UnqualifiedDataTypes-2.1.xsd new file mode 100644 index 0000000..8864e6e --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-UnqualifiedDataTypes-2.1.xsd @@ -0,0 +1,554 @@ + + + + + + + + + + UBLUDT000001 + UDT + Amount. Type + 1.0 + A number of monetary units specified using a given unit of currency. + Amount + + + + + + + + UNDT000001-SC2 + SC + Amount. Currency. Identifier + The currency of the amount. + Amount Currency + Identification + Identifier + string + Reference UNECE Rec 9, using 3-letter alphabetic codes. + + + + + + + + + + + UBLUDT000002 + UDT + Binary Object. Type + 1.0 + A set of finite-length sequences of binary octets. + Binary Object + binary + + + + + + + + UNDT000002-SC3 + SC + Binary Object. Mime. Code + The mime type of the binary object. + Binary Object + Mime + Code + string + + + + + + + + + + + UBLUDT000003 + UDT + Graphic. Type + 1.0 + A diagram, graph, mathematical curve, or similar representation. + Graphic + binary + + + + + + + + UNDT000003-SC3 + SC + Graphic. Mime. Code + The mime type of the graphic object. + Graphic + Mime + Code + normalizedString + + + + + + + + + + + UBLUDT000004 + UDT + Picture. Type + 1.0 + A diagram, graph, mathematical curve, or similar representation. + Picture + binary + + + + + + + + UNDT000004-SC3 + SC + Picture. Mime. Code + The mime type of the picture object. + Picture + Mime + Code + normalizedString + + + + + + + + + + + UBLUDT000005 + UDT + Sound. Type + 1.0 + An audio representation. + Sound + binary + + + + + + + + UNDT000005-SC3 + SC + Sound. Mime. Code + The mime type of the sound object. + Sound + Mime + Code + normalizedString + + + + + + + + + + + UBLUDT000006 + UDT + Video. Type + 1.0 + A video representation. + Video + binary + + + + + + + + UNDT000006-SC3 + SC + Video. Mime. Code + The mime type of the video object. + Video + Mime + Code + normalizedString + + + + + + + + + + + UBLUDT000007 + UDT + Code. Type + 1.0 + A character string (letters, figures, or symbols) that for brevity and/or language + independence may be used to represent or replace a definitive value or text of an attribute, + together with relevant supplementary information. + + Code + string + Other supplementary components in the CCT are captured as part of the token and name for + the schema module containing the code list and thus, are not declared as attributes. + + + + + + + + + + + + UBLUDT000008 + UDT + Date Time. Type + 1.0 + A particular point in the progression of time, together with relevant supplementary + information. + + Date Time + string + Can be used for a date and/or time. + + + + + + + + + + + UBLUDT000009 + UDT + Date. Type + 1.0 + One calendar day according the Gregorian calendar. + Date + string + + + + + + + + + + + UBLUDT0000010 + UDT + Time. Type + 1.0 + An instance of time that occurs every day. + Time + string + + + + + + + + + + + UBLUDT0000011 + UDT + Identifier. Type + 1.0 + A character string to identify and uniquely distinguish one instance of an object in an + identification scheme from all other objects in the same scheme, together with relevant + supplementary information. + + Identifier + string + Other supplementary components in the CCT are captured as part of the token and name for + the schema module containing the identifier list and thus, are not declared as attributes. + + + + + + + + + + + + UBLUDT0000012 + UDT + Indicator. Type + 1.0 + A list of two mutually exclusive Boolean values that express the only possible states + of a property. + + Indicator + string + + + + + + + + + + + UBLUDT0000013 + UDT + Measure. Type + 1.0 + A numeric value determined by measuring an object using a specified unit of measure. + + Measure + Type + decimal + + + + + + + + UNDT000013-SC2 + SC + Measure. Unit. Code + The type of unit of measure. + Measure Unit + Code + Code + normalizedString + Reference UNECE Rec. 20 and X12 355 + + + + + + + + + + + UBLUDT0000014 + UDT + Numeric. Type + 1.0 + Numeric information that is assigned or is determined by calculation, counting, or + sequencing. It does not require a unit of quantity or unit of measure. + + Numeric + string + + + + + + + + + + + UBLUDT0000015 + UDT + 1.0 + Value. Type + Numeric information that is assigned or is determined by calculation, counting, or + sequencing. It does not require a unit of quantity or unit of measure. + + Value + string + + + + + + + + + + + UBLUDT0000016 + UDT + 1.0 + Percent. Type + Numeric information that is assigned or is determined by calculation, counting, or + sequencing and is expressed as a percentage. It does not require a unit of quantity or unit of + measure. + + Percent + string + + + + + + + + + + + UBLUDT0000017 + UDT + 1.0 + Rate. Type + A numeric expression of a rate that is assigned or is determined by calculation, + counting, or sequencing. It does not require a unit of quantity or unit of measure. + + Rate + string + + + + + + + + + + + UBLUDT0000018 + UDT + Quantity. Type + 1.0 + A counted number of non-monetary units, possibly including a fractional part. + + Quantity + decimal + + + + + + + + + + + UBLUDT0000019 + UDT + Text. Type + 1.0 + A character string (i.e. a finite set of characters), generally in the form of words of + a language. + + Text + string + + + + + + + + + + + UBLUDT0000020 + UDT + Name. Type + 1.0 + A character string that constitutes the distinctive designation of a person, place, + thing or concept. + + Name + string + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv132-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv132-2.1.xsd new file mode 100644 index 0000000..1d09373 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv132-2.1.xsd @@ -0,0 +1,499 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv141-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv141-2.1.xsd new file mode 100644 index 0000000..a0a098a --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-XAdESv141-2.1.xsd @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-xmldsig-core-schema-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-xmldsig-core-schema-2.1.xsd new file mode 100644 index 0000000..8d19821 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/common/UBL-xmldsig-core-schema-2.1.xsd @@ -0,0 +1,332 @@ + + + + + + + + + ]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-CreditNote-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-CreditNote-2.1.xsd new file mode 100644 index 0000000..eec54a0 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-CreditNote-2.1.xsd @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd new file mode 100644 index 0000000..c1ae3f2 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl new file mode 100644 index 0000000..18c3d1e --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl @@ -0,0 +1,1383 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / + + + + + + *: + + [namespace-uri()=' + + '] + + + + [ + + ] + + + + / + + @ + + + @*[local-name()=' + + ' and namespace-uri()=' + + '] + + + + + + + + + / + + + [ + + ] + + + + /@ + + + + + + + / + + + [ + + ] + + + + /@ + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + U + + U + + + + U. + + n + + + + U. + + _ + + _ + + + + + + + + + + + + + + + + + + + + + + + UBL-T10 + UBL-T10 + + + + + + + + CodesT10 + CodesT10 + + + + + + + + BIIRULES T10 bound to UBL + + + + + + + + + + + + + + BII2-T10-R025 + fatal + + + + [BII2-T10-R025]-Each document level allowance or charge details MUST have an allowance + and charge reason text + + + + + + + + + + + BII2-T10-R043 + fatal + + + + [BII2-T10-R043]-Document level allowances and charges details MUST have allowance and + charge VAT category if the invoice has a VAT total amount + + + + + + + + + + + + + + + + + BII2-T10-R001 + fatal + + + + [BII2-T10-R001]-An invoice MUST have a customization identifier + + + + + + + + + + BII2-T10-R002 + fatal + + + + [BII2-T10-R002]-An invoice MUST have a business profile identifier + + + + + + + + + + BII2-T10-R003 + fatal + + + + [BII2-T10-R003]-An invoice MUST have an invoice identifier + + + + + + + + + + BII2-T10-R004 + fatal + + + + [BII2-T10-R004]-An invoice MUST have an invoice issue date + + + + + + + + + + BII2-T10-R005 + fatal + + + + [BII2-T10-R005]-An invoice MUST specify the currency code for the document + + + + + + + + + + BII2-T10-R006 + fatal + + + + [BII2-T10-R006]-An invoice MUST have a seller name and/or a seller identifier + + + + + + + + + + BII2-T10-R008 + fatal + + + + [BII2-T10-R008]-An invoice MUST have a buyer name and/or a buyer identifier + + + + + + + + + + BII2-T10-R010 + fatal + + + + [BII2-T10-R010]-An invoice MUST have the sum of line amounts + + + + + + + + + + BII2-T10-R011 + fatal + + + + [BII2-T10-R011]-An invoice MUST have the invoice total without VAT + + + + + + + + + + BII2-T10-R012 + fatal + + + + [BII2-T10-R012]-An invoice MUST have the invoice total with VAT (value of purchase) + + + + + + + + + + + BII2-T10-R013 + fatal + + + + [BII2-T10-R013]-An invoice MUST have the amount due for payment + + + + + + + + + + BII2-T10-R014 + fatal + + + + [BII2-T10-R014]-An invoice MUST have at least one invoice line + + + + + + + + + + BII2-T10-R015 + fatal + + + + [BII2-T10-R015]-An invoice MUST specify the VAT total amount, if there are VAT line + amounts + + + + + + + + + + + BII2-T10-R026 + fatal + + + + [BII2-T10-R026]-An invoice MUST contain VAT category details unless VAT total amount is + omitted. + + + + + + + + + + + BII2-T10-R035 + fatal + + + + [BII2-T10-R035]-Invoice total with VAT MUST NOT be negative + + + + + + + + + + BII2-T10-R037 + fatal + + + + [BII2-T10-R037]-Amount due for payment in an invoice MUST NOT be negative + + + + + + + + + + BII2-T10-R044 + fatal + + + + [BII2-T10-R044]-A seller VAT identifier MUST be provided if the invoice has a VAT total + amount + + + + + + + + + + + BII2-T10-R047 + fatal + + + + [BII2-T10-R047]-A buyer VAT identifier MUST be present if the VAT category code is + reverse VAT + + + + + + + + + + + BII2-T10-R048 + fatal + + + + [BII2-T10-R048]-An invoice with a VAT category code of reverse charge MUST NOT contain + other VAT categories. + + + + + + + + + + + BII2-T10-R058 + fatal + + + + [BII2-T10-R058]-Invoice total without VAT MUST be equal to the sum of VAT category + taxable amounts + + + + + + + + + + + + + + + + + BII2-T10-R017 + fatal + + + + [BII2-T10-R017]-Each invoice line MUST have an invoice line identifier + + + + + + + + + + BII2-T10-R018 + fatal + + + + [BII2-T10-R018]-Each invoice line MUST have an invoiced quantity + + + + + + + + + + BII2-T10-R019 + fatal + + + + [BII2-T10-R019]-Each invoice line MUST have a quantity unit of measure + + + + + + + + + + BII2-T10-R020 + fatal + + + + [BII2-T10-R020]-Each invoice line MUST have an invoice line net amount + + + + + + + + + + BII2-T10-R021 + fatal + + + + [BII2-T10-R021]-Each invoice line MUST have an invoice line item name and/or the invoice + line item identifier + + + + + + + + + + + BII2-T10-R032 + fatal + + + + [BII2-T10-R032]-A scheme identifier for the invoice line item registered identifier MUST + be provided if invoice line item registered identifiers are used to identify a product.(e.g. + GTIN) + + + + + + + + + + + BII2-T10-R033 + fatal + + + + [BII2-T10-R033]-A scheme identifier for a invoice line item commodity classification MUST + be provided if invoice line item commodity classification are used to classify an invoice line + item (e.g. CPV or UNSPSC) + + + + + + + + + + + BII2-T10-R034 + fatal + + + + [BII2-T10-R034]-Invoice line item net price MUST NOT be negative + + + + + + + + + + BII2-T10-R046 + fatal + + + + [BII2-T10-R046]-Each invoice line MUST be categorized with the invoice line VAT category + if the invoice has a VAT total amount + + + + + + + + + + + + + + + + + BII2-T10-R023 + fatal + + + + [BII2-T10-R023]-Each invoice period information MUST have an invoice period start date + + + + + + + + + + + BII2-T10-R024 + fatal + + + + [BII2-T10-R024]-Each invoice period information MUST have an invoice period end date + + + + + + + + + + + BII2-T10-R031 + fatal + + + + [BII2-T10-R031]-An invoice period end date MUST be later or equal to an invoice period + start date + + + + + + + + + + + + + + + + + BII2-T10-R039 + fatal + + + + [BII2-T10-R039]-An account identifier MUST be present if payment means type is funds + transfer + + + + + + + + + + + BII2-T10-R040 + fatal + + + + [BII2-T10-R040]-A sellers financial institution identifier MUST be provided if the scheme + of the account identifier is IBAN and the payment means is international bank transfer + + + + + + + + + + + BII2-T10-R041 + fatal + + + + [BII2-T10-R041]-A payment means MUST specify the payment means type + + + + + + + + + + BII2-T10-R042 + fatal + + + + [BII2-T10-R042]-A sellers financial institution identifier scheme MUST be BIC if the + scheme of the account identifier is IBAN and the payment means type is international account + transfer + + + + + + + + + + + + + + + + + BII2-T10-R051 + fatal + + + + [BII2-T10-R051]-Sum of line amounts MUST equal the invoice line net amounts + + + + + + + + + + BII2-T10-R052 + fatal + + + + [BII2-T10-R052]-An invoice total without VAT MUST equal the sum of line amounts plus the + sum of charges on document level minus the sum of allowances on document level + + + + + + + + + + + BII2-T10-R053 + fatal + + + + [BII2-T10-R053]-An invoice total with VAT MUST equal the invoice total without VAT plus + the VAT total amount and the rounding of invoice total + + + + + + + + + + + BII2-T10-R054 + fatal + + + + [BII2-T10-R054]-The sum of allowances at document level MUST be equal to the sum of + document level allowance amounts + + + + + + + + + + + BII2-T10-R055 + fatal + + + + [BII2-T10-R055]-The sum of charges at document level MUST be equal to the sum of document + level charge amounts + + + + + + + + + + + BII2-T10-R056 + fatal + + + + [BII2-T10-R056]-Amount due for payment MUST be equal to the invoice total amount with VAT + minus the paid amounts + + + + + + + + + + + + + + + + + BII2-T10-R027 + fatal + + + + [BII2-T10-R027]-Each VAT category details MUST have a VAT category taxable amount + + + + + + + + + + + BII2-T10-R028 + fatal + + + + [BII2-T10-R028]-Each VAT category details MUST have a VAT category tax amount + + + + + + + + + + BII2-T10-R029 + fatal + + + + [BII2-T10-R029]-Every VAT category details MUST be defined through a VAT category code + + + + + + + + + + + BII2-T10-R030 + fatal + + + + [BII2-T10-R030]-The VAT category percentage MUST be provided if the VAT category code is + standard. + + + + + + + + + + + BII2-T10-R045 + fatal + + + + [BII2-T10-R045]-A VAT exemption reason MUST be provided if the VAT category code is + exempt or reverse charge. + + + + + + + + + + + + + + + + + BII2-T10-R049 + fatal + + + + [BII2-T10-R049]-The invoice total without VAT MUST be equal to the VAT category taxable + amount if the VAT category code is reverse charge + + + + + + + + + + + BII2-T10-R050 + fatal + + + + [BII2-T10-R050]-The VAT category tax amount MUST be zero if the VAT category code is + reverse charge (since there is only one VAT category allowed it follows that the invoice tax + total for reverse charge invoices is zero) + + + + + + + + + + + + + + + + + + + + + + + + CL-T10-R001 + fatal + + + + [CL-T10-R001]-An Invoice MUST be coded with the InvoiceTypeCode code list UNCL D1001 BII2 + subset + + + + + + + + + + + + + + + + + CL-T10-R002 + fatal + + + + [CL-T10-R002]-DocumentCurrencyCode MUST be coded using ISO code list 4217 + + + + + + + + + + + + + + + + CL-T10-R003 + fatal + + + + [CL-T10-R003]-currencyID MUST be coded using ISO code list 4217 + + + + + + + + + + + + + + + + CL-T10-R004 + fatal + + + + [CL-T10-R004]-Country codes in an invoice MUST be coded using ISO code list 3166-1 + + + + + + + + + + + + + + + + + CL-T10-R006 + fatal + + + + [CL-T10-R006]-Payment means in an invoice MUST be coded using UNCL 4461 BII2 subset + + + + + + + + + + + + + + + + + CL-T10-R007 + fatal + + + + [CL-T10-R007]-Invoice tax categories MUST be coded using UNCL 5305 code list BII2 + subset + + + + + + + + + + + + + + + + + CL-T10-R008 + fatal + + + + [CL-T10-R008]-For Mime code in attribute use MIMEMediaType. + + + + + + + + + + + + + + + + CL-T10-R010 + warning + + + + [CL-T10-R010]-Coded allowance and charge reasons SHOULD belong to the UNCL 4465 code list + BII2 subset + + + + + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl new file mode 100644 index 0000000..8b1dc3b --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl @@ -0,0 +1,1243 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + / + + + + + + *: + + [namespace-uri()=' + + '] + + + + [ + + ] + + + + / + + @ + + + @*[local-name()=' + + ' and namespace-uri()=' + + '] + + + + + + + + + / + + + [ + + ] + + + + /@ + + + + + + + / + + + [ + + ] + + + + /@ + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + U + + U + + + + U. + + n + + + + U. + + _ + + _ + + + + + + + + + + + + + + + + + + + + + + + UBL-T10 + UBL-T10 + + + + + + + + CodesT10 + CodesT10 + + + + + + + + OPENPEPPOL T10 bound to UBL + + + + + + + + + + + + + + EUGEN-T10-R012 + fatal + + + + [EUGEN-T10-R012]-An allowance percentage MUST NOT be negative. + + + + + + + + + + EUGEN-T10-R022 + fatal + + + + [EUGEN-T10-R022]-An allowance or charge amount MUST NOT be negative. + + + + + + + + + + EUGEN-T10-R052 + fatal + + + + [EUGEN-T10-R052]-Document level amounts cannot have more than 2 decimals + + + + + + + + + + + + + + + + EUGEN-T10-R029 + fatal + + + + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier attribute + 'UNCL4465'. + + + + + + + + + + + + + + + + + EUGEN-T10-R027 + fatal + + + + [EUGEN-T10-R027]-A country identification code MUST have a list identifier attribute + 'ISO3166-1:Alpha2'. + + + + + + + + + + + + + + + + + EUGEN-T10-R026 + fatal + + + + [EUGEN-T10-R026]-A currency code element MUST have a list identifier attribute + 'ISO4217'. + + + + + + + + + + + + + + + + + EUGEN-T10-R036 + fatal + + + + [EUGEN-T10-R036]-An invoice MUST have a buyer name + + + + + + + + + + EUGEN-T10-R038 + fatal + + + + [EUGEN-T10-R038]-An invoice MUST have a buyer postal address + + + + + + + + + + EUGEN-T10-R040 + warning + + + + [EUGEN-T10-R040]-A customer SHOULD provide information about its legal entity + information + + + + + + + + + + + + + + + + + EUGEN-T10-R034 + fatal + + + + [EUGEN-T10-R034]-An delivery location identifier MUST have a scheme identifier + attribute. + + + + + + + + + + + + + + + + + EUGEN-T10-R033 + fatal + + + + [EUGEN-T10-R033]-A document type code MUST have a list identifier attribute 'UNCL1001'. + + + + + + + + + + + + + + + + + EUGEN-T10-R023 + fatal + + + + [EUGEN-T10-R023]-An endpoint identifier MUST have a scheme identifier attribute. + + + + + + + + + + + + + + + + + EUGEN-T10-R031 + fatal + + + + [EUGEN-T10-R031]-A financial account identifier MUST have a scheme identifier + attribute. + + + + + + + + + + + + + + + + + EUGEN-T10-R044 + fatal + + + + [EUGEN-T10-R044]-If the tax currency code is different from the document currency code, + the tax exchange rate MUST be provided + + + + + + + + + + + EUGEN-T10-R047 + warning + + + + [EUGEN-T10-R047]- An invoice should not contain empty elements + + + + + + + + + + EUGEN-T10-R053 + fatal + + + + [EUGEN-T10-R053]- An invoice must have an Invoice type code + + + + + + + + + + + + + + + + EUGEN-T10-R025 + fatal + + + + [EUGEN-T10-R025]-An invoice type code MUST have a list identifier attribute 'UNCL1001'. + + + + + + + + + + + + + + + + + EUGEN-T10-R054 + warning + + + + [EUGEN-T10-R054]-A party legal entity company identifier SHOULD have a scheme identifier + attribute. + + + + + + + + + + + + + + + + + EUGEN-T10-R024 + fatal + + + + [EUGEN-T10-R024]-A party identifier MUST have a scheme identifier attribute. + + + + + + + + + + + + + + + + EUGEN-T10-R004 + warning + + + + [EUGEN-T10-R004]-If the payment means are international account transfer and the account + id is IBAN then the financial institution should be identified by using the BIC id. + + + + + + + + + + + + + + + + + EUGEN-T10-R028 + fatal + + + + [EUGEN-T10-R028]-A payment means code MUST have a list identifier attribute 'UNCL4461'. + + + + + + + + + + + + + + + + + EUGEN-T10-R035 + fatal + + + + [EUGEN-T10-R035]-An invoice MUST have a seller name + + + + + + + + + + EUGEN-T10-R037 + fatal + + + + [EUGEN-T10-R037]-An invoice MUST have a seller postal address + + + + + + + + + + EUGEN-T10-R039 + warning + + + + [EUGEN-T10-R039]-A supplier SHOULD provide information about its legal entity + information + + + + + + + + + + + EUGEN-T10-R041 + warning + + + + [EUGEN-T10-R041]-The VAT identifier for the supplier SHOULD be prefixed with country code + for companies with VAT registration in EU countries + + + + + + + + + + + + + + + + + EUGEN-T10-R008 + fatal + + + + [EUGEN-T10-R008]-For each tax subcategory the category ID and the applicable tax + percentage MUST be provided. + + + + + + + + + + + + + + + + + EUGEN-T10-R032 + fatal + + + + [EUGEN-T10-R032]-A tax category identifier MUST have a scheme identifier attribute + 'UNCL5305'. + + + + + + + + + + + + + + + + + EUGEN-T10-R045 + fatal + + + + [EUGEN-T10-R045]-Tax exchange rate MUST specify the calculation rate and the operator + code. + + + + + + + + + + + + + + + + + EUGEN-T10-R043 + fatal + + + + [EUGEN-T10-R043]-The total tax amount MUST equal the sum of tax amounts per category. + + + + + + + + + + + EUGEN-T10-R049 + fatal + + + + [EUGEN-T10-R049]- Total tax amount cannot have more than 2 decimals. + + + + + + + + + + + + + + + + EUGEN-T10-R050 + fatal + + + + [EUGEN-T10-R050]- Tax subtotal amounts cannot have more than 2 decimals. + + + + + + + + + + EUGEN-T10-R051 + fatal + + + + [EUGEN-T10-R051]-Document level amounts cannot have more than 2 decimals + + + + + + + + + + EUGEN-T10-R042 + fatal + + + + [EUGEN-T10-R042]-The tax amount per category MUST be the taxable amount multiplied by the + category percentage. + + + + + + + + + + + EUGEN-T10-R046 + fatal + + + + [EUGEN-T10-R046]-If the tax currency code is different from the document currency code, + each tax subtotal has to include the tax amount in both currencies + + + + + + + + + + + + + + + + + EUGEN-T10-R030 + fatal + + + + [EUGEN-T10-R030]-A unit code attribute MUST have a unit code list identifier attribute + 'UNECERec20'. + + + + + + + + + + + + + + + + + EUGEN-T10-R048 + fatal + + + + [EUGEN-T10-R048]-Document level amounts cannot have more than 2 decimals + + + + + + + + + + + + + + + + + + + + + + + OP-T10-R001 + fatal + + + + [OP-T10-R001]-Contract document type code MUST be coded using UNCL 1001 list BII2 + subset. + + + + + + + + + + + + + + + + + OP-T10-R002 + fatal + + + + [OP-T10-R002]-An Endpoint Identifier Scheme MUST be from the list of PEPPOL Party + Identifiers described in the "PEPPOL Policy for using Identifiers". + + + + + + + + + + + + + + + + + OP-T10-R003 + fatal + + + + [OP-T10-R003]-An Party Identifier Scheme MUST be from the list of PEPPOL Party + Identifiers described in the "PEPPOL Policy for using Identifiers". + + + + + + + + + + + + + + + + + OP-T10-R004 + fatal + + + + [OP-T10-R004]-A payee account identifier scheme MUST be from the Account ID PEPPOL code + list + + + + + + + + + + + + + + + + + OP-T10-R006 + fatal + + + + [OP-T10-R006]-Unit code MUST be coded according to the UN/ECE Recommendation 20 + + + + + + + + + + + + + + + + + OP-T10-R008 + fatal + + + + [OP-T10-R008]-A Party Company Identifier Scheme MUST be from the list of PEPPOL Party + Identifiers described in the "PEPPOL Policy for using Identifiers". + + + + + + + + + + + + + + + + + OP-T10-R009 + fatal + + + + [OP-T10-R009]-TaxCurrencyCode MUST be coded using ISO code list 4217 + + + + + + + + + + + + + + + + OP-T10-R010 + fatal + + + + [OP-T10-R010]-SourceCurrencyCode MUST be coded using ISO code list 4217 + + + + + + + + + + + + + + + + OP-T10-R011 + fatal + + + + [OP-T10-R011]-TargetCurrencyCode MUST be coded using ISO code list 4217 + + + + + + + + + + diff --git a/src/test/resources/examples/repository/resources/eRechnung/default-report.xsl b/src/test/resources/examples/repository/resources/eRechnung/default-report.xsl new file mode 100644 index 0000000..1d3b383 --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/default-report.xsl @@ -0,0 +1,756 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + false + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unexpected result from schematron validation - there is no + svrl:schematron-output element! + + + + + + + + + + + + + + + + + + + + + + + error + warning + information + warning + error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dies ist das zentrale Template des Skripts. Angewandt auf ein + report-Dokument ergänzt es dieses um eine Handlungsempfehlung in Form eines + accept + oder reject Elements. + + + + + + + + reject + reject + accept + + + + + + + + + + + Ermittelt für eine während der Validierung ausgegebene Fehlernachricht deren + Fehlerlevel (error, warning, information) gemäß der + benutzerspezifischen Qualifizierung. + + Jede Fehlernachricht hat im Rahmen der Validierung ein solches Fehlerlevel + erhalten (siehe Attribut @level). Im Regelfall entspricht die + benutzerspezifische Qualifizierung unverändert diesem Level. Nutzer können jedoch im + Rahmen der Bewertung eigene Qualifizierungen vereinbaren und in dem als Parameter + + übergebenen + assessment + Element für bestimmte, anhand des Fehlercodes identifizierten Fehlermeldungen eine + eigene Qualifizierung als customLevel festlegen. + + Dies kann z. B. genutzt werden, um einen error, der ansonsten zur + Rückweisung der Nachricht führen würde, zumindest zeitweilig als + warning + zu qualifizieren, so dass eine entsprechende + Dokumenteninstanz trotz einer Warnung angenommen und verarbeitet würde. + + Die Funktion prüft für eine Fehlernachricht, ob deren @code Attribut + Bestandteil der für ein bestimmtes customLevel des + + Parameters angegebenen Fehlercodes ist. + Falls ja, dann gilt das jeweilige customLevel. Andernfalls wird der im + Rahmen der Validierung ermittelte Fehlerlevel unverändert übernommen. + + + Eine im Rahmen der Validierung ausgegebene + Fehlernachricht + + + + + + + + + + + + + + + + + + + + + + + + + + + Generiert das head Element eines eingebetteten HTML Dokuments, + welches den Prüf- und Bewertungsbericht visualisiert und die Handlungsempfehlung + begründet + + + + + + Prüfbericht + + + + + +

Prüfbericht

+ + + + + + + + + + + + + + + + + + +
+ + + + + Generiert am Beginn eines eingebetteten HTML Dokuments, welches den Prüf- und + Bewertungsbericht visualisiert und die Handlungsempfehlung begründet, eine Übersicht + mit Metadaten des geprüften Dokuments. + + + + + + + + + + + + Generiert am Ende eines eingebetteten HTML Dokuments, welches den Prüf- und + Bewertungsbericht visualisiert und die Handlungsempfehlung begründet, eine Übersicht + mit Metadaten zum Prüfmodul. + + + + +

+ Dieser Prüfbericht wurde erstellt mit + + . +

+
+ + + + Generiert in dem eingebetetteten HTML Dokument eine Tabelle mit den während der + Validierung ausgegebenen Daten. + + + + +

Übersicht der Validierungsergebnisse:

+ + + + + + + + + + + + + + + + + + + + +
PrüfschrittFehlerWarnungenInformationen
+ + ( + + ) + + + + + + +
+ +

Validierungsergebnisse im Detail:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PosCodeAdj. Grad (Grad)Text
+ + + + + + + + + + +
+ + Pfad: + + + Zeile: + + + Spalte: + +
+
+ + + + Generiert in dem eingebetteten HTML Dokument eine Aussage zur Konformität des + geprüften Dokuments zu den formalen Vorgaben. + + + + + + + + +

+ Konformitätsprüfung: + Das geprüfte Dokument enthält + + + weder Fehler noch Warnungen. Es ist konform zu den formalen Vorgaben. + + + + nicht konform + zu den formalen Vorgaben. + + +

+
+ +

+ Konformitätsprüfung: + Das geprüfte Dokument entspricht keinen zulässigen Dokumenttyp und ist damit + nicht konform + zu den formalen Vorgaben. +

+
+
+ +
+ + + + Generiert in dem eingebetteten HTML Dokument die Aussage zur + Handlungsempfehlung. + + + + + + + + +

Bewertung: Es wird empfohlen das Dokument zurückzuweisen.

+
+ +

Bewertung: Es wird empfohlen das Dokument anzunehmen und weiter zu verarbeiten.

+
+ +

Bewertung: Es wird empfohlen das Dokument anzunehmen und zu verarbeiten, da die + vorhandenen Fehler derzeit toleriert werden. +

+
+ +

Bewertung: Es wird empfohlen das Dokument zurückzuweisen.

+
+
+
+ + + + +

+ Inhalt des Rechnungsdokuments: +

+ + +
+
+ + + + Eine Element wird als eine Zeile in einer Tabelle visualisiert. Die erste Spalte + enthält die Zeilennummer, die zweite Attribute und Text des Elements + + + + + + + + + + + + + + + + + + + + + + Ein Textbereich (in der Zeile des Elements) + + + +
+ +
+
+ + +
+ [ … ] +
+
+ + + + + + Ein Attributbereich (in der Zeile des Elements) + + + +
+ +
+
+ + +
\ No newline at end of file diff --git a/src/test/resources/examples/repository/resources/eRechnung/report.xsl b/src/test/resources/examples/repository/resources/eRechnung/report.xsl new file mode 100644 index 0000000..f4f03fb --- /dev/null +++ b/src/test/resources/examples/repository/resources/eRechnung/report.xsl @@ -0,0 +1,607 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unexpected result from schematron validation - there is no svrl:schematron-output element! + + + + + + + + + + + + + + + + + error + warning + information + warning + error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + step_ + + + + + + + + + + message_ + + + + + + + + + + + + + + + Dies ist das zentrale Template des Skripts. Angewandt auf ein + validationReport-Dokument, und unter Nutzung des Parameters wird eine Handlungsempfehlung in Form eines + accept oder reject Elements erstellt, welches eine + Begründung der jeweiligen Empfehlung enthalten kann. + Das Template realisiert eine Funktion f:validationReport, assessment → + suggestion + + + + + + + + + + + + + + + + + + + + + Ermittelt für eine während der Validierung ausgegebene Fehlernachricht deren + Fehlerlevel (error, warning, information) gemäß der + benutzerspezifischen Qualifizierung. + Jede Fehlernachricht hat im Rahmen der Validierung ein solches Fehlerlevel + erhalten (siehe Attribut @level). Im Regelfall entspricht die + benutzerspezifische Qualifizierung unverändert diesem Level. Nutzer können jedoch im + Rahmen der Bewertung eigene Qualifizierungen vereinbaren und in dem als Parameter + übergebenen assessment + Element für bestimmte, anhand des Fehlercodes identifizierten Fehlermeldungen eine + eigene Qualifizierung als customLevel festlegen. + Dies kann z. B. genutzt werden, um einen error, der ansonsten zur + Rückweisung der Nachricht führen würde, zumindest zeitweilig als + warning zu qualifizieren, so dass eine entsprechende + Dokumenteninstanz trotz einer Warnung angenommen und verarbeitet würde. + Die Funktion prüft für eine Fehlernachricht, ob deren @code Attribut + Bestandteil der für ein bestimmtes customLevel des Parameters angegebenen Fehlercodes ist. + Falls ja, dann gilt das jeweilige customLevel. Andernfalls wird der im + Rahmen der Validierung ermittelte Fehlerlevel unverändert übernommen. + + Eine im Rahmen der Validierung ausgegebene + Fehlernachricht + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generiert das head Element eines eingebetteten HTML Dokuments, + welches den Prüf- und Bewertungsbericht visualisiert und die Handlungsempfehlung + begründet + + + + + Pruefbericht der KoSIT + + + + + + + Generiert die Überschrift des eines eingebetteten HTML Dokuments, welches den + Prüf- und Bewertungsbericht visualisiert und die Handlungsempfehlung + begründet + + + +

Prüfbericht der KoSIT

+
+ + + + Generiert am Beginn eines eingebetteten HTML Dokuments, welches den Prüf- und + Bewertungsbericht visualisiert und die Handlungsempfehlung begründet, eine Übersicht + mit Metadaten des geprüften Dokuments. + + + +

+ Angaben zum geprüften Dokument +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Prüfbericht Nr. + +
Dokument: + +
Szenario: + +
Zeitpunkt: + +
Validierungsschritte:FehlerWarnungInformation
+ + + + + + + + + +
+
+ + + + Generiert am Ende eines eingebetteten HTML Dokuments, welches den Prüf- und + Bewertungsbericht visualisiert und die Handlungsempfehlung begründet, eine Übersicht + mit Metadaten zum Prüfmodul. + + + +

+ Erstellt mit: + + für das InstructionSet + + + + vom + + . +

+
+ + + + Generiert in dem eingebetetteten HTML Dokument eine Tabelle mit den während der + Validierung ausgegebenen Daten. + + + + + + + + + + +
+
+ + + + Generiert in der HTML-Tabelle der Validierungsnachtichten in dem eingebetteten + HTML Dokument dn Tabellenkopf + + + + + + Pos + Code + CustomLevel (Level) + Step + Text + + + + + + + Generiert in der HTML-Tabelle der Validierungsnachtichten in dem eingebetteten + HTML Dokument eine oder mehrere Zeilen pro Validierungsnachricht + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Generiert in dem eingebetteten HTML Dokument eine Aussage zur Konformität des + geprüften Dokuments zu den formalen Vorgaben. + + + + + +

+ Konformitätsprüfung: + Das geprüfte Dokument enthält + + + weder Fehler noch Warnungen. Es ist konform zu den formalen Vorgaben. + + + + nicht konform + zu den formalen Vorgaben. + + +

+
+ + + + Generiert in dem eingebetteten HTML Dokument die Aussage zur + Handlungsempfehlung. + + + + + +

+ Bewertung: + + + Es wird empfohlen das Dokument anzunehmen un weiter zu verarbeiten. + + + Es wird empfohlen das Dokument anzunehmen und zu verarbeiten, da die vorhandenen Fehler derzeit toleriert werden. + + + Es wird empfohlen das Dokument zurückzuweisen. + + +

+
+ + +
\ No newline at end of file diff --git a/src/test/resources/examples/results/report.xml b/src/test/resources/examples/results/report.xml new file mode 100644 index 0000000..ed8de55 --- /dev/null +++ b/src/test/resources/examples/results/report.xml @@ -0,0 +1,330 @@ + + + + + + KoSIT POC + + 2017-09-01T13:13:59.055+02:00 + + + SHA-256 + 4exhW9EJxAbhlZLHZ3mYZ3/hWGG5e6mIpiTAlGTpQ7s= + + + /C:/Developer/source/init/eRechnung-Check/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml + + + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + [CL-T10-R010]-Coded allowance and charge reasons SHOULD belong to the UNCL 4465 code list BII2 subset + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + [EUGEN-T10-R026]-A currency code element MUST have a list identifier attribute 'ISO4217'. + + + [EUGEN-T10-R041]-The VAT identifier for the supplier SHOULD be prefixed with country code for companies + with VAT registration in EU countries + + + [EUGEN-T10-R054]-A party legal entity company identifier SHOULD have a scheme identifier attribute. + + + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier attribute 'UNCL4465'. + + + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier attribute 'UNCL4465'. + + + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier attribute 'UNCL4465'. + + + + + + + + + Pruefbericht der KoSIT + + + +

Prüfbericht der KoSIT

+

Angaben zum geprüften Dokument

+ + + + + + + + + + + + + + + + + + +
Dokument: + /C:/Developer/source/init/eRechnung-Check/src/test/resources/examples/UBLReady/UBLReady_EU_UBL-NL_20170102_FULL.xml +
Szenario: +
Zeitpunkt:1.9.2017 13:13:59
Validierungsschritte:FehlerWarnungInformation
+

Konformitätsprüfung:Das geprüfte Dokument enthält 4 Fehler / 3 + Warnungen. Es ist nicht konform zu den formalen Vorgaben. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PosCodeCustomLevel (Level)StepText
1CL-T10-R010warning + [CL-T10-R010]-Coded allowance and charge reasons SHOULD belong to the UNCL 4465 + code list BII2 subset +
+ +
2EUGEN-T10-R026error + [EUGEN-T10-R026]-A currency code element MUST have a list identifier attribute + 'ISO4217'. +
+ +
3EUGEN-T10-R041warning + [EUGEN-T10-R041]-The VAT identifier for the supplier SHOULD be prefixed with + country code for companies with VAT registration in EU countries +
+ +
4EUGEN-T10-R054warning + [EUGEN-T10-R054]-A party legal entity company identifier SHOULD have a scheme + identifier attribute. +
+ +
5EUGEN-T10-R029error + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier + attribute 'UNCL4465'. +
+ +
6EUGEN-T10-R029error + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier + attribute 'UNCL4465'. +
+ +
7EUGEN-T10-R029error + [EUGEN-T10-R029]-An allowance charge reason code MUST have a list identifier + attribute 'UNCL4465'. +
+ +
+

Bewertung:Es wird empfohlen das Dokument zurückzuweisen. +

+

Erstellt mit: KoSIT POC für das InstructionSet + + vom . +

+ + +
+
+
+
\ No newline at end of file diff --git a/src/test/resources/examples/versioning/scenarios-base.xml b/src/test/resources/examples/versioning/scenarios-base.xml new file mode 100644 index 0000000..1673d90 --- /dev/null +++ b/src/test/resources/examples/versioning/scenarios-base.xml @@ -0,0 +1,66 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + + + default + resources/eRechnung/report.xsl + + + +
diff --git a/src/test/resources/examples/versioning/scenarios-increment.xml b/src/test/resources/examples/versioning/scenarios-increment.xml new file mode 100644 index 0000000..c656458 --- /dev/null +++ b/src/test/resources/examples/versioning/scenarios-increment.xml @@ -0,0 +1,66 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + + + default + resources/eRechnung/report.xsl + + + +
diff --git a/src/test/resources/examples/versioning/scenarios-newfeature.xml b/src/test/resources/examples/versioning/scenarios-newfeature.xml new file mode 100644 index 0000000..fc8c9c5 --- /dev/null +++ b/src/test/resources/examples/versioning/scenarios-newfeature.xml @@ -0,0 +1,60 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + toTest + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + +
diff --git a/src/test/resources/examples/versioning/scenarios-newversion.xml b/src/test/resources/examples/versioning/scenarios-newversion.xml new file mode 100644 index 0000000..694f75a --- /dev/null +++ b/src/test/resources/examples/versioning/scenarios-newversion.xml @@ -0,0 +1,60 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + toTest + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/UBL-2.1/xsl/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report.xsl + + + + +
diff --git a/src/test/resources/invalid/scenarios-illformed.xml b/src/test/resources/invalid/scenarios-illformed.xml new file mode 100644 index 0000000..b7d5569 --- /dev/null +++ b/src/test/resources/invalid/scenarios-illformed.xml @@ -0,0 +1,90 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + XMeld 2.1 + http://www.osci.de/xmeld21 + /xmeld:* + + + XML Schema von XMeld 2.1 (aggregiert) + resources/xmeld21/xmeld-nachrichten.xsd + + + + + XInneres Prüfregeln + resources/xmeld21/xinneres-pruefregeln.xsl + + + + + Default Report + resources/default/report.xsl + + + + + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + + resources/eRechnung/report-erechnung.xsl + + EUGEN-T110-R019 + + + + +
diff --git a/src/test/resources/invalid/scenarios-invalid.xml b/src/test/resources/invalid/scenarios-invalid.xml new file mode 100644 index 0000000..9ef90e1 --- /dev/null +++ b/src/test/resources/invalid/scenarios-invalid.xml @@ -0,0 +1,87 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für + mögliche weitergehende Prüfungen mit Schematron. +

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + XMeld 2.1 + http://www.osci.de/xmeld21 + /xmeld:* + + + + XInneres Prüfregeln + resources/xmeld21/xinneres-pruefregeln.xsl + + + + + Default Report + resources/default/report.xsl + + + + + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + + resources/eRechnung/report-erechnung.xsl + + EUGEN-T110-R019 + + + + +
diff --git a/src/test/resources/valid/report.xml b/src/test/resources/valid/report.xml new file mode 100644 index 0000000..ce52c82 --- /dev/null +++ b/src/test/resources/valid/report.xml @@ -0,0 +1,101 @@ + + + + + + + Prüfmodul der KoSIT POC + + + 2017-08-17T12:00:00 + + + + fake + 0x0c + + ABHanAZR_AllesKorrekt.xml + + + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + resources/eRechnung/report-erechnung.xsl + + + + + + 123 + ABC GmbH + + + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + + + openPEPPOL Rules for Invoice + ../resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/OPENPEPPOL-UBL-T10.xsl + + [EUGEN-T110-R025]-UBLVersionID must be 2.1 + + + + + + EUGEN-T110-R024 + + + ... + + + + + + diff --git a/src/test/resources/valid/scenarios.xml b/src/test/resources/valid/scenarios.xml new file mode 100644 index 0000000..426e90c --- /dev/null +++ b/src/test/resources/valid/scenarios.xml @@ -0,0 +1,96 @@ + + + + + XInneres + 2017-08-08 + +

Prüft XInneres Nachrichten anhand der von uns offiziell herausgegebenen XML Schemata und Beispielen für mögliche weitergehende Prüfungen mit Schematron.

+

Prüft elektronische Rechnungen im Format UBL 2.1

+
+ + + XMeld 2.1 + http://www.osci.de/xmeld21 + /xmeld:* + + + XML Schema von XMeld 2.1 (aggregiert) + resources/xmeld21/xmeld-nachrichten.xsd + + + + + XInneres Prüfregeln + resources/xmeld21/xinneres-pruefregeln.xsl + + + + + Default Report + resources/default/report.xsl + + + + + + UBL 2.1 Invoice + urn:oasis:names:specification:ubl:schema:xsd:Invoice-2 + /invoice:Invoice + + + + UBL 2.1 Invoice + resources/eRechnung/UBL-2.1/xsdrt/maindoc/UBL-Invoice-2.1.xsd + + + + + BII Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/BIIRULES-UBL-T10.xsl + + + + + openPEPPOL Rules for Invoice + resources/eRechnung/BIS2.0-VA-V3.4.0/XSLT/OPENPEPPOL-UBL-T10.xsl + + + + + Report für eRechnung + + resources/eRechnung/report-erechnung.xsl + + EUGEN-T110-R019 + + + + + + default + resources/eRechnung/report.xsl + + + +