Search in sources :

Example 1 with IValidationArtefact

use of com.helger.phive.api.artefact.IValidationArtefact in project phive by phax.

the class ValidationExecutorXSD method applyValidation.

@Nonnull
public ValidationResult applyValidation(@Nonnull final IValidationSourceXML aSource, @Nullable final Locale aLocale) {
    ValueEnforcer.notNull(aSource, "Source");
    final IValidationArtefact aVA = getValidationArtefact();
    // Find the XML schema required for validation
    // as we don't have a node, we need to trust the implementation class
    final Schema aSchema = m_aSchemaProvider.get();
    assert aSchema != null;
    final ErrorList aErrorList = new ErrorList();
    try {
        // Apply the XML schema validation
        XMLSchemaValidationHelper.validate(aSchema, aSource.getAsTransformSource(), aErrorList, aLocale);
    } catch (final IllegalArgumentException ex) {
        // Happens when non-XML document is trying to be parsed
        if (ex.getCause() instanceof SAXParseException) {
            aErrorList.add(AbstractSAXErrorHandler.getSaxParseError(EErrorLevel.FATAL_ERROR, (SAXParseException) ex.getCause()));
        } else {
            aErrorList.add(SingleError.builderFatalError().errorLocation(new SimpleLocation(aVA.getRuleResourcePath())).errorText("The document to be validated is not an XML document").linkedException(ex).build());
        }
    }
    // Build result object
    return new ValidationResult(aVA, aErrorList.getAllFailures());
}
Also used : ErrorList(com.helger.commons.error.list.ErrorList) IValidationArtefact(com.helger.phive.api.artefact.IValidationArtefact) SAXParseException(org.xml.sax.SAXParseException) Schema(javax.xml.validation.Schema) SimpleLocation(com.helger.commons.location.SimpleLocation) ValidationResult(com.helger.phive.api.result.ValidationResult) Nonnull(javax.annotation.Nonnull)

Example 2 with IValidationArtefact

use of com.helger.phive.api.artefact.IValidationArtefact in project phive by phax.

the class ValidationExecutorXSDPartial method applyValidation.

@Nonnull
public ValidationResult applyValidation(@Nonnull final IValidationSourceXML aSource, @Nullable final Locale aLocale) {
    ValueEnforcer.notNull(aSource, "Source");
    final IValidationArtefact aVA = getValidationArtefact();
    NodeList aNodeSet;
    try {
        aNodeSet = (NodeList) m_aPartialContext.getXPathExpression().evaluate(aSource.getNode(), XPathConstants.NODESET);
    } catch (final XPathExpressionException ex) {
        throw new IllegalStateException(ex);
    }
    final ErrorList aErrorList = new ErrorList();
    final int nMatchingNodes = aNodeSet.getLength();
    if (m_aPartialContext.hasMinNodeCount())
        if (nMatchingNodes < m_aPartialContext.getMinNodeCount()) {
            // Too little matches found
            aErrorList.add(SingleError.builderFatalError().errorLocation(aVA.getRuleResourcePath()).errorText("The minimum number of result nodes (" + m_aPartialContext.getMinNodeCount() + ") is not met").build());
        }
    if (m_aPartialContext.hasMaxNodeCount())
        if (nMatchingNodes > m_aPartialContext.getMaxNodeCount()) {
            // Too little matches found
            aErrorList.add(SingleError.builderFatalError().errorLocation(aVA.getRuleResourcePath()).errorText("The maximum number of result nodes (" + m_aPartialContext.getMaxNodeCount() + ") is not met").build());
        }
    if (nMatchingNodes == 0) {
        // No match found - nothing to do
        return new ValidationResult(aVA, aErrorList);
    }
    // Find the XML schema required for validation
    // as we don't have a node, we need to trust the implementation class
    final Schema aSchema = m_aSchemaProvider.get();
    assert aSchema != null;
    for (int i = 0; i < aNodeSet.getLength(); ++i) {
        // Build a partial source
        final IValidationSourceXML aRealSource = new ValidationSourceXML(aSource.getSystemID(), aNodeSet.item(i), true);
        try {
            // Apply the XML schema validation
            XMLSchemaValidationHelper.validate(aSchema, aRealSource.getAsTransformSource(), aErrorList, aLocale);
        } catch (final IllegalArgumentException ex) {
            // Happens when non-XML document is trying to be parsed
            if (ex.getCause() instanceof SAXParseException) {
                aErrorList.add(AbstractSAXErrorHandler.getSaxParseError(EErrorLevel.FATAL_ERROR, (SAXParseException) ex.getCause()));
            } else {
                aErrorList.add(SingleError.builderFatalError().errorLocation(aVA.getRuleResourcePath()).errorFieldName("Context[" + i + "]").errorText("The document to be validated is not an XML document").linkedException(ex).build());
            }
        }
    }
    // Build result object
    return new ValidationResult(aVA, aErrorList.getAllFailures());
}
Also used : ErrorList(com.helger.commons.error.list.ErrorList) IValidationArtefact(com.helger.phive.api.artefact.IValidationArtefact) XPathExpressionException(javax.xml.xpath.XPathExpressionException) SAXParseException(org.xml.sax.SAXParseException) NodeList(org.w3c.dom.NodeList) Schema(javax.xml.validation.Schema) ValidationSourceXML(com.helger.phive.engine.source.ValidationSourceXML) IValidationSourceXML(com.helger.phive.engine.source.IValidationSourceXML) IValidationSourceXML(com.helger.phive.engine.source.IValidationSourceXML) ValidationResult(com.helger.phive.api.result.ValidationResult) Nonnull(javax.annotation.Nonnull)

