From 6698e6b8653c00486aae2ec699d99f3905dc8119 Mon Sep 17 00:00:00 2001 From: Marija Stojanovic Date: Wed, 27 Aug 2025 13:15:59 +0000 Subject: [PATCH 1/6] Resolve "Surefire Test Error running de.kosit.validationtool.impl.xml.RemoteResolvingStrategyTest fails without http.proxy setting" --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index 7214bfe..174abe0 100644 --- a/pom.xml +++ b/pom.xml @@ -464,6 +464,12 @@ maven-surefire-plugin 3.5.3 + + + java.net.useSystemProxies + true + + -Dfile.encoding=UTF-8 ${jacocoSurefire} From 7a7712188d8fe9830503ac726850a1bf8f9bb095 Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Wed, 27 Aug 2025 16:21:12 +0200 Subject: [PATCH 2/6] WiP Sysout debugging --- .../validationtool/cmd/CommandlineApplicationTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java index adfdec3..cd0cf45 100644 --- a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java +++ b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java @@ -76,11 +76,17 @@ public class CommandlineApplicationTest { final String[] args = { "-?" }; CommandLineApplication.mainProgram(args); assertThat(CommandLine.getErrorOutput()).isEmpty(); + log.warn("Philip1"); checkForHelp(CommandLine.getOutputLines()); + log.warn("Philip2"); } private static void checkForHelp(final List outputLines) { assertThat(outputLines.size()).isPositive(); + log.warn("!!!!"); + for (final String s : outputLines) + log.warn(s); + log.warn("!!!"); assertThat(outputLines.stream().filter(l -> l.startsWith("Usage: KoSIT Validator"))).hasSize(1); } From a8a3fd100cd7eeee0475ab7d7bfb12528edc3312 Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Wed, 27 Aug 2025 17:08:19 +0200 Subject: [PATCH 3/6] Checking only for "Usage:" but as a constant; No ANSI codes! --- .../de/kosit/validationtool/cmd/CommandLineOptions.java | 8 ++++---- .../validationtool/cmd/CommandlineApplicationTest.java | 8 +------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java index 6381ecf..99cab94 100644 --- a/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java +++ b/src/main/java/de/kosit/validationtool/cmd/CommandLineOptions.java @@ -20,12 +20,10 @@ import java.nio.file.Path; import java.util.List; import java.util.concurrent.Callable; +import de.kosit.validationtool.cmd.CommandLineApplication.Level; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; - -import de.kosit.validationtool.cmd.CommandLineApplication.Level; - import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; import picocli.CommandLine.Help.Visibility; @@ -38,10 +36,12 @@ import picocli.CommandLine.Parameters; * @author Andreas Penski */ @Command(description = "Structural and semantic validation of xml files", name = "KoSIT Validator", mixinStandardHelpOptions = false, - separator = " ") + separator = " ", synopsisHeading = CommandLineOptions.SYNOSIS_HEADING) @Getter public class CommandLineOptions implements Callable { + static final String SYNOSIS_HEADING = "Usage: "; + /** * @author Andreas Penski */ diff --git a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java index cd0cf45..782d401 100644 --- a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java +++ b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java @@ -76,18 +76,12 @@ public class CommandlineApplicationTest { final String[] args = { "-?" }; CommandLineApplication.mainProgram(args); assertThat(CommandLine.getErrorOutput()).isEmpty(); - log.warn("Philip1"); checkForHelp(CommandLine.getOutputLines()); - log.warn("Philip2"); } private static void checkForHelp(final List outputLines) { assertThat(outputLines.size()).isPositive(); - log.warn("!!!!"); - for (final String s : outputLines) - log.warn(s); - log.warn("!!!"); - assertThat(outputLines.stream().filter(l -> l.startsWith("Usage: KoSIT Validator"))).hasSize(1); + assertThat(outputLines.stream().filter(l -> l.startsWith(CommandLineOptions.SYNOSIS_HEADING))).hasSize(1); } @Test From 122b647853f21cd629ed44d65500c32720bc6d37 Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Wed, 27 Aug 2025 17:30:08 +0200 Subject: [PATCH 4/6] Resolve #129 - Api Doc Updates --- docs/api.md | 102 ++++++++++-------- pom.xml | 2 +- .../docs/MiscDocExampleCodes.java | 51 +++++++++ .../validationtool/docs/MyValidator.java | 31 ++++++ .../validationtool/docs/StandardExample.java | 54 ++++++++++ 5 files changed, 197 insertions(+), 43 deletions(-) create mode 100644 src/test/java/de/kosit/validationtool/docs/MiscDocExampleCodes.java create mode 100644 src/test/java/de/kosit/validationtool/docs/MyValidator.java create mode 100644 src/test/java/de/kosit/validationtool/docs/StandardExample.java diff --git a/docs/api.md b/docs/api.md index b26d428..caa93fe 100644 --- a/docs/api.md +++ b/docs/api.md @@ -12,8 +12,8 @@ Then you can declare the dependency as follows: ```xml - de.kosit - validationtool + org.kosit + validator ${validator.version} ``` @@ -22,10 +22,12 @@ Then you can declare the dependency as follows: ```js dependencies { - compile group: 'de.kosit', name: 'validationtool', version: '1.1.0' + compile group: 'org.kosit', name: 'validator', version: '1.5.1' } ``` +Hint: prior to v1.5.1 the group ID was `de.kosit` and the artifact ID was `validationtool`. + ## Usage Prerequisite for use is a valid [scenario definition](configurations.md) and the a folder with all necessary artifacts for validation (repository) either on the filesystem or on the classpath. @@ -33,34 +35,39 @@ Prerequisite for use is a valid [scenario definition](configurations.md) and the The following example demonstrates loading scenario.xml and whole configuration from classpath and validating one XML document: ```java -package org.kosit.validator.example; +package de.kosit.validationtool.docs; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; +import org.w3c.dom.Document; + import de.kosit.validationtool.api.Check; import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.api.Result; import de.kosit.validationtool.impl.DefaultCheck; -import org.w3c.dom.Document; +import de.kosit.validationtool.impl.xml.ProcessorProvider; +/** + * Example code that is used in the docs/api.md file + */ public class StandardExample { - public void run(Path testDocument) throws URISyntaxException { + public void run(final Path testDocument) throws URISyntaxException { // Load scenarios.xml from classpath - URL scenarios = this.getClass().getClassLoader().getResource("scenarios.xml"); + final URL scenarios = this.getClass().getClassLoader().getResource("examples/simple/scenarios-with-relative-paths.xml"); // Load the rest of the specific Validator configuration from classpath - Configuration config = Configuration.load(scenarios.toURI()).build(); + final Configuration config = Configuration.load(scenarios.toURI()).build(ProcessorProvider.getProcessor()); // Use the default validation procedure - Check validator = new DefaultCheck(config); + final Check validator = new DefaultCheck(config); // Validate a single document - Input document = InputFactory.read(testDocument); + final Input document = InputFactory.read(testDocument); // Get Result including information about the whole validation - Result report = validator.checkInput(document); + final Result report = validator.checkInput(document); System.out.println("Is processing succesful=" + report.isProcessingSuccessful()); // Get report document if processing was successful Document result = null; @@ -70,13 +77,16 @@ public class StandardExample { // continue processing results... } - public static void main(String[] args) throws Exception { + public static void main(final String[] args) throws Exception { + // Use e.g. "src/test/resources/examples/simple/input/foo.xml" + if (args.length == 0) { + throw new IllegalStateException("Provide a test document filename on the commandline"); + } // Path of document for validation - Path testDoc = Paths.get(args[0]); - StandardExample example = new StandardExample(); + final Path testDoc = Paths.get(args[0]); + final StandardExample example = new StandardExample(); // run example validation example.run(testDoc); - } } ``` @@ -134,26 +144,36 @@ Instead of pre-configured [scenario files](configurations.md) it is possible to A simple configuration looks like this: ```java -import static de.kosit.validationtool.config.ConfigurationBuilder.*; -import de.kosit.validationtool.api.Configuration; -import java.net.URI; -import java.nio.file.Path; +package de.kosit.validationtool.docs; +import static de.kosit.validationtool.config.ConfigurationBuilder.fallback; +import static de.kosit.validationtool.config.ConfigurationBuilder.report; +import static de.kosit.validationtool.config.ConfigurationBuilder.scenario; +import static de.kosit.validationtool.config.ConfigurationBuilder.schema; +import static de.kosit.validationtool.config.ConfigurationBuilder.schematron; + +import java.net.URI; +import java.nio.file.Paths; + +import de.kosit.validationtool.api.Check; +import de.kosit.validationtool.api.Configuration; +import de.kosit.validationtool.impl.DefaultCheck; +import de.kosit.validationtool.impl.xml.ProcessorProvider; + +/** + * Example code that is used in the docs/api.md file + */ public class MyValidator { - public static void main(String[] args) { - Configuration config = Configuration.create().name("myconfiguration") - .with(scenario("firstScenario") - .match("//myNode") - .validate(schema("Sample Schema").schemaLocation(URI.create("simple.xsd"))) - .validate(schematron("my rules").source("myRules.xsl")) - .with(report("my report").source("report.xsl"))) - .with(fallback().name("default-report").source("fallback.xsl")) - .useRepository(Paths.get("/opt/myrepository")) - .build(); - Check validator = new DefaultCheck(config); - // .. run your checks - } + public static void main(final String[] args) { + final Configuration config = Configuration.create().name("myconfiguration") + .with(scenario("firstScenario").match("//myNode").validate(schema("Sample Schema").schemaLocation(URI.create("simple.xsd"))) + .validate(schematron("my rules").source("myRules.xsl")).with(report("my report").source("report.xsl"))) + .with(fallback().name("default-report").source("fallback.xsl")).useRepository(Paths.get("/opt/myrepository")) + .build(ProcessorProvider.getProcessor()); + final Check validator = new DefaultCheck(config); + // .. run your checks + } } ``` @@ -188,19 +208,17 @@ which further opens the second to load resources also from remote locations via You can configure usage of one of these implementations using the `ResolvingMode` via -````java -Conifuguration config = Configuration.load(URI.create("myscenarios.xml")) - .resolvingMode(ResolvingMode.STRICT_LOCAL) - .build(); -```` +```java +final Configuration config = Configuration.load(URI.create("myscenarios.xml")).setResolvingMode(ResolvingMode.STRICT_LOCAL) + .build(ProcessorProvider.getProcessor()); +``` If you decide to implement your own strategy, you can configure this via: -````java -Conifuguration config = Configuration.load(URI.create("myscenarios.xml")) - .resolvingStrategy(new MyCustomResolvingConfigurationStrategy()) - .build(); -```` +```java +final Configuration config = Configuration.load(URI.create("myscenarios.xml")) + .setResolvingStrategy(new MyCustomResolvingConfigurationStrategy()).build(ProcessorProvider.getProcessor()); +``` --- diff --git a/pom.xml b/pom.xml index 174abe0..85cdba0 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ KoSIT XML Prüftool Implementierung org.kosit - validationtool + validator 1.5.1-SNAPSHOT KoSIT XML Validator against XSD and Schematron based on defined scenarios. diff --git a/src/test/java/de/kosit/validationtool/docs/MiscDocExampleCodes.java b/src/test/java/de/kosit/validationtool/docs/MiscDocExampleCodes.java new file mode 100644 index 0000000..ae8aa29 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/docs/MiscDocExampleCodes.java @@ -0,0 +1,51 @@ +package de.kosit.validationtool.docs; + +import java.net.URI; + +import javax.xml.transform.URIResolver; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import de.kosit.validationtool.api.Configuration; +import de.kosit.validationtool.api.ResolvingConfigurationStrategy; +import de.kosit.validationtool.impl.ResolvingMode; +import de.kosit.validationtool.impl.xml.ProcessorProvider; +import net.sf.saxon.lib.UnparsedTextURIResolver; + +public class MiscDocExampleCodes { + + void m1() { + final Configuration config = Configuration.load(URI.create("myscenarios.xml")).setResolvingMode(ResolvingMode.STRICT_LOCAL) + .build(ProcessorProvider.getProcessor()); + } + + private static final class MyCustomResolvingConfigurationStrategy implements ResolvingConfigurationStrategy { + + public SchemaFactory createSchemaFactory() { + // TODO + return null; + } + + public URIResolver createResolver(final URI scenarioRepository) { + // TODO + return null; + } + + public UnparsedTextURIResolver createUnparsedTextURIResolver(final URI scenarioRepository) { + // TODO + return null; + } + + public Validator createValidator(final Schema schema) { + // TODO + return null; + } + } + + void m2() { + final Configuration config = Configuration.load(URI.create("myscenarios.xml")) + .setResolvingStrategy(new MyCustomResolvingConfigurationStrategy()).build(ProcessorProvider.getProcessor()); + } + +} diff --git a/src/test/java/de/kosit/validationtool/docs/MyValidator.java b/src/test/java/de/kosit/validationtool/docs/MyValidator.java new file mode 100644 index 0000000..7d4acd9 --- /dev/null +++ b/src/test/java/de/kosit/validationtool/docs/MyValidator.java @@ -0,0 +1,31 @@ +package de.kosit.validationtool.docs; + +import static de.kosit.validationtool.config.ConfigurationBuilder.fallback; +import static de.kosit.validationtool.config.ConfigurationBuilder.report; +import static de.kosit.validationtool.config.ConfigurationBuilder.scenario; +import static de.kosit.validationtool.config.ConfigurationBuilder.schema; +import static de.kosit.validationtool.config.ConfigurationBuilder.schematron; + +import java.net.URI; +import java.nio.file.Paths; + +import de.kosit.validationtool.api.Check; +import de.kosit.validationtool.api.Configuration; +import de.kosit.validationtool.impl.DefaultCheck; +import de.kosit.validationtool.impl.xml.ProcessorProvider; + +/** + * Example code that is used in the docs/api.md file + */ +public class MyValidator { + + public static void main(final String[] args) { + final Configuration config = Configuration.create().name("myconfiguration") + .with(scenario("firstScenario").match("//myNode").validate(schema("Sample Schema").schemaLocation(URI.create("simple.xsd"))) + .validate(schematron("my rules").source("myRules.xsl")).with(report("my report").source("report.xsl"))) + .with(fallback().name("default-report").source("fallback.xsl")).useRepository(Paths.get("/opt/myrepository")) + .build(ProcessorProvider.getProcessor()); + final Check validator = new DefaultCheck(config); + // .. run your checks + } +} \ No newline at end of file diff --git a/src/test/java/de/kosit/validationtool/docs/StandardExample.java b/src/test/java/de/kosit/validationtool/docs/StandardExample.java new file mode 100644 index 0000000..71025fe --- /dev/null +++ b/src/test/java/de/kosit/validationtool/docs/StandardExample.java @@ -0,0 +1,54 @@ +package de.kosit.validationtool.docs; + +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.w3c.dom.Document; + +import de.kosit.validationtool.api.Check; +import de.kosit.validationtool.api.Configuration; +import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.api.Result; +import de.kosit.validationtool.impl.DefaultCheck; +import de.kosit.validationtool.impl.xml.ProcessorProvider; + +/** + * Example code that is used in the docs/api.md file + */ +public class StandardExample { + + public void run(final Path testDocument) throws URISyntaxException { + // Load scenarios.xml from classpath + final URL scenarios = this.getClass().getClassLoader().getResource("examples/simple/scenarios-with-relative-paths.xml"); + // Load the rest of the specific Validator configuration from classpath + final Configuration config = Configuration.load(scenarios.toURI()).build(ProcessorProvider.getProcessor()); + // Use the default validation procedure + final Check validator = new DefaultCheck(config); + // Validate a single document + final Input document = InputFactory.read(testDocument); + // Get Result including information about the whole validation + final Result report = validator.checkInput(document); + System.out.println("Is processing succesful=" + report.isProcessingSuccessful()); + // Get report document if processing was successful + Document result = null; + if (report.isProcessingSuccessful()) { + result = report.getReportDocument(); + } + // continue processing results... + } + + public static void main(final String[] args) throws Exception { + // Use e.g. "src/test/resources/examples/simple/input/foo.xml" + if (args.length == 0) { + throw new IllegalStateException("Provide a test document filename on the commandline"); + } + // Path of document for validation + final Path testDoc = Paths.get(args[0]); + final StandardExample example = new StandardExample(); + // run example validation + example.run(testDoc); + } +} \ No newline at end of file From 911b9a32919c6497a4a4d303b79ce54be4a7cbec Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Wed, 27 Aug 2025 17:40:46 +0200 Subject: [PATCH 5/6] Resolve "Check result to stdout causes an exception" --- .../java/de/kosit/validationtool/impl/Printer.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/kosit/validationtool/impl/Printer.java b/src/main/java/de/kosit/validationtool/impl/Printer.java index c165d97..cdfbbb4 100644 --- a/src/main/java/de/kosit/validationtool/impl/Printer.java +++ b/src/main/java/de/kosit/validationtool/impl/Printer.java @@ -38,7 +38,11 @@ public class Printer { * @param params the params. */ public static void writeOut(final String message, final Object... params) { - System.out.println(new MessageFormat(message, Locale.ENGLISH).format(params)); + try { + System.out.println(new MessageFormat(message, Locale.ENGLISH).format(params)); + } catch (final RuntimeException ex) { + System.err.println("[Format error!] <" + message + "> with params <" + params + ">"); + } } /** @@ -48,7 +52,11 @@ public class Printer { * @param params the params. */ public static void writeErr(final String message, final Object... params) { - System.err.println(new MessageFormat(message, Locale.ENGLISH).format(params)); + try { + System.err.println(new MessageFormat(message, Locale.ENGLISH).format(params)); + } catch (final RuntimeException ex) { + System.err.println("[Format error!] <" + message + "> with params <" + params + ">"); + } } /** From 5e57c3e97845254430ee6b73006cc3174db1ffc2 Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Wed, 27 Aug 2025 18:14:09 +0200 Subject: [PATCH 6/6] Resolve "If the CLI is invoked without any parameter, the usage is shown twice" --- .../kosit/validationtool/cmd/CommandLineApplication.java | 7 +++---- .../validationtool/cmd/CommandlineApplicationTest.java | 8 ++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java index b2a4fcd..09e3757 100644 --- a/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java +++ b/src/main/java/de/kosit/validationtool/cmd/CommandLineApplication.java @@ -25,7 +25,6 @@ import org.fusesource.jansi.AnsiRenderer.Code; import de.kosit.validationtool.cmd.report.Line; import de.kosit.validationtool.impl.Printer; - import picocli.CommandLine; import picocli.CommandLine.ParseResult; @@ -79,11 +78,11 @@ public class CommandLineApplication { final CommandLine commandLine = new CommandLine(new CommandLineOptions()); try { commandLine.setExecutionExceptionHandler(CommandLineApplication::logExecutionException); - commandLine.execute(args); - if (commandLine.isUsageHelpRequested()) { + final int cmdlineRetVal = commandLine.execute(args); + if (commandLine.isUsageHelpRequested() || cmdlineRetVal == CommandLine.ExitCode.USAGE) { resultStatus = ReturnValue.HELP_REQUEST; } else { - resultStatus = ObjectUtils.defaultIfNull(commandLine.getExecutionResult(), ReturnValue.PARSING_ERROR); + resultStatus = ObjectUtils.getIfNull(commandLine.getExecutionResult(), ReturnValue.PARSING_ERROR); if (resultStatus.isError()) { commandLine.usage(System.out); } diff --git a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java index 782d401..f8ce55d 100644 --- a/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java +++ b/src/test/java/de/kosit/validationtool/cmd/CommandlineApplicationTest.java @@ -84,6 +84,14 @@ public class CommandlineApplicationTest { assertThat(outputLines.stream().filter(l -> l.startsWith(CommandLineOptions.SYNOSIS_HEADING))).hasSize(1); } + @Test + public void testNoArguments() { + final String[] args = {}; + CommandLineApplication.mainProgram(args); + assertThat(CommandLine.getErrorOutput()).isNotEmpty(); + checkForHelp(CommandLine.getErrorLines()); + } + @Test public void testRequiredScenarioFile() { final String[] args = { "arguments", "egal welche", "argumente drin sind" };