From 2069c0d04eb0594f0aefe47ddf2d86b5791e4855 Mon Sep 17 00:00:00 2001 From: "Andreas Penski (init)" Date: Fri, 24 May 2019 11:32:08 +0200 Subject: [PATCH] =?UTF-8?q?(chore)=20R=C3=BCckgabe=20der=20Schematron-Erge?= =?UTF-8?q?bnisse=20als=20komplexes=20Objekt=20in=20der=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../de/kosit/validationtool/api/Result.java | 10 +- .../impl/ConversionService.java | 93 ++++++---- .../validationtool/impl/DefaultCheck.java | 5 +- .../validationtool/impl/DefaultResult.java | 12 +- .../validationtool/impl/model/BaseOutput.java | 72 ++++++++ .../tasks/SchematronValidationAction.java | 28 +-- .../impl/tasks/ValidateReportInputAction.java | 8 +- src/main/model/binding/global.xjb | 7 + src/main/model/xsd/createReportInput.xsd | 7 +- src/main/model/xsd/svrl-kosit.xsd | 161 ++++++++++++++++++ src/main/model/xsd/xml.xsd | 10 ++ 11 files changed, 354 insertions(+), 59 deletions(-) create mode 100644 src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java create mode 100644 src/main/model/xsd/svrl-kosit.xsd create mode 100644 src/main/model/xsd/xml.xsd diff --git a/src/main/java/de/kosit/validationtool/api/Result.java b/src/main/java/de/kosit/validationtool/api/Result.java index b4b9dcb..27d4adc 100644 --- a/src/main/java/de/kosit/validationtool/api/Result.java +++ b/src/main/java/de/kosit/validationtool/api/Result.java @@ -2,6 +2,7 @@ package de.kosit.validationtool.api; import java.util.List; +import org.oclc.purl.dsdl.svrl.SchematronOutput; import org.w3c.dom.Document; import net.sf.saxon.s9api.XdmNode; @@ -39,9 +40,12 @@ public interface Result { * wurden. */ List getSchemaViolations(); - - // TODO scheitert momentan daran, das intern kein svlr o.ä. zur Verfügung steht - // List getSchematronResult(); + /** + * Liefert die Ergebnisse der Schematron-Prüfungen, in der Reihenfolge der Szenario-Konfiguration. + * + * @return Liste mit Schematron-Ergebnissen + */ + List getSchematronResult(); } diff --git a/src/main/java/de/kosit/validationtool/impl/ConversionService.java b/src/main/java/de/kosit/validationtool/impl/ConversionService.java index eea4acc..2bc4185 100644 --- a/src/main/java/de/kosit/validationtool/impl/ConversionService.java +++ b/src/main/java/de/kosit/validationtool/impl/ConversionService.java @@ -27,14 +27,26 @@ import java.util.Arrays; import java.util.Collection; import java.util.StringJoiner; -import javax.xml.bind.*; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.JAXBIntrospector; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.ValidationEventHandler; import javax.xml.bind.annotation.XmlRegistry; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; -import javax.xml.stream.*; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; +import org.apache.commons.lang3.StringUtils; import org.w3c.dom.Document; import lombok.extern.slf4j.Slf4j; @@ -45,6 +57,32 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class ConversionService { + /** + * Exception while serializing/deserializing with jaxb. + */ + public class ConversionExeption extends RuntimeException { + + /** + * Constructor. + * + * @param message the message. + * @param cause the cause + */ + public ConversionExeption(final String message, final Exception cause) { + super(message, cause); + } + + /** + * Constructor. + * + * @param message the message. + */ + public ConversionExeption(final String message) { + super(message); + } + } + + private static final int MAX_LOG_CONTENT = 50; // context setup private JAXBContext jaxbContext; @@ -68,7 +106,7 @@ public class ConversionService { * Initialisiert den default context; Alle Packages mit {@link XmlRegistry XmlRegistries}. */ public void initialize() { - Collection p = new ArrayList<>(); + final Collection p = new ArrayList<>(); p.add(de.kosit.validationtool.model.reportInput.ObjectFactory.class.getPackage()); p.add(de.kosit.validationtool.model.scenarios.ObjectFactory.class.getPackage()); initialize(p); @@ -77,6 +115,7 @@ public class ConversionService { public void initialize(final Package... context) { initialize(Arrays.asList(context)); } + /** * Initialisiert den conversion service mit den angegegebenen Packages. * @@ -84,7 +123,7 @@ public class ConversionService { */ public void initialize(final Collection context) { final String[] packages = context != null ? context.stream().map(Package::getName).toArray(String[]::new) : new String[0]; - StringJoiner joiner = new StringJoiner(":"); + final StringJoiner joiner = new StringJoiner(":"); Arrays.stream(packages).forEach(p -> joiner.add(p)); initialize(joiner.toString()); } @@ -121,11 +160,11 @@ public class ConversionService { return readXml(xml, type, null, null); } - public T readXml(final URI xml, final Class type, Schema schema) { + public T readXml(final URI xml, final Class type, final Schema schema) { return readXml(xml, type, schema, null); } - public T readXml(final URI xml, final Class type, Schema schema, ValidationEventHandler handler) { + public T readXml(final URI xml, final Class type, final Schema schema, final ValidationEventHandler handler) { checkInputEmpty(xml); checkTypeEmpty(type); CollectingErrorEventHandler defaultHandler = null; @@ -167,11 +206,11 @@ public class ConversionService { return writeXml(model, null, null); } - public String writeXml(final T model, Schema schema, ValidationEventHandler handler) { + public String writeXml(final T model, final Schema schema, final ValidationEventHandler handler) { if (model == null) { throw new ConversionExeption("Can not serialize null"); } - try ( StringWriter w = new StringWriter() ) { + try ( final StringWriter w = new StringWriter() ) { final JAXBIntrospector introspector = getJaxbContext().createJAXBIntrospector(); final Marshaller marshaller = getJaxbContext().createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); @@ -189,17 +228,17 @@ public class ConversionService { } xmlStreamWriter.flush(); return w.toString(); - } catch (JAXBException | IOException | XMLStreamException e) { + } catch (final JAXBException | IOException | XMLStreamException e) { throw new ConversionExeption(String.format("Error serializing Object %s", model.getClass().getName()), e); } } - public Document writeDocument(T input) { + public Document writeDocument(final T input) { if (input == null) { throw new ConversionExeption("Can not serialize null"); } - DocumentBuilder builder = ObjectFactory.createDocumentBuilder(false); - Document document = builder.newDocument(); + final DocumentBuilder builder = ObjectFactory.createDocumentBuilder(false); + final Document document = builder.newDocument(); // Marshal the Object to a Document Marshaller marshaller = null; @@ -208,34 +247,20 @@ public class ConversionService { marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal(input, document); return document; - } catch (JAXBException e) { + } catch (final JAXBException e) { throw new ConversionExeption(String.format("Error serializing Object %s to document", input.getClass().getName()), e); } } - /** - * Exception while serializing/deserializing with jaxb. - */ - public class ConversionExeption extends RuntimeException { + public T readDocument(final Source source, final Class type) { + try { + final Unmarshaller u = getJaxbContext().createUnmarshaller(); - /** - * Constructor. - * - * @param message the message. - * @param cause the cause - */ - public ConversionExeption(final String message, final Exception cause) { - super(message, cause); - } + return u.unmarshal(source, type).getValue(); - /** - * Constructor. - * - * @param message the message. - */ - public ConversionExeption(final String message) { - super(message); + } catch (final JAXBException e) { + throw new ConversionExeption(String.format("Can not unmarshal to type %s: %s", type.getSimpleName(), + StringUtils.abbreviate(source.getSystemId(), MAX_LOG_CONTENT)), e); } } - } diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java index 7ecb1aa..a411a99 100644 --- a/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java +++ b/src/main/java/de/kosit/validationtool/impl/DefaultCheck.java @@ -22,6 +22,7 @@ package de.kosit.validationtool.impl; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -88,7 +89,7 @@ public class DefaultCheck implements Check { this.checkSteps.add(new DocumentParseAction()); this.checkSteps.add(new ScenarioSelectionAction(this.repository)); this.checkSteps.add(new SchemaValidationAction()); - this.checkSteps.add(new SchematronValidationAction(configuration.getScenarioRepository())); + this.checkSteps.add(new SchematronValidationAction(configuration.getScenarioRepository(), this.conversionService)); this.checkSteps.add(new ValidateReportInputAction(this.conversionService, this.contentRepository.getReportInputSchema())); this.checkSteps .add(new CreateReportAction(processor, this.conversionService, this.repository, configuration.getScenarioRepository())); @@ -137,6 +138,8 @@ public class DefaultCheck implements Check { if (t.getSchemaValidationResult() != null) { result.setSchemaViolations(convertErrors(t.getSchemaValidationResult().getErrors())); } + result.setSchematronResult(t.getReportInput().getValidationResultsSchematron().stream() + .map(e -> e.getResults().getSchematronOutput()).collect(Collectors.toList())); return result; } diff --git a/src/main/java/de/kosit/validationtool/impl/DefaultResult.java b/src/main/java/de/kosit/validationtool/impl/DefaultResult.java index aaa2712..192008d 100644 --- a/src/main/java/de/kosit/validationtool/impl/DefaultResult.java +++ b/src/main/java/de/kosit/validationtool/impl/DefaultResult.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import org.oclc.purl.dsdl.svrl.SchematronOutput; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -41,6 +42,10 @@ public class DefaultResult implements Result { @Getter private List schemaViolations = new ArrayList<>(); + @Getter + @Setter(AccessLevel.PACKAGE) + private List schematronResult; + public DefaultResult(final XdmNode report, final AcceptRecommendation recommendation, final ContentRepository repository) { this.report = report; this.acceptRecommendation = recommendation; @@ -67,17 +72,18 @@ public class DefaultResult implements Result { return AcceptRecommendation.ACCEPTABLE.equals(this.acceptRecommendation); } + public List extractHtmlAsString() { - return extractHtml().stream().map(this::convertToString).collect(Collectors.toList()); + return extractHtml().stream().map(DefaultResult::convertToString).collect(Collectors.toList()); } - private String convertToString(final XdmNode element) { + private static String convertToString(final XdmNode element) { try { final StringWriter writer = new StringWriter(); final Serializer serializer = ObjectFactory.createProcessor().newSerializer(writer); serializer.serializeNode(element); return writer.toString(); - } catch (SaxonApiException e) { + } catch (final SaxonApiException e) { throw new IllegalStateException("Can not convert to string", e); } } diff --git a/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java b/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java new file mode 100644 index 0000000..b6a670b --- /dev/null +++ b/src/main/java/de/kosit/validationtool/impl/model/BaseOutput.java @@ -0,0 +1,72 @@ +package de.kosit.validationtool.impl.model; + +import java.io.Serializable; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.oclc.purl.dsdl.svrl.ActivePattern; +import org.oclc.purl.dsdl.svrl.FailedAssert; +import org.oclc.purl.dsdl.svrl.FiredRule; + +/** + * Basis-Klasse um spezifische Erweiterungen an der generierten Klasse {@link org.oclc.purl.dsdl.svrl.SchematronOutput} + * umzusetzen. + * + * @author Andreas Penski + */ +public abstract class BaseOutput { + + public abstract List getActivePatternAndFiredRuleAndFailedAssert(); + + /** + * Gibt die Liste der {@link FailedAssert} zurück + * + * @return Liste mit {@link FailedAssert} + */ + public List getFailedAsserts() { + return filter(FailedAssert.class); + } + + /** + * Gibt die Liste der {@link FailedAssert} zurück + * + * @return Liste mit {@link FailedAssert} + */ + public List getFiredRules() { + return filter(FiredRule.class); + } + + /** + * Ermittelt, ob es bei der Validierung {@link FailedAssert}s gab. + * + * @return true wenn mindestens ein {@link FailedAssert} vorhanden ist + */ + public boolean hasFailedAsserts() { + return getFailedAsserts().size() > 0; + } + + /** + * Gibt die Liste der {@link ActivePattern} zurück + * + * @return Liste mit {@link ActivePattern} + */ + public List getActivePatterns() { + return filter(ActivePattern.class); + } + + private List filter(final Class type) { + return getActivePatternAndFiredRuleAndFailedAssert().stream().filter(type::isInstance).map(type::cast).collect(Collectors.toList()); + } + + /** + * Sucht nach einem {@link FailedAssert} mit einem definierten Namen. + * + * @param name der Name + * @return Optional mit dem {@link FailedAssert} + */ + public Optional findFailedAssert(final String name) { + return getFailedAsserts().stream().filter(e -> e.getId().equals(name)).findAny(); + } + +} diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java index e27a660..f2e544d 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/SchematronValidationAction.java @@ -23,11 +23,15 @@ import java.net.URI; import java.util.List; import java.util.stream.Collectors; +import javax.xml.transform.dom.DOMSource; + +import org.oclc.purl.dsdl.svrl.SchematronOutput; import org.w3c.dom.Document; import lombok.RequiredArgsConstructor; import de.kosit.validationtool.impl.CollectingErrorEventHandler; +import de.kosit.validationtool.impl.ConversionService; import de.kosit.validationtool.impl.ObjectFactory; import de.kosit.validationtool.impl.RelativeUriResolver; import de.kosit.validationtool.impl.model.BaseScenario; @@ -50,37 +54,39 @@ public class SchematronValidationAction implements CheckAction { private final URI repository; - private List validate(XdmNode document, ScenarioType scenario) { + private final ConversionService conversionService; + + private List validate(final XdmNode document, final ScenarioType scenario) { return scenario.getSchematronValidations().stream().map(v -> validate(document, v)).collect(Collectors.toList()); } - private ValidationResultsSchematron validate(XdmNode document, BaseScenario.Transformation validation) { + private ValidationResultsSchematron validate(final XdmNode document, final BaseScenario.Transformation validation) { try { final XsltTransformer transformer = validation.getExecutable().load(); // resolving nur relative zum Repository - final RelativeUriResolver resolver = new RelativeUriResolver(repository); + final RelativeUriResolver resolver = new RelativeUriResolver(this.repository); transformer.setURIResolver(resolver); - CollectingErrorEventHandler e = new CollectingErrorEventHandler(); + final CollectingErrorEventHandler e = new CollectingErrorEventHandler(); transformer.setMessageListener(e); - Document result = ObjectFactory.createDocumentBuilder(false).newDocument(); + final Document result = ObjectFactory.createDocumentBuilder(false).newDocument(); transformer.setDestination(new DOMDestination(result)); transformer.setInitialContextNode(document); transformer.transform(); - ValidationResultsSchematron s = new ValidationResultsSchematron(); + final ValidationResultsSchematron s = new ValidationResultsSchematron(); s.setResource(validation.getResourceType()); - ValidationResultsSchematron.Results r = new ValidationResultsSchematron.Results(); - r.setAny(result.getDocumentElement()); + final ValidationResultsSchematron.Results r = new ValidationResultsSchematron.Results(); + r.setSchematronOutput(this.conversionService.readDocument(new DOMSource(result), SchematronOutput.class)); s.setResults(r); return s; - } catch (SaxonApiException e) { + } catch (final SaxonApiException e) { throw new IllegalStateException("Can not run schematron validation", e); } } @Override - public void check(Bag results) { + public void check(final Bag results) { final CreateReportInput report = results.getReportInput(); final List validationResult = validate(results.getParserResult().getObject(), results.getScenarioSelectionResult().getObject()); @@ -88,7 +94,7 @@ public class SchematronValidationAction implements CheckAction { } @Override - public boolean isSkipped(Bag results) { + public boolean isSkipped(final Bag results) { return results.getSchemaValidationResult() == null || results.getSchemaValidationResult().isInvalid(); } } diff --git a/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java b/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java index 57747d8..1cb0fb1 100644 --- a/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java +++ b/src/main/java/de/kosit/validationtool/impl/tasks/ValidateReportInputAction.java @@ -45,7 +45,7 @@ public class ValidateReportInputAction implements CheckAction { private final Schema schema; @Override - public void check(Bag bag) { + public void check(final Bag bag) { final Result results = validate(bag.getReportInput()); if (!results.isValid()) { log.error("Report input has errors {}", results.getErrors()); @@ -60,9 +60,9 @@ public class ValidateReportInputAction implements CheckAction { * @param der Typ des Objekts * @return ein Validierungsergebnis */ - private Result validate(T object) { - CollectingErrorEventHandler h = new CollectingErrorEventHandler(); - final String result = conversionService.writeXml(object, schema, h); + private Result validate(final T object) { + final CollectingErrorEventHandler h = new CollectingErrorEventHandler(); + final String result = this.conversionService.writeXml(object, this.schema, h); return new Result<>(StringUtils.isNotBlank(result), h.getErrors()); } } diff --git a/src/main/model/binding/global.xjb b/src/main/model/binding/global.xjb index 1391881..b8e336f 100644 --- a/src/main/model/binding/global.xjb +++ b/src/main/model/binding/global.xjb @@ -52,4 +52,11 @@ + + + + de.kosit.validationtool.impl.model.BaseOutput + + + \ No newline at end of file diff --git a/src/main/model/xsd/createReportInput.xsd b/src/main/model/xsd/createReportInput.xsd index 9cc0390..e44c841 100644 --- a/src/main/model/xsd/createReportInput.xsd +++ b/src/main/model/xsd/createReportInput.xsd @@ -20,8 +20,9 @@ + xmlns:s="http://www.xoev.de/de/validator/framework/1/scenarios" xmlns:svrl="http://purl.oclc.org/dsdl/svrl" + targetNamespace="http://www.xoev.de/de/validator/framework/1/createreportinput" version="1.0.0" + elementFormDefault="qualified" attributeFormDefault="unqualified"> @@ -88,7 +89,7 @@ - + diff --git a/src/main/model/xsd/svrl-kosit.xsd b/src/main/model/xsd/svrl-kosit.xsd new file mode 100644 index 0000000..2fd478a --- /dev/null +++ b/src/main/model/xsd/svrl-kosit.xsd @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/model/xsd/xml.xsd b/src/main/model/xsd/xml.xsd new file mode 100644 index 0000000..d3847fc --- /dev/null +++ b/src/main/model/xsd/xml.xsd @@ -0,0 +1,10 @@ + + + + + + + + +