Example 3 with IValidationArtefact

use of com.helger.phive.api.artefact.IValidationArtefact in project phive by phax.

the class ValidationExecutorSchematron method _createSchematronResource.

@Nonnull
private AbstractSchematronResource _createSchematronResource(@Nullable final Locale aLocale, @Nonnull final ErrorList aErrorList, @Nonnull final Consumer<ESchematronOutput> aSpecialOutputHdl) {
    final IValidationArtefact aArtefact = getValidationArtefact();
    // get the Schematron resource to be used for this validation artefact
    final IReadableResource aSCHRes = aArtefact.getRuleResource();
    final IValidationType aVT = aArtefact.getValidationArtefactType();
    if (aVT == EValidationType.SCHEMATRON_PURE) {
        final SchematronResourcePure aPureSCH = new SchematronResourcePure(aSCHRes);
        aPureSCH.setErrorHandler(new WrappedCollectingPSErrorHandler(aErrorList));
        // consecutive calls!
        return aPureSCH;
    }
    if (aVT == EValidationType.SCHEMATRON_SCH) {
        final SchematronResourceSCH aSCHSCH = new SchematronResourceSCH(aSCHRes);
        aSCHSCH.setErrorListener(new WrappedCollectingTransformErrorListener(aErrorList));
        if (aLocale != null && StringHelper.hasText(aLocale.getLanguage()))
            aSCHSCH.setLanguageCode(aLocale.getLanguage());
        return aSCHSCH;
    }
    if (aVT == EValidationType.SCHEMATRON_SCHXSLT) {
        final SchematronResourceSchXslt_XSLT2 aSCHSCH = new SchematronResourceSchXslt_XSLT2(aSCHRes);
        aSCHSCH.setErrorListener(new WrappedCollectingTransformErrorListener(aErrorList));
        if (aLocale != null && StringHelper.hasText(aLocale.getLanguage()))
            aSCHSCH.setLanguageCode(aLocale.getLanguage());
        return aSCHSCH;
    }
    if (aVT == EValidationType.SCHEMATRON_XSLT) {
        final SchematronResourceXSLT aSCHXSLT = new SchematronResourceXSLT(aSCHRes);
        aSCHXSLT.setErrorListener(new WrappedCollectingTransformErrorListener(aErrorList));
        return aSCHXSLT;
    }
    if (aVT == EValidationType.SCHEMATRON_OIOUBL) {
        final SchematronResourceXSLT aSCHXSLT = new SchematronResourceXSLT(aSCHRes);
        aSCHXSLT.setErrorListener(new WrappedCollectingTransformErrorListener(aErrorList));
        // Special output layout
        aSpecialOutputHdl.accept(ESchematronOutput.OIOUBL);
        return aSCHXSLT;
    }
    throw new IllegalStateException("Unsupported Schematron validation type: " + aVT);
}
Also used : IValidationType(com.helger.phive.api.IValidationType) SchematronResourceXSLT(com.helger.schematron.xslt.SchematronResourceXSLT) SchematronResourceSCH(com.helger.schematron.sch.SchematronResourceSCH) IValidationArtefact(com.helger.phive.api.artefact.IValidationArtefact) SchematronResourceSchXslt_XSLT2(com.helger.schematron.schxslt.xslt2.SchematronResourceSchXslt_XSLT2) IReadableResource(com.helger.commons.io.resource.IReadableResource) WrappedCollectingTransformErrorListener(com.helger.xml.transform.WrappedCollectingTransformErrorListener) WrappedCollectingPSErrorHandler(com.helger.schematron.pure.errorhandler.WrappedCollectingPSErrorHandler) SchematronResourcePure(com.helger.schematron.pure.SchematronResourcePure) Nonnull(javax.annotation.Nonnull)

Example 4 with IValidationArtefact

use of com.helger.phive.api.artefact.IValidationArtefact in project phive by phax.

the class ValidationExecutorSchematron method applyValidation.

