Commit 977e9923 authored by rwm's avatar rwm
Browse files

cda-validation Projekt beinhalted aktuelle Schematron-Regeln und Beispiele sowie Validierungscode

parent 2c835347
.settings/
.classpath
.project
target/
\ No newline at end of file
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<name>AKTIN : DWH Import : CDA Validation</name>
<groupId>org.aktin</groupId>
<artifactId>cda-validation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.aktin</groupId>
<artifactId>dwh-import</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<properties>
<schematronVersion>20150824T134031</schematronVersion>
<examplesVersion>20150824T134031</examplesVersion>
<schematronArchive>aktin-runtime-${schematronVersion}</schematronArchive>
<examplesArchive>aktin-xml-${examplesVersion}</examplesArchive>
</properties>
<build>
<resources>
<resource>
<directory>${project.build.directory}/schematron/${schematronArchive}</directory>
</resource>
<resource>
<directory>${project.build.directory}/examples/${examplesArchive}</directory>
<excludes>
<exclude>**/.DS_Store</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>download-files</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- schematron files -->
<get src="http://aktin.art-decor.org/${schematronArchive}.zip"
dest="${project.build.directory}/schematron.zip"
verbose="false"
usetimestamp="true"/>
<unzip src="${project.build.directory}/schematron.zip" dest="${project.build.directory}/schematron" />
<!-- download examples -->
<get src="http://aktin.art-decor.org/${examplesArchive}.zip"
dest="${project.build.directory}/examples.zip"
verbose="false"
usetimestamp="true"/>
<unzip src="${project.build.directory}/examples.zip" dest="${project.build.directory}/examples" />
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- XSLT and XPath processor -->
<dependency>
<groupId>net.sf.saxon</groupId>
<artifactId>Saxon-HE</artifactId><!--
<version>9.6.0-7</version>-->
</dependency>
<!-- unit tests -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId><!--
<version>4.11</version>
<scope>test</scope>-->
</dependency>
</dependencies>
</project>
\ No newline at end of file
package org.aktin.cda;
public class CDAConstants {
public static final String SVRL_NS_URI = "http://purl.oclc.org/dsdl/svrl";
public static final String HL7_NS_URI = "urn:hl7-org:v3";
public static final String CDA_NS_URI = HL7_NS_URI;
public static final String SVRL_NS_PREFIX = "svrl";
public static final String HL7_NS_PREFIX = "hl7";
public static final String CDA_NS_PREFIX = "cda";
}
package org.aktin.cda;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Result of a CDA validation operation.
*
* @author marap1
*
*/
public class ValidationResult {
private Document result;
private NodeList failedAsserts;
//private Validator validator;
ValidationResult(Validator validator, Document svrlSchematronOutput) throws XPathExpressionException{
//this.validator = validator;
this.result = svrlSchematronOutput;
failedAsserts = validator.selectFailedAsserts(result);
}
/**
* Determine whether the document is valid.
* This method checks whether the resulting svrl output contains no failed-assert elements.
* @return {@code true} for documents without errors, {@code false} if at least one failed-assert was found.
*/
public boolean isValid(){
return failedAsserts.getLength() == 0;
}
/**
* Get the number of validation errors
* @return error count
*/
public int getErrorCount(){
return failedAsserts.getLength();
}
/**
* Fills the provided list with error descriptions
*
* @param list list which will contain error descriptions after the method returns
*/
public void getErrors(List<String> list){
for( int i=0; i<failedAsserts.getLength(); i++ ){
Node failedAssert = failedAsserts.item(i);
Node text = failedAssert.getFirstChild();
if( text != null && text.getLocalName().equals("text") && text.getNamespaceURI().equals(CDAConstants.SVRL_NS_URI) ){
list.add(text.getTextContent());
}
}
}
}
package org.aktin.cda;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Iterator;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
/**
* Perform CDA validation according to schematron rules.
* <p>
* This implementation is probably not thread-safe: A single {@link Transformer}
* instance is used for all calls to {@link #validate(Source)}.
*
* @author marap1
*
*/
public class Validator implements URIResolver, NamespaceContext {
private static final Logger log = Logger.getLogger(Validator.class.getName());
private TransformerFactory factory;
private URL svrlTransformation;
private static final String svrlSystemId = "urn:local:svrl";
private Transformer transformer;
// XPaths to interpret the svrl result
private XPathFactory xfactory;
private XPathExpression selectFailedAsserts;
public Validator() throws IOException, TransformerConfigurationException{
factory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", null);
// resolve internal URIs
factory.setURIResolver(this);
log.getClass(); // prevent unused warnings
svrlTransformation = getClass().getResource("/schematron_svrl/aktin-basism.xsl");
try( InputStream in = svrlTransformation.openStream() ){
StreamSource xsl = new StreamSource(in);
xsl.setSystemId(svrlSystemId);
transformer = factory.newTransformer(xsl);
}
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
// no need for Saxon??
xfactory = XPathFactory.newInstance();
try {
XPath xpath = xfactory.newXPath();
xpath.setNamespaceContext(this);
selectFailedAsserts = xpath.compile("/svrl:schematron-output/svrl:failed-assert");
} catch (XPathExpressionException e) {
throw new IOException(e);
}
}
/**
* Find failed assertations
* @param svrlDoc svrl result
* @return node list of failed-assertation elements
* @throws XPathExpressionException failure
*/
NodeList selectFailedAsserts(Document svrlDoc) throws XPathExpressionException{
NodeList ret = (NodeList) selectFailedAsserts.evaluate(svrlDoc, XPathConstants.NODESET);
return ret;
}
/**
* Validate a CDA document
*
* @param cdaSource CDA document source to validate
* @return validation result
* @throws TransformerException if the transformation fails
* @throws XPathExpressionException if the transformation result could not be processed with XPath expressions to find validation errors
*/
public ValidationResult validate(Source cdaSource) throws TransformerException, XPathExpressionException{
//Result result = new StreamResult(System.out);
DOMResult result = new DOMResult();
transformer.transform(cdaSource, result);
return new ValidationResult(this, (Document)result.getNode());
}
/**
* Resolves included URIs during transformation
*/
@Override
public Source resolve(String href, String base) throws TransformerException {
// TODO does this still work for recursive includes? e.g. a.xml includes a/b.xml includes b/c.xml
if( base.equals(svrlSystemId) ){
try {
URL url = new URL(svrlTransformation, href);
return new StreamSource(url.openStream(), svrlSystemId);
} catch (IOException e) {
throw new TransformerException(e);
}
}else{
throw new TransformerException("Unable to resolve '"+href+"' under: "+base);
}
}
/**
* Resolves prefixes in XPath expressions
*/
@Override
public String getNamespaceURI(String prefix) {
switch( prefix ){
case CDAConstants.SVRL_NS_PREFIX:
return CDAConstants.SVRL_NS_URI;
case "xsi":
return XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
case XMLConstants.XML_NS_PREFIX:
return XMLConstants.XML_NS_URI;
default:
return XMLConstants.NULL_NS_URI;
}
}
@Override
public String getPrefix(String namespaceURI) {
// not needed
throw new UnsupportedOperationException();
}
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
// not needed
throw new UnsupportedOperationException();
}
}
package org.aktin.cda;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.xpath.XPathExpressionException;
import org.junit.Assert;
import org.junit.Test;
public class TestValidator {
private static final String[] exampleDocuments = new String[]{
"/CDAexample/basismodul-beispiel-storyboard01.xml",
"/CDAexample/basismodul-beispiel-storyboard02.xml",
"/CDAexample/basismodul-beispiel-storyboard04.xml",
};
private static final String[] invalidExampleDocuments = new String[]{
"/CDAexample/basismodul-beispiel-storyboard01-error1.xml"
};
@Test
public void validateExampleDocuments() throws TransformerException, IOException, XPathExpressionException{
Validator v = new Validator();
for( String example : exampleDocuments ){
try( InputStream in = getClass().getResourceAsStream(example) ){
Assert.assertTrue(in.available() > 0);
ValidationResult res = v.validate(new StreamSource(in));
Assert.assertTrue("Successful validation expected", res.isValid());
}
}
for( String example : invalidExampleDocuments ){
try( InputStream in = getClass().getResourceAsStream(example) ){
Assert.assertTrue(in.available() > 0);
ValidationResult res = v.validate(new StreamSource(in));
Assert.assertFalse("Document validation should produce errors", res.isValid());
}
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment