Improving validation documentation
This commit is contained in:
parent
685bd9345b
commit
59da230702
|
@ -29,12 +29,43 @@ import ca.uhn.fhir.parser.StrictErrorHandler;
|
|||
import ca.uhn.fhir.rest.client.IGenericClient;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import ca.uhn.fhir.validation.SchemaBaseValidator;
|
||||
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
import ca.uhn.fhir.validation.schematron.SchematronBaseValidator;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class ValidatorExamples {
|
||||
|
||||
public void validationIntro() {
|
||||
// START SNIPPET: validationIntro
|
||||
FhirContext ctx = FhirContext.forDstu2();
|
||||
|
||||
// Ask the context for a validator
|
||||
FhirValidator validator = ctx.newValidator();
|
||||
|
||||
// Create some modules and register them
|
||||
IValidatorModule module1 = new SchemaBaseValidator(ctx);
|
||||
validator.registerValidatorModule(module1);
|
||||
IValidatorModule module2 = new SchematronBaseValidator(ctx);
|
||||
validator.registerValidatorModule(module2);
|
||||
|
||||
// Pass a resource in to be validated. The resource can
|
||||
// be an IBaseResource instance, or can be a raw String
|
||||
// containing a serialized resource as text.
|
||||
Patient resource = new Patient();
|
||||
ValidationResult result = validator.validateWithResult(resource);
|
||||
String resourceText = "<Patient.....>";
|
||||
ValidationResult result2 = validator.validateWithResult(resourceText);
|
||||
|
||||
// The result object now contains the validation results
|
||||
for (SingleValidationMessage next : result.getMessages()) {
|
||||
System.out.println(next.getLocationString() + " " + next.getMessage());
|
||||
}
|
||||
// END SNIPPET: validationIntro
|
||||
}
|
||||
|
||||
// START SNIPPET: serverValidation
|
||||
public class MyRestfulServer extends RestfulServer {
|
||||
|
||||
|
@ -96,6 +127,15 @@ public class ValidatorExamples {
|
|||
// Request a validator and apply it
|
||||
FhirValidator val = ctx.newValidator();
|
||||
|
||||
// Create the Schema/Schematron modules and register them. Note that
|
||||
// you might want to consider keeping these modules around as long-term
|
||||
// objects: they parse and then store schemas, which can be an expensive
|
||||
// operation.
|
||||
IValidatorModule module1 = new SchemaBaseValidator(ctx);
|
||||
IValidatorModule module2 = new SchematronBaseValidator(ctx);
|
||||
val.registerValidatorModule(module1);
|
||||
val.registerValidatorModule(module2);
|
||||
|
||||
ValidationResult result = val.validateWithResult(p);
|
||||
if (result.isSuccessful()) {
|
||||
|
||||
|
|
|
@ -26,12 +26,28 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
*/
|
||||
|
||||
/**
|
||||
* Registers
|
||||
* An individual validation module, which applies validation rules against
|
||||
* resources and adds failure/informational messages as it goes.
|
||||
*
|
||||
* See <a href="http://jamesagnew.github.io/hapi-fhir/doc_validation.html">Validation</a>
|
||||
* for a list of available modules. You may also create your own.
|
||||
*/
|
||||
public interface IValidatorModule {
|
||||
|
||||
/**
|
||||
* Validate the actual resource.
|
||||
*
|
||||
* The {@link IValidationContext} can be used to access the resource being validated,
|
||||
* and is populated with the results.
|
||||
*/
|
||||
void validateResource(IValidationContext<IBaseResource> theCtx);
|
||||
|
||||
/**
|
||||
* This method applies only to DSTU1 Atom Bundles. All other validation will pass through
|
||||
* {@link #validateResource(IValidationContext)} inclusing DSTU2+ Bundle resources. If you
|
||||
* will not be validating DSTU1 Bundles, you may implement this method as
|
||||
* a NO-OP.
|
||||
*/
|
||||
void validateBundle(IValidationContext<Bundle> theContext);
|
||||
|
||||
}
|
||||
|
|
|
@ -75,7 +75,7 @@ public class SchemaBaseValidator implements IValidatorModule {
|
|||
private Map<String, Schema> myKeyToSchema = new HashMap<String, Schema>();
|
||||
private FhirContext myCtx;
|
||||
|
||||
SchemaBaseValidator(FhirContext theContext) {
|
||||
public SchemaBaseValidator(FhirContext theContext) {
|
||||
myCtx = theContext;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,10 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu21.hapi.validation.DefaultProfileValidationSupport;
|
||||
|
@ -51,9 +53,11 @@ public class FhirInstanceValidatorTest {
|
|||
|
||||
private FhirValidator myVal;
|
||||
private ArrayList<String> myValidConcepts;
|
||||
private Set<String> myValidSystems = new HashSet<String>();
|
||||
private Map<String, ValueSetExpansionComponent> mySupportedCodeSystemsForExpansion;
|
||||
|
||||
private void addValidConcept(String theSystem, String theCode) {
|
||||
myValidSystems.add(theSystem);
|
||||
myValidConcepts.add(theSystem + "___" + theCode);
|
||||
}
|
||||
|
||||
|
@ -87,8 +91,8 @@ public class FhirInstanceValidatorTest {
|
|||
when(myMockSupport.isCodeSystemSupported(any(FhirContext.class), any(String.class))).thenAnswer(new Answer<Boolean>() {
|
||||
@Override
|
||||
public Boolean answer(InvocationOnMock theInvocation) throws Throwable {
|
||||
boolean retVal = mySupportedCodeSystemsForExpansion.containsKey(theInvocation.getArguments()[0]);
|
||||
ourLog.info("isCodeSystemSupported({}) : {}", new Object[] { theInvocation.getArguments()[0], retVal });
|
||||
boolean retVal = myValidSystems.contains(theInvocation.getArguments()[1]);
|
||||
ourLog.info("isCodeSystemSupported({}) : {}", new Object[] { theInvocation.getArguments()[1], retVal });
|
||||
return retVal;
|
||||
}
|
||||
});
|
||||
|
@ -289,6 +293,27 @@ public class FhirInstanceValidatorTest {
|
|||
assertThat(errors.toString(), containsString(""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceContainingLoincCode() {
|
||||
addValidConcept("http://loinc.org", "1234567");
|
||||
|
||||
Observation input = new Observation();
|
||||
// input.getMeta().addProfile("http://hl7.org/fhir/StructureDefinition/devicemetricobservation");
|
||||
|
||||
input.addIdentifier().setSystem("http://acme").setValue("12345");
|
||||
input.getEncounter().setReference("http://foo.com/Encounter/9");
|
||||
input.setStatus(ObservationStatus.FINAL);
|
||||
input.getCode().addCoding().setSystem("http://loinc.org").setCode("12345");
|
||||
|
||||
myInstanceVal.setValidationSupport(myMockSupport);
|
||||
ValidationResult output = myVal.validateWithResult(input);
|
||||
List<SingleValidationMessage> errors = logResultsAndReturnAll(output);
|
||||
|
||||
assertThat(errors.toString(), containsString("information"));
|
||||
assertThat(errors.toString(), containsString("Unknown code: http://loinc.org / 12345"));
|
||||
assertEquals(1, errors.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidateResourceWithDefaultValueset() {
|
||||
Observation input = new Observation();
|
||||
|
|
|
@ -273,7 +273,9 @@
|
|||
</p>
|
||||
<p>
|
||||
See the <a href="./doc_validation.html">Validation Page</a> for information on
|
||||
available IValidationModule validation modules. Any of the <b>Resource Validators</b>
|
||||
available
|
||||
<a href="./apidocs/ca/uhn/fhir/validation/IValidatorModule.html">IValidatorModule</a>
|
||||
validation modules. Any of the <b>Resource Validators</b>
|
||||
listed on that page can be enabled in these interceptors (note that the <b>Parser Validators</b>
|
||||
can not).
|
||||
</p>
|
||||
|
|
|
@ -14,6 +14,12 @@
|
|||
sections below.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<b>Resource Validation</b>
|
||||
is validation of the raw or parsed resource against
|
||||
the official FHIR validation rules (e.g. Schema/Schematron/Profile/StructureDefinition/ValueSet)
|
||||
as well as against custom profiles which have been developed.
|
||||
</li>
|
||||
<li>
|
||||
<b>Parser Validation</b>
|
||||
is validation at runtime during the parsing
|
||||
|
@ -25,85 +31,40 @@
|
|||
that no data is being lost during parsing, but is less comprehensive than resource validation
|
||||
against raw text data.
|
||||
</li>
|
||||
<li>
|
||||
<b>Resource Validation</b>
|
||||
is validation of the raw or parsed resource against
|
||||
the official FHIR validation rules (e.g. Schema/Schematron/Profile/StructureDefinition/ValueSet).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Parser Validation">
|
||||
|
||||
<p>
|
||||
Parser validation is controlled by calling
|
||||
<code>setParserErrorHandler(IParserErrorHandler)</code>
|
||||
on
|
||||
either the FhirContext or on individual parser instances. This method
|
||||
takes an
|
||||
<code>IParserErrorHandler</code>
|
||||
, which is a callback that
|
||||
will be invoked any time a parse issue is detected.
|
||||
</p>
|
||||
<p>
|
||||
There are two implementations of
|
||||
<code>IParserErrorHandler</code>
|
||||
worth
|
||||
mentioning. You can also supply your own implementation if you want.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="./apidocs/ca/uhn/fhir/parser/LenientErrorHandler.html">LenientErrorHandler</a>
|
||||
logs any errors but does not abort parsing. By default this handler is used, and it
|
||||
logs errors at "warning" level. It can also be configured to silently
|
||||
ignore issues.
|
||||
</li>
|
||||
<li>
|
||||
<a href="./apidocs/ca/uhn/fhir/parser/StrictErrorHandler.html">StrictErrorHandler</a>
|
||||
throws a
|
||||
<code>DataFormatException</code>
|
||||
if any errors are detected.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The following example shows how to configure a parser to use strict validation.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="parserValidation" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
You can also configure the error handler at the FhirContext level, which is useful
|
||||
for clients.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="clientValidation" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
FhirContext level validators can also be useful on servers.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="serverValidation" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
</section>
|
||||
|
||||
<!-- RESOURCE VALIDATION -->
|
||||
|
||||
<section name="Resource Validation (Schema/Schematron)">
|
||||
<section name="Resource Validation">
|
||||
|
||||
<p>
|
||||
HAPI provides a built-in and configurable mechanism for validating resources.
|
||||
This mechanism is called the
|
||||
<i>Resource Validator</i>
|
||||
.
|
||||
<i>Resource Validator.</i>
|
||||
</p>
|
||||
<p>
|
||||
The resource validator is an extendible and modular system, and you
|
||||
can configure it in a number of ways in order to get the specific
|
||||
type of validation you want to achieve.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The validator can be manually invoked at any time by creating a
|
||||
validator and configuring it with one or more
|
||||
<a href="./apidocs/ca/uhn/fhir/validation/IValidatorModule.html">IValidatorModule</a>
|
||||
instances.
|
||||
</p>
|
||||
|
||||
<macro name="snippet">
|
||||
<param name="id" value="validationIntro" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
</section>
|
||||
|
||||
<section name="Resource Validation Module: Schema/Schematron">
|
||||
|
||||
<p>
|
||||
FHIR resource definitions are distributed with a set of XML schema files (XSD)
|
||||
|
@ -262,6 +223,66 @@
|
|||
|
||||
</section>
|
||||
|
||||
<section name="Parser Validation">
|
||||
|
||||
<p>
|
||||
Parser validation is controlled by calling
|
||||
<code>setParserErrorHandler(IParserErrorHandler)</code>
|
||||
on
|
||||
either the FhirContext or on individual parser instances. This method
|
||||
takes an
|
||||
<code>IParserErrorHandler</code>
|
||||
, which is a callback that
|
||||
will be invoked any time a parse issue is detected.
|
||||
</p>
|
||||
<p>
|
||||
There are two implementations of
|
||||
<code>IParserErrorHandler</code>
|
||||
worth
|
||||
mentioning. You can also supply your own implementation if you want.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="./apidocs/ca/uhn/fhir/parser/LenientErrorHandler.html">LenientErrorHandler</a>
|
||||
logs any errors but does not abort parsing. By default this handler is used, and it
|
||||
logs errors at "warning" level. It can also be configured to silently
|
||||
ignore issues.
|
||||
</li>
|
||||
<li>
|
||||
<a href="./apidocs/ca/uhn/fhir/parser/StrictErrorHandler.html">StrictErrorHandler</a>
|
||||
throws a
|
||||
<code>DataFormatException</code>
|
||||
if any errors are detected.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The following example shows how to configure a parser to use strict validation.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="parserValidation" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
You can also configure the error handler at the FhirContext level, which is useful
|
||||
for clients.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="clientValidation" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
<p>
|
||||
FhirContext level validators can also be useful on servers.
|
||||
</p>
|
||||
<macro name="snippet">
|
||||
<param name="id" value="serverValidation" />
|
||||
<param name="file" value="examples/src/main/java/example/ValidatorExamples.java" />
|
||||
</macro>
|
||||
|
||||
</section>
|
||||
|
||||
</body>
|
||||
|
||||
</document>
|
||||
|
|
Loading…
Reference in New Issue