diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java index 52afd11..7ecb1aa 100644 --- a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java +++ b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java @@ -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); diff --git a/src/main/java/de/kosit/validationtool/impl/HtmlExtraction.java b/src/main/java/de/kosit/validationtool/impl/HtmlExtraction.java index 3506976..2e1210d 100644 --- a/src/main/java/de/kosit/validationtool/impl/HtmlExtraction.java +++ b/src/main/java/de/kosit/validationtool/impl/HtmlExtraction.java @@ -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 diff --git a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java index 575cf42..294500c 100644 --- a/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java +++ b/src/main/java/de/kosit/validationtool/impl/ScenarioRepository.java @@ -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 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 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 selectScenario(final XdmNode document) { - Result result = new Result<>(); + final Result result; final List 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) { diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java b/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java index 9bf9ec2..b90f7e1 100644 --- a/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java +++ b/src/main/java/de/kosit/validationtool/impl/model/BaseScenario.java @@ -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(); diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java index 67d4ae4..e24ba4c 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ComputeAcceptanceAction.java @@ -36,7 +36,7 @@ public class ComputeAcceptanceAction implements CheckAction { @Override public boolean isSkipped(final Bag results) { - return results.getScenarioSelectionResult().isInvalid(); + return results.getReport() == null; } } diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java index 966859a..3cb3a1f 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/CreateReportAction.java @@ -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 scenario = results.getScenarioSelectionResult(); - return scenario != null && scenario.isValid() ? loadFromScenario(scenario.getObject()) : loadFallback(); + return loadFromScenario(scenario.getObject()); } - private XsltExecutable loadFallback() { - return repository.getNoScenarioReport(); - } + } diff --git a/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java b/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java index a261f43..dbaa52b 100644 --- a/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java +++ b/src/test/java/de/kosit/validationtool/impl/ScenarioRepositoryTest.java @@ -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 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 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); diff --git a/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheck.java b/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheck.java index 8310c22..1444646 100644 --- a/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheck.java +++ b/src/test/java/de/kosit/validationtool/impl/SimpleScenarioCheck.java @@ -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); } + }