WARNING: This server provides a static reference view of the NetKernel documentation. Links to dynamic content do not work. For the best experience we recommend you install NetKernel and view the documentation in the live system .

API

Schemas can be attached to HDS documents or may be applied stand alone.

A schema can be attached to an IHDSDocument when it is constructed as representation from an IHDSMutator using toDocument(). This serves the purpose to validate the document against the schema. Any client then using that document then knows that the document conforms to the schema.

All IHDSDocument objects have a schema, any document not specifically assigned one will get an instance of org.netkernel.mod.hds.impl.HDSNullSchema. The null schema places no constraint on the document.

This HDS module contains a Schematron implementation of HDS schema. However implementations are pluggable. Future work could include XMLSchema and RelaxNG style schema implementations.

//example endpoint that creates HDS representation with schema 
import org.netkernel.mod.hds.*;
import org.netkernel.mod.hds.schematron.HDSSchematron;

IHDSMutator mdoc=HDSFactory.newDocument()
    .pushNode("root")
    .addNode("value",0.0072973525664);
    
IHDSMutator mschema=HDSFactory.newDocument()
    .pushNode("schema").addNode("@id","urn:example:schema")
        .pushNode("pattern")
            .pushNode("rule").addNode("@context","/*")
                .pushNode("assert","expected root named root").addNode("@test","name()='root')
                .popNode()
            .popNode()
        .popNode()
    .popNode();
    
IHDSSchema schema = new HDSSchematron(mschema.toDocument(false));   
IHDSDocument result=mdoc.toDocument( false, schema ); // schema validation will be performed here
context.createResponseFrom( result );   

//example endpoint that uses a HDS argument
import org.netkernel.mod.hds.*;

IHDSDocument operand = context.source( "arg:operand", IHDSDocument.class );
IHDSSchema schema = operand.getSchema();
System.out.println( "operand has a schema of "+schema.getId() );
IHDSDocument validationResult=schema.validate( operand );
boolean success = org.netkernel.mod.hds.impl.Utils.isValidationResultSuccess( validationResult );
System.out.println( "is operand valid? "+success );
System.out.println( "validation result "+validationResult );

Schematron

HDS Schematron is based upon XML Schematron. It is a simple approach to defining structure and content based around a list of XPath assertions.

This is the schema for HDS Schematron defined in HDS:

<schema id="urn:org:netkernel:mod:hds:schematron:specification">
  <pattern name="check structure">
    <rule context="/">
      <assert test="schema">root should be named schema</assert>
    </rule>
    <rule context="/schema/*[name()!='pattern' and name()!='@id' ]">
      <report test=".">schema should only have pattern or id children</report>
    </rule>
    <rule context="/schema">
      <assert test="@id">schema must have @id child</assert>
    </rule>
    <rule context="/schema/pattern/*[name()!='@name' and name()!='rule']">
      <report test=".">pattern should only have rule or @name children</report>
    </rule>
    <rule context="/schema/pattern/rule/*[name()!='@context' and name()!='assert' and name()!='report']">
      <report test=".">rule should only have assert, report or @context children</report>
    </rule>
    <rule context="/schema/pattern/rule">
      <assert test="@context">rule should have @context child</assert>
      <assert test="count(assert | report)>1">rule should have at least one assert or report child</assert>
    </rule>
    <rule context="/schema/pattern/rule/*">
      <assert test="@test">assert and report should have @test child</assert>
      <report test="*[name()!='@test']">assert and report should only have @test child</report>
    </rule>
  </pattern>
  <pattern name="check values">
    <rule context="/schema | /schema/pattern | /schema/pattern/rule">
      <assert test="instanceOf(.,'null')">schema,pattern,rule nodes should have no value</assert>
    </rule>
    <rule context="/schema/@id | /schema/pattern/@name | /schema/pattern/rule/@context | /schema/pattern/rule/*/@test">
      <assert test="instanceOf(.,'java.lang.String')">@id,@name,@context,@test nodes should be strings</assert>
    </rule>
  </pattern>
</schema>

Schematron consists of a set of rules nested inside pattern groupings. Each rule can have one or more asserts or reports. Asserts that evaluate to false or zero nodes are validation errors. Reports that evaluate to true or one or more nodes are validation errors.

Schematron has a subtle evaluation concept that one the first rule in a pattern that matches a document node will be evaluated. So if you have multiple rules that look at the same set of nodes then it's better to put them in distinct pattern groupings.

The tests with asserts and report nodes are evaluated relative to the context of a rule.

Validation Result Document

When a schema is evaluated against a document the output is a result validation document. The result contains a /errors/@valid node whose value is the overall success of validation. In addition zero or more /error/error nodes may appear which contain specific info, warning, error, or fatal level reports containing an xpath and message.

The schema for the result document is:

<schema id="urn:org:netkernel:mod:hds:schematron:result">
  <pattern name="check structure">
    <rule context="/">
      <assert test="errors">root should be named errors</assert>
    </rule>
    <rule context="/errors/*[name()!='error'] | /errors/attribute::*[name()!='@valid']">
      <report test=".">errors should only have error, @valid children</report>
    </rule>
    <rule context="/errors/error/*[name()!='xpath' and name!='message' and name!='level']">
      <report test=".">error should only have xpath,message,level children</report>
    </rule>
    <rule context="/errors/error[not(xpath) or not(message)]">
      <report test=".">error should have xpath and message children</report>
    </rule>
  </pattern>
  <pattern name="check values">
    <rule context="/errors | /errors/error">
      <assert test="instanceOf(.,'null')">errors,error nodes should have no value</assert>
    </rule>
    <rule context="/errors/error">
      <assert test="instanceOf(xpath,'java.lang.String')">@xpath nodes should be strings</assert>
      <assert test="instanceOf(message,'java.lang.String')">@message nodes should be strings</assert>
      <assert test="instanceOf(level,'java.lang.String')">@level nodes should be strings</assert>
      <assert test="regex(level,'info|warning|error|fatal')">@level nodes should be info|warning|error|fatal</assert>
    </rule>
  </pattern>
</schema>

Additional custom functions

HDS has support for the core XPath 1.0 functions. In addition we've added three functions to support schematron validation of documents.

instanceOf

This function tests to see if the value of a node or nodes are all an instance of particular Java interface or class.

For example:

<rule context="/">
  <assert test="instanceOf( //name, 'java.lang.String' )">All names should be strings</assert>
  <assert test="instanceOf( //universe/age, 'java.lang.Number' )">Age of universe should should be numeric</assert>
</rule>

"null" is a special value for instanceOf - it will test that value is a null reference.

regex

This function tests that string values of nodes match a given regular expression:

<rule context="/">
  <assert test="regex( //phone, '[0-9\+\ ]+' )">Phone numbers should be formed</assert>
</rule>

toStringEquals

This function tests the value of a non-string POJO inside a document against a string within an XPath expression (which only contains strings) by performing a .toString() method on the POJO.

<rule context="/">
  <assert test="toStringEquals( //quantity, '18' )">quantity number should be 18</assert>
</rule>