@Nonnull
public ValidationResult applyValidation(@Nonnull final IValidationSourceXML aSource, @Nullable final Locale aLocale) {
    ValueEnforcer.notNull(aSource, "Source");
    final IValidationArtefact aArtefact = getValidationArtefact();
    // Get source as XML DOM Node
    Node aNode = null;
    try {
        aNode = SchematronResourceHelper.getNodeOfSource(aSource.getAsTransformSource(), new DOMReaderSettings().setFeatureValues(EXMLParserFeature.AVOID_XML_ATTACKS));
    } catch (final Exception ex) {
        throw new IllegalStateException("For Schematron validation to work, the source must be valid XML which it is not.", ex);
    }
    if (StringHelper.hasText(m_sPrerequisiteXPath)) {
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("Using Schematron prerequisite path '" + m_sPrerequisiteXPath + "'");
        // Check if the artefact can be applied on the given document by
        // checking the prerequisite XPath
        final XPath aXPathContext = XPathHelper.createNewXPath();
        if (m_aNamespaceContext != null)
            aXPathContext.setNamespaceContext(m_aNamespaceContext);
        try {
            final Boolean aResult = XPathExpressionHelper.evalXPathToBoolean(aXPathContext, m_sPrerequisiteXPath, XMLHelper.getOwnerDocument(aNode));
            if (aResult != null && !aResult.booleanValue()) {
                if (LOGGER.isInfoEnabled())
                    LOGGER.info("Ignoring validation artefact " + aArtefact.getRuleResourcePath() + " because the prerequisite XPath expression '" + m_sPrerequisiteXPath + "' is not fulfilled.");
                return ValidationResult.createIgnoredResult(aArtefact);
            }
        } catch (final IllegalArgumentException ex) {
            // Catch errors in prerequisite XPaths - most likely because of
            // missing namespace prefixes...
            final String sErrorMsg = "Failed to verify if validation artefact " + aArtefact.getRuleResourcePath() + " matches the prerequisite XPath expression '" + m_sPrerequisiteXPath + "' - ignoring validation artefact.";
            LOGGER.error(sErrorMsg, ex);
            return new ValidationResult(aArtefact, new ErrorList(SingleError.builderError().errorText(sErrorMsg).linkedException(ex).build()));
        }
    }
    // No prerequisite or prerequisite matched
    final ErrorList aErrorList = new ErrorList();
    final Wrapper<ESchematronOutput> aOutput = new Wrapper<>(ESchematronOutput.SVRL);
    final AbstractSchematronResource aSCH = _createSchematronResource(aLocale, aErrorList, aOutput::set);
    // Don't cache to avoid that errors in the Schematron are hidden on
    // consecutive calls!
    aSCH.setUseCache(m_bCacheSchematron);
    try {
        // Main application of Schematron
        final Document aDoc = aSCH.applySchematronValidation(new DOMSource(aNode));
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("SVRL: " + XMLWriter.getNodeAsString(aDoc));
        switch(aOutput.get()) {
            case SVRL:
                {
                    final SchematronOutputType aSVRL = aDoc == null || aDoc.getDocumentElement() == null ? null : new SVRLMarshaller().read(aDoc);
                    if (aSVRL != null) {
                        // Convert failed asserts and successful reports to error objects
                        for (final SVRLFailedAssert aFailedAssert : SVRLHelper.getAllFailedAssertions(aSVRL)) aErrorList.add(aFailedAssert.getAsResourceError(aSource.getSystemID()));
                        for (final SVRLSuccessfulReport aSuccessfulReport : SVRLHelper.getAllSuccessfulReports(aSVRL)) aErrorList.add(aSuccessfulReport.getAsResourceError(aSource.getSystemID()));
                    } else {
                        // Schematron does not create SVRL!
                        LOGGER.warn("Failed to read the result as SVRL:" + (aDoc != null ? "\n" + XMLWriter.getNodeAsString(aDoc) : " no XML Document created"));
                        aErrorList.add(SingleError.builderError().errorLocation(aArtefact.getRuleResourcePath()).errorText("Internal error interpreting Schematron result").errorFieldName(aDoc != null ? XMLWriter.getNodeAsString(aDoc) : null).build());
                    }
                    break;
                }
            case OIOUBL:
                {
                    if (aDoc != null && aDoc.getDocumentElement() != null) {
                        for (final Element eError : XMLHelper.getChildElementIterator(aDoc.getDocumentElement(), "Error")) {
                            // final String sContext = eError.getAttribute ("context");
                            final String sPattern = XMLHelper.getFirstChildElementOfName(eError, "Pattern").getTextContent();
                            final String sDescription = XMLHelper.getFirstChildElementOfName(eError, "Description").getTextContent();
                            final String sXPath = XMLHelper.getFirstChildElementOfName(eError, "Xpath").getTextContent();
                            aErrorList.add(new SVRLErrorBuilder(sPattern).errorLocation(new SimpleLocation(aSource.getSystemID())).errorText(sDescription).errorFieldName(sXPath).build());
                        }
                    } else {
                        // Schematron does not create SVRL!
                        LOGGER.warn("Failed to read the result as OIOUBL result:" + (aDoc != null ? "\n" + XMLWriter.getNodeAsString(aDoc) : " no XML Document created"));
                        aErrorList.add(SingleError.builderError().errorLocation(aArtefact.getRuleResourcePath()).errorText("Internal error - no Schematron output created for OIOUBL").build());
                    }
                    break;
                }
            default:
                throw new IllegalStateException("Unsupported output type");
        }
    } catch (final Exception ex) {
        // Usually an error in the Schematron
        aErrorList.add(SingleError.builderError().errorLocation(aArtefact.getRuleResourcePath()).errorText(ex.getMessage()).linkedException(ex).build());
    }
    // Apply custom levels
    if (m_aCustomErrorLevels != null && aErrorList.isNotEmpty()) {
        final ErrorList aOldErrorList = aErrorList.getClone();
        aErrorList.clear();
        for (final IError aCurError : aOldErrorList) {
            final String sErrorID = aCurError.getErrorID();
            final IErrorLevel aCustomLevel = m_aCustomErrorLevels.get(sErrorID);
            if (aCustomLevel != null) {
                if (LOGGER.isDebugEnabled())
                    LOGGER.debug("Changing error level of '" + sErrorID + "' from " + aCurError.getErrorLevel().getNumericLevel() + " to " + aCustomLevel + " (" + aCustomLevel.getNumericLevel() + ")");
                aErrorList.add(SingleError.builder(aCurError).errorLevel(aCustomLevel).build());
            } else {
                // No change
                aErrorList.add(aCurError);
            }
        }
    }
    return new ValidationResult(aArtefact, aErrorList);
}
Also used : DOMSource(javax.xml.transform.dom.DOMSource) SVRLFailedAssert(com.helger.schematron.svrl.SVRLFailedAssert) Node(org.w3c.dom.Node) Element(org.w3c.dom.Element) SVRLMarshaller(com.helger.schematron.svrl.SVRLMarshaller) ValidationResult(com.helger.phive.api.result.ValidationResult) Document(org.w3c.dom.Document) SVRLSuccessfulReport(com.helger.schematron.svrl.SVRLSuccessfulReport) SimpleLocation(com.helger.commons.location.SimpleLocation) DOMReaderSettings(com.helger.xml.serialize.read.DOMReaderSettings) XPath(javax.xml.xpath.XPath) Wrapper(com.helger.commons.wrapper.Wrapper) IValidationArtefact(com.helger.phive.api.artefact.IValidationArtefact) AbstractSchematronResource(com.helger.schematron.AbstractSchematronResource) IError(com.helger.commons.error.IError) SchematronOutputType(com.helger.schematron.svrl.jaxb.SchematronOutputType) ErrorList(com.helger.commons.error.list.ErrorList) IErrorLevel(com.helger.commons.error.level.IErrorLevel) SVRLErrorBuilder(com.helger.schematron.svrl.SVRLResourceError.SVRLErrorBuilder) Nonnull(javax.annotation.Nonnull)

Aggregations

IValidationArtefact (com.helger.phive.api.artefact.IValidationArtefact)4 Nonnull (javax.annotation.Nonnull)4 ErrorList (com.helger.commons.error.list.ErrorList)3 ValidationResult (com.helger.phive.api.result.ValidationResult)3 SimpleLocation (com.helger.commons.location.SimpleLocation)2 Schema (javax.xml.validation.Schema)2 SAXParseException (org.xml.sax.SAXParseException)2 IError (com.helger.commons.error.IError)1 IErrorLevel (com.helger.commons.error.level.IErrorLevel)1 IReadableResource (com.helger.commons.io.resource.IReadableResource)1 Wrapper (com.helger.commons.wrapper.Wrapper)1 IValidationType (com.helger.phive.api.IValidationType)1 IValidationSourceXML (com.helger.phive.engine.source.IValidationSourceXML)1 ValidationSourceXML (com.helger.phive.engine.source.ValidationSourceXML)1 AbstractSchematronResource (com.helger.schematron.AbstractSchematronResource)1 SchematronResourcePure (com.helger.schematron.pure.SchematronResourcePure)1 WrappedCollectingPSErrorHandler (com.helger.schematron.pure.errorhandler.WrappedCollectingPSErrorHandler)1 SchematronResourceSCH (com.helger.schematron.sch.SchematronResourceSCH)1 SchematronResourceSchXslt_XSLT2 (com.helger.schematron.schxslt.xslt2.SchematronResourceSchXslt_XSLT2)1 SVRLFailedAssert (com.helger.schematron.svrl.SVRLFailedAssert)1