From 7a86f049ace4baa2d213016737773ca72c140789 Mon Sep 17 00:00:00 2001 From: "Andreas Penski (init)" Date: Tue, 21 Apr 2020 08:34:56 +0200 Subject: [PATCH] Refactor: don't reuse JAXB objects for internal configuration; create a Configuration interface. --- .../api/CheckConfiguration.java | 65 +++-- .../validationtool/api/Configuration.java | 59 +++++ .../de/kosit/validationtool/cmd/Daemon.java | 10 +- .../de/kosit/validationtool/cmd/Health.java | 72 +++--- .../config/BaseConfiguration.java | 92 +++++++ .../config/ConfigurationBuilder.java | 10 + .../config/LoadConfiguration.java | 178 ++++++++++++++ .../config/ScenarioBuilder.java | 72 ++++++ .../impl/ContentRepository.java | 74 +++++- .../validationtool/impl/DefaultCheck.java | 17 +- .../validationtool/impl/ObjectFactory.java | 2 +- .../validationtool/impl/ResolvingMode.java | 45 ++++ .../kosit/validationtool/impl/Scenario.java | 83 +++++++ .../impl/ScenarioRepository.java | 126 ++-------- .../impl/model/BaseScenario.java | 224 ------------------ .../impl/tasks/CheckAction.java | 4 +- .../impl/tasks/ComputeAcceptanceAction.java | 11 +- .../impl/tasks/CreateReportAction.java | 13 +- .../impl/tasks/ScenarioSelectionAction.java | 10 +- .../impl/tasks/SchemaValidationAction.java | 14 +- .../tasks/SchematronValidationAction.java | 15 +- src/main/model/binding/global.xjb | 3 - .../impl/ContentRepositoryTest.java | 20 +- .../impl/ConversionServiceTest.java | 8 +- .../impl/ScenarioRepositoryTest.java | 101 +++++--- .../validationtool/impl/VersioningTest.java | 11 +- .../tasks/ComputeAcceptanceActionTest.java | 16 +- .../impl/tasks/SchemaValidatorActionTest.java | 4 +- .../tasks/SchematronValidationActionTest.java | 6 +- .../impl/tasks/TestBagBuilder.java | 23 +- 30 files changed, 871 insertions(+), 517 deletions(-) create mode 100644 src/main/java/de/kosit/validationtool/api/Configuration.java create mode 100644 src/main/java/de/kosit/validationtool/config/BaseConfiguration.java create mode 100644 src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java create mode 100644 src/main/java/de/kosit/validationtool/config/LoadConfiguration.java create mode 100644 src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java create mode 100644 src/main/java/de/kosit/validationtool/impl/ResolvingMode.java create mode 100644 src/main/java/de/kosit/validationtool/impl/Scenario.java delete mode 100644 src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java diff --git a/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java b/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java index e507daf..31f6aff 100644 --- a/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java +++ b/src/main/java/de/kosit/validationtool/api/CheckConfiguration.java @@ -20,24 +20,31 @@ package de.kosit.validationtool.api; import java.net.URI; +import java.util.List; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import de.kosit.validationtool.impl.RelativeUriResolver; +import de.kosit.validationtool.config.LoadConfiguration; +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.Scenario; + +import net.sf.saxon.s9api.Processor; /** * Zentrale Konfigration einer Prüf-Instanz. * * @author Andreas Penski + * @deprecated since 2.0 use {@link Configuration} instead */ @Getter @Setter @Slf4j @RequiredArgsConstructor -public class CheckConfiguration { +@Deprecated +public class CheckConfiguration implements Configuration { /** * URL, die auf die scenerio.xml Datei zeigt. @@ -49,22 +56,52 @@ public class CheckConfiguration { */ private URI scenarioRepository; + private LoadConfiguration delegate; - /** - * Liefert das Repository mit den Artefakten der einzelnen Szenarien. - * - * @return uri die durch entsprechende resolver aufgelöst werden kann - */ - public URI getScenarioRepository() { - if (this.scenarioRepository == null) { - this.scenarioRepository = createDefaultRepository(); + private LoadConfiguration getDelegate() { + if (this.delegate == null) { + this.delegate = Configuration.load(this.scenarioDefinition, this.scenarioRepository); } - return this.scenarioRepository; + return this.delegate; } - private URI createDefaultRepository() { - log.info("Creating default scenario repository (alongside scenario definition)"); - return RelativeUriResolver.resolve(URI.create("."), this.scenarioDefinition); + @Override + public List getScenarios() { + return getDelegate().getScenarios(); } + @Override + public Scenario getFallbackScenario() { + return getDelegate().getFallbackScenario(); + } + + @Override + public void build() { + getDelegate().build(); + } + + @Override + public String getDate() { + return getDelegate().getDate(); + } + + @Override + public String getName() { + return getDelegate().getName(); + } + + @Override + public String getAuthor() { + return getDelegate().getAuthor(); + } + + @Override + public Processor getProcessor() { + return getDelegate().getProcessor(); + } + + @Override + public ContentRepository getContentRepository() { + return getDelegate().getContentRepository(); + } } diff --git a/src/main/java/de/kosit/validationtool/api/Configuration.java b/src/main/java/de/kosit/validationtool/api/Configuration.java new file mode 100644 index 0000000..ac99275 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/api/Configuration.java @@ -0,0 +1,59 @@ +package de.kosit.validationtool.api; + +import java.net.URI; +import java.util.List; + +import de.kosit.validationtool.config.ConfigurationBuilder; +import de.kosit.validationtool.config.LoadConfiguration; +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.Scenario; + +import net.sf.saxon.s9api.Processor; + +/** + * Configuration of the actual {@link Check} instance. This is a contruct and can be used implemented by custom + * configuration classes. There are two implementations supported out of the box: + * + *
    + *
  1. {@link LoadConfiguration} implements loading {@link Check} configurations from a scenario.xml file
  2. + *
  3. Using a builder style api {@link de.kosit.validationtool.config.ConfigurationBuilder}to configure the + * {@link Check}
  4. + *
+ * + * Both methods can be used via convinience methods. See below. + * + * @author Andreas Penski + */ + +public interface Configuration { + + List getScenarios(); + + static LoadConfiguration load(final URI scenarioDefinition) { + return load(scenarioDefinition, null); + } + + static LoadConfiguration load(final URI scenarioDefinition, final URI repository) { + final LoadConfiguration config = new LoadConfiguration(scenarioDefinition, repository); + config.build(); + return config; + } + + static ConfigurationBuilder create() { + return new ConfigurationBuilder(); + } + + Scenario getFallbackScenario(); + + void build(); + + String getAuthor(); + + String getName(); + + String getDate(); + + Processor getProcessor(); + + ContentRepository getContentRepository(); +} diff --git a/src/main/java/de/kosit/validationtool/cmd/Daemon.java b/src/main/java/de/kosit/validationtool/cmd/Daemon.java index 560c039..91aceda 100644 --- a/src/main/java/de/kosit/validationtool/cmd/Daemon.java +++ b/src/main/java/de/kosit/validationtool/cmd/Daemon.java @@ -27,11 +27,11 @@ import lombok.extern.slf4j.Slf4j; import de.kosit.validationtool.api.Check; import de.kosit.validationtool.api.CheckConfiguration; +import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.impl.DefaultCheck; import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.input.SourceInput; -import de.kosit.validationtool.model.scenarios.Scenarios; /** * HTTP-Daemon für die Bereitstellung der Prüf-Funktionalität via http. @@ -98,10 +98,10 @@ class Daemon { @Slf4j static class HealthHandler implements HttpHandler { - private final Scenarios scenarios; + private final Configuration scenarios; - HealthHandler(final Scenarios scenarios) { - this.scenarios = scenarios; + HealthHandler(final Configuration config) { + this.scenarios = config; } @Override @@ -188,7 +188,7 @@ class Daemon { server = HttpServer.create(new InetSocketAddress(this.hostName, this.port), 0); final DefaultCheck check = new DefaultCheck(config); server.createContext("/", new HttpServerHandler(check)); - server.createContext("/health", new HealthHandler(check.getRepository().getScenarios())); + server.createContext("/health", new HealthHandler(config)); server.setExecutor(Executors.newFixedThreadPool(this.threadCount)); server.start(); log.info("Server unter Port {} ist erfolgreich gestartet", this.port); diff --git a/src/main/java/de/kosit/validationtool/cmd/Health.java b/src/main/java/de/kosit/validationtool/cmd/Health.java index e3056a6..2694142 100644 --- a/src/main/java/de/kosit/validationtool/cmd/Health.java +++ b/src/main/java/de/kosit/validationtool/cmd/Health.java @@ -1,8 +1,6 @@ package de.kosit.validationtool.cmd; import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -10,7 +8,8 @@ import org.w3c.dom.Node; import lombok.extern.slf4j.Slf4j; -import de.kosit.validationtool.model.scenarios.Scenarios; +import de.kosit.validationtool.api.Configuration; +import de.kosit.validationtool.impl.ObjectFactory; /** * Klasse zur Erzeugung Health Xml , die optiamle Status. @@ -26,15 +25,15 @@ class Health { private final long totalMemory; - private final Scenarios scenarios; + private final Configuration config; - Health(Scenarios scenarios) { + Health(final Configuration config) { - Runtime runtime = Runtime.getRuntime(); - freeMemory = runtime.freeMemory(); - maxMemory = runtime.maxMemory(); - totalMemory = runtime.totalMemory(); - this.scenarios = scenarios; + final Runtime runtime = Runtime.getRuntime(); + this.freeMemory = runtime.freeMemory(); + this.maxMemory = runtime.maxMemory(); + this.totalMemory = runtime.totalMemory(); + this.config = config; } /** @@ -42,20 +41,13 @@ class Health { * */ Document writeHealthXml() { - DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder dBuilder; - Document doc = null; - try { - dBuilder = dbFactory.newDocumentBuilder(); - doc = dBuilder.newDocument(); - Element rootElement = doc.createElementNS("https://localhost:8080/Health", "Health"); - doc.appendChild(rootElement); - rootElement.appendChild(getMemory(doc, freeMemory, maxMemory, totalMemory)); - rootElement.appendChild(getState(doc)); - rootElement.appendChild(getScenario(doc, scenarios)); - } catch (ParserConfigurationException e) { - log.error("Fehler beim Schreiben der Status-Informationen", e); - } + final DocumentBuilder dBuilder = ObjectFactory.createDocumentBuilder(false); + final Document doc = dBuilder.newDocument(); + final Element rootElement = doc.createElementNS("https://localhost:8080/Health", "Health"); + doc.appendChild(rootElement); + rootElement.appendChild(getMemory(doc, this.freeMemory, this.maxMemory, this.totalMemory)); + rootElement.appendChild(getState(doc)); + rootElement.appendChild(getScenario(doc, this.config)); return doc; } @@ -65,10 +57,10 @@ class Health { * @param doc Vom Typ Dokument. * */ - private Node getState(Document doc) { - Element state = doc.createElement("state"); + private static Node getState(final Document doc) { + final Element state = doc.createElement("state"); state.setAttribute("indicator", "OK"); - Element stateNode = doc.createElement("message"); + final Element stateNode = doc.createElement("message"); stateNode.appendChild(doc.createTextNode("System is up and running normally")); state.appendChild(stateNode); return state; @@ -78,13 +70,13 @@ class Health { * Methode, die schreibt das Scnarios Information Node im Xml File * * @param doc Vom Typ Dokument . - * @param scenarios Vom Typ {@link Scenarios} das verwendete scenario. + * @param config Vom Typ {@link Configuration} das verwendete scenario. * */ - private Node getScenario(Document doc, Scenarios scenarios) { - Element scenario = doc.createElement("scenario"); - Element scenarioNameNode = doc.createElement("name"); - scenarioNameNode.appendChild(doc.createTextNode(scenarios.getName())); + private static Node getScenario(final Document doc, final Configuration config) { + final Element scenario = doc.createElement("scenario"); + final Element scenarioNameNode = doc.createElement("name"); + scenarioNameNode.appendChild(doc.createTextNode(config.getName())); scenario.appendChild(scenarioNameNode); return scenario; } @@ -98,18 +90,18 @@ class Health { * @param totalMemory Vom Typ long , der Gesamte speicher. * */ - private static Node getMemory(Document doc, long freeMemory, long maxMemory, long totalMemory) { - Element memory = doc.createElement("memoryState"); - String freeM = Long.toString(freeMemory); - Element freeMNode = doc.createElement("freeMemory"); + private static Node getMemory(final Document doc, final long freeMemory, final long maxMemory, final long totalMemory) { + final Element memory = doc.createElement("memoryState"); + final String freeM = Long.toString(freeMemory); + final Element freeMNode = doc.createElement("freeMemory"); freeMNode.appendChild(doc.createTextNode(freeM)); memory.appendChild(freeMNode); - String maxM = Long.toString(maxMemory); - Element maxMNode = doc.createElement("maxMemory"); + final String maxM = Long.toString(maxMemory); + final Element maxMNode = doc.createElement("maxMemory"); maxMNode.appendChild(doc.createTextNode(maxM)); memory.appendChild(maxMNode); - String totalM = Long.toString(totalMemory); - Element totalMNode = doc.createElement("totalMemory"); + final String totalM = Long.toString(totalMemory); + final Element totalMNode = doc.createElement("totalMemory"); totalMNode.appendChild(doc.createTextNode(totalM)); memory.appendChild(totalMNode); return memory; diff --git a/src/main/java/de/kosit/validationtool/config/BaseConfiguration.java b/src/main/java/de/kosit/validationtool/config/BaseConfiguration.java new file mode 100644 index 0000000..167099a --- /dev/null +++ b/src/main/java/de/kosit/validationtool/config/BaseConfiguration.java @@ -0,0 +1,92 @@ +package de.kosit.validationtool.config; + +import java.util.List; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.api.Configuration; +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.Scenario; + +import net.sf.saxon.s9api.Processor; + +/** + * Base configuration class. + * + * @author Andreas Penski + */ +@Slf4j +public abstract class BaseConfiguration implements Configuration { + + @RequiredArgsConstructor + @Getter + @Setter + protected static class RuntimeArtefacts { + + private final List scenarios; + + private final Scenario fallbackScenario; + + private String name; + + private String author; + + private String date; + } + + private RuntimeArtefacts artefacts; + + protected abstract RuntimeArtefacts buildArtefacts(); + + @Override + public void build() { + if (this.artefacts != null) { + log.warn("Configuration already complete. Will drop previous artefacts and build again"); + } + this.artefacts = buildArtefacts(); + } + + @Override + public List getScenarios() { + assertBuild(); + return this.artefacts.getScenarios(); + } + + @Override + public Scenario getFallbackScenario() { + assertBuild(); + return this.artefacts.getFallbackScenario(); + } + + private void assertBuild() { + if (this.artefacts == null) { + throw new IllegalStateException("Configuration"); + } + } + + @Override + public Processor getProcessor() { + return ObjectFactory.createProcessor(); + } + + @Override + public String getAuthor() { + assertBuild(); + return this.artefacts.getAuthor(); + } + + @Override + public String getName() { + assertBuild(); + return this.artefacts.getName(); + } + + @Override + public String getDate() { + assertBuild(); + return this.artefacts.getDate(); + } +} diff --git a/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java b/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java new file mode 100644 index 0000000..27dc6b5 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/config/ConfigurationBuilder.java @@ -0,0 +1,10 @@ +package de.kosit.validationtool.config; + +/** + * @author Andreas Penski + */ +public class ConfigurationBuilder { + + private ScenarioBuilder scenarioBuilder; + +} diff --git a/src/main/java/de/kosit/validationtool/config/LoadConfiguration.java b/src/main/java/de/kosit/validationtool/config/LoadConfiguration.java new file mode 100644 index 0000000..e9f52e0 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/config/LoadConfiguration.java @@ -0,0 +1,178 @@ +package de.kosit.validationtool.config; + +import static org.apache.commons.lang3.StringUtils.startsWith; + +import java.net.MalformedURLException; +import java.net.URI; +import java.util.List; +import java.util.stream.Collectors; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; + +import de.kosit.validationtool.api.Check; +import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.impl.CollectingErrorEventHandler; +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.ConversionService; +import de.kosit.validationtool.impl.RelativeUriResolver; +import de.kosit.validationtool.impl.Scenario; +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.CreateReportType; +import de.kosit.validationtool.model.scenarios.ScenarioType; +import de.kosit.validationtool.model.scenarios.Scenarios; + +import net.sf.saxon.s9api.QName; +import net.sf.saxon.s9api.XdmNode; +import net.sf.saxon.s9api.XdmNodeKind; + +/** + * Configuration class that loads neccessary {@link Check} configuration from an existing scenario.xml specification. + * This is the recommended option when an official configuration exists as is the case with 'xrechnung'. + * + * @author Andreas Penski + */ +@AllArgsConstructor +@Slf4j +public class LoadConfiguration extends BaseConfiguration { + + 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"; + + /** + * URL, die auf die scenerio.xml Datei zeigt. + */ + @Getter(AccessLevel.PACKAGE) + private final URI scenarioDefinition; + + /** + * Root-Ordner mit den von den einzelnen Szenarien benötigten Dateien + */ + private final URI scenarioRepository; + + URI getScenarioRepository() { + if (this.scenarioRepository == null) { + log.info("Creating default scenario repository (alongside scenario definition)"); + return RelativeUriResolver.resolve(URI.create("."), this.scenarioDefinition); + } + return this.scenarioRepository; + } + + private static void checkVersion(final URI scenarioDefinition) { + try { + final Result result = DocumentParseAction.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 (final MalformedURLException e) { + throw new IllegalStateException("Error reading definition file"); + } + } + + private static XdmNode findRoot(final XdmNode doc) { + for (final XdmNode node : doc.children()) { + if (node.getNodeKind() == XdmNodeKind.ELEMENT) { + return node; + } + } + throw new IllegalArgumentException("Kein root element gefunden"); + } + + private static boolean isSupportedDocument(final XdmNode doc) { + final XdmNode root = findRoot(doc); + final String frameworkVersion = root.getAttributeValue(new QName("frameworkVersion")); + return startsWith(frameworkVersion, SUPPORTED_MAJOR_VERSION) + && root.getNodeName().getNamespaceURI().equals(SUPPORTED_MAJOR_VERSION_SCHEMA); + } + + private static Scenario createFallback(final Scenarios scenarios, final ContentRepository repository) { + final ScenarioType t = new ScenarioType(); + t.setName("Fallback-Scenario"); + t.setMatch("count(/)<0"); + final CreateReportType reportType = new CreateReportType(); + reportType.setResource(scenarios.getNoScenarioReport().getResource()); + // always reject + t.setAcceptMatch("count(/)<0"); + t.setCreateReport(reportType); + final Scenario sceanrio = initialize(t, repository); + sceanrio.setFallback(true); + return sceanrio; + } + + @Override + protected RuntimeArtefacts buildArtefacts() { + final ContentRepository contentRepository = buildContentRepository(); + final Scenarios def = loadScenarios(); + final List scenarios = initializeScenarios(def, contentRepository); + final Scenario fallbackScenario = createFallback(def, contentRepository); + final RuntimeArtefacts runtimeArtefacts = new RuntimeArtefacts(scenarios, fallbackScenario); + runtimeArtefacts.setAuthor(def.getAuthor()); + runtimeArtefacts.setDate(def.getDate().toString()); + runtimeArtefacts.setName(def.getName()); + return runtimeArtefacts; + } + + private static List initializeScenarios(final Scenarios def, final ContentRepository contentRepository) { + return def.getScenario().stream().map(s -> initialize(s, contentRepository)).collect(Collectors.toList()); + } + + private ContentRepository buildContentRepository() { + return new ContentRepository(getProcessor(), getScenarioRepository()); + } + + @Override + public ContentRepository getContentRepository() { + return buildContentRepository(); + } + + private Scenarios loadScenarios() { + final ConversionService conversionService = new ConversionService(); + checkVersion(this.scenarioDefinition); + log.info("Loading scenarios from {}", this.scenarioDefinition); + final CollectingErrorEventHandler handler = new CollectingErrorEventHandler(); + final Scenarios scenarios = conversionService.readXml(this.scenarioDefinition, Scenarios.class, + getContentRepository().getScenarioSchema(), handler); + if (!handler.hasErrors()) { + log.info("Loading scenario content from {}", this.scenarioRepository); + } else { + throw new IllegalStateException( + String.format("Can not load scenarios from %s due to %s", getScenarioDefinition(), handler.getErrorDescription())); + } + return scenarios; + + } + + private static Scenario initialize(final ScenarioType def, final ContentRepository repository) { + final Scenario s = new Scenario(def); + s.setSchema(repository.createSchema(def)); + s.setReportTransformation(repository.createReportTransformation(def)); + s.setMatchExecutable(repository.createMatchExecutable(def)); + if (def.getAcceptMatch() != null) { + s.setAcceptExecutable(repository.createAccepptExecutable(def)); + } + return s; + } + + @Override + public String getAuthor() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public String getDate() { + return null; + } +} diff --git a/src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java b/src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java new file mode 100644 index 0000000..0a2a700 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/config/ScenarioBuilder.java @@ -0,0 +1,72 @@ +package de.kosit.validationtool.config; + +import java.net.URL; +import java.util.Collections; +import java.util.Map; + +import javax.xml.validation.Schema; + +import org.w3c.dom.ls.LSResourceResolver; + +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.model.scenarios.ScenarioType; + +import net.sf.saxon.s9api.XsltExecutable; + +/** + * @author Andreas Penski + */ +public class ScenarioBuilder { + + private final ScenarioType scenario; + + private final ContentRepository contentRepository = new ContentRepository(ObjectFactory.createProcessor(), null); + + ScenarioBuilder(final String name) { + this.scenario = new ScenarioType(); + this.scenario.setName(name); + } + + public ScenarioBuilder matches(final String xpath) { + return matches(xpath, Collections.emptyMap()); + } + + private ScenarioBuilder matches(final String xpath, final Map namespaces) { + // final XPathExecutable matchExecutable = this.contentRepository.createXPath(xpath, namespaces); + // this.scenario.setMatchExecutable(matchExecutable); + // this.scenario.setMatch(xpath); + // if (namespaces != null) { + // this.scenario.getNamespace().addAll(namespaces.entrySet().stream().map(e -> { + // NamespaceType t = new NamespaceType(); + // t.setPrefix(e.getKey()); + // t.setValue(e.getValue()); + // return t; + // }).collect(Collectors.toList())); + // } else { + // this.scenario.getNamespace().clear(); + // } + return this; + } + + public ScenarioBuilder schemaValidation(final Schema schema) { + return this; + } + + public ScenarioBuilder schemaValidation(final URL url) { + return schemalidation(url, null); + } + + private ScenarioBuilder schemalidation(final URL url, final LSResourceResolver resolver) { + return this; + } + + public ScenarioBuilder addSchematronValidation(final XsltExecutable executable) { + return this; + } + + public ScenarioBuilder withReportGenerator(final XsltExecutable executable) { + return this; + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java index 0da0736..4e56e4a 100644 --- a/src/main/java/de/kosit/validationtool/impl/ContentRepository.java +++ b/src/main/java/de/kosit/validationtool/impl/ContentRepository.java @@ -24,9 +24,12 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Collection; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.xml.transform.Source; +import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; @@ -39,6 +42,11 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import de.kosit.validationtool.impl.Scenario.Transformation; +import de.kosit.validationtool.model.scenarios.NamespaceType; +import de.kosit.validationtool.model.scenarios.ResourceType; +import de.kosit.validationtool.model.scenarios.ScenarioType; + import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XPathCompiler; @@ -55,14 +63,16 @@ import net.sf.saxon.s9api.XsltExecutable; @Slf4j public class ContentRepository { + private Schema reportInputSchema; + @Getter private final Processor processor; private final URI repository; - private Schema reportInputSchema; + private final ResolvingMode mode = ResolvingMode.STRICT_RELATIVE; - private static Source resolve(final URL resource) { + private Source resolve(final URL resource) { try { return new StreamSource(resource.openStream(), resource.toURI().getRawPath()); } catch (final IOException | URISyntaxException e) { @@ -70,7 +80,7 @@ public class ContentRepository { } } - private static Schema createSchema(final Source[] schemaSources, final LSResourceResolver resourceResolver) { + private Schema createSchema(final Source[] schemaSources, final LSResourceResolver resourceResolver) { try { final SchemaFactory sf = ObjectFactory.createSchemaFactory(); sf.setResourceResolver(resourceResolver); @@ -80,7 +90,7 @@ public class ContentRepository { } } - private static Schema createSchema(final Source[] schemaSources) { + private Schema createSchema(final Source[] schemaSources) { return createSchema(schemaSources, null); } @@ -116,11 +126,11 @@ public class ContentRepository { * @param url die url * @return das erzeugte Schema */ - public static Schema createSchema(final URL url) { + public Schema createSchema(final URL url) { return createSchema(url, null); } - public static Schema createSchema(final URL url, final LSResourceResolver resourceResolver) { + public Schema createSchema(final URL url, final LSResourceResolver resourceResolver) { log.info("Load schema from source {}", url.getPath()); return createSchema(new Source[] { resolve(url) }, resourceResolver); } @@ -130,7 +140,7 @@ public class ContentRepository { * * @return Scenario-Schema */ - public static Schema getScenarioSchema() { + public Schema getScenarioSchema() { return createSchema(ContentRepository.class.getResource("/xsd/scenarios.xsd")); } @@ -140,11 +150,11 @@ public class ContentRepository { * @return ReportInput-Schema */ public Schema getReportInputSchema() { - if (this.reportInputSchema == null) { + if (reportInputSchema == null) { final Source source = resolve(ContentRepository.class.getResource("/xsd/createReportInput.xsd")); - this.reportInputSchema = createSchema(new Source[] { source }, new ClassPathResourceResolver("/xsd")); + reportInputSchema = createSchema(new Source[] { source }, new ClassPathResourceResolver("/xsd")); } - return this.reportInputSchema; + return reportInputSchema; } /** @@ -157,8 +167,23 @@ public class ContentRepository { return createSchema(uris.stream().map(s -> resolve(URI.create(s))).toArray(Source[]::new)); } + /** + * Liefert das Schema zu diesem Szenario. + * + * @return das passende Schema + */ + public Schema createSchema(final ScenarioType s) { + Schema schema = null; + if (s.getValidateWithXmlSchema() != null) { + final List schemaResources = s.getValidateWithXmlSchema().getResource().stream().map(ResourceType::getLocation) + .collect(Collectors.toList()); + schema = createSchema(schemaResources); + } + return schema; + } + private Source resolve(final URI source) { - final URI resolved = RelativeUriResolver.resolve(source, this.repository); + final URI resolved = this.mode.resolve(source, this.repository); return new StreamSource(resolved.toASCIIString()); } @@ -187,7 +212,30 @@ public class ContentRepository { * * @return ein neuer Resolver */ - public RelativeUriResolver createResolver() { - return new RelativeUriResolver(this.repository); + public URIResolver createResolver() { + return this.mode.createResolver(this.repository); + } + + /** + * Gibt eine Transformation zurück. + * + * @return initialisierte Transformation + */ + public Transformation createReportTransformation(final ScenarioType t) { + final ResourceType resource = t.getCreateReport().getResource(); + final XsltExecutable executable = loadXsltScript(URI.create(resource.getLocation())); + return new Transformation(executable, resource); + } + + public XPathExecutable createMatchExecutable(final ScenarioType s) { + final Map namespaces = s.getNamespace().stream() + .collect(Collectors.toMap(NamespaceType::getPrefix, NamespaceType::getValue)); + return createXPath(s.getMatch(), namespaces); + } + + public XPathExecutable createAccepptExecutable(final ScenarioType s) { + final Map namespaces = s.getNamespace().stream() + .collect(Collectors.toMap(NamespaceType::getPrefix, NamespaceType::getValue)); + return createXPath(s.getAcceptMatch(), namespaces); } } diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java index 02e2922..2d9fa78 100644 --- a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java +++ b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java @@ -28,7 +28,7 @@ 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.Configuration; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.Result; import de.kosit.validationtool.api.XmlError; @@ -73,20 +73,22 @@ public class DefaultCheck implements Check { * * @param configuration die Konfiguration */ - public DefaultCheck(final CheckConfiguration configuration) { + public DefaultCheck(final Configuration configuration) { final Processor processor = ObjectFactory.createProcessor(); this.conversionService = new ConversionService(); - this.contentRepository = new ContentRepository(processor, configuration.getScenarioRepository()); - this.repository = new ScenarioRepository(this.contentRepository); - this.repository.initialize(configuration); + this.repository = new ScenarioRepository(configuration); + + // TODO get rid of it + this.contentRepository = configuration.getContentRepository(); this.checkSteps = new ArrayList<>(); this.checkSteps.add(new DocumentParseAction()); this.checkSteps.add(new CreateDocumentIdentificationAction()); this.checkSteps.add(new ScenarioSelectionAction(this.repository)); this.checkSteps.add(new SchemaValidationAction()); this.checkSteps.add(new SchematronValidationAction(this.contentRepository, this.conversionService)); - this.checkSteps.add(new ValidateReportInputAction(this.conversionService, this.contentRepository.getReportInputSchema())); - this.checkSteps.add(new CreateReportAction(processor, this.conversionService, this.repository, this.contentRepository)); + this.checkSteps + .add(new ValidateReportInputAction(this.conversionService, configuration.getContentRepository().getReportInputSchema())); + this.checkSteps.add(new CreateReportAction(processor, this.conversionService, this.contentRepository)); this.checkSteps.add(new ComputeAcceptanceAction()); } @@ -139,5 +141,4 @@ public class DefaultCheck implements Check { return (List) (List) errors; } - } diff --git a/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java b/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java index eace869..76b66ee 100644 --- a/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java +++ b/src/main/java/de/kosit/validationtool/impl/ObjectFactory.java @@ -207,7 +207,7 @@ public class ObjectFactory { final 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 + processor.getUnderlyingConfiguration().setUnparsedTextURIResolver(resolver); //grundsätzlich Feature-konfiguration: processor.setConfigurationProperty(FeatureKeys.DTD_VALIDATION, false); diff --git a/src/main/java/de/kosit/validationtool/impl/ResolvingMode.java b/src/main/java/de/kosit/validationtool/impl/ResolvingMode.java new file mode 100644 index 0000000..618c74a --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/ResolvingMode.java @@ -0,0 +1,45 @@ +package de.kosit.validationtool.impl; + +import java.net.URI; + +import javax.xml.transform.URIResolver; + +import org.apache.commons.lang3.NotImplementedException; + +/** + * Defines how artefacts are resolved internally. + * + * @author Andreas Penski + */ +public enum ResolvingMode { + + /** + * Resolving using only the configured content repository. No furthing resolving allowed. This + */ + STRICT_RELATIVE { + + @Override + public URI resolve(final URI source, final URI repository) { + return RelativeUriResolver.resolve(source, repository); + } + + @Override + public URIResolver createResolver(final URI repository) { + return new RelativeUriResolver(repository); + } + }, + + STRICT_LOCAL, + + JDK_SUPPORTED, + + CUSTOM; + + public URI resolve(final URI source, final URI repository) { + throw new NotImplementedException("Not yet implemented"); + } + + public URIResolver createResolver(final URI repository) { + throw new NotImplementedException("Not yet implemented"); + } +} diff --git a/src/main/java/de/kosit/validationtool/impl/Scenario.java b/src/main/java/de/kosit/validationtool/impl/Scenario.java new file mode 100644 index 0000000..159fa87 --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/Scenario.java @@ -0,0 +1,83 @@ +package de.kosit.validationtool.impl; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import javax.xml.validation.Schema; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import de.kosit.validationtool.model.scenarios.ResourceType; +import de.kosit.validationtool.model.scenarios.ScenarioType; + +import net.sf.saxon.s9api.XPathExecutable; +import net.sf.saxon.s9api.XPathSelector; +import net.sf.saxon.s9api.XsltExecutable; + +/** + * @author Andreas Penski + */ +@RequiredArgsConstructor + +@Setter +@Getter +public class Scenario { + + /** + * Runtime objects for a transformation e.g. schematron or report. + */ + @Getter + @Setter + @AllArgsConstructor + public static class Transformation { + + private XsltExecutable executable; + + private ResourceType resourceType; + } + + private final ScenarioType configuration; + + private Schema schema; + + private boolean fallback; + + private XPathExecutable matchExecutable; + + private XPathExecutable acceptExecutable; + + @Setter + private List schematronValidations; + + private Transformation reportTransformation; + + public List getSchematronValidations() { + return this.schematronValidations == null ? Collections.emptyList() : this.schematronValidations; + } + + public String getName() { + return this.configuration.getName(); + } + + public XPathSelector getMatchSelector() { + if (this.matchExecutable == null) { + throw new IllegalStateException("No match executable supplied"); + } + return this.matchExecutable.load(); + } + + /** + * Liefert einen neuen XPath-Selector zur Evaluierung der {@link de.kosit.validationtool.api.AcceptRecommendation}. + * + * @return neuer Selector + */ + public Optional getAcceptSelector() { + final XPathSelector selector = this.acceptExecutable != null ? this.acceptExecutable.load() : null; + return Optional.ofNullable(selector); + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java index 6992329..de5b7de 100644 --- a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java +++ b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java @@ -19,34 +19,18 @@ package de.kosit.validationtool.impl; -import static org.apache.commons.lang3.StringUtils.startsWith; - -import java.net.MalformedURLException; -import java.net.URI; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import de.kosit.validationtool.api.CheckConfiguration; -import de.kosit.validationtool.api.InputFactory; +import de.kosit.validationtool.api.Configuration; 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.CreateReportType; -import de.kosit.validationtool.model.scenarios.ScenarioType; -import de.kosit.validationtool.model.scenarios.Scenarios; -import net.sf.saxon.s9api.QName; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XPathSelector; import net.sf.saxon.s9api.XdmNode; -import net.sf.saxon.s9api.XdmNodeKind; /** * Repository for die aktiven Szenario einer Prüfinstanz. @@ -54,86 +38,29 @@ import net.sf.saxon.s9api.XdmNodeKind; * @author Andreas Penski */ @Slf4j -@RequiredArgsConstructor + public class ScenarioRepository { - private static final String SUPPORTED_MAJOR_VERSION = "1"; + private final Configuration configuration; - private static final String SUPPORTED_MAJOR_VERSION_SCHEMA = "http://www.xoev.de/de/validator/framework/1/scenarios"; - - - @Getter(value = AccessLevel.PACKAGE) - private final ContentRepository repository; - - @Getter - private Scenarios scenarios; - - @Setter(AccessLevel.PACKAGE) - @Getter - private ScenarioType fallbackScenario; - - private static boolean isSupportedDocument(final XdmNode doc) { - final XdmNode root = findRoot(doc); - final String frameworkVersion = root.getAttributeValue(new QName("frameworkVersion")); - return startsWith(frameworkVersion, SUPPORTED_MAJOR_VERSION) - && root.getNodeName().getNamespaceURI().equals(SUPPORTED_MAJOR_VERSION_SCHEMA); + public ScenarioRepository(final Configuration configuration) { + this.configuration = configuration; + configuration.build(); + log.info("Loaded scenarios for {} by {} from {}. The following scenarios are available:\n\n{}", configuration.getName(), + configuration.getAuthor(), configuration.getDate(), summarizeScenarios()); } - private static XdmNode findRoot(final XdmNode doc) { - for (final XdmNode node : doc.children()) { - if (node.getNodeKind() == XdmNodeKind.ELEMENT) { - return node; - } - } - throw new IllegalArgumentException("Kein root element gefunden"); + public Scenario getFallbackScenario() { + return this.configuration.getFallbackScenario(); } - private static void checkVersion(final URI scenarioDefinition) { - final DocumentParseAction p = new DocumentParseAction(); - try { - final Result result = DocumentParseAction.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 (final MalformedURLException e) { - throw new IllegalStateException("Error reading definition file"); - } - } - - - - /** - * Initialisiert das Repository mit der angegebenen Konfiguration. - * - * @param config die Konfiguration - */ - public void initialize(final CheckConfiguration config) { - final ConversionService conversionService = new ConversionService(); - checkVersion(config.getScenarioDefinition()); - log.info("Loading scenarios from {}", config.getScenarioDefinition()); - final CollectingErrorEventHandler handler = new CollectingErrorEventHandler(); - this.scenarios = conversionService.readXml(config.getScenarioDefinition(), Scenarios.class, ContentRepository.getScenarioSchema(), - handler); - if (!handler.hasErrors()) { - log.info("Loaded scenarios for {} by {} from {}. The following scenarios are available:\n\n{}", this.scenarios.getName(), - this.scenarios.getAuthor(), this.scenarios.getDate(), summarizeScenarios()); - log.info("Loading scenario content from {}", config.getScenarioRepository()); - getScenarios().getScenario().forEach(s -> s.initialize(this.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 - this.fallbackScenario = createFallback(); - + public List getScenarios() { + return this.configuration.getScenarios(); } private String summarizeScenarios() { final StringBuilder b = new StringBuilder(); - this.scenarios.getScenario().forEach(s -> { + getScenarios().forEach(s -> { b.append(s.getName()); b.append("\n"); }); @@ -146,9 +73,9 @@ public class ScenarioRepository { * @param document das Eingabedokument * @return ein Ergebnis-Objekt zur weiteren Verarbeitung */ - public Result selectScenario(final XdmNode document) { - final Result result; - final List collect = this.scenarios.getScenario().stream().filter(s -> match(document, s)) + public Result selectScenario(final XdmNode document) { + final Result result; + final List collect = getScenarios().stream().filter(s -> match(document, s)) .collect(Collectors.toList()); if (collect.size() == 1) { result = new Result<>(collect.get(0)); @@ -162,23 +89,9 @@ public class ScenarioRepository { } - private ScenarioType createFallback() { - final ScenarioType t = new ScenarioType(); - t.setFallback(true); - t.setName("Fallback-Scenario"); - t.setMatch("count(/)<0"); - final CreateReportType reportType = new CreateReportType(); - reportType.setResource(this.scenarios.getNoScenarioReport().getResource()); - t.initialize(this.repository, true); - // always reject - t.setAcceptMatch("count(/)<0"); - t.setCreateReport(reportType); - return t; - } - - private static boolean match(final XdmNode document, final ScenarioType scenario) { + private static boolean match(final XdmNode document, final Scenario scenario) { try { - final XPathSelector selector = scenario.getSelector(); + final XPathSelector selector = scenario.getMatchSelector(); selector.setContextItem(document); return selector.effectiveBooleanValue(); } catch (final SaxonApiException e) { @@ -187,7 +100,4 @@ public class ScenarioRepository { return false; } - void initialize(final 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 deleted file mode 100644 index c92ebaa..0000000 --- a/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * 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.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.validation.Schema; - -import org.apache.commons.lang3.NotImplementedException; - -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.CreateReportType; -import de.kosit.validationtool.model.scenarios.NamespaceType; -import de.kosit.validationtool.model.scenarios.ResourceType; -import de.kosit.validationtool.model.scenarios.ValidateWithSchematron; -import de.kosit.validationtool.model.scenarios.ValidateWithXmlSchema; - -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 - */ -@XmlAccessorType(XmlAccessType.NONE) -public abstract class BaseScenario { - - /** - * Laufzeitinformationen über eine Transformation. - */ - @Getter - @Setter - @AllArgsConstructor - public static class Transformation { - - private XsltExecutable executable; - - private ResourceType resourceType; - } - - @XmlTransient - @Getter - @Setter - private boolean fallback; - - private XPathExecutable matchExecutable; - - private XPathExecutable acceptExecutable; - - @Setter - @XmlTransient - private Schema schema; - - @Setter - private List schematronValidations; - - private ContentRepository repository; - - private Transformation reportTransformation; - - /** - * Gibt eine Transformation zurück. - * - * @return initialisierte Transformation - */ - public Transformation getReportTransformation() { - if (this.reportTransformation == null) { - final ResourceType resource = getCreateReport().getResource(); - final XsltExecutable executable = this.repository.loadXsltScript(URI.create(resource.getLocation())); - this.reportTransformation = new Transformation(executable, resource); - } - return this.reportTransformation; - } - - /** - * Lieferrt das Schema zu diesem Szenario. - * - * @return das passende Schema - */ - public Schema getSchema() { - if (this.schema == null && getValidateWithXmlSchema() != null) { - final List schemaResources = getValidateWithXmlSchema().getResource().stream().map(ResourceType::getLocation) - .collect(Collectors.toList()); - this.schema = this.repository.createSchema(schemaResources); - } - return this.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(final ContentRepository repository, final 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 (this.schematronValidations == null) { - this.schematronValidations = new ArrayList<>(); - getValidateWithSchematron().forEach(v -> { - if (v.isPsvi()) { - throw new NotImplementedException("This implemenation does not support PSVI usage"); - } - final XsltExecutable xsltExecutable = this.repository.loadXsltScript(URI.create(v.getResource().getLocation())); - this.schematronValidations.add(new Transformation(xsltExecutable, v.getResource())); - }); - } - return this.schematronValidations; - } - - /** - * Der XPath-Selector zur Identifikation des Scenarios. - * - * @return vorbereiteten selector - * @see ScenarioRepository#selectScenario(net.sf.saxon.s9api.XdmNode) - */ - public XPathSelector getSelector() { - if (this.matchExecutable == null) { - this.matchExecutable = this.repository.createXPath(getMatch(), prepareNamespaces()); - } - return this.matchExecutable.load(); - } - - /** - * Liefert einen neuen XPath-Selector zur Evaluierung der {@link de.kosit.validationtool.api.AcceptRecommendation}. - * - * @return neuer Selector - */ - public XPathSelector getAcceptSelector() { - if (this.acceptExecutable == null) { - this.acceptExecutable = this.repository.createXPath(getAcceptMatch(), prepareNamespaces()); - } - return this.acceptExecutable.load(); - } - - private Map prepareNamespaces() { - return getNamespace().stream().collect(Collectors.toMap(NamespaceType::getPrefix, NamespaceType::getValue)); - } - - /** - * Getter aus dem schema. - * - * @return xpath match - */ - public abstract String getMatch(); - - public abstract String getAcceptMatch(); - - /** - * 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(); - -} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java index bc362c5..23d6476 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CheckAction.java @@ -30,11 +30,11 @@ import lombok.Setter; import de.kosit.validationtool.api.AcceptRecommendation; import de.kosit.validationtool.api.Input; +import de.kosit.validationtool.impl.Scenario; 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.reportInput.XMLSyntaxError; -import de.kosit.validationtool.model.scenarios.ScenarioType; import net.sf.saxon.s9api.XdmNode; @@ -55,7 +55,7 @@ public interface CheckAction { @Setter class Bag { - private Result scenarioSelectionResult; + private Result scenarioSelectionResult; @Setter(AccessLevel.NONE) private CreateReportInput reportInput; diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java index f4c5ca2..3e5db25 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java @@ -1,6 +1,6 @@ package de.kosit.validationtool.impl.tasks; -import static org.apache.commons.lang3.StringUtils.isNotBlank; +import java.util.Optional; import org.oclc.purl.dsdl.svrl.FailedAssert; @@ -25,9 +25,9 @@ public class ComputeAcceptanceAction implements CheckAction { @Override public void check(final Bag results) { if (preCondtionsMatch(results)) { - final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch(); - if (results.getSchemaValidationResult().isValid() && isNotBlank(acceptMatch)) { - evaluateAcceptanceMatch(results); + final Optional acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptSelector(); + if (results.getSchemaValidationResult().isValid() && acceptMatch.isPresent()) { + evaluateAcceptanceMatch(results, acceptMatch.get()); } else { evaluateSchemaAndSchematron(results); } @@ -53,9 +53,8 @@ public class ComputeAcceptanceAction implements CheckAction { .flatMap(e -> e.getActivePatternAndFiredRuleAndFailedAssert().stream()).anyMatch(FailedAssert.class::isInstance); } - private static void evaluateAcceptanceMatch(final Bag results) { + private static void evaluateAcceptanceMatch(final Bag results, final XPathSelector selector) { try { - final XPathSelector selector = results.getScenarioSelectionResult().getObject().getAcceptSelector(); selector.setContextItem(results.getReport()); results.setAcceptStatus(selector.effectiveBooleanValue() ? AcceptRecommendation.ACCEPTABLE : AcceptRecommendation.REJECT); } catch (final SaxonApiException e) { diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java index 9809479..cfd9ad2 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java @@ -22,6 +22,7 @@ package de.kosit.validationtool.impl.tasks; import java.util.Collection; import java.util.stream.Collectors; +import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Document; @@ -35,10 +36,8 @@ import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.EngineInformation; import de.kosit.validationtool.impl.ObjectFactory; -import de.kosit.validationtool.impl.RelativeUriResolver; -import de.kosit.validationtool.impl.ScenarioRepository; +import de.kosit.validationtool.impl.Scenario; import de.kosit.validationtool.model.reportInput.XMLSyntaxError; -import de.kosit.validationtool.model.scenarios.ScenarioType; import net.sf.saxon.s9api.BuildingContentHandler; import net.sf.saxon.s9api.DocumentBuilder; @@ -64,11 +63,9 @@ public class CreateReportAction implements CheckAction { private final ConversionService conversionService; - private final ScenarioRepository scenarioRepository; - private final ContentRepository contentRepository; - private static XsltExecutable loadFromScenario(final ScenarioType object) { + private static XsltExecutable loadFromScenario(final Scenario object) { return object.getReportTransformation().getExecutable(); } @@ -85,10 +82,10 @@ public class CreateReportAction implements CheckAction { final XsltTransformer transformer = getTransformation(results).load(); transformer.setInitialContextNode(root); final CollectingErrorEventHandler e = new CollectingErrorEventHandler(); - final RelativeUriResolver resolver = this.contentRepository.createResolver(); + final URIResolver resolver = this.contentRepository.createResolver(); transformer.setMessageListener(e); transformer.setURIResolver(resolver); - transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver); + // transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver); if (parsedDocument != null) { transformer.setParameter(new QName("input-document"), parsedDocument); } diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java index 63a11f6..90b5c46 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ScenarioSelectionAction.java @@ -22,10 +22,10 @@ package de.kosit.validationtool.impl.tasks; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import de.kosit.validationtool.impl.Scenario; 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.scenarios.ScenarioType; import net.sf.saxon.s9api.XdmNode; @@ -44,7 +44,7 @@ public class ScenarioSelectionAction implements CheckAction { @Override public void check(final Bag results) { final CreateReportInput report = results.getReportInput(); - final Result scenarioTypeResult; + final Result scenarioTypeResult; if (results.getParserResult().isValid()) { scenarioTypeResult = determineScenario(results.getParserResult().getObject()); @@ -53,15 +53,15 @@ public class ScenarioSelectionAction implements CheckAction { } results.setScenarioSelectionResult(scenarioTypeResult); if (!scenarioTypeResult.getObject().isFallback()) { - report.setScenario(scenarioTypeResult.getObject()); + report.setScenario(scenarioTypeResult.getObject().getConfiguration()); log.info("Schenario {} identified for {}", scenarioTypeResult.getObject().getName(), results.getInput().getName()); } else { log.error("No valid schenario configuration found for {}", results.getInput().getName()); } } - private Result determineScenario(final XdmNode document) { - final Result result = this.repository.selectScenario(document); + private Result determineScenario(final XdmNode document) { + final Result result = this.repository.selectScenario(document); if (result.isInvalid()) { return new Result<>(this.repository.getFallbackScenario()); } diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java index f3859e4..89ddd7c 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchemaValidationAction.java @@ -42,12 +42,12 @@ import lombok.extern.slf4j.Slf4j; import de.kosit.validationtool.api.Input; import de.kosit.validationtool.impl.CollectingErrorEventHandler; import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.Scenario; import de.kosit.validationtool.impl.input.AbstractInput; 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; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.Serializer; @@ -132,17 +132,17 @@ public class SchemaValidationAction implements CheckAction { @Getter private long inMemoryLimit = Long.parseLong(System.getProperty(LIMIT_PARAMETER, BA_LIMIT.toString())) * FileUtils.ONE_MB; - private Result validate(final Bag results, final ScenarioType scenarioType) { - log.debug("Validating document using scenario {}", scenarioType.getName()); + private Result validate(final Bag results, final Scenario scenario) { + log.debug("Validating document using scenario {}", scenario.getConfiguration().getName()); final CollectingErrorEventHandler errorHandler = new CollectingErrorEventHandler(); try ( final SourceProvider validateInput = resolveSource(results) ) { - final Validator validator = ObjectFactory.createValidator(scenarioType.getSchema()); + final Validator validator = ObjectFactory.createValidator(scenario.getSchema()); validator.setErrorHandler(errorHandler); validator.validate(validateInput.getSource()); return new Result<>(!errorHandler.hasErrors(), errorHandler.getErrors()); } catch (final SAXException | SaxonApiException | IOException e) { - final String msg = String.format("Error processing schema validation for scenario %s", scenarioType.getName()); + final String msg = String.format("Error processing schema validation for scenario %s", scenario.getConfiguration().getName()); log.error(msg, e); results.addProcessingError(msg); return new Result<>(Boolean.FALSE); @@ -152,14 +152,14 @@ public class SchemaValidationAction implements CheckAction { @Override public void check(final Bag results) { final CreateReportInput report = results.getReportInput(); - final ScenarioType scenario = results.getScenarioSelectionResult().getObject(); + final Scenario scenario = results.getScenarioSelectionResult().getObject(); final Result validateResult = validate(results, scenario); results.setSchemaValidationResult(validateResult); final ValidationResultsXmlSchema result = new ValidationResultsXmlSchema(); report.setValidationResultsXmlSchema(result); - result.getResource().addAll(scenario.getValidateWithXmlSchema().getResource()); + result.getResource().addAll(scenario.getConfiguration().getValidateWithXmlSchema().getResource()); if (!validateResult.isValid()) { result.getXmlSyntaxError().addAll(validateResult.getErrors()); } diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java index 531ef4f..377e195 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java @@ -22,6 +22,7 @@ package de.kosit.validationtool.impl.tasks; import java.util.List; import java.util.stream.Collectors; +import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; import org.oclc.purl.dsdl.svrl.SchematronOutput; @@ -34,11 +35,9 @@ import de.kosit.validationtool.impl.CollectingErrorEventHandler; import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.ObjectFactory; -import de.kosit.validationtool.impl.RelativeUriResolver; -import de.kosit.validationtool.impl.model.BaseScenario; +import de.kosit.validationtool.impl.Scenario; 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.DOMDestination; import net.sf.saxon.s9api.SaxonApiException; @@ -58,17 +57,17 @@ public class SchematronValidationAction implements CheckAction { private final ConversionService conversionService; - private List validate(final Bag results, final XdmNode document, final ScenarioType scenario) { + private List validate(final Bag results, final XdmNode document, final Scenario scenario) { return scenario.getSchematronValidations().stream().map(v -> validate(results, document, v)).collect(Collectors.toList()); } - private ValidationResultsSchematron validate(final Bag results, final XdmNode document, final BaseScenario.Transformation validation) { + private ValidationResultsSchematron validate(final Bag results, final XdmNode document, final Scenario.Transformation validation) { final ValidationResultsSchematron s = new ValidationResultsSchematron(); s.setResource(validation.getResourceType()); try { final XsltTransformer transformer = validation.getExecutable().load(); // resolving nur relative zum Repository - final RelativeUriResolver resolver = this.repository.createResolver(); + final URIResolver resolver = this.repository.createResolver(); transformer.setURIResolver(resolver); final CollectingErrorEventHandler e = new CollectingErrorEventHandler(); transformer.setMessageListener(e); @@ -107,7 +106,7 @@ public class SchematronValidationAction implements CheckAction { return results.getSchemaValidationResult() == null || results.getSchemaValidationResult().isInvalid(); } - private static boolean hasNoSchematrons(final ScenarioType object) { - return object.getValidateWithSchematron() == null || object.getValidateWithSchematron().size() == 0; + private static boolean hasNoSchematrons(final Scenario object) { + return object.getSchematronValidations().isEmpty(); } } diff --git a/src/main/model/binding/global.xjb b/src/main/model/binding/global.xjb index b8e336f..33eced9 100644 --- a/src/main/model/binding/global.xjb +++ b/src/main/model/binding/global.xjb @@ -42,9 +42,6 @@ - - de.kosit.validationtool.impl.model.BaseScenario - diff --git a/src/test/java/de/kosit/validationtool/impl/ContentRepositoryTest.java b/src/test/java/de/kosit/validationtool/impl/ContentRepositoryTest.java index e70948b..4eb20cb 100644 --- a/src/test/java/de/kosit/validationtool/impl/ContentRepositoryTest.java +++ b/src/test/java/de/kosit/validationtool/impl/ContentRepositoryTest.java @@ -42,7 +42,7 @@ import net.sf.saxon.s9api.XPathExecutable; import net.sf.saxon.s9api.XsltExecutable; /** - * Testet das ContentRepository. + * Testet das repository. * * @author Andreas Penski */ @@ -60,7 +60,7 @@ public class ContentRepositoryTest { @Test public void testCreateSchema() throws MalformedURLException { - final Schema schema = ContentRepository.createSchema(Helper.ASSERTION_SCHEMA.toURL()); + final Schema schema = this.repository.createSchema(Helper.ASSERTION_SCHEMA.toURL()); assertThat(schema).isNotNull(); } @@ -73,7 +73,7 @@ public class ContentRepositoryTest { @Test public void testCreateSchemaNotExisting() throws Exception { this.exception.expect(IllegalStateException.class); - ContentRepository.createSchema(Simple.NOT_EXISTING.toURL()); + this.repository.createSchema(Simple.NOT_EXISTING.toURL()); } @Test @@ -122,16 +122,26 @@ public class ContentRepositoryTest { @Test public void testLoadSchema() { final URL main = RelativeUriResolverTest.class.getClassLoader().getResource("loading/main.xsd"); - final Schema schema = ContentRepository.createSchema(main, new ClassPathResourceResolver("/loading")); + final Schema schema = this.repository.createSchema(main, new ClassPathResourceResolver("/loading")); assertThat(schema).isNotNull(); } @Test public void testLoadSchemaPackaged() throws URISyntaxException { final URL main = RelativeUriResolverTest.class.getClassLoader().getResource("packaged/main.xsd"); - final Schema schema = ContentRepository.createSchema(main, + final Schema schema = this.repository.createSchema(main, new ClassPathResourceResolver(RelativeUriResolverTest.class.getClassLoader().getResource("packaged/").toURI())); assertThat(schema).isNotNull(); } + // @Test + // public void loadFromJar() throws URISyntaxException { + // this.content = new ContentRepository(ObjectFactory.createProcessor(), Helper.JAR_REPOSITORY.toURI()); + // this.repository = new ScenarioRepository(this.content); + // final CheckConfiguration conf = new CheckConfiguration( + // ScenarioRepository.class.getClassLoader().getResource("xrechnung/scenarios.xml").toURI()); + // ScenarioRepository.initialize(conf); + // assertThat(this.repository.getScenarios()).isNotNull(); + // } + } diff --git a/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java b/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java index 0353bac..60500c5 100644 --- a/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java +++ b/src/test/java/de/kosit/validationtool/impl/ConversionServiceTest.java @@ -72,7 +72,7 @@ public class ConversionServiceTest { } @Test - public void testUnmarshal() throws URISyntaxException { + public void testUnmarshal() { final Scenarios s = this.service.readXml(Simple.SCENARIOS, Scenarios.class); assertThat(s).isNotNull(); assertThat(s.getName()).isEqualToIgnoringCase("HTML-TestSuite"); @@ -80,7 +80,7 @@ public class ConversionServiceTest { @Test public void testUnmarshalWithSchema() { - final Scenarios s = this.service.readXml(Simple.SCENARIOS, Scenarios.class, ContentRepository.createSchema(SCHEMA)); + final Scenarios s = this.service.readXml(Simple.SCENARIOS, Scenarios.class, this.repository.createSchema(SCHEMA)); assertThat(s).isNotNull(); assertThat(s.getName()).isEqualToIgnoringCase("HTML-TestSuite"); } @@ -88,13 +88,13 @@ public class ConversionServiceTest { @Test public void testUnmarshalInvalidXml() { this.exception.expect(ConversionService.ConversionExeption.class); - this.service.readXml(Invalid.SCENARIOS, Scenarios.class, ContentRepository.createSchema(SCHEMA)); + this.service.readXml(Invalid.SCENARIOS, Scenarios.class, this.repository.createSchema(SCHEMA)); } @Test public void testUnmarshalIllFormed() { this.exception.expect(ConversionService.ConversionExeption.class); - this.service.readXml(Invalid.SCENARIOS_ILLFORMED, Scenarios.class, ContentRepository.createSchema(SCHEMA)); + this.service.readXml(Invalid.SCENARIOS_ILLFORMED, Scenarios.class, this.repository.createSchema(SCHEMA)); } @Test diff --git a/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java b/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java index abfab1d..e450050 100644 --- a/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java +++ b/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java @@ -24,20 +24,25 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; import java.net.URI; -import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import de.kosit.validationtool.api.CheckConfiguration; +import lombok.Data; + +import de.kosit.validationtool.api.Configuration; import de.kosit.validationtool.impl.Helper.Simple; 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; +import net.sf.saxon.s9api.Processor; +import net.sf.saxon.s9api.XPathExecutable; import net.sf.saxon.s9api.XdmNode; /** @@ -48,57 +53,84 @@ import net.sf.saxon.s9api.XdmNode; public class ScenarioRepositoryTest { + @Data + private static class DummyConfiguration implements Configuration { + + private List scenarios; + + private Scenario fallbackScenario; + + private String author; + + private String name; + + private String date; + + private Processor processor; + + private ContentRepository contentRepository; + + @Override + public void build() { + // nothing + } + } + @Rule public ExpectedException expectedException = ExpectedException.none(); - ContentRepository content; - private ScenarioRepository repository; + private DummyConfiguration configInstance; + @Before public void setup() { - this.content = new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY); - final Scenarios def = new Scenarios(); - final ScenarioType t = new ScenarioType(); - t.setMatch("//*:name"); - t.setName("Test"); - t.initialize(this.content, true); - def.getScenario().add(t); - this.repository = new ScenarioRepository(this.content); - this.repository.initialize(def); + final Scenario s = createScenario(); + + this.configInstance = new DummyConfiguration(); + this.configInstance.setScenarios(new ArrayList<>()); + this.configInstance.getScenarios().add(s); + this.repository = new ScenarioRepository(this.configInstance); + } + + private static Scenario createScenario() { + final Scenario s = new Scenario(new ScenarioType()); + s.setMatchExecutable(createXpath("//*:name")); + return s; } @Test public void testHappyCase() throws Exception { - final Result scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); + final Result scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); assertThat(scenario).isNotNull(); assertThat(scenario.isValid()).isTrue(); } @Test public void testNonMatch() throws Exception { - this.repository.getScenarios().getScenario().clear(); - final ScenarioType fallback = new ScenarioType(); - fallback.setName("fallback"); - this.repository.setFallbackScenario(fallback); - final Result scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); + this.configInstance.setScenarios(new ArrayList<>()); + final Scenario fallback = createFallback(); + this.configInstance.setFallbackScenario(fallback); + final Result scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); assertThat(scenario).isNotNull(); assertThat(scenario.isValid()).isFalse(); assertThat(scenario.getObject().getName()).isEqualTo("fallback"); } + private static Scenario createFallback() { + final ScenarioType t = new ScenarioType(); + t.setName("fallback"); + final Scenario fallback = new Scenario(t); + fallback.setFallback(true); + return fallback; + } + @Test public void testMultiMatch() throws Exception { - final ScenarioType t = new ScenarioType(); - t.setMatch("//*:name"); - t.setName("Test"); - t.initialize(this.content, true); - this.repository.getScenarios().getScenario().add(t); - final ScenarioType fallback = new ScenarioType(); - fallback.setName("fallback"); - this.repository.setFallbackScenario(fallback); - final Result scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); + this.configInstance.getScenarios().add(createScenario()); + this.configInstance.setFallbackScenario(createFallback()); + final Result scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); assertThat(scenario).isNotNull(); assertThat(scenario.isValid()).isFalse(); assertThat(scenario.getObject().getName()).isEqualTo("fallback"); @@ -109,14 +141,7 @@ public class ScenarioRepositoryTest { return DocumentParseAction.parseDocument(read(uri.toURL())).getObject(); } - @Test - public void loadFromJar() throws URISyntaxException { - this.content = new ContentRepository(ObjectFactory.createProcessor(), Helper.JAR_REPOSITORY.toURI()); - this.repository = new ScenarioRepository(this.content); - final CheckConfiguration conf = new CheckConfiguration( - ScenarioRepository.class.getClassLoader().getResource("xrechnung/scenarios.xml").toURI()); - this.repository.initialize(conf); - assertThat(this.repository.getScenarios()).isNotNull(); + private static XPathExecutable createXpath(final String expression) { + return new ContentRepository(ObjectFactory.createProcessor(), null).createXPath(expression, new HashMap<>()); } - } diff --git a/src/test/java/de/kosit/validationtool/impl/VersioningTest.java b/src/test/java/de/kosit/validationtool/impl/VersioningTest.java index 661db36..ff67943 100644 --- a/src/test/java/de/kosit/validationtool/impl/VersioningTest.java +++ b/src/test/java/de/kosit/validationtool/impl/VersioningTest.java @@ -29,6 +29,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import de.kosit.validationtool.impl.Helper.Simple; import de.kosit.validationtool.model.scenarios.Scenarios; /** @@ -51,33 +52,35 @@ public class VersioningTest { private ConversionService service; + private ContentRepository repository; @Before public void setup() { + this.repository = new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY); this.service = new ConversionService(); } @Test public void testBase() throws URISyntaxException { - final Scenarios result = this.service.readXml(BASE.toURI(), Scenarios.class, ContentRepository.getScenarioSchema()); + final Scenarios result = this.service.readXml(BASE.toURI(), Scenarios.class, this.repository.getScenarioSchema()); assertThat(result).isNotNull(); } @Test public void testFrameworkIncrement() throws URISyntaxException { - final Scenarios result = this.service.readXml(INCREMENT.toURI(), Scenarios.class, ContentRepository.getScenarioSchema()); + final Scenarios result = this.service.readXml(INCREMENT.toURI(), Scenarios.class, this.repository.getScenarioSchema()); assertThat(result).isNotNull(); } @Test public void testNewFeature() throws URISyntaxException { this.exception.expect(ConversionService.ConversionExeption.class); - this.service.readXml(NEW_FEATURE.toURI(), Scenarios.class, ContentRepository.getScenarioSchema()); + this.service.readXml(NEW_FEATURE.toURI(), Scenarios.class, this.repository.getScenarioSchema()); } @Test public void testNewVersion() throws URISyntaxException { this.exception.expect(ConversionService.ConversionExeption.class); - this.service.readXml(NEW_VERSION.toURI(), Scenarios.class, ContentRepository.getScenarioSchema()); + this.service.readXml(NEW_VERSION.toURI(), Scenarios.class, this.repository.getScenarioSchema()); } } diff --git a/src/test/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceActionTest.java b/src/test/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceActionTest.java index 53c9885..0065997 100644 --- a/src/test/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceActionTest.java +++ b/src/test/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceActionTest.java @@ -4,12 +4,17 @@ import static de.kosit.validationtool.impl.tasks.TestBagBuilder.createBag; import static org.assertj.core.api.Assertions.assertThat; import java.util.Collections; +import java.util.HashMap; import org.junit.Test; import de.kosit.validationtool.api.AcceptRecommendation; +import de.kosit.validationtool.impl.ContentRepository; +import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.tasks.CheckAction.Bag; +import net.sf.saxon.s9api.XPathExecutable; + /** * Tests the 'acceptMatch' functionality. * @@ -44,7 +49,7 @@ public class ComputeAcceptanceActionTest { @Test public void testValidAcceptMatch() { final Bag bag = createBag(true, true); - bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 0"); + bag.getScenarioSelectionResult().getObject().setAcceptExecutable(createXpath("count(//doesnotExist) = 0")); this.action.check(bag); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE); } @@ -52,7 +57,7 @@ public class ComputeAcceptanceActionTest { @Test public void testAcceptMatchNotSatisfied() { final Bag bag = createBag(true, true); - bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 1"); + bag.getScenarioSelectionResult().getObject().setAcceptExecutable(createXpath("count(//doesnotExist) = 1")); this.action.check(bag); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT); } @@ -60,7 +65,7 @@ public class ComputeAcceptanceActionTest { @Test public void testAcceptMatchOverridesSchematronErrors() { final Bag bag = createBag(true, false); - bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 0"); + bag.getScenarioSelectionResult().getObject().setAcceptExecutable(createXpath("count(//doesnotExist) = 0")); this.action.check(bag); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE); } @@ -68,7 +73,7 @@ public class ComputeAcceptanceActionTest { @Test public void testValidAcceptMatchOnSchemaFailed() { final Bag bag = createBag(false, true); - bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 0"); + bag.getScenarioSelectionResult().getObject().setAcceptExecutable(createXpath("count(//doesnotExist) = 0")); this.action.check(bag); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT); } @@ -98,4 +103,7 @@ public class ComputeAcceptanceActionTest { } + private static XPathExecutable createXpath(final String expression) { + return new ContentRepository(ObjectFactory.createProcessor(), null).createXPath(expression, new HashMap<>()); + } } diff --git a/src/test/java/de/kosit/validationtool/impl/tasks/SchemaValidatorActionTest.java b/src/test/java/de/kosit/validationtool/impl/tasks/SchemaValidatorActionTest.java index d720475..354076e 100644 --- a/src/test/java/de/kosit/validationtool/impl/tasks/SchemaValidatorActionTest.java +++ b/src/test/java/de/kosit/validationtool/impl/tasks/SchemaValidatorActionTest.java @@ -46,9 +46,9 @@ import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.Helper.Simple; import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.Scenario; import de.kosit.validationtool.impl.input.SourceInput; import de.kosit.validationtool.impl.tasks.CheckAction.Bag; -import de.kosit.validationtool.model.scenarios.ScenarioType; /** * Tests die {@link SchemaValidationAction}. @@ -154,7 +154,7 @@ public class SchemaValidatorActionTest { @Test public void testProcessingError() throws IOException, SAXException { final CheckAction.Bag bag = createBag(InputFactory.read(Simple.SIMPLE_VALID.toURL())); - final ScenarioType scenario = bag.getScenarioSelectionResult().getObject(); + final Scenario scenario = bag.getScenarioSelectionResult().getObject(); final Schema schema = mock(Schema.class); final Validator validator = mock(Validator.class); when(schema.newValidator()).thenReturn(validator); diff --git a/src/test/java/de/kosit/validationtool/impl/tasks/SchematronValidationActionTest.java b/src/test/java/de/kosit/validationtool/impl/tasks/SchematronValidationActionTest.java index 6a9a868..80b7176 100644 --- a/src/test/java/de/kosit/validationtool/impl/tasks/SchematronValidationActionTest.java +++ b/src/test/java/de/kosit/validationtool/impl/tasks/SchematronValidationActionTest.java @@ -17,9 +17,9 @@ import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.Helper.Simple; import de.kosit.validationtool.impl.ObjectFactory; -import de.kosit.validationtool.impl.model.BaseScenario.Transformation; +import de.kosit.validationtool.impl.Scenario; +import de.kosit.validationtool.impl.Scenario.Transformation; import de.kosit.validationtool.model.scenarios.ResourceType; -import de.kosit.validationtool.model.scenarios.ScenarioType; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.XsltExecutable; @@ -44,7 +44,7 @@ public class SchematronValidationActionTest { public void testProcessingError() throws IOException, SaxonApiException { final CheckAction.Bag bag = createBag(InputFactory.read(Simple.SIMPLE_VALID.toURL()), true); - final ScenarioType scenario = bag.getScenarioSelectionResult().getObject(); + final Scenario scenario = bag.getScenarioSelectionResult().getObject(); final XsltExecutable exec = mock(XsltExecutable.class); final XsltTransformer transformer = mock(XsltTransformer.class); doThrow(new SaxonApiException("invalid")).when(transformer).transform(); diff --git a/src/test/java/de/kosit/validationtool/impl/tasks/TestBagBuilder.java b/src/test/java/de/kosit/validationtool/impl/tasks/TestBagBuilder.java index 0626a66..78a14f5 100644 --- a/src/test/java/de/kosit/validationtool/impl/tasks/TestBagBuilder.java +++ b/src/test/java/de/kosit/validationtool/impl/tasks/TestBagBuilder.java @@ -1,10 +1,14 @@ package de.kosit.validationtool.impl.tasks; +import java.net.MalformedURLException; import java.net.URI; +import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.List; +import javax.xml.validation.Schema; + import org.oclc.purl.dsdl.svrl.FailedAssert; import org.oclc.purl.dsdl.svrl.SchematronOutput; @@ -12,8 +16,8 @@ import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.Helper; -import de.kosit.validationtool.impl.Helper.Simple; import de.kosit.validationtool.impl.ObjectFactory; +import de.kosit.validationtool.impl.Scenario; import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.tasks.CheckAction.Bag; import de.kosit.validationtool.model.reportInput.CreateReportInput; @@ -50,8 +54,9 @@ public class TestBagBuilder { return bag; } - private static ScenarioType createScenario(final URI schemafile) { - final ContentRepository repository = new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY); + private static Scenario createScenario(final URI schemafile) { + + try { final ScenarioType t = new ScenarioType(); final ValidateWithXmlSchema v = new ValidateWithXmlSchema(); final ResourceType r = new ResourceType(); @@ -59,8 +64,16 @@ public class TestBagBuilder { r.setName("invoice"); v.getResource().add(r); t.setValidateWithXmlSchema(v); - t.initialize(repository, true); - return t; + final Scenario scenario = new Scenario(t); + scenario.setSchema(createSchema(schemafile.toURL())); + return scenario; + } catch (final MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } + + private static Schema createSchema(final URL toURL) { + return new ContentRepository(ObjectFactory.createProcessor(), null).createSchema(toURL); } private static XdmNode createReport() {