From 361ed5863d36a70df92def306ace26b383b439df Mon Sep 17 00:00:00 2001 From: Philip Helger Date: Wed, 13 Aug 2025 18:27:06 +0200 Subject: [PATCH] Resolve "UnsupportedOperationException because of read-only List" --- .../kosit/validationtool/impl/Scenario.java | 20 ++++++++++--------- .../config/ScenarioBuilderTest.java | 20 ++++++++++++++++++- .../config/TestConfigurationFactory.java | 2 ++ .../de/kosit/validationtool/impl/Helper.java | 3 ++- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/kosit/validationtool/impl/Scenario.java b/src/main/java/de/kosit/validationtool/impl/Scenario.java index 23deb7d..d92768a 100644 --- a/src/main/java/de/kosit/validationtool/impl/Scenario.java +++ b/src/main/java/de/kosit/validationtool/impl/Scenario.java @@ -16,22 +16,20 @@ package de.kosit.validationtool.impl; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import javax.xml.transform.URIResolver; import javax.xml.validation.Schema; +import de.kosit.validationtool.api.ResolvingConfigurationStrategy; +import de.kosit.validationtool.model.scenarios.ResourceType; +import de.kosit.validationtool.model.scenarios.ScenarioType; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; - -import de.kosit.validationtool.api.ResolvingConfigurationStrategy; -import de.kosit.validationtool.model.scenarios.ResourceType; -import de.kosit.validationtool.model.scenarios.ScenarioType; - import net.sf.saxon.lib.UnparsedTextURIResolver; import net.sf.saxon.s9api.XPathExecutable; import net.sf.saxon.s9api.XPathSelector; @@ -80,7 +78,11 @@ public class Scenario { private Transformation reportTransformation; public List getSchematronValidations() { - return this.schematronValidations == null ? Collections.emptyList() : this.schematronValidations; + // Must return a mutable list + if (this.schematronValidations == null) { + this.schematronValidations = new ArrayList<>(); + } + return this.schematronValidations; } public String getName() { @@ -95,9 +97,9 @@ public class Scenario { } /** - * Liefert einen neuen XPath-Selector zur Evaluierung der {@link de.kosit.validationtool.api.AcceptRecommendation}. + * Returns a new XPath selector for evaluating the {@link de.kosit.validationtool.api.AcceptRecommendation}. * - * @return neuer Selector + * @return new selector */ public Optional getAcceptSelector() { final XPathSelector selector = this.acceptExecutable != null ? this.acceptExecutable.load() : null; diff --git a/src/test/java/de/kosit/validationtool/config/ScenarioBuilderTest.java b/src/test/java/de/kosit/validationtool/config/ScenarioBuilderTest.java index 42f2f58..f9f5590 100644 --- a/src/test/java/de/kosit/validationtool/config/ScenarioBuilderTest.java +++ b/src/test/java/de/kosit/validationtool/config/ScenarioBuilderTest.java @@ -34,7 +34,6 @@ import de.kosit.validationtool.impl.Scenario; import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.model.scenarios.NamespaceType; import de.kosit.validationtool.model.scenarios.ScenarioType; - import net.sf.saxon.s9api.XPathExecutable; /** @@ -140,6 +139,25 @@ public class ScenarioBuilderTest { assertThat(configuration.getNamespace()).isEmpty(); } + @Test + public void testConfigureWithSchematron() { + final ContentRepository repository = Simple.createContentRepository(); + final XPathExecutable match = repository.createXPath("//*", null); + final XPathExecutable accept = repository.createXPath("//*", null); + final ScenarioBuilder builder = createScenario(); + builder.getNamespaces().clear(); + + builder.match(match); + builder.acceptWith(accept); + final Result result = builder.build(repository); + assertThat(result.isValid()).isTrue(); + final ScenarioType configuration = result.getObject().getConfiguration(); + assertThat(configuration.getMatch()).isNotEmpty(); + assertThat(configuration.getAcceptMatch()).isNotEmpty(); + assertThat(configuration.getNamespace()).isEmpty(); + assertThat(configuration.getValidateWithSchematron()).isNotEmpty(); + } + @Test public void testBasicAttributes() { final ContentRepository repository = Simple.createContentRepository(); diff --git a/src/test/java/de/kosit/validationtool/config/TestConfigurationFactory.java b/src/test/java/de/kosit/validationtool/config/TestConfigurationFactory.java index 79ec407..0daacf7 100644 --- a/src/test/java/de/kosit/validationtool/config/TestConfigurationFactory.java +++ b/src/test/java/de/kosit/validationtool/config/TestConfigurationFactory.java @@ -20,6 +20,7 @@ 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.util.Date; @@ -46,6 +47,7 @@ public class TestConfigurationFactory { public static ScenarioBuilder createScenario() { return scenario("simple").validate(schema("Sample Schema").schemaLocation(URI.create("simple.xsd"))) + .validate(schematron("Sample Schematron").source(Simple.SCHEMATRON)) .with(report("Report für eRechnung").source("report.xsl")).acceptWith("count(//test:rejected) = 0") .declareNamespace("cri", "http://www.xoev.de/de/validator/framework/1/createreportinput") .declareNamespace("rpt", "http://validator.kosit.de/test-report") diff --git a/src/test/java/de/kosit/validationtool/impl/Helper.java b/src/test/java/de/kosit/validationtool/impl/Helper.java index 334791c..4562fb6 100644 --- a/src/test/java/de/kosit/validationtool/impl/Helper.java +++ b/src/test/java/de/kosit/validationtool/impl/Helper.java @@ -32,7 +32,6 @@ import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.tasks.DocumentParseAction; import de.kosit.validationtool.impl.xml.ProcessorProvider; import de.kosit.validationtool.model.reportInput.XMLSyntaxError; - import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.Serializer; @@ -84,6 +83,8 @@ public class Helper { public static final URI SCHEMA = REPOSITORY_URI.resolve("simple.xsd"); + public static final URI SCHEMATRON = REPOSITORY_URI.resolve("simple-schematron-error.xsl"); + public static final ContentRepository createContentRepository() { final ResolvingConfigurationStrategy strategy = ResolvingMode.STRICT_RELATIVE.getStrategy(); return new ContentRepository(Helper.getTestProcessor(), strategy, Simple.REPOSITORY_URI);