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

@ -1,21 +1,21 @@
package de.kosit.validationtool.api;
/**
* Status der Empfehlung.
* Tri-state describtion of a Recommendation.
*/
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,
/**
* Das Dokument ist gemäß Konfiguration valide und kann akzeptiert werden.
* Recommendation is to accept input based on the evaluation of the overall validation.
*/
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
}
}

View file

@ -2,6 +2,7 @@ package de.kosit.validationtool.api;
import java.util.List;
import org.oclc.purl.dsdl.svrl.FailedAssert;
import org.oclc.purl.dsdl.svrl.SchematronOutput;
import org.w3c.dom.Document;
@ -9,7 +10,7 @@ import net.sf.saxon.s9api.XdmNode;
/**
* API Rückgabe Objekt des Ergebnisses des Validierungsprozesses.
*
*
* @author Andreas Penski
*/
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
* keine Aussage über die zur Akzeptanz.
*
*
* @return true, wenn die Verarbeitung komplett und erfolgreich durchlaufen wurde
* @see #getAcceptRecommendation()
*/
@ -25,7 +26,7 @@ public interface Result {
/**
* Gibt eine Liste mit Verarbeitungsfehlermeldungen zurück.
*
*
* @return Liste mit Fehlermeldungen
*/
List<String> getProcessingErrors();
@ -36,7 +37,9 @@ public interface Result {
XdmNode getReport();
/**
* Das evaluierte Ergebnis.
* The Recommendation based on the evaluation of this Result.
*
* @return AcceptRecommendation
*/
AcceptRecommendation getAcceptRecommendation();
@ -62,22 +65,36 @@ public interface Result {
/**
* Liefert die Ergebnisse der Schematron-Prüfungen, in der Reihenfolge der Szenario-Konfiguration.
*
*
* @return Liste mit Schematron-Ergebnissen
*/
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
*/
boolean isSchemaValid();
/**
* Liefert ein true, wenn der Prüfling eine well-formed XML-Datei ist.
*
*
* @return true wenn well-formed
*/
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}
*/
@Override
public List<FailedAssert> getFailedAsserts() {
return filterSchematronResult(FailedAssert.class);
}
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 org.oclc.purl.dsdl.svrl.FailedAssert;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.AcceptRecommendation;
import net.sf.saxon.s9api.SaxonApiException;
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
*/
@ -20,23 +24,49 @@ public class ComputeAcceptanceAction implements CheckAction {
@Override
public void check(final Bag results) {
final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch();
if (isNotBlank(acceptMatch)) {
try {
final XPathSelector selector = results.getScenarioSelectionResult().getObject().getAcceptSelector();
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);
if (preCondtionsMatch(results)) {
final String acceptMatch = results.getScenarioSelectionResult().getObject().getAcceptMatch();
if (results.getSchemaValidationResult().isValid() && isNotBlank(acceptMatch)) {
evaluateAcceptanceMatch(results);
} else {
evaluateSchemaAndSchematron(results);
}
} else {
results.setAcceptStatus(AcceptRecommendation.REJECT);
}
}
@Override
public boolean isSkipped(final Bag results) {
return results.getReport() == null;
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 {
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;
}
}