Add validation options to RepositoryValidingInterceptor (#2294)
* Add repository validating interceptor outcome to response * Add a doc * Add a test and some docs * Rework validation
This commit is contained in:
parent
391a6d1a3f
commit
66e1a51e01
|
@ -28,6 +28,7 @@ import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder;
|
|||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -107,11 +108,44 @@ public class RepositoryValidatingInterceptorExamples {
|
|||
ruleBuilder
|
||||
.forResourcesOfType("Patient")
|
||||
.requireValidationToDeclaredProfiles()
|
||||
.dontReject()
|
||||
.neverReject()
|
||||
.tagOnSeverity(ResultSeverityEnum.ERROR, "http://example.com", "validation-failure");
|
||||
//END SNIPPET: requireValidationToDeclaredProfilesTagOnFailure
|
||||
}
|
||||
|
||||
public void requireValidationToDeclaredProfilesAdditionalOptions() {
|
||||
RepositoryValidatingRuleBuilder ruleBuilder = myAppCtx.getBean(RepositoryValidatingRuleBuilder.class);
|
||||
|
||||
//START SNIPPET: requireValidationToDeclaredProfilesAdditionalOptions
|
||||
ruleBuilder
|
||||
.forResourcesOfType("Patient")
|
||||
.requireValidationToDeclaredProfiles()
|
||||
|
||||
// Configure the validator to never reject extensions
|
||||
.allowAnyExtensions()
|
||||
|
||||
// Configure the validator to not perform terminology validation
|
||||
.disableTerminologyChecks()
|
||||
|
||||
// Configure the validator to raise an error if a resource being
|
||||
// validated declares a profile, and the StructureDefinition for
|
||||
// this profile can not be found.
|
||||
.errorOnUnknownProfiles()
|
||||
|
||||
// Configure the validator to suppress the information-level
|
||||
// message that is added to the validation result if a profile
|
||||
// StructureDefinition does not declare a binding for a coded
|
||||
// field.
|
||||
.suppressNoBindingMessage()
|
||||
|
||||
// Configure the validator to suppress the warning-level message
|
||||
// that is added when validating a code that can't be found in a
|
||||
// ValueSet that has an extensible binding.
|
||||
.suppressWarningForExtensibleValueSetValidation();
|
||||
//END SNIPPET: requireValidationToDeclaredProfilesAdditionalOptions
|
||||
}
|
||||
|
||||
|
||||
public void disallowProfiles() {
|
||||
RepositoryValidatingRuleBuilder ruleBuilder = myAppCtx.getBean(RepositoryValidatingRuleBuilder.class);
|
||||
|
||||
|
|
|
@ -95,6 +95,13 @@ By default, resource updates/changes resulting in failing validation will cause
|
|||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RepositoryValidatingInterceptorExamples.java|requireValidationToDeclaredProfilesTagOnFailure}}
|
||||
```
|
||||
|
||||
## Configuring the Validator
|
||||
|
||||
The following snippet shows a number of additional optional settings that can be chained onto the validation rule.
|
||||
|
||||
```java
|
||||
{{snippet:classpath:/ca/uhn/hapi/fhir/docs/RepositoryValidatingInterceptorExamples.java|requireValidationToDeclaredProfilesAdditionalOptions}}
|
||||
```
|
||||
|
||||
# Rules: Disallow Specific Profiles
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ public final class RepositoryValidatingRuleBuilder implements IRuleRoot {
|
|||
* Specifies that the resource should not be rejected from storage even if it does not pass validation.
|
||||
*/
|
||||
@Nonnull
|
||||
public FinalizedRequireValidationRule dontReject() {
|
||||
public FinalizedRequireValidationRule neverReject() {
|
||||
myRule.dontReject();
|
||||
return this;
|
||||
}
|
||||
|
@ -292,6 +292,57 @@ public final class RepositoryValidatingRuleBuilder implements IRuleRoot {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator to never reject extensions
|
||||
*/
|
||||
@Nonnull
|
||||
public FinalizedRequireValidationRule allowAnyExtensions() {
|
||||
myRule.getValidator().setAnyExtensionsAllowed(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator to not perform terminology validation
|
||||
*/
|
||||
@Nonnull
|
||||
public FinalizedRequireValidationRule disableTerminologyChecks() {
|
||||
myRule.getValidator().setNoTerminologyChecks(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator to raise an error if a resource being validated
|
||||
* declares a profile, and the StructureDefinition for this profile
|
||||
* can not be found.
|
||||
*/
|
||||
@Nonnull
|
||||
public FinalizedRequireValidationRule errorOnUnknownProfiles() {
|
||||
myRule.getValidator().setErrorForUnknownProfiles(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator to suppress the information-level message that
|
||||
* is added to the validation result if a profile StructureDefinition does
|
||||
* not declare a binding for a coded field.
|
||||
*/
|
||||
@Nonnull
|
||||
public FinalizedRequireValidationRule suppressNoBindingMessage() {
|
||||
myRule.getValidator().setNoBindingMsgSuppressed(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the validator to suppress the warning-level message that
|
||||
* is added when validating a code that can't be found in an ValueSet that
|
||||
* has an extensible binding.
|
||||
*/
|
||||
@Nonnull
|
||||
public FinalizedRequireValidationRule suppressWarningForExtensibleValueSetValidation() {
|
||||
myRule.getValidator().setNoExtensibleWarnings(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -117,6 +117,14 @@ class RequireValidationRule extends BaseTypedRule {
|
|||
.toString();
|
||||
}
|
||||
|
||||
public FhirInstanceValidator getValidator() {
|
||||
return myValidator;
|
||||
}
|
||||
|
||||
public void setAllowAnyExtensions() {
|
||||
myValidator.setAnyExtensionsAllowed(true);
|
||||
}
|
||||
|
||||
private static class TagOnSeverity {
|
||||
private final int mySeverity;
|
||||
private final String myTagSystem;
|
||||
|
|
|
@ -264,13 +264,40 @@ public class RepositoryValidatingInterceptorR4Test extends BaseJpaR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequireValidation_AdditionalOptions() {
|
||||
List<IRepositoryValidatingRule> rules = newRuleBuilder()
|
||||
.forResourcesOfType("Observation")
|
||||
.requireValidationToDeclaredProfiles()
|
||||
.withBestPracticeWarningLevel("IGNORE")
|
||||
.allowAnyExtensions()
|
||||
.disableTerminologyChecks()
|
||||
.errorOnUnknownProfiles()
|
||||
.suppressNoBindingMessage()
|
||||
.suppressWarningForExtensibleValueSetValidation()
|
||||
.build();
|
||||
|
||||
myValInterceptor.setRules(rules);
|
||||
|
||||
Observation obs = new Observation();
|
||||
obs.getCode().addCoding().setSystem("http://foo").setCode("123").setDisplay("help im a bug");
|
||||
obs.setStatus(Observation.ObservationStatus.AMENDED);
|
||||
try {
|
||||
IIdType id = myObservationDao.create(obs).getId();
|
||||
assertEquals("1", id.getVersionIdPart());
|
||||
} catch (PreconditionFailedException e) {
|
||||
// should not happen
|
||||
fail(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(e.getOperationOutcome()));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequireValidation_FailNoRejectAndTag() {
|
||||
List<IRepositoryValidatingRule> rules = newRuleBuilder()
|
||||
.forResourcesOfType("Observation")
|
||||
.requireValidationToDeclaredProfiles()
|
||||
.withBestPracticeWarningLevel("IGNORE")
|
||||
.dontReject()
|
||||
.neverReject()
|
||||
.tagOnSeverity(ResultSeverityEnum.ERROR, "http://foo", "validation-error")
|
||||
.build();
|
||||
myValInterceptor.setRules(rules);
|
||||
|
|
Loading…
Reference in New Issue