mirror of
https://github.com/itplr-kosit/validator.git
synced 2026-05-25 16:55:39 +00:00
Merge remote-tracking branch 'origin/branch-1.2.x'
# Conflicts: # CHANGELOG.md # src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java
This commit is contained in:
commit
6aab106075
11 changed files with 307 additions and 75 deletions
20
CHANGELOG.md
20
CHANGELOG.md
|
|
@ -7,14 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## next version (unreleased)
|
## next version (unreleased)
|
||||||
|
|
||||||
# Added
|
### Added
|
||||||
|
|
||||||
- Support java.xml.transform.Source/java.xml.transform.StreamSource as Input
|
- Support java.xml.transform.Source/java.xml.transform.StreamSource as Input
|
||||||
|
|
||||||
# Changed
|
### Changed
|
||||||
|
|
||||||
- Inputs are NOT read into memory (e.g. Byte-Array) prior processing within the validator. This reduces memory consumption.
|
- Inputs are NOT read into memory (e.g. Byte-Array) prior processing within the validator. This reduces memory consumption.
|
||||||
|
|
||||||
|
## 1.2.0 (unreleased)
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Provide access to schematron result through Result.java
|
||||||
|
- *Result#getFailedAsserts()* returns a list of failed asserts found by schematron
|
||||||
|
- *Result#isSchematronValid()* convinience access to evaluate whether schematron was processed without any *FailedAsserts*
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- *getAcceptRecommendation()* does not _only_ work when _acceptMatch_ is configured in the scenario
|
||||||
|
- schema correct is a precondion, of the checked instance is not valid, this evaluates to _REJECTED_
|
||||||
|
- if _acceptMatch_ is configured, the result is based on the boolean result of the xpath expression evaluated against the generated report
|
||||||
|
- if *no* _acceptMatch_ is configured, the result is based on evaluation of schema and schematron correctness
|
||||||
|
- _UNDEFINED_ is only returned, when processing is stopped somehow
|
||||||
|
- *isAcceptable()* can no evaluate to true, when no _acceptMatch_ is configured (see above)
|
||||||
|
|
||||||
## 1.1.3
|
## 1.1.3
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
||||||
18
docs/api.md
18
docs/api.md
|
|
@ -89,3 +89,21 @@ Initializing all XML artifacts and XSLT-executables is expensive. The `Check` in
|
||||||
|
|
||||||
The only input `de.kosit.validationtool.api.Input` which can be created by various methods of `de.kosit.validationtool.api.InputFactory`.
|
The only input `de.kosit.validationtool.api.Input` which can be created by various methods of `de.kosit.validationtool.api.InputFactory`.
|
||||||
The `InputFactory` calculates a hash sum for each Input which is also written to the Report. _SHA-256_ from the JDK is the default algorithm. It can be changed using the `read`-methods of `InputFactory`.
|
The `InputFactory` calculates a hash sum for each Input which is also written to the Report. _SHA-256_ from the JDK is the default algorithm. It can be changed using the `read`-methods of `InputFactory`.
|
||||||
|
|
||||||
|
## Accept Recommendation and Accept Match
|
||||||
|
|
||||||
|
A tri-state Object `AcceptRecommendation` can be retrieved from the `Result` using `getAcceptRecommendation()`.
|
||||||
|
|
||||||
|
The three defined states are:
|
||||||
|
|
||||||
|
1. `UNDEFINED` i.e. the evaluation of the overall validation could not be computed.
|
||||||
|
2. `ACCEPTABLE` i.e. the recommendation is to accept input based on the evaluation of the overall validation.
|
||||||
|
3. `REJECT` i.e. the recommendation is to reject input based on the evaluation of the overall validation.
|
||||||
|
|
||||||
|
By default it is `UNDEFINED`.
|
||||||
|
|
||||||
|
### Accept Match in Scenario Configuration
|
||||||
|
|
||||||
|
For your own configuration you can add an `acceptMatch` element in each scenario. It can contain in XPATH expression over your own defined `Report` to compute a boolean. An XPATH expression evaluating to true will lead to an `ACCEPTABLE` amd otherwise to a `REJECT` recommendation.
|
||||||
|
|
||||||
|
This allows to have own control over what validation result is to be considered acceptable for your own application context.
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,9 @@ the validation and generates a report in XML format. This report is then the inp
|
||||||
|
|
||||||
The validator reports valid/invalid, a configuration reports acceptance/rejection!
|
The validator reports valid/invalid, a configuration reports acceptance/rejection!
|
||||||
|
|
||||||
## General process
|
## General default process
|
||||||
|
|
||||||
The general process is like this:
|
The general process is like this (the default is defined in `DefaultCheck`):
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
|
|
||||||
|
|
@ -30,6 +30,7 @@ sequenceDiagram
|
||||||
e->>e: validate Schematron
|
e->>e: validate Schematron
|
||||||
e->>e: create Validator Report
|
e->>e: create Validator Report
|
||||||
e->>+c: execute configuration report generator
|
e->>+c: execute configuration report generator
|
||||||
|
e->>e: Compute Recommendation
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -50,3 +51,8 @@ sequenceDiagram
|
||||||
6. *execute configuration report generator*
|
6. *execute configuration report generator*
|
||||||
|
|
||||||
The Validator will search for the XSLT as configured in scenario.xml and execute it with the Validator Report as input
|
The Validator will search for the XSLT as configured in scenario.xml and execute it with the Validator Report as input
|
||||||
|
7. compute Recommendation
|
||||||
|
|
||||||
|
In case a scenario contains an `acceptMatch` element with an XPATH expression, this expression will be executed.
|
||||||
|
|
||||||
|
In case the XPATH returns `true`, the recommendation will be set to `ACCEPT` else to `REJECT`. In case no such XPATH is defined it is `UNDEFINED`.
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
package de.kosit.validationtool.api;
|
package de.kosit.validationtool.api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status der Empfehlung.
|
* Tri-state describtion of a Recommendation.
|
||||||
*/
|
*/
|
||||||
public enum AcceptRecommendation {
|
public enum AcceptRecommendation {
|
||||||
/**
|
/**
|
||||||
* Nicht definiert, weil eine Evaluierung nicht durchgeführt wurde, oder nicht durchgeführt werden konnte.
|
* The evaluation of the overall validation could not be computed.
|
||||||
*/
|
*/
|
||||||
UNDEFINED,
|
UNDEFINED,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Das Dokument ist gemäß Konfiguration valide und kann akzeptiert werden.
|
* Recommendation is to accept input based on the evaluation of the overall validation.
|
||||||
*/
|
*/
|
||||||
ACCEPTABLE,
|
ACCEPTABLE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Das Dokuemnt ist gemäß Konfiguration invalide und sollte NICHT akzeptiert werden.
|
* Recommendation is to reject input based on the evaluation of the overall validation.
|
||||||
*/
|
*/
|
||||||
REJECT
|
REJECT
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package de.kosit.validationtool.api;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.oclc.purl.dsdl.svrl.FailedAssert;
|
||||||
import org.oclc.purl.dsdl.svrl.SchematronOutput;
|
import org.oclc.purl.dsdl.svrl.SchematronOutput;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
|
||||||
|
|
@ -9,7 +10,7 @@ import net.sf.saxon.s9api.XdmNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API Rückgabe Objekt des Ergebnisses des Validierungsprozesses.
|
* API Rückgabe Objekt des Ergebnisses des Validierungsprozesses.
|
||||||
*
|
*
|
||||||
* @author Andreas Penski
|
* @author Andreas Penski
|
||||||
*/
|
*/
|
||||||
public interface Result {
|
public interface Result {
|
||||||
|
|
@ -17,7 +18,7 @@ public interface Result {
|
||||||
/**
|
/**
|
||||||
* Zeigt an, ob die Verarbeitung durch den Validator erfolgreich durchlaufen wurde. Diese Funktion macht ausdrücklich
|
* Zeigt an, ob die Verarbeitung durch den Validator erfolgreich durchlaufen wurde. Diese Funktion macht ausdrücklich
|
||||||
* keine Aussage über die zur Akzeptanz.
|
* keine Aussage über die zur Akzeptanz.
|
||||||
*
|
*
|
||||||
* @return true, wenn die Verarbeitung komplett und erfolgreich durchlaufen wurde
|
* @return true, wenn die Verarbeitung komplett und erfolgreich durchlaufen wurde
|
||||||
* @see #getAcceptRecommendation()
|
* @see #getAcceptRecommendation()
|
||||||
*/
|
*/
|
||||||
|
|
@ -25,7 +26,7 @@ public interface Result {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt eine Liste mit Verarbeitungsfehlermeldungen zurück.
|
* Gibt eine Liste mit Verarbeitungsfehlermeldungen zurück.
|
||||||
*
|
*
|
||||||
* @return Liste mit Fehlermeldungen
|
* @return Liste mit Fehlermeldungen
|
||||||
*/
|
*/
|
||||||
List<String> getProcessingErrors();
|
List<String> getProcessingErrors();
|
||||||
|
|
@ -36,7 +37,9 @@ public interface Result {
|
||||||
XdmNode getReport();
|
XdmNode getReport();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Das evaluierte Ergebnis.
|
* The Recommendation based on the evaluation of this Result.
|
||||||
|
*
|
||||||
|
* @return AcceptRecommendation
|
||||||
*/
|
*/
|
||||||
AcceptRecommendation getAcceptRecommendation();
|
AcceptRecommendation getAcceptRecommendation();
|
||||||
|
|
||||||
|
|
@ -62,22 +65,36 @@ public interface Result {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Liefert die Ergebnisse der Schematron-Prüfungen, in der Reihenfolge der Szenario-Konfiguration.
|
* Liefert die Ergebnisse der Schematron-Prüfungen, in der Reihenfolge der Szenario-Konfiguration.
|
||||||
*
|
*
|
||||||
* @return Liste mit Schematron-Ergebnissen
|
* @return Liste mit Schematron-Ergebnissen
|
||||||
*/
|
*/
|
||||||
List<SchematronOutput> getSchematronResult();
|
List<SchematronOutput> getSchematronResult();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Liefert ein true, wenn keine Schema-Violations vorhanden sind.
|
* Returns {@link org.oclc.purl.dsdl.svrl.FailedAssert FailedAsserts} of a schematron evaluation.
|
||||||
*
|
*
|
||||||
|
* @return list of {@link org.oclc.purl.dsdl.svrl.FailedAssert FailedAsserts}, if any, empty list otherwise
|
||||||
|
*/
|
||||||
|
List<FailedAssert> getFailedAsserts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert ein true, wenn keine Schema-Violations vorhanden sind.
|
||||||
|
*
|
||||||
* @return true wenn Schema-valide
|
* @return true wenn Schema-valide
|
||||||
*/
|
*/
|
||||||
boolean isSchemaValid();
|
boolean isSchemaValid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Liefert ein true, wenn der Prüfling eine well-formed XML-Datei ist.
|
* Liefert ein true, wenn der Prüfling eine well-formed XML-Datei ist.
|
||||||
*
|
*
|
||||||
* @return true wenn well-formed
|
* @return true wenn well-formed
|
||||||
*/
|
*/
|
||||||
boolean isWellformed();
|
boolean isWellformed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true, if schematron has been checked and the result does not contain any {@link FailedAssert FailedAsserts}.
|
||||||
|
*
|
||||||
|
* @return true, if valid
|
||||||
|
*/
|
||||||
|
boolean isSchematronValid();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,12 +127,19 @@ public class DefaultResult implements Result {
|
||||||
*
|
*
|
||||||
* @return die {@link FailedAssert}
|
* @return die {@link FailedAssert}
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public List<FailedAssert> getFailedAsserts() {
|
public List<FailedAssert> getFailedAsserts() {
|
||||||
return filterSchematronResult(FailedAssert.class);
|
return filterSchematronResult(FailedAssert.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> List<T> filterSchematronResult(final Class<T> type) {
|
private <T> List<T> filterSchematronResult(final Class<T> type) {
|
||||||
return getSchematronResult().stream().filter(type::isInstance).map(type::cast).collect(Collectors.toList());
|
return getSchematronResult() != null
|
||||||
|
? getSchematronResult().stream().filter(type::isInstance).map(type::cast).collect(Collectors.toList())
|
||||||
|
: Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSchematronValid() {
|
||||||
|
return getSchematronResult() != null && getFailedAsserts().isEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,19 @@ package de.kosit.validationtool.impl.tasks;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
|
import org.oclc.purl.dsdl.svrl.FailedAssert;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import de.kosit.validationtool.api.AcceptRecommendation;
|
import de.kosit.validationtool.api.AcceptRecommendation;
|
||||||
|
|
||||||
|
import net.sf.saxon.s9api.SaxonApiException;
|
||||||
import net.sf.saxon.s9api.XPathSelector;
|
import net.sf.saxon.s9api.XPathSelector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Berechnet die Akzeptanz-Empfehlung gemäß konfigurierten 'acceptMatch' des aktuellen Szenarios.
|
* Computes a {@link AcceptRecommendation} for this instance. This is either based on an 'acceptMatch'-configuration of
|
||||||
|
* the active scenario or based on overall evaluation about schema and semantic (schematron) correctness of the
|
||||||
*
|
*
|
||||||
* @author Andreas Penski
|
* @author Andreas Penski
|
||||||
*/
|
*/
|
||||||
|
|
@ -20,23 +24,49 @@ public class ComputeAcceptanceAction implements CheckAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void check(final Bag results) {
|
public void check(final Bag results) {
|
||||||
final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch();
|
if (preCondtionsMatch(results)) {
|
||||||
if (isNotBlank(acceptMatch)) {
|
final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch();
|
||||||
|
if (results.getSchemaValidationResult().isValid() && isNotBlank(acceptMatch)) {
|
||||||
try {
|
evaluateAcceptanceMatch(results);
|
||||||
|
} else {
|
||||||
final XPathSelector selector = results.getScenarioSelectionResult().getObject().getAcceptSelector();
|
evaluateSchemaAndSchematron(results);
|
||||||
selector.setContextItem(results.getReport());
|
|
||||||
results.setAcceptStatus(selector.effectiveBooleanValue() ? AcceptRecommendation.ACCEPTABLE : AcceptRecommendation.REJECT);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
log.error("Fehler bei Evaluierung des Accept-Status: {}", e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
results.setAcceptStatus(AcceptRecommendation.REJECT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void evaluateSchemaAndSchematron(final Bag results) {
|
||||||
public boolean isSkipped(final Bag results) {
|
if (results.getSchemaValidationResult().isValid() && isSchematronValid(results)) {
|
||||||
return results.getReport() == null;
|
results.setAcceptStatus(AcceptRecommendation.ACCEPTABLE);
|
||||||
|
} else {
|
||||||
|
results.setAcceptStatus(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSchematronValid(final Bag results) {
|
||||||
|
return !hasSchematronErrors(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSchematronErrors(final Bag results) {
|
||||||
|
return results.getReportInput().getValidationResultsSchematron().stream().map(e -> e.getResults().getSchematronOutput())
|
||||||
|
.flatMap(e -> e.getActivePatternAndFiredRuleAndFailedAssert().stream()).anyMatch(FailedAssert.class::isInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void evaluateAcceptanceMatch(final Bag results) {
|
||||||
|
try {
|
||||||
|
final XPathSelector selector = results.getScenarioSelectionResult().getObject().getAcceptSelector();
|
||||||
|
selector.setContextItem(results.getReport());
|
||||||
|
results.setAcceptStatus(selector.effectiveBooleanValue() ? AcceptRecommendation.ACCEPTABLE : AcceptRecommendation.REJECT);
|
||||||
|
} catch (final SaxonApiException e) {
|
||||||
|
final String msg = "Error evaluating accept recommendation: %s";
|
||||||
|
log.error(msg);
|
||||||
|
results.addProcessingError(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean preCondtionsMatch(final Bag results) {
|
||||||
|
return results.getReport() != null && results.getSchemaValidationResult() != null && results.getScenarioSelectionResult() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<!--
|
<!--
|
||||||
~ Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
|
~ Licensed to the Koordinierungsstelle für IT-Standards (KoSIT) under
|
||||||
~ one or more contributor license agreements. See the NOTICE file
|
~ one or more contributor license agreements. See the NOTICE file
|
||||||
|
|
@ -19,46 +19,44 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- $Id$ -->
|
<!-- $Id$ -->
|
||||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:s="http://www.xoev.de/de/validator/framework/1/scenarios"
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:s="http://www.xoev.de/de/validator/framework/1/scenarios" targetNamespace="http://www.xoev.de/de/validator/framework/1/scenarios" version="1.1.0" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||||
targetNamespace="http://www.xoev.de/de/validator/framework/1/scenarios" version="1.1.0" elementFormDefault="qualified"
|
|
||||||
attributeFormDefault="unqualified">
|
|
||||||
|
|
||||||
<xs:element name="scenarios">
|
<xs:element name="scenarios">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="name" type="xs:token"/>
|
<xs:element name="name" type="xs:token" />
|
||||||
<xs:element minOccurs="0" name="author" type="xs:token"/>
|
<xs:element minOccurs="0" name="author" type="xs:token" />
|
||||||
<xs:element name="date" type="xs:date"/>
|
<xs:element name="date" type="xs:date" />
|
||||||
<xs:element name="description" type="s:DescriptionType"/>
|
<xs:element name="description" type="s:DescriptionType" />
|
||||||
<xs:element ref="s:scenario" minOccurs="1" maxOccurs="unbounded"/>
|
<xs:element ref="s:scenario" minOccurs="1" maxOccurs="unbounded" />
|
||||||
<xs:element name="noScenarioReport" type="s:NoScenarioReportType"/>
|
<xs:element name="noScenarioReport" type="s:NoScenarioReportType" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
<xs:attribute name="frameworkVersion" type="xs:string" use="required"/>
|
<xs:attribute name="frameworkVersion" type="xs:string" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
||||||
<xs:element name="scenario" type="s:ScenarioType"/>
|
<xs:element name="scenario" type="s:ScenarioType" />
|
||||||
|
|
||||||
<xs:complexType name="NoScenarioReportType">
|
<xs:complexType name="NoScenarioReportType">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element ref="s:resource"/>
|
<xs:element ref="s:resource" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="DescriptionType">
|
<xs:complexType name="DescriptionType">
|
||||||
<xs:choice maxOccurs="unbounded">
|
<xs:choice maxOccurs="unbounded">
|
||||||
<xs:element name="p" type="xs:normalizedString"/>
|
<xs:element name="p" type="xs:normalizedString" />
|
||||||
<xs:element name="ol">
|
<xs:element name="ol">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element maxOccurs="unbounded" name="li" type="xs:normalizedString"/>
|
<xs:element maxOccurs="unbounded" name="li" type="xs:normalizedString" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="ul">
|
<xs:element name="ul">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element maxOccurs="unbounded" name="li" type="xs:normalizedString"/>
|
<xs:element maxOccurs="unbounded" name="li" type="xs:normalizedString" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
|
|
@ -68,72 +66,73 @@
|
||||||
<!-- TODO: Prüfen, ob restriction passt -->
|
<!-- TODO: Prüfen, ob restriction passt -->
|
||||||
<xs:simpleType name="ErrorLevelType">
|
<xs:simpleType name="ErrorLevelType">
|
||||||
<xs:restriction base="xs:token">
|
<xs:restriction base="xs:token">
|
||||||
<xs:enumeration value="error"/>
|
<xs:enumeration value="error" />
|
||||||
<xs:enumeration value="warning"/>
|
<xs:enumeration value="warning" />
|
||||||
<xs:enumeration value="information"/>
|
<xs:enumeration value="information" />
|
||||||
</xs:restriction>
|
</xs:restriction>
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:simpleType name="Tokens">
|
<xs:simpleType name="Tokens">
|
||||||
<xs:list itemType="xs:token"/>
|
<xs:list itemType="xs:token" />
|
||||||
</xs:simpleType>
|
</xs:simpleType>
|
||||||
|
|
||||||
<xs:complexType name="ScenarioType">
|
<xs:complexType name="ScenarioType">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="name" type="xs:token"/>
|
<xs:element name="name" type="xs:token" />
|
||||||
<xs:element minOccurs="0" name="description" type="s:DescriptionType"/>
|
<xs:element minOccurs="0" name="description" type="s:DescriptionType" />
|
||||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="namespace" type="s:NamespaceType"/>
|
<xs:element minOccurs="0" maxOccurs="unbounded" name="namespace" type="s:NamespaceType" />
|
||||||
<xs:element name="match" type="xs:string"/>
|
<xs:element name="match" type="xs:string" />
|
||||||
<xs:element name="validateWithXmlSchema" type="s:ValidateWithXmlSchema"/>
|
<xs:element name="validateWithXmlSchema" type="s:ValidateWithXmlSchema" />
|
||||||
<xs:element name="validateWithSchematron" maxOccurs="unbounded" minOccurs="0" type="s:ValidateWithSchematron"/>
|
<xs:element name="validateWithSchematron" maxOccurs="unbounded" minOccurs="0" type="s:ValidateWithSchematron" />
|
||||||
<xs:element name="createReport" type="s:CreateReportType"/>
|
<xs:element name="createReport" type="s:CreateReportType" />
|
||||||
<!-- Optional da nachträglich eingeführt -->
|
<!-- Optional da nachträglich eingeführt -->
|
||||||
|
<!-- An XPATH expression to be applied to a generated validation report as defined in the createReport element -->
|
||||||
<xs:element name="acceptMatch" type="xs:string" minOccurs="0" />
|
<xs:element name="acceptMatch" type="xs:string" minOccurs="0" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:element name="resource" type="s:ResourceType"/>
|
<xs:element name="resource" type="s:ResourceType" />
|
||||||
|
|
||||||
<xs:complexType name="NamespaceType">
|
<xs:complexType name="NamespaceType">
|
||||||
<xs:simpleContent>
|
<xs:simpleContent>
|
||||||
<xs:extension base="xs:anyURI">
|
<xs:extension base="xs:anyURI">
|
||||||
<xs:attribute name="prefix" use="required"/>
|
<xs:attribute name="prefix" use="required" />
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:simpleContent>
|
</xs:simpleContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="ResourceType">
|
<xs:complexType name="ResourceType">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element name="name" type="xs:token"/>
|
<xs:element name="name" type="xs:token" />
|
||||||
<xs:element name="location" type="xs:anyURI"/>
|
<xs:element name="location" type="xs:anyURI" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="ValidateWithXmlSchema">
|
<xs:complexType name="ValidateWithXmlSchema">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element ref="s:resource" maxOccurs="unbounded"/>
|
<xs:element ref="s:resource" maxOccurs="unbounded" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="ValidateWithSchematron">
|
<xs:complexType name="ValidateWithSchematron">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element ref="s:resource"/>
|
<xs:element ref="s:resource" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
<xs:attribute name="psvi" type="xs:boolean" default="false" use="optional"/>
|
<xs:attribute name="psvi" type="xs:boolean" default="false" use="optional" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
|
|
||||||
<xs:complexType name="CreateReportType">
|
<xs:complexType name="CreateReportType">
|
||||||
<xs:sequence>
|
<xs:sequence>
|
||||||
<xs:element ref="s:resource"/>
|
<xs:element ref="s:resource" />
|
||||||
<xs:element maxOccurs="3" minOccurs="0" name="customLevel" type="s:CustomErrorLevel"/>
|
<xs:element maxOccurs="3" minOccurs="0" name="customLevel" type="s:CustomErrorLevel" />
|
||||||
</xs:sequence>
|
</xs:sequence>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
||||||
<xs:complexType name="CustomErrorLevel">
|
<xs:complexType name="CustomErrorLevel">
|
||||||
<xs:simpleContent>
|
<xs:simpleContent>
|
||||||
<xs:extension base="s:Tokens">
|
<xs:extension base="s:Tokens">
|
||||||
<xs:attribute name="level" type="s:ErrorLevelType" use="required"/>
|
<xs:attribute name="level" type="s:ErrorLevelType" use="required" />
|
||||||
</xs:extension>
|
</xs:extension>
|
||||||
</xs:simpleContent>
|
</xs:simpleContent>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,9 @@ public class DefaultCheckTest {
|
||||||
final Result doc = this.implementation.checkInput(read(Simple.FOO));
|
final Result doc = this.implementation.checkInput(read(Simple.FOO));
|
||||||
assertThat(doc).isNotNull();
|
assertThat(doc).isNotNull();
|
||||||
assertThat(doc.getReport()).isNotNull();
|
assertThat(doc.getReport()).isNotNull();
|
||||||
|
// happy case has schematron errors !??
|
||||||
assertThat(doc.isAcceptable()).isFalse();
|
assertThat(doc.isAcceptable()).isFalse();
|
||||||
assertThat(doc.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.UNDEFINED);
|
assertThat(doc.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import de.kosit.validationtool.impl.Helper.Simple;
|
||||||
*
|
*
|
||||||
* @author Andreas Penski
|
* @author Andreas Penski
|
||||||
*/
|
*/
|
||||||
public class SimpleScenarioCheck {
|
public class SimpleScenarioCheckTest {
|
||||||
|
|
||||||
private DefaultCheck implementation;
|
private DefaultCheck implementation;
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ public class SimpleScenarioCheck {
|
||||||
public void testWithoutAcceptMatch() throws MalformedURLException {
|
public void testWithoutAcceptMatch() throws MalformedURLException {
|
||||||
final Result result = this.implementation.checkInput(InputFactory.read(Simple.FOO.toURL()));
|
final Result result = this.implementation.checkInput(InputFactory.read(Simple.FOO.toURL()));
|
||||||
assertThat(result).isNotNull();
|
assertThat(result).isNotNull();
|
||||||
assertThat(result.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.UNDEFINED);
|
assertThat(result.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.ACCEPTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
package de.kosit.validationtool.impl.tasks;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.oclc.purl.dsdl.svrl.FailedAssert;
|
||||||
|
import org.oclc.purl.dsdl.svrl.SchematronOutput;
|
||||||
|
|
||||||
|
import de.kosit.validationtool.api.AcceptRecommendation;
|
||||||
|
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.model.Result;
|
||||||
|
import de.kosit.validationtool.impl.tasks.CheckAction.Bag;
|
||||||
|
import de.kosit.validationtool.model.reportInput.CreateReportInput;
|
||||||
|
import de.kosit.validationtool.model.reportInput.ValidationResultsSchematron;
|
||||||
|
import de.kosit.validationtool.model.reportInput.ValidationResultsSchematron.Results;
|
||||||
|
import de.kosit.validationtool.model.reportInput.XMLSyntaxError;
|
||||||
|
import de.kosit.validationtool.model.scenarios.ScenarioType;
|
||||||
|
|
||||||
|
import net.sf.saxon.s9api.XdmNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the 'acceptMatch' functionality.
|
||||||
|
*
|
||||||
|
* @author Andreas Penski
|
||||||
|
*/
|
||||||
|
public class ComputeAcceptanceActionTest {
|
||||||
|
|
||||||
|
private final ComputeAcceptanceAction action = new ComputeAcceptanceAction();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleTest() {
|
||||||
|
final Bag bag = createBag(true, true);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.UNDEFINED);
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSchemaFailed() {
|
||||||
|
final Bag bag = createBag(false, true);
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSchematronFailed() {
|
||||||
|
final Bag bag = createBag(true, false);
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidAcceptMatch() {
|
||||||
|
final Bag bag = createBag(true, true);
|
||||||
|
bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 0");
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAcceptMatchNotSatisfied() {
|
||||||
|
final Bag bag = createBag(true, true);
|
||||||
|
bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 1");
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidAcceptMatchOnSchematronFailed() {
|
||||||
|
final Bag bag = createBag(true, false);
|
||||||
|
bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 0");
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.ACCEPTABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidAcceptMatchOnSchemaFailed() {
|
||||||
|
final Bag bag = createBag(false, true);
|
||||||
|
bag.getScenarioSelectionResult().getObject().setAcceptMatch("count(//doesnotExist) = 0");
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMissingSchemaCheck() {
|
||||||
|
final Bag bag = createBag(null, Collections.emptyList());
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMissingReport() {
|
||||||
|
final Bag bag = createBag(false, true);
|
||||||
|
bag.setReport(null);
|
||||||
|
this.action.check(bag);
|
||||||
|
assertThat(bag.getAcceptStatus()).isEqualTo(AcceptRecommendation.REJECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bag createBag(final boolean schemaValid, final boolean schematronValid) {
|
||||||
|
final Result<Boolean, XMLSyntaxError> schemaResult = schemaValid ? new Result<>(true)
|
||||||
|
: new Result<>(Collections.singletonList(new XMLSyntaxError()));
|
||||||
|
final List<ValidationResultsSchematron> schematronResult = schematronValid ? Collections.emptyList() : createSchematronError();
|
||||||
|
return createBag(schemaResult, schematronResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ValidationResultsSchematron> createSchematronError() {
|
||||||
|
final ValidationResultsSchematron v = new ValidationResultsSchematron();
|
||||||
|
final SchematronOutput out = new SchematronOutput();
|
||||||
|
final FailedAssert f = new FailedAssert();
|
||||||
|
out.getActivePatternAndFiredRuleAndFailedAssert().add(f);
|
||||||
|
final Results r = new Results();
|
||||||
|
r.setSchematronOutput(out);
|
||||||
|
v.setResults(r);
|
||||||
|
return Collections.singletonList(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bag createBag(final Result<Boolean, XMLSyntaxError> schemaResult,
|
||||||
|
final Collection<ValidationResultsSchematron> schematronResult) {
|
||||||
|
final ScenarioType t = new ScenarioType();
|
||||||
|
t.initialize(new ContentRepository(ObjectFactory.createProcessor(), Simple.REPOSITORY), true);
|
||||||
|
final CreateReportInput reportInput = new CreateReportInput();
|
||||||
|
reportInput.getValidationResultsSchematron().addAll(schematronResult);
|
||||||
|
final Bag b = new Bag(InputFactory.read("<someXml></someXml>".getBytes(), "someCheck"), reportInput);
|
||||||
|
final Result<XdmNode, XMLSyntaxError> parseREsult = DocumentParseAction.parseDocument(b.getInput());
|
||||||
|
b.setReport(parseREsult.getObject());
|
||||||
|
b.setParserResult(parseREsult);
|
||||||
|
b.setSchemaValidationResult(schemaResult);
|
||||||
|
b.setScenarioSelectionResult(new Result<>(t));
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue