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:
Andreas Penski (init) 2020-03-23 11:14:29 +01:00
commit 6aab106075
11 changed files with 307 additions and 75 deletions

View file

@ -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

View file

@ -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.

View file

@ -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`.

View file

@ -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
} }

View file

@ -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;
@ -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();
@ -67,6 +70,13 @@ public interface Result {
*/ */
List<SchematronOutput> getSchematronResult(); List<SchematronOutput> getSchematronResult();
/**
* 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. * Liefert ein true, wenn keine Schema-Violations vorhanden sind.
* *
@ -80,4 +90,11 @@ public interface Result {
* @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();
} }

View file

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

View file

@ -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) {
if (preCondtionsMatch(results)) {
final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch(); final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch();
if (isNotBlank(acceptMatch)) { if (results.getSchemaValidationResult().isValid() && isNotBlank(acceptMatch)) {
evaluateAcceptanceMatch(results);
} else {
evaluateSchemaAndSchematron(results);
}
} else {
results.setAcceptStatus(AcceptRecommendation.REJECT);
}
}
private void evaluateSchemaAndSchematron(final Bag results) {
if (results.getSchemaValidationResult().isValid() && isSchematronValid(results)) {
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 { try {
final XPathSelector selector = results.getScenarioSelectionResult().getObject().getAcceptSelector(); 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 Exception e) { } catch (final SaxonApiException e) {
log.error("Fehler bei Evaluierung des Accept-Status: {}", e.getMessage(), e); final String msg = "Error evaluating accept recommendation: %s";
} log.error(msg);
results.addProcessingError(msg);
} }
} }
@Override private static boolean preCondtionsMatch(final Bag results) {
public boolean isSkipped(final Bag results) { return results.getReport() != null && results.getSchemaValidationResult() != null && results.getScenarioSelectionResult() != null;
return results.getReport() == null;
} }
} }

View file

@ -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>

View file

@ -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

View file

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

View file

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