#21 Umbau NoScenarioMatch, als Fallback match

This commit is contained in:
Andreas Penski (init) 2019-05-17 16:11:02 +02:00 committed by Andreas Penski
parent b350334a04
commit cadedaf062
8 changed files with 55 additions and 45 deletions

View file

@ -81,7 +81,7 @@ public class DefaultCheck implements Check {
final Processor processor = ObjectFactory.createProcessor();
this.conversionService = new ConversionService();
this.contentRepository = new ContentRepository(processor, configuration.getScenarioRepository());
this.repository = new ScenarioRepository(processor, this.contentRepository);
this.repository = new ScenarioRepository(this.contentRepository);
this.repository.initialize(configuration);
this.checkSteps = new ArrayList<>();
this.checkSteps.add(DefaultCheck::createDocumentIdentification);

View file

@ -14,6 +14,8 @@ import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmNode;
/**
* Funktion zum Extrahieren von HTML-Artefakten / Knoten aus einem XML-Dokument.
*
* @author Andreas Penski
*/
@RequiredArgsConstructor

View file

@ -23,13 +23,14 @@ import static org.apache.commons.lang3.StringUtils.startsWith;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.Iterator;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import de.kosit.validationtool.api.CheckConfiguration;
@ -37,16 +38,15 @@ import de.kosit.validationtool.api.InputFactory;
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.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XPathSelector;
import net.sf.saxon.s9api.XdmNode;
import net.sf.saxon.s9api.XdmNodeKind;
import net.sf.saxon.s9api.XsltExecutable;
/**
* Repository for die aktiven Szenario einer Prüfinstanz.
@ -61,18 +61,17 @@ public class ScenarioRepository {
private static final String SUPPORTED_MAJOR_VERSION_SCHEMA = "http://www.xoev.de/de/validator/framework/1/scenarios";
@Getter(value = AccessLevel.PRIVATE)
private final Processor processor;
@Getter(value = AccessLevel.PRIVATE)
private final ContentRepository repository;
private XsltExecutable noScenarioReport;
@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"));
@ -81,9 +80,7 @@ public class ScenarioRepository {
}
private static XdmNode findRoot(final XdmNode doc) {
final Iterator<XdmNode> it = doc.children().iterator();
while (it.hasNext()) {
final XdmNode node = it.next();
for (final XdmNode node : doc.children()) {
if (node.getNodeKind() == XdmNodeKind.ELEMENT) {
return node;
}
@ -92,7 +89,6 @@ public class ScenarioRepository {
}
private static void checkVersion(final URI scenarioDefinition) {
final DocumentParseAction p = new DocumentParseAction();
try {
final Result<XdmNode, XMLSyntaxError> result = DocumentParseAction.parseDocument(InputFactory.read(scenarioDefinition.toURL()));
if (result.isValid() && !isSupportedDocument(result.getObject())) {
@ -106,13 +102,7 @@ public class ScenarioRepository {
}
}
public XsltExecutable getNoScenarioReport() {
if (this.noScenarioReport == null) {
this.noScenarioReport = this.repository
.loadXsltScript(URI.create(this.scenarios.getNoScenarioReport().getResource().getLocation()));
}
return this.noScenarioReport;
}
/**
* Initialisiert das Repository mit der angegebenen Konfiguration.
@ -136,7 +126,7 @@ public class ScenarioRepository {
handler.getErrorDescription()));
}
// initialize fallback report eager
getNoScenarioReport();
this.fallbackScenario = createFallback();
}
@ -150,26 +140,39 @@ public class ScenarioRepository {
}
/**
* Ermittelt für das angegebene Dokument das passende Szenario.
*
* Ermittelt für das gegebene Dokument das passende Szenario.
*
* @param document das Eingabedokument
* @return ein Ergebnis-Objekt zur weiteren Verarbeitung
*/
public Result<ScenarioType, String> selectScenario(final XdmNode document) {
Result<ScenarioType, String> result = new Result<>();
final Result<ScenarioType, String> result;
final List<ScenarioType> collect = this.scenarios.getScenario().stream().filter(s -> match(document, s))
.collect(Collectors.toList());
if (collect.size() == 1) {
result = new Result<>(collect.get(0));
} else if (collect.isEmpty()) {
result.getErrors().add("None of the loaded scenarios matches the specified document");
result = new Result<>(getFallbackScenario(),
Collections.singleton("None of the loaded scenarios matches the specified document"));
} else {
result.getErrors().add("More than on scenario matches the specified document");
result = new Result<>(getFallbackScenario(), Collections.singleton("More than on scenario matches the specified document"));
}
return result;
}
private ScenarioType createFallback() {
final ScenarioType t = new ScenarioType();
t.setName("Fallback-Scenario");
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 {
final XPathSelector selector = scenario.getSelector();
@ -179,7 +182,6 @@ public class ScenarioRepository {
log.error("Error evaluating xpath expression", e);
}
return false;
}
void initialize(final Scenarios def) {

View file

@ -160,8 +160,6 @@ public abstract class BaseScenario {
*/
public XPathSelector getAcceptSelector() {
if (this.acceptExecutable == null) {
System.out.println(getAcceptMatch());
System.out.println(prepareNamespaces());
this.acceptExecutable = this.repository.createXPath(getAcceptMatch(), prepareNamespaces());
}
return this.acceptExecutable.load();

View file

@ -36,7 +36,7 @@ public class ComputeAcceptanceAction implements CheckAction {
@Override
public boolean isSkipped(final Bag results) {
return results.getScenarioSelectionResult().isInvalid();
return results.getReport() == null;
}
}

View file

@ -61,24 +61,24 @@ public class CreateReportAction implements CheckAction {
private final URI contentRepository;
private static XsltExecutable loadFromScenario(ScenarioType object) {
private static XsltExecutable loadFromScenario(final ScenarioType object) {
return object.getReportTransformation().getExecutable();
}
@Override
public void check(Bag results) {
final DocumentBuilder documentBuilder = processor.newDocumentBuilder();
public void check(final Bag results) {
final DocumentBuilder documentBuilder = this.processor.newDocumentBuilder();
try {
final XdmNode parsedDocument = results.getParserResult().isValid() ? results.getParserResult().getObject()
: ObjectFactory.createProcessor().newDocumentBuilder().newBuildingContentHandler().getDocumentNode();
final Document reportInput = conversionService.writeDocument(results.getReportInput());
final Document reportInput = this.conversionService.writeDocument(results.getReportInput());
final XdmNode root = documentBuilder.build(new DOMSource(reportInput));
final XsltTransformer transformer = getTransformation(results).load();
transformer.setInitialContextNode(root);
CollectingErrorEventHandler e = new CollectingErrorEventHandler();
RelativeUriResolver resolver = new RelativeUriResolver(contentRepository);
final CollectingErrorEventHandler e = new CollectingErrorEventHandler();
final RelativeUriResolver resolver = new RelativeUriResolver(this.contentRepository);
transformer.setMessageListener(e);
transformer.setURIResolver(resolver);
transformer.getUnderlyingController().setUnparsedTextURIResolver(resolver);
@ -88,17 +88,15 @@ public class CreateReportAction implements CheckAction {
transformer.transform();
results.setReport(destination.getXdmNode());
} catch (SaxonApiException e) {
} catch (final SaxonApiException e) {
throw new IllegalStateException("Can not create final report", e);
}
}
private XsltExecutable getTransformation(Bag results) {
private static XsltExecutable getTransformation(final Bag results) {
final Result<ScenarioType, String> scenario = results.getScenarioSelectionResult();
return scenario != null && scenario.isValid() ? loadFromScenario(scenario.getObject()) : loadFallback();
return loadFromScenario(scenario.getObject());
}
private XsltExecutable loadFallback() {
return repository.getNoScenarioReport();
}
}

View file

@ -66,7 +66,7 @@ public class ScenarioRepositoryTest {
t.setName("Test");
t.initialize(this.content, true);
def.getScenario().add(t);
this.repository = new ScenarioRepository(ObjectFactory.createProcessor(), this.content);
this.repository = new ScenarioRepository(this.content);
this.repository.initialize(def);
}
@ -80,9 +80,14 @@ public class ScenarioRepositoryTest {
@Test
public void testNonMatch() throws Exception {
this.repository.getScenarios().getScenario().clear();
final ScenarioType fallback = new ScenarioType();
fallback.setName("fallback");
this.repository.setFallbackScenario(fallback);
final Result<ScenarioType, String> scenario = this.repository.selectScenario(load(SAMPLE));
assertThat(scenario).isNotNull();
assertThat(scenario.isValid()).isFalse();
assertThat(scenario.getObject().getName()).isEqualTo("fallback");
}
@Test
@ -92,9 +97,13 @@ public class ScenarioRepositoryTest {
t.setName("Test");
t.initialize(this.content, true);
this.repository.getScenarios().getScenario().add(t);
final ScenarioType fallback = new ScenarioType();
fallback.setName("fallback");
this.repository.setFallbackScenario(fallback);
final Result<ScenarioType, String> scenario = this.repository.selectScenario(load(SAMPLE));
assertThat(scenario).isNotNull();
assertThat(scenario.isValid()).isFalse();
assertThat(scenario.getObject().getName()).isEqualTo("fallback");
}
private static XdmNode load(final URL url) throws IOException {
@ -105,7 +114,7 @@ public class ScenarioRepositoryTest {
@Test
public void loadFromJar() throws URISyntaxException {
this.content = new ContentRepository(ObjectFactory.createProcessor(), Helper.JAR_REPOSITORY.toURI());
this.repository = new ScenarioRepository(ObjectFactory.createProcessor(), this.content);
this.repository = new ScenarioRepository(this.content);
final CheckConfiguration conf = new CheckConfiguration(
ScenarioRepository.class.getClassLoader().getResource("xrechnung/scenarios.xml").toURI());
this.repository.initialize(conf);

View file

@ -49,7 +49,7 @@ public class SimpleScenarioCheck {
public void testUnknown() throws MalformedURLException {
final Result result = this.implementation.checkInput(InputFactory.read(Simple.UNKNOWN.toURL()));
assertThat(result).isNotNull();
assertThat(result.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.UNDEFINED);
assertThat(result.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.REJECT);
}
@Test
@ -58,4 +58,5 @@ public class SimpleScenarioCheck {
assertThat(result).isNotNull();
assertThat(result.getAcceptRecommendation()).isEqualTo(AcceptRecommendation.UNDEFINED);
}
}