Refactor: don't reuse JAXB objects for internal configuration; create a Configuration interface.

This commit is contained in:
Andreas Penski (init) 2020-04-21 08:34:56 +02:00
parent c8b3c1977c
commit 7a86f049ac
30 changed files with 871 additions and 517 deletions

View file

@ -20,24 +20,31 @@
package de.kosit.validationtool.api; package de.kosit.validationtool.api;
import java.net.URI; import java.net.URI;
import java.util.List;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; 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. * Zentrale Konfigration einer Prüf-Instanz.
* *
* @author Andreas Penski * @author Andreas Penski
* @deprecated since 2.0 use {@link Configuration} instead
*/ */
@Getter @Getter
@Setter @Setter
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
public class CheckConfiguration { @Deprecated
public class CheckConfiguration implements Configuration {
/** /**
* URL, die auf die scenerio.xml Datei zeigt. * URL, die auf die scenerio.xml Datei zeigt.
@ -49,22 +56,52 @@ public class CheckConfiguration {
*/ */
private URI scenarioRepository; private URI scenarioRepository;
private LoadConfiguration delegate;
/** private LoadConfiguration getDelegate() {
* Liefert das Repository mit den Artefakten der einzelnen Szenarien. if (this.delegate == null) {
* this.delegate = Configuration.load(this.scenarioDefinition, this.scenarioRepository);
* @return uri die durch entsprechende resolver aufgelöst werden kann
*/
public URI getScenarioRepository() {
if (this.scenarioRepository == null) {
this.scenarioRepository = createDefaultRepository();
} }
return this.scenarioRepository; return this.delegate;
} }
private URI createDefaultRepository() { @Override
log.info("Creating default scenario repository (alongside scenario definition)"); public List<Scenario> getScenarios() {
return RelativeUriResolver.resolve(URI.create("."), this.scenarioDefinition); 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();
}
} }

View file

@ -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:
*
* <ol>
* <li>{@link LoadConfiguration} implements loading {@link Check} configurations from a scenario.xml file</li>
* <li>Using a builder style api {@link de.kosit.validationtool.config.ConfigurationBuilder}to configure the
* {@link Check}</li>
* </ol>
*
* Both methods can be used via convinience methods. See below.
*
* @author Andreas Penski
*/
public interface Configuration {
List<Scenario> 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();
}

View file

@ -27,11 +27,11 @@ import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Check; import de.kosit.validationtool.api.Check;
import de.kosit.validationtool.api.CheckConfiguration; import de.kosit.validationtool.api.CheckConfiguration;
import de.kosit.validationtool.api.Configuration;
import de.kosit.validationtool.api.InputFactory; import de.kosit.validationtool.api.InputFactory;
import de.kosit.validationtool.impl.DefaultCheck; import de.kosit.validationtool.impl.DefaultCheck;
import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.input.SourceInput; 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. * HTTP-Daemon für die Bereitstellung der Prüf-Funktionalität via http.
@ -98,10 +98,10 @@ class Daemon {
@Slf4j @Slf4j
static class HealthHandler implements HttpHandler { static class HealthHandler implements HttpHandler {
private final Scenarios scenarios; private final Configuration scenarios;
HealthHandler(final Scenarios scenarios) { HealthHandler(final Configuration config) {
this.scenarios = scenarios; this.scenarios = config;
} }
@Override @Override
@ -188,7 +188,7 @@ class Daemon {
server = HttpServer.create(new InetSocketAddress(this.hostName, this.port), 0); server = HttpServer.create(new InetSocketAddress(this.hostName, this.port), 0);
final DefaultCheck check = new DefaultCheck(config); final DefaultCheck check = new DefaultCheck(config);
server.createContext("/", new HttpServerHandler(check)); 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.setExecutor(Executors.newFixedThreadPool(this.threadCount));
server.start(); server.start();
log.info("Server unter Port {} ist erfolgreich gestartet", this.port); log.info("Server unter Port {} ist erfolgreich gestartet", this.port);

View file

@ -1,8 +1,6 @@
package de.kosit.validationtool.cmd; package de.kosit.validationtool.cmd;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
@ -10,7 +8,8 @@ import org.w3c.dom.Node;
import lombok.extern.slf4j.Slf4j; 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. * Klasse zur Erzeugung Health Xml , die optiamle Status.
@ -26,15 +25,15 @@ class Health {
private final long totalMemory; private final long totalMemory;
private final Scenarios scenarios; private final Configuration config;
Health(Scenarios scenarios) { Health(final Configuration config) {
Runtime runtime = Runtime.getRuntime(); final Runtime runtime = Runtime.getRuntime();
freeMemory = runtime.freeMemory(); this.freeMemory = runtime.freeMemory();
maxMemory = runtime.maxMemory(); this.maxMemory = runtime.maxMemory();
totalMemory = runtime.totalMemory(); this.totalMemory = runtime.totalMemory();
this.scenarios = scenarios; this.config = config;
} }
/** /**
@ -42,20 +41,13 @@ class Health {
* *
*/ */
Document writeHealthXml() { Document writeHealthXml() {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); final DocumentBuilder dBuilder = ObjectFactory.createDocumentBuilder(false);
DocumentBuilder dBuilder; final Document doc = dBuilder.newDocument();
Document doc = null; final Element rootElement = doc.createElementNS("https://localhost:8080/Health", "Health");
try { doc.appendChild(rootElement);
dBuilder = dbFactory.newDocumentBuilder(); rootElement.appendChild(getMemory(doc, this.freeMemory, this.maxMemory, this.totalMemory));
doc = dBuilder.newDocument(); rootElement.appendChild(getState(doc));
Element rootElement = doc.createElementNS("https://localhost:8080/Health", "Health"); rootElement.appendChild(getScenario(doc, this.config));
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);
}
return doc; return doc;
} }
@ -65,10 +57,10 @@ class Health {
* @param doc Vom Typ Dokument. * @param doc Vom Typ Dokument.
* *
*/ */
private Node getState(Document doc) { private static Node getState(final Document doc) {
Element state = doc.createElement("state"); final Element state = doc.createElement("state");
state.setAttribute("indicator", "OK"); 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")); stateNode.appendChild(doc.createTextNode("System is up and running normally"));
state.appendChild(stateNode); state.appendChild(stateNode);
return state; return state;
@ -78,13 +70,13 @@ class Health {
* Methode, die schreibt das Scnarios Information Node im Xml File * Methode, die schreibt das Scnarios Information Node im Xml File
* *
* @param doc Vom Typ Dokument . * @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) { private static Node getScenario(final Document doc, final Configuration config) {
Element scenario = doc.createElement("scenario"); final Element scenario = doc.createElement("scenario");
Element scenarioNameNode = doc.createElement("name"); final Element scenarioNameNode = doc.createElement("name");
scenarioNameNode.appendChild(doc.createTextNode(scenarios.getName())); scenarioNameNode.appendChild(doc.createTextNode(config.getName()));
scenario.appendChild(scenarioNameNode); scenario.appendChild(scenarioNameNode);
return scenario; return scenario;
} }
@ -98,18 +90,18 @@ class Health {
* @param totalMemory Vom Typ long , der Gesamte speicher. * @param totalMemory Vom Typ long , der Gesamte speicher.
* *
*/ */
private static Node getMemory(Document doc, long freeMemory, long maxMemory, long totalMemory) { private static Node getMemory(final Document doc, final long freeMemory, final long maxMemory, final long totalMemory) {
Element memory = doc.createElement("memoryState"); final Element memory = doc.createElement("memoryState");
String freeM = Long.toString(freeMemory); final String freeM = Long.toString(freeMemory);
Element freeMNode = doc.createElement("freeMemory"); final Element freeMNode = doc.createElement("freeMemory");
freeMNode.appendChild(doc.createTextNode(freeM)); freeMNode.appendChild(doc.createTextNode(freeM));
memory.appendChild(freeMNode); memory.appendChild(freeMNode);
String maxM = Long.toString(maxMemory); final String maxM = Long.toString(maxMemory);
Element maxMNode = doc.createElement("maxMemory"); final Element maxMNode = doc.createElement("maxMemory");
maxMNode.appendChild(doc.createTextNode(maxM)); maxMNode.appendChild(doc.createTextNode(maxM));
memory.appendChild(maxMNode); memory.appendChild(maxMNode);
String totalM = Long.toString(totalMemory); final String totalM = Long.toString(totalMemory);
Element totalMNode = doc.createElement("totalMemory"); final Element totalMNode = doc.createElement("totalMemory");
totalMNode.appendChild(doc.createTextNode(totalM)); totalMNode.appendChild(doc.createTextNode(totalM));
memory.appendChild(totalMNode); memory.appendChild(totalMNode);
return memory; return memory;

View file

@ -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<Scenario> 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<Scenario> 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();
}
}

View file

@ -0,0 +1,10 @@
package de.kosit.validationtool.config;
/**
* @author Andreas Penski
*/
public class ConfigurationBuilder {
private ScenarioBuilder scenarioBuilder;
}

View file

@ -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<XdmNode, XMLSyntaxError> 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<Scenario> 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<Scenario> 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;
}
}

View file

@ -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<String, String> 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;
}
}

View file

@ -24,9 +24,12 @@ import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors;
import javax.xml.transform.Source; import javax.xml.transform.Source;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource; import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema; import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory; import javax.xml.validation.SchemaFactory;
@ -39,6 +42,11 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; 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.Processor;
import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathCompiler; import net.sf.saxon.s9api.XPathCompiler;
@ -55,14 +63,16 @@ import net.sf.saxon.s9api.XsltExecutable;
@Slf4j @Slf4j
public class ContentRepository { public class ContentRepository {
private Schema reportInputSchema;
@Getter @Getter
private final Processor processor; private final Processor processor;
private final URI repository; 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 { try {
return new StreamSource(resource.openStream(), resource.toURI().getRawPath()); return new StreamSource(resource.openStream(), resource.toURI().getRawPath());
} catch (final IOException | URISyntaxException e) { } 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 { try {
final SchemaFactory sf = ObjectFactory.createSchemaFactory(); final SchemaFactory sf = ObjectFactory.createSchemaFactory();
sf.setResourceResolver(resourceResolver); 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); return createSchema(schemaSources, null);
} }
@ -116,11 +126,11 @@ public class ContentRepository {
* @param url die url * @param url die url
* @return das erzeugte Schema * @return das erzeugte Schema
*/ */
public static Schema createSchema(final URL url) { public Schema createSchema(final URL url) {
return createSchema(url, null); 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()); log.info("Load schema from source {}", url.getPath());
return createSchema(new Source[] { resolve(url) }, resourceResolver); return createSchema(new Source[] { resolve(url) }, resourceResolver);
} }
@ -130,7 +140,7 @@ public class ContentRepository {
* *
* @return Scenario-Schema * @return Scenario-Schema
*/ */
public static Schema getScenarioSchema() { public Schema getScenarioSchema() {
return createSchema(ContentRepository.class.getResource("/xsd/scenarios.xsd")); return createSchema(ContentRepository.class.getResource("/xsd/scenarios.xsd"));
} }
@ -140,11 +150,11 @@ public class ContentRepository {
* @return ReportInput-Schema * @return ReportInput-Schema
*/ */
public Schema getReportInputSchema() { public Schema getReportInputSchema() {
if (this.reportInputSchema == null) { if (reportInputSchema == null) {
final Source source = resolve(ContentRepository.class.getResource("/xsd/createReportInput.xsd")); 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)); 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<String> schemaResources = s.getValidateWithXmlSchema().getResource().stream().map(ResourceType::getLocation)
.collect(Collectors.toList());
schema = createSchema(schemaResources);
}
return schema;
}
private Source resolve(final URI source) { 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()); return new StreamSource(resolved.toASCIIString());
} }
@ -187,7 +212,30 @@ public class ContentRepository {
* *
* @return ein neuer Resolver * @return ein neuer Resolver
*/ */
public RelativeUriResolver createResolver() { public URIResolver createResolver() {
return new RelativeUriResolver(this.repository); 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<String, String> namespaces = s.getNamespace().stream()
.collect(Collectors.toMap(NamespaceType::getPrefix, NamespaceType::getValue));
return createXPath(s.getMatch(), namespaces);
}
public XPathExecutable createAccepptExecutable(final ScenarioType s) {
final Map<String, String> namespaces = s.getNamespace().stream()
.collect(Collectors.toMap(NamespaceType::getPrefix, NamespaceType::getValue));
return createXPath(s.getAcceptMatch(), namespaces);
} }
} }

View file

@ -28,7 +28,7 @@ import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Check; 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.Input;
import de.kosit.validationtool.api.Result; import de.kosit.validationtool.api.Result;
import de.kosit.validationtool.api.XmlError; import de.kosit.validationtool.api.XmlError;
@ -73,20 +73,22 @@ public class DefaultCheck implements Check {
* *
* @param configuration die Konfiguration * @param configuration die Konfiguration
*/ */
public DefaultCheck(final CheckConfiguration configuration) { public DefaultCheck(final Configuration configuration) {
final Processor processor = ObjectFactory.createProcessor(); final Processor processor = ObjectFactory.createProcessor();
this.conversionService = new ConversionService(); this.conversionService = new ConversionService();
this.contentRepository = new ContentRepository(processor, configuration.getScenarioRepository()); this.repository = new ScenarioRepository(configuration);
this.repository = new ScenarioRepository(this.contentRepository);
this.repository.initialize(configuration); // TODO get rid of it
this.contentRepository = configuration.getContentRepository();
this.checkSteps = new ArrayList<>(); this.checkSteps = new ArrayList<>();
this.checkSteps.add(new DocumentParseAction()); this.checkSteps.add(new DocumentParseAction());
this.checkSteps.add(new CreateDocumentIdentificationAction()); this.checkSteps.add(new CreateDocumentIdentificationAction());
this.checkSteps.add(new ScenarioSelectionAction(this.repository)); this.checkSteps.add(new ScenarioSelectionAction(this.repository));
this.checkSteps.add(new SchemaValidationAction()); this.checkSteps.add(new SchemaValidationAction());
this.checkSteps.add(new SchematronValidationAction(this.contentRepository, this.conversionService)); this.checkSteps.add(new SchematronValidationAction(this.contentRepository, this.conversionService));
this.checkSteps.add(new ValidateReportInputAction(this.conversionService, this.contentRepository.getReportInputSchema())); this.checkSteps
this.checkSteps.add(new CreateReportAction(processor, this.conversionService, this.repository, this.contentRepository)); .add(new ValidateReportInputAction(this.conversionService, configuration.getContentRepository().getReportInputSchema()));
this.checkSteps.add(new CreateReportAction(processor, this.conversionService, this.contentRepository));
this.checkSteps.add(new ComputeAcceptanceAction()); this.checkSteps.add(new ComputeAcceptanceAction());
} }
@ -139,5 +141,4 @@ public class DefaultCheck implements Check {
return (List<XmlError>) (List<?>) errors; return (List<XmlError>) (List<?>) errors;
} }
} }

View file

@ -207,7 +207,7 @@ public class ObjectFactory {
final SecureUriResolver resolver = new SecureUriResolver(); final SecureUriResolver resolver = new SecureUriResolver();
processor.getUnderlyingConfiguration().setCollectionFinder(resolver); processor.getUnderlyingConfiguration().setCollectionFinder(resolver);
processor.getUnderlyingConfiguration().setOutputURIResolver(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: //grundsätzlich Feature-konfiguration:
processor.setConfigurationProperty(FeatureKeys.DTD_VALIDATION, false); processor.setConfigurationProperty(FeatureKeys.DTD_VALIDATION, false);

View file

@ -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");
}
}

View file

@ -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<Transformation> schematronValidations;
private Transformation reportTransformation;
public List<Transformation> 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<XPathSelector> getAcceptSelector() {
final XPathSelector selector = this.acceptExecutable != null ? this.acceptExecutable.load() : null;
return Optional.ofNullable(selector);
}
}

View file

@ -19,34 +19,18 @@
package de.kosit.validationtool.impl; 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.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.CheckConfiguration; import de.kosit.validationtool.api.Configuration;
import de.kosit.validationtool.api.InputFactory;
import de.kosit.validationtool.impl.model.Result; 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.SaxonApiException;
import net.sf.saxon.s9api.XPathSelector; import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmNode; import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmNodeKind;
/** /**
* Repository for die aktiven Szenario einer Prüfinstanz. * Repository for die aktiven Szenario einer Prüfinstanz.
@ -54,86 +38,29 @@ import net.sf.saxon.s9api.XdmNodeKind;
* @author Andreas Penski * @author Andreas Penski
*/ */
@Slf4j @Slf4j
@RequiredArgsConstructor
public class ScenarioRepository { 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"; public ScenarioRepository(final Configuration configuration) {
this.configuration = configuration;
configuration.build();
@Getter(value = AccessLevel.PACKAGE) log.info("Loaded scenarios for {} by {} from {}. The following scenarios are available:\n\n{}", configuration.getName(),
private final ContentRepository repository; configuration.getAuthor(), configuration.getDate(), summarizeScenarios());
@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);
} }
private static XdmNode findRoot(final XdmNode doc) { public Scenario getFallbackScenario() {
for (final XdmNode node : doc.children()) { return this.configuration.getFallbackScenario();
if (node.getNodeKind() == XdmNodeKind.ELEMENT) {
return node;
}
}
throw new IllegalArgumentException("Kein root element gefunden");
} }
private static void checkVersion(final URI scenarioDefinition) { public List<Scenario> getScenarios() {
final DocumentParseAction p = new DocumentParseAction(); return this.configuration.getScenarios();
try {
final Result<XdmNode, XMLSyntaxError> 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();
} }
private String summarizeScenarios() { private String summarizeScenarios() {
final StringBuilder b = new StringBuilder(); final StringBuilder b = new StringBuilder();
this.scenarios.getScenario().forEach(s -> { getScenarios().forEach(s -> {
b.append(s.getName()); b.append(s.getName());
b.append("\n"); b.append("\n");
}); });
@ -146,9 +73,9 @@ public class ScenarioRepository {
* @param document das Eingabedokument * @param document das Eingabedokument
* @return ein Ergebnis-Objekt zur weiteren Verarbeitung * @return ein Ergebnis-Objekt zur weiteren Verarbeitung
*/ */
public Result<ScenarioType, String> selectScenario(final XdmNode document) { public Result<Scenario, String> selectScenario(final XdmNode document) {
final Result<ScenarioType, String> result; final Result<Scenario, String> result;
final List<ScenarioType> collect = this.scenarios.getScenario().stream().filter(s -> match(document, s)) final List<Scenario> collect = getScenarios().stream().filter(s -> match(document, s))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (collect.size() == 1) { if (collect.size() == 1) {
result = new Result<>(collect.get(0)); result = new Result<>(collect.get(0));
@ -162,23 +89,9 @@ public class ScenarioRepository {
} }
private ScenarioType createFallback() { private static boolean match(final XdmNode document, final Scenario scenario) {
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) {
try { try {
final XPathSelector selector = scenario.getSelector(); final XPathSelector selector = scenario.getMatchSelector();
selector.setContextItem(document); selector.setContextItem(document);
return selector.effectiveBooleanValue(); return selector.effectiveBooleanValue();
} catch (final SaxonApiException e) { } catch (final SaxonApiException e) {
@ -187,7 +100,4 @@ public class ScenarioRepository {
return false; return false;
} }
void initialize(final Scenarios def) {
this.scenarios = def;
}
} }

View file

@ -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<Transformation> 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<String> 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<Transformation> 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<String, String> 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<NamespaceType> getNamespace();
/**
* Getter aus dem schema.
*
* @return Validierungsanweisungen
*/
public abstract ValidateWithXmlSchema getValidateWithXmlSchema();
/**
* Getter aus dem schema.
*
* @return Validierungsanweisungne
*/
public abstract List<ValidateWithSchematron> getValidateWithSchematron();
/**
* Getter aus dem schema.
*
* @return report informationen
*/
public abstract CreateReportType getCreateReport();
}

View file

@ -30,11 +30,11 @@ import lombok.Setter;
import de.kosit.validationtool.api.AcceptRecommendation; import de.kosit.validationtool.api.AcceptRecommendation;
import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.Input;
import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.model.reportInput.CreateReportInput; import de.kosit.validationtool.model.reportInput.CreateReportInput;
import de.kosit.validationtool.model.reportInput.ProcessingError; import de.kosit.validationtool.model.reportInput.ProcessingError;
import de.kosit.validationtool.model.reportInput.XMLSyntaxError; import de.kosit.validationtool.model.reportInput.XMLSyntaxError;
import de.kosit.validationtool.model.scenarios.ScenarioType;
import net.sf.saxon.s9api.XdmNode; import net.sf.saxon.s9api.XdmNode;
@ -55,7 +55,7 @@ public interface CheckAction {
@Setter @Setter
class Bag { class Bag {
private Result<ScenarioType, String> scenarioSelectionResult; private Result<Scenario, String> scenarioSelectionResult;
@Setter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
private CreateReportInput reportInput; private CreateReportInput reportInput;

View file

@ -1,6 +1,6 @@
package de.kosit.validationtool.impl.tasks; 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; import org.oclc.purl.dsdl.svrl.FailedAssert;
@ -25,9 +25,9 @@ public class ComputeAcceptanceAction implements CheckAction {
@Override @Override
public void check(final Bag results) { public void check(final Bag results) {
if (preCondtionsMatch(results)) { if (preCondtionsMatch(results)) {
final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch(); final Optional<XPathSelector> acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptSelector();
if (results.getSchemaValidationResult().isValid() && isNotBlank(acceptMatch)) { if (results.getSchemaValidationResult().isValid() && acceptMatch.isPresent()) {
evaluateAcceptanceMatch(results); evaluateAcceptanceMatch(results, acceptMatch.get());
} else { } else {
evaluateSchemaAndSchematron(results); evaluateSchemaAndSchematron(results);
} }
@ -53,9 +53,8 @@ public class ComputeAcceptanceAction implements CheckAction {
.flatMap(e -> e.getActivePatternAndFiredRuleAndFailedAssert().stream()).anyMatch(FailedAssert.class::isInstance); .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 { try {
final XPathSelector selector = results.getScenarioSelectionResult().getObject().getAcceptSelector();
selector.setContextItem(results.getReport()); selector.setContextItem(results.getReport());
results.setAcceptStatus(selector.effectiveBooleanValue() ? AcceptRecommendation.ACCEPTABLE : AcceptRecommendation.REJECT); results.setAcceptStatus(selector.effectiveBooleanValue() ? AcceptRecommendation.ACCEPTABLE : AcceptRecommendation.REJECT);
} catch (final SaxonApiException e) { } catch (final SaxonApiException e) {

View file

@ -22,6 +22,7 @@ package de.kosit.validationtool.impl.tasks;
import java.util.Collection; import java.util.Collection;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Document; 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.ConversionService;
import de.kosit.validationtool.impl.EngineInformation; import de.kosit.validationtool.impl.EngineInformation;
import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.RelativeUriResolver; import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.ScenarioRepository;
import de.kosit.validationtool.model.reportInput.XMLSyntaxError; 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.BuildingContentHandler;
import net.sf.saxon.s9api.DocumentBuilder; import net.sf.saxon.s9api.DocumentBuilder;
@ -64,11 +63,9 @@ public class CreateReportAction implements CheckAction {
private final ConversionService conversionService; private final ConversionService conversionService;
private final ScenarioRepository scenarioRepository;
private final ContentRepository contentRepository; private final ContentRepository contentRepository;
private static XsltExecutable loadFromScenario(final ScenarioType object) { private static XsltExecutable loadFromScenario(final Scenario object) {
return object.getReportTransformation().getExecutable(); return object.getReportTransformation().getExecutable();
} }
@ -85,10 +82,10 @@ public class CreateReportAction implements CheckAction {
final XsltTransformer transformer = getTransformation(results).load(); final XsltTransformer transformer = getTransformation(results).load();
transformer.setInitialContextNode(root); transformer.setInitialContextNode(root);
final CollectingErrorEventHandler e = new CollectingErrorEventHandler(); final CollectingErrorEventHandler e = new CollectingErrorEventHandler();
final RelativeUriResolver resolver = this.contentRepository.createResolver(); final URIResolver resolver = this.contentRepository.createResolver();
transformer.setMessageListener(e); transformer.setMessageListener(e);
transformer.setURIResolver(resolver); transformer.setURIResolver(resolver);
transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver); // transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver);
if (parsedDocument != null) { if (parsedDocument != null) {
transformer.setParameter(new QName("input-document"), parsedDocument); transformer.setParameter(new QName("input-document"), parsedDocument);
} }

View file

@ -22,10 +22,10 @@ package de.kosit.validationtool.impl.tasks;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.ScenarioRepository; import de.kosit.validationtool.impl.ScenarioRepository;
import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.model.reportInput.CreateReportInput; import de.kosit.validationtool.model.reportInput.CreateReportInput;
import de.kosit.validationtool.model.scenarios.ScenarioType;
import net.sf.saxon.s9api.XdmNode; import net.sf.saxon.s9api.XdmNode;
@ -44,7 +44,7 @@ public class ScenarioSelectionAction implements CheckAction {
@Override @Override
public void check(final Bag results) { public void check(final Bag results) {
final CreateReportInput report = results.getReportInput(); final CreateReportInput report = results.getReportInput();
final Result<ScenarioType, String> scenarioTypeResult; final Result<Scenario, String> scenarioTypeResult;
if (results.getParserResult().isValid()) { if (results.getParserResult().isValid()) {
scenarioTypeResult = determineScenario(results.getParserResult().getObject()); scenarioTypeResult = determineScenario(results.getParserResult().getObject());
@ -53,15 +53,15 @@ public class ScenarioSelectionAction implements CheckAction {
} }
results.setScenarioSelectionResult(scenarioTypeResult); results.setScenarioSelectionResult(scenarioTypeResult);
if (!scenarioTypeResult.getObject().isFallback()) { if (!scenarioTypeResult.getObject().isFallback()) {
report.setScenario(scenarioTypeResult.getObject()); report.setScenario(scenarioTypeResult.getObject().getConfiguration());
log.info("Schenario {} identified for {}", scenarioTypeResult.getObject().getName(), results.getInput().getName()); log.info("Schenario {} identified for {}", scenarioTypeResult.getObject().getName(), results.getInput().getName());
} else { } else {
log.error("No valid schenario configuration found for {}", results.getInput().getName()); log.error("No valid schenario configuration found for {}", results.getInput().getName());
} }
} }
private Result<ScenarioType, String> determineScenario(final XdmNode document) { private Result<Scenario, String> determineScenario(final XdmNode document) {
final Result<ScenarioType, String> result = this.repository.selectScenario(document); final Result<Scenario, String> result = this.repository.selectScenario(document);
if (result.isInvalid()) { if (result.isInvalid()) {
return new Result<>(this.repository.getFallbackScenario()); return new Result<>(this.repository.getFallbackScenario());
} }

View file

@ -42,12 +42,12 @@ import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.Input; import de.kosit.validationtool.api.Input;
import de.kosit.validationtool.impl.CollectingErrorEventHandler; import de.kosit.validationtool.impl.CollectingErrorEventHandler;
import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.input.AbstractInput; import de.kosit.validationtool.impl.input.AbstractInput;
import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.model.reportInput.CreateReportInput; import de.kosit.validationtool.model.reportInput.CreateReportInput;
import de.kosit.validationtool.model.reportInput.ValidationResultsXmlSchema; import de.kosit.validationtool.model.reportInput.ValidationResultsXmlSchema;
import de.kosit.validationtool.model.reportInput.XMLSyntaxError; 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.SaxonApiException;
import net.sf.saxon.s9api.Serializer; import net.sf.saxon.s9api.Serializer;
@ -132,17 +132,17 @@ public class SchemaValidationAction implements CheckAction {
@Getter @Getter
private long inMemoryLimit = Long.parseLong(System.getProperty(LIMIT_PARAMETER, BA_LIMIT.toString())) * FileUtils.ONE_MB; private long inMemoryLimit = Long.parseLong(System.getProperty(LIMIT_PARAMETER, BA_LIMIT.toString())) * FileUtils.ONE_MB;
private Result<Boolean, XMLSyntaxError> validate(final Bag results, final ScenarioType scenarioType) { private Result<Boolean, XMLSyntaxError> validate(final Bag results, final Scenario scenario) {
log.debug("Validating document using scenario {}", scenarioType.getName()); log.debug("Validating document using scenario {}", scenario.getConfiguration().getName());
final CollectingErrorEventHandler errorHandler = new CollectingErrorEventHandler(); final CollectingErrorEventHandler errorHandler = new CollectingErrorEventHandler();
try ( final SourceProvider validateInput = resolveSource(results) ) { try ( final SourceProvider validateInput = resolveSource(results) ) {
final Validator validator = ObjectFactory.createValidator(scenarioType.getSchema()); final Validator validator = ObjectFactory.createValidator(scenario.getSchema());
validator.setErrorHandler(errorHandler); validator.setErrorHandler(errorHandler);
validator.validate(validateInput.getSource()); validator.validate(validateInput.getSource());
return new Result<>(!errorHandler.hasErrors(), errorHandler.getErrors()); return new Result<>(!errorHandler.hasErrors(), errorHandler.getErrors());
} catch (final SAXException | SaxonApiException | IOException e) { } 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); log.error(msg, e);
results.addProcessingError(msg); results.addProcessingError(msg);
return new Result<>(Boolean.FALSE); return new Result<>(Boolean.FALSE);
@ -152,14 +152,14 @@ public class SchemaValidationAction implements CheckAction {
@Override @Override
public void check(final Bag results) { public void check(final Bag results) {
final CreateReportInput report = results.getReportInput(); final CreateReportInput report = results.getReportInput();
final ScenarioType scenario = results.getScenarioSelectionResult().getObject(); final Scenario scenario = results.getScenarioSelectionResult().getObject();
final Result<Boolean, XMLSyntaxError> validateResult = validate(results, scenario); final Result<Boolean, XMLSyntaxError> validateResult = validate(results, scenario);
results.setSchemaValidationResult(validateResult); results.setSchemaValidationResult(validateResult);
final ValidationResultsXmlSchema result = new ValidationResultsXmlSchema(); final ValidationResultsXmlSchema result = new ValidationResultsXmlSchema();
report.setValidationResultsXmlSchema(result); report.setValidationResultsXmlSchema(result);
result.getResource().addAll(scenario.getValidateWithXmlSchema().getResource()); result.getResource().addAll(scenario.getConfiguration().getValidateWithXmlSchema().getResource());
if (!validateResult.isValid()) { if (!validateResult.isValid()) {
result.getXmlSyntaxError().addAll(validateResult.getErrors()); result.getXmlSyntaxError().addAll(validateResult.getErrors());
} }

View file

@ -22,6 +22,7 @@ package de.kosit.validationtool.impl.tasks;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import org.oclc.purl.dsdl.svrl.SchematronOutput; 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.ContentRepository;
import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.ConversionService;
import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.RelativeUriResolver; import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.model.BaseScenario;
import de.kosit.validationtool.model.reportInput.CreateReportInput; import de.kosit.validationtool.model.reportInput.CreateReportInput;
import de.kosit.validationtool.model.reportInput.ValidationResultsSchematron; 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.DOMDestination;
import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.SaxonApiException;
@ -58,17 +57,17 @@ public class SchematronValidationAction implements CheckAction {
private final ConversionService conversionService; private final ConversionService conversionService;
private List<ValidationResultsSchematron> validate(final Bag results, final XdmNode document, final ScenarioType scenario) { private List<ValidationResultsSchematron> validate(final Bag results, final XdmNode document, final Scenario scenario) {
return scenario.getSchematronValidations().stream().map(v -> validate(results, document, v)).collect(Collectors.toList()); 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(); final ValidationResultsSchematron s = new ValidationResultsSchematron();
s.setResource(validation.getResourceType()); s.setResource(validation.getResourceType());
try { try {
final XsltTransformer transformer = validation.getExecutable().load(); final XsltTransformer transformer = validation.getExecutable().load();
// resolving nur relative zum Repository // resolving nur relative zum Repository
final RelativeUriResolver resolver = this.repository.createResolver(); final URIResolver resolver = this.repository.createResolver();
transformer.setURIResolver(resolver); transformer.setURIResolver(resolver);
final CollectingErrorEventHandler e = new CollectingErrorEventHandler(); final CollectingErrorEventHandler e = new CollectingErrorEventHandler();
transformer.setMessageListener(e); transformer.setMessageListener(e);
@ -107,7 +106,7 @@ public class SchematronValidationAction implements CheckAction {
return results.getSchemaValidationResult() == null || results.getSchemaValidationResult().isInvalid(); return results.getSchemaValidationResult() == null || results.getSchemaValidationResult().isInvalid();
} }
private static boolean hasNoSchematrons(final ScenarioType object) { private static boolean hasNoSchematrons(final Scenario object) {
return object.getValidateWithSchematron() == null || object.getValidateWithSchematron().size() == 0; return object.getSchematronValidations().isEmpty();
} }
} }

View file

@ -42,9 +42,6 @@
<jaxb:schemaBindings> <jaxb:schemaBindings>
<jaxb:package name="de.kosit.validationtool.model.scenarios"/> <jaxb:package name="de.kosit.validationtool.model.scenarios"/>
</jaxb:schemaBindings> </jaxb:schemaBindings>
<jaxb:bindings node="//xs:complexType[@name='ScenarioType']">
<inheritance:extends>de.kosit.validationtool.impl.model.BaseScenario</inheritance:extends>
</jaxb:bindings>
</jaxb:bindings> </jaxb:bindings>
<jaxb:bindings schemaLocation="../xsd/assertions.xsd"> <jaxb:bindings schemaLocation="../xsd/assertions.xsd">
<jaxb:schemaBindings> <jaxb:schemaBindings>

View file

@ -42,7 +42,7 @@ import net.sf.saxon.s9api.XPathExecutable;
import net.sf.saxon.s9api.XsltExecutable; import net.sf.saxon.s9api.XsltExecutable;
/** /**
* Testet das ContentRepository. * Testet das repository.
* *
* @author Andreas Penski * @author Andreas Penski
*/ */
@ -60,7 +60,7 @@ public class ContentRepositoryTest {
@Test @Test
public void testCreateSchema() throws MalformedURLException { 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(); assertThat(schema).isNotNull();
} }
@ -73,7 +73,7 @@ public class ContentRepositoryTest {
@Test @Test
public void testCreateSchemaNotExisting() throws Exception { public void testCreateSchemaNotExisting() throws Exception {
this.exception.expect(IllegalStateException.class); this.exception.expect(IllegalStateException.class);
ContentRepository.createSchema(Simple.NOT_EXISTING.toURL()); this.repository.createSchema(Simple.NOT_EXISTING.toURL());
} }
@Test @Test
@ -122,16 +122,26 @@ public class ContentRepositoryTest {
@Test @Test
public void testLoadSchema() { public void testLoadSchema() {
final URL main = RelativeUriResolverTest.class.getClassLoader().getResource("loading/main.xsd"); 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(); assertThat(schema).isNotNull();
} }
@Test @Test
public void testLoadSchemaPackaged() throws URISyntaxException { public void testLoadSchemaPackaged() throws URISyntaxException {
final URL main = RelativeUriResolverTest.class.getClassLoader().getResource("packaged/main.xsd"); 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())); new ClassPathResourceResolver(RelativeUriResolverTest.class.getClassLoader().getResource("packaged/").toURI()));
assertThat(schema).isNotNull(); 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();
// }
} }

View file

@ -72,7 +72,7 @@ public class ConversionServiceTest {
} }
@Test @Test
public void testUnmarshal() throws URISyntaxException { public void testUnmarshal() {
final Scenarios s = this.service.readXml(Simple.SCENARIOS, Scenarios.class); final Scenarios s = this.service.readXml(Simple.SCENARIOS, Scenarios.class);
assertThat(s).isNotNull(); assertThat(s).isNotNull();
assertThat(s.getName()).isEqualToIgnoringCase("HTML-TestSuite"); assertThat(s.getName()).isEqualToIgnoringCase("HTML-TestSuite");
@ -80,7 +80,7 @@ public class ConversionServiceTest {
@Test @Test
public void testUnmarshalWithSchema() { 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).isNotNull();
assertThat(s.getName()).isEqualToIgnoringCase("HTML-TestSuite"); assertThat(s.getName()).isEqualToIgnoringCase("HTML-TestSuite");
} }
@ -88,13 +88,13 @@ public class ConversionServiceTest {
@Test @Test
public void testUnmarshalInvalidXml() { public void testUnmarshalInvalidXml() {
this.exception.expect(ConversionService.ConversionExeption.class); 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 @Test
public void testUnmarshalIllFormed() { public void testUnmarshalIllFormed() {
this.exception.expect(ConversionService.ConversionExeption.class); 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 @Test

View file

@ -24,20 +24,25 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException; import java.io.IOException;
import java.net.URI; 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.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; 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.Helper.Simple;
import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.impl.tasks.DocumentParseAction; import de.kosit.validationtool.impl.tasks.DocumentParseAction;
import de.kosit.validationtool.model.scenarios.ScenarioType; 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; import net.sf.saxon.s9api.XdmNode;
/** /**
@ -48,57 +53,84 @@ import net.sf.saxon.s9api.XdmNode;
public class ScenarioRepositoryTest { public class ScenarioRepositoryTest {
@Data
private static class DummyConfiguration implements Configuration {
private List<Scenario> 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 @Rule
public ExpectedException expectedException = ExpectedException.none(); public ExpectedException expectedException = ExpectedException.none();
ContentRepository content;
private ScenarioRepository repository; private ScenarioRepository repository;
private DummyConfiguration configInstance;
@Before @Before
public void setup() { public void setup() {
this.content = new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY); final Scenario s = createScenario();
final Scenarios def = new Scenarios();
final ScenarioType t = new ScenarioType(); this.configInstance = new DummyConfiguration();
t.setMatch("//*:name"); this.configInstance.setScenarios(new ArrayList<>());
t.setName("Test"); this.configInstance.getScenarios().add(s);
t.initialize(this.content, true); this.repository = new ScenarioRepository(this.configInstance);
def.getScenario().add(t); }
this.repository = new ScenarioRepository(this.content);
this.repository.initialize(def); private static Scenario createScenario() {
final Scenario s = new Scenario(new ScenarioType());
s.setMatchExecutable(createXpath("//*:name"));
return s;
} }
@Test @Test
public void testHappyCase() throws Exception { public void testHappyCase() throws Exception {
final Result<ScenarioType, String> scenario = this.repository.selectScenario(load(Simple.SCENARIOS)); final Result<Scenario, String> scenario = this.repository.selectScenario(load(Simple.SCENARIOS));
assertThat(scenario).isNotNull(); assertThat(scenario).isNotNull();
assertThat(scenario.isValid()).isTrue(); assertThat(scenario.isValid()).isTrue();
} }
@Test @Test
public void testNonMatch() throws Exception { public void testNonMatch() throws Exception {
this.repository.getScenarios().getScenario().clear(); this.configInstance.setScenarios(new ArrayList<>());
final ScenarioType fallback = new ScenarioType(); final Scenario fallback = createFallback();
fallback.setName("fallback"); this.configInstance.setFallbackScenario(fallback);
this.repository.setFallbackScenario(fallback); final Result<Scenario, String> scenario = this.repository.selectScenario(load(Simple.SCENARIOS));
final Result<ScenarioType, String> scenario = this.repository.selectScenario(load(Simple.SCENARIOS));
assertThat(scenario).isNotNull(); assertThat(scenario).isNotNull();
assertThat(scenario.isValid()).isFalse(); assertThat(scenario.isValid()).isFalse();
assertThat(scenario.getObject().getName()).isEqualTo("fallback"); 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 @Test
public void testMultiMatch() throws Exception { public void testMultiMatch() throws Exception {
final ScenarioType t = new ScenarioType(); this.configInstance.getScenarios().add(createScenario());
t.setMatch("//*:name"); this.configInstance.setFallbackScenario(createFallback());
t.setName("Test"); final Result<Scenario, String> scenario = this.repository.selectScenario(load(Simple.SCENARIOS));
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<ScenarioType, String> scenario = this.repository.selectScenario(load(Simple.SCENARIOS));
assertThat(scenario).isNotNull(); assertThat(scenario).isNotNull();
assertThat(scenario.isValid()).isFalse(); assertThat(scenario.isValid()).isFalse();
assertThat(scenario.getObject().getName()).isEqualTo("fallback"); assertThat(scenario.getObject().getName()).isEqualTo("fallback");
@ -109,14 +141,7 @@ public class ScenarioRepositoryTest {
return DocumentParseAction.parseDocument(read(uri.toURL())).getObject(); return DocumentParseAction.parseDocument(read(uri.toURL())).getObject();
} }
@Test private static XPathExecutable createXpath(final String expression) {
public void loadFromJar() throws URISyntaxException { return new ContentRepository(ObjectFactory.createProcessor(), null).createXPath(expression, new HashMap<>());
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();
} }
} }

View file

@ -29,6 +29,7 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import de.kosit.validationtool.impl.Helper.Simple;
import de.kosit.validationtool.model.scenarios.Scenarios; import de.kosit.validationtool.model.scenarios.Scenarios;
/** /**
@ -51,33 +52,35 @@ public class VersioningTest {
private ConversionService service; private ConversionService service;
private ContentRepository repository;
@Before @Before
public void setup() { public void setup() {
this.repository = new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY);
this.service = new ConversionService(); this.service = new ConversionService();
} }
@Test @Test
public void testBase() throws URISyntaxException { 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(); assertThat(result).isNotNull();
} }
@Test @Test
public void testFrameworkIncrement() throws URISyntaxException { 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(); assertThat(result).isNotNull();
} }
@Test @Test
public void testNewFeature() throws URISyntaxException { public void testNewFeature() throws URISyntaxException {
this.exception.expect(ConversionService.ConversionExeption.class); 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 @Test
public void testNewVersion() throws URISyntaxException { public void testNewVersion() throws URISyntaxException {
this.exception.expect(ConversionService.ConversionExeption.class); 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());
} }
} }

View file

@ -4,12 +4,17 @@ import static de.kosit.validationtool.impl.tasks.TestBagBuilder.createBag;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import org.junit.Test; import org.junit.Test;
import de.kosit.validationtool.api.AcceptRecommendation; 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 de.kosit.validationtool.impl.tasks.CheckAction.Bag;
import net.sf.saxon.s9api.XPathExecutable;
/** /**
* Tests the 'acceptMatch' functionality. * Tests the 'acceptMatch' functionality.
* *
@ -44,7 +49,7 @@ public class ComputeAcceptanceActionTest {
@Test @Test
public void testValidAcceptMatch() { public void testValidAcceptMatch() {
final Bag bag = createBag(true, true); 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); this.action.check(bag);
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE);
} }
@ -52,7 +57,7 @@ public class ComputeAcceptanceActionTest {
@Test @Test
public void testAcceptMatchNotSatisfied() { public void testAcceptMatchNotSatisfied() {
final Bag bag = createBag(true, true); 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); this.action.check(bag);
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
} }
@ -60,7 +65,7 @@ public class ComputeAcceptanceActionTest {
@Test @Test
public void testAcceptMatchOverridesSchematronErrors() { public void testAcceptMatchOverridesSchematronErrors() {
final Bag bag = createBag(true, false); 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); this.action.check(bag);
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE); assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE);
} }
@ -68,7 +73,7 @@ public class ComputeAcceptanceActionTest {
@Test @Test
public void testValidAcceptMatchOnSchemaFailed() { public void testValidAcceptMatchOnSchemaFailed() {
final Bag bag = createBag(false, true); 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); this.action.check(bag);
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT); 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<>());
}
} }

View file

@ -46,9 +46,9 @@ import de.kosit.validationtool.api.InputFactory;
import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.ContentRepository;
import de.kosit.validationtool.impl.Helper.Simple; import de.kosit.validationtool.impl.Helper.Simple;
import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.input.SourceInput; import de.kosit.validationtool.impl.input.SourceInput;
import de.kosit.validationtool.impl.tasks.CheckAction.Bag; import de.kosit.validationtool.impl.tasks.CheckAction.Bag;
import de.kosit.validationtool.model.scenarios.ScenarioType;
/** /**
* Tests die {@link SchemaValidationAction}. * Tests die {@link SchemaValidationAction}.
@ -154,7 +154,7 @@ public class SchemaValidatorActionTest {
@Test @Test
public void testProcessingError() throws IOException, SAXException { public void testProcessingError() throws IOException, SAXException {
final CheckAction.Bag bag = createBag(InputFactory.read(Simple.SIMPLE_VALID.toURL())); 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 Schema schema = mock(Schema.class);
final Validator validator = mock(Validator.class); final Validator validator = mock(Validator.class);
when(schema.newValidator()).thenReturn(validator); when(schema.newValidator()).thenReturn(validator);

View file

@ -17,9 +17,9 @@ import de.kosit.validationtool.impl.ContentRepository;
import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.ConversionService;
import de.kosit.validationtool.impl.Helper.Simple; import de.kosit.validationtool.impl.Helper.Simple;
import de.kosit.validationtool.impl.ObjectFactory; 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.ResourceType;
import de.kosit.validationtool.model.scenarios.ScenarioType;
import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltExecutable; import net.sf.saxon.s9api.XsltExecutable;
@ -44,7 +44,7 @@ public class SchematronValidationActionTest {
public void testProcessingError() throws IOException, SaxonApiException { public void testProcessingError() throws IOException, SaxonApiException {
final CheckAction.Bag bag = createBag(InputFactory.read(Simple.SIMPLE_VALID.toURL()), true); 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 XsltExecutable exec = mock(XsltExecutable.class);
final XsltTransformer transformer = mock(XsltTransformer.class); final XsltTransformer transformer = mock(XsltTransformer.class);
doThrow(new SaxonApiException("invalid")).when(transformer).transform(); doThrow(new SaxonApiException("invalid")).when(transformer).transform();

View file

@ -1,10 +1,14 @@
package de.kosit.validationtool.impl.tasks; package de.kosit.validationtool.impl.tasks;
import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URL;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.xml.validation.Schema;
import org.oclc.purl.dsdl.svrl.FailedAssert; import org.oclc.purl.dsdl.svrl.FailedAssert;
import org.oclc.purl.dsdl.svrl.SchematronOutput; 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.api.InputFactory;
import de.kosit.validationtool.impl.ContentRepository; import de.kosit.validationtool.impl.ContentRepository;
import de.kosit.validationtool.impl.Helper; import de.kosit.validationtool.impl.Helper;
import de.kosit.validationtool.impl.Helper.Simple;
import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.ObjectFactory;
import de.kosit.validationtool.impl.Scenario;
import de.kosit.validationtool.impl.model.Result; import de.kosit.validationtool.impl.model.Result;
import de.kosit.validationtool.impl.tasks.CheckAction.Bag; import de.kosit.validationtool.impl.tasks.CheckAction.Bag;
import de.kosit.validationtool.model.reportInput.CreateReportInput; import de.kosit.validationtool.model.reportInput.CreateReportInput;
@ -50,8 +54,9 @@ public class TestBagBuilder {
return bag; return bag;
} }
private static ScenarioType createScenario(final URI schemafile) { private static Scenario createScenario(final URI schemafile) {
final ContentRepository repository = new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY);
try {
final ScenarioType t = new ScenarioType(); final ScenarioType t = new ScenarioType();
final ValidateWithXmlSchema v = new ValidateWithXmlSchema(); final ValidateWithXmlSchema v = new ValidateWithXmlSchema();
final ResourceType r = new ResourceType(); final ResourceType r = new ResourceType();
@ -59,8 +64,16 @@ public class TestBagBuilder {
r.setName("invoice"); r.setName("invoice");
v.getResource().add(r); v.getResource().add(r);
t.setValidateWithXmlSchema(v); t.setValidateWithXmlSchema(v);
t.initialize(repository, true); final Scenario scenario = new Scenario(t);
return 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() { private static XdmNode createReport() {