This commit is contained in:
James Agnew 2024-11-27 08:24:33 -05:00 committed by GitHub
commit d0499d5911
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 836 additions and 0 deletions

View File

@ -0,0 +1,70 @@
package org.hl7.fhir.r4.validation;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.IValidationSupport;
import ca.uhn.fhir.test.BaseTest;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import org.hl7.fhir.common.hapi.validation.support.PrePopulatedValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* See #6424
*/
public class ConvertedStructureDefinitionValidationTest extends BaseTest {
private static final Logger ourLog = LoggerFactory.getLogger(ConvertedStructureDefinitionValidationTest.class);
private final FhirContext myCtx = FhirContext.forR4Cached();
@Test
public void testInvalidateCacheThenValidate() throws Exception {
// Create a validation support that loads the patient-citizenship extension
PrePopulatedValidationSupport val = new PrePopulatedValidationSupport(myCtx);
val.addStructureDefinition(loadResource(myCtx, StructureDefinition.class, "r4/extension-patient-citizenship.json"));
IValidationSupport builtInValidationSupport = myCtx.getValidationSupport();
ValidationSupportChain validationSupport = new ValidationSupportChain(val, builtInValidationSupport);
FhirInstanceValidator instanceValidator = new FhirInstanceValidator(validationSupport);
instanceValidator.setBestPracticeWarningLevel(BestPracticeWarningLevel.Ignore);
FhirValidator validator = myCtx.newValidator();
validator.registerValidatorModule(instanceValidator);
// Create a patient with an invalid citizenship extension
Patient patient = new Patient();
patient.setActive(true);
Extension citizenship = patient.addExtension();
citizenship.setUrl("http://hl7.org/fhir/StructureDefinition/patient-citizenship");
citizenship.addExtension("period", new StringType("NOT A PERIOD"));
// Validate once
ValidationResult outcome = validator.validateWithResult(patient);
ourLog.info(myCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome.toOperationOutcome()));
assertEquals("The Profile 'http://hl7.org/fhir/StructureDefinition/patient-citizenship|5.1.0' definition allows for the type Period but found type string", outcome.getMessages().get(0).getMessage());
assertEquals(1, outcome.getMessages().size());
// Invalidate the caches
instanceValidator.invalidateCaches();
// Validate a second time
outcome = validator.validateWithResult(patient);
ourLog.info(myCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome.toOperationOutcome()));
assertEquals("The Profile 'http://hl7.org/fhir/StructureDefinition/patient-citizenship|5.1.0' definition allows for the type Period but found type string", outcome.getMessages().get(0).getMessage());
assertEquals(1, outcome.getMessages().size());
}
}

View File

@ -0,0 +1,766 @@
{
"resourceType" : "StructureDefinition",
"id" : "patient-citizenship",
"url" : "http://hl7.org/fhir/StructureDefinition/patient-citizenship",
"identifier" : [{
"system" : "urn:ietf:rfc:3986",
"value" : "urn:oid:2.16.840.1.113883.4.642.5.1330"
}],
"version" : "5.1.0",
"name" : "PatCitizenship",
"title" : "Patient Citizenship",
"status" : "active",
"experimental" : false,
"date" : "2020-12-28T16:55:11+11:00",
"publisher" : "HL7 International / Patient Administration",
"contact" : [{
"telecom" : [{
"system" : "url",
"value" : "http://www.hl7.org/Special/committees/pafm"
}]
}],
"description" : "The patient's legal status as citizen of a country.",
"jurisdiction" : [{
"coding" : [{
"system" : "http://unstats.un.org/unsd/methods/m49/m49.htm",
"code" : "001"
}]
}],
"fhirVersion" : "5.0.0",
"mapping" : [{
"identity" : "rim",
"uri" : "http://hl7.org/v3",
"name" : "RIM Mapping"
}],
"kind" : "complex-type",
"abstract" : false,
"context" : [{
"type" : "element",
"expression" : "Patient"
}],
"type" : "Extension",
"baseDefinition" : "http://hl7.org/fhir/StructureDefinition/Extension",
"derivation" : "constraint",
"snapshot" : {
"element" : [{
"id" : "Extension",
"path" : "Extension",
"short" : "Nation(s) where the patient claims citizenship",
"definition" : "The patient's legal status as citizen of a country.",
"min" : 0,
"max" : "*",
"base" : {
"path" : "Extension",
"min" : 0,
"max" : "*"
},
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
},
{
"key" : "ext-1",
"severity" : "error",
"human" : "Must have either extensions or value[x], not both",
"expression" : "extension.exists() != value.exists()",
"source" : "http://hl7.org/fhir/StructureDefinition/Extension"
}],
"isModifier" : false
},
{
"id" : "Extension.id",
"path" : "Extension.id",
"representation" : ["xmlAttr"],
"short" : "Unique id for inter-element referencing",
"definition" : "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"min" : 0,
"max" : "1",
"base" : {
"path" : "Element.id",
"min" : 0,
"max" : "1"
},
"type" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type",
"valueUrl" : "id"
}],
"code" : "http://hl7.org/fhirpath/System.String"
}],
"condition" : ["ele-1"],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "n/a"
}]
},
{
"id" : "Extension.extension",
"path" : "Extension.extension",
"slicing" : {
"discriminator" : [{
"type" : "value",
"path" : "url"
}],
"description" : "Extensions are always sliced by (at least) url",
"rules" : "open"
},
"short" : "Additional content defined by implementations",
"definition" : "May be used to represent additional information that is not part of the basic definition of the element. To make the use of extensions safe and managable, there is a strict set of governance applied to the definition and use of extensions. Though any implementer can define an extension, there is a set of requirements that SHALL be met as part of the definition of the extension.",
"comment" : "There can be no stigma associated with the use of extensions by any application, project, or standard - regardless of the institution or jurisdiction that uses or defines the extensions. The use of extensions is what allows the FHIR specification to retain a core level of simplicity for everyone.",
"alias" : ["extensions",
"user content"],
"min" : 0,
"max" : "*",
"base" : {
"path" : "Element.extension",
"min" : 0,
"max" : "*"
},
"type" : [{
"code" : "Extension"
}],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
},
{
"key" : "ext-1",
"severity" : "error",
"human" : "Must have either extensions or value[x], not both",
"expression" : "extension.exists() != value.exists()",
"source" : "http://hl7.org/fhir/StructureDefinition/Extension"
}],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "n/a"
}]
},
{
"id" : "Extension.extension:code",
"path" : "Extension.extension",
"sliceName" : "code",
"short" : "Nation code of citizenship",
"definition" : "Nation code representing the citizenship of patient.",
"min" : 0,
"max" : "1",
"base" : {
"path" : "Element.extension",
"min" : 0,
"max" : "*"
},
"type" : [{
"code" : "Extension"
}],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
},
{
"key" : "ext-1",
"severity" : "error",
"human" : "Must have either extensions or value[x], not both",
"expression" : "extension.exists() != value.exists()",
"source" : "http://hl7.org/fhir/StructureDefinition/Extension"
}],
"isModifier" : false,
"isSummary" : false
},
{
"id" : "Extension.extension:code.id",
"path" : "Extension.extension.id",
"representation" : ["xmlAttr"],
"short" : "Unique id for inter-element referencing",
"definition" : "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"min" : 0,
"max" : "1",
"base" : {
"path" : "Element.id",
"min" : 0,
"max" : "1"
},
"type" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type",
"valueUrl" : "id"
}],
"code" : "http://hl7.org/fhirpath/System.String"
}],
"condition" : ["ele-1"],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "n/a"
}]
},
{
"id" : "Extension.extension:code.extension",
"path" : "Extension.extension.extension",
"slicing" : {
"discriminator" : [{
"type" : "value",
"path" : "url"
}],
"description" : "Extensions are always sliced by (at least) url",
"rules" : "open"
},
"short" : "Extension",
"definition" : "An Extension",
"min" : 0,
"max" : "0",
"base" : {
"path" : "Element.extension",
"min" : 0,
"max" : "*"
},
"type" : [{
"code" : "Extension"
}],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
},
{
"key" : "ext-1",
"severity" : "error",
"human" : "Must have either extensions or value[x], not both",
"expression" : "extension.exists() != value.exists()",
"source" : "http://hl7.org/fhir/StructureDefinition/Extension"
}],
"isModifier" : false,
"isSummary" : false
},
{
"id" : "Extension.extension:code.url",
"path" : "Extension.extension.url",
"representation" : ["xmlAttr"],
"short" : "identifies the meaning of the extension",
"definition" : "Source of the definition for the extension code - a logical name or a URL.",
"comment" : "The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.",
"min" : 1,
"max" : "1",
"base" : {
"path" : "Extension.url",
"min" : 1,
"max" : "1"
},
"type" : [{
"code" : "uri"
}],
"fixedUri" : "code",
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "N/A"
}]
},
{
"id" : "Extension.extension:code.value[x]",
"path" : "Extension.extension.value[x]",
"short" : "Value of extension",
"definition" : "Value of extension - must be one of a constrained set of the data types (see [Extensibility](http://hl7.org/fhir/R5/extensibility.html) for a list).",
"min" : 1,
"max" : "1",
"base" : {
"path" : "Extension.value[x]",
"min" : 0,
"max" : "1"
},
"type" : [{
"code" : "CodeableConcept"
}],
"condition" : ["ext-1"],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
}],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "N/A"
}]
},
{
"id" : "Extension.extension:period",
"path" : "Extension.extension",
"sliceName" : "period",
"short" : "Time period of citizenship",
"definition" : "Period when citizenship was effective.",
"min" : 0,
"max" : "1",
"base" : {
"path" : "Element.extension",
"min" : 0,
"max" : "*"
},
"type" : [{
"code" : "Extension"
}],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
},
{
"key" : "ext-1",
"severity" : "error",
"human" : "Must have either extensions or value[x], not both",
"expression" : "extension.exists() != value.exists()",
"source" : "http://hl7.org/fhir/StructureDefinition/Extension"
}],
"isModifier" : false,
"isSummary" : false
},
{
"id" : "Extension.extension:period.id",
"path" : "Extension.extension.id",
"representation" : ["xmlAttr"],
"short" : "Unique id for inter-element referencing",
"definition" : "Unique id for the element within a resource (for internal references). This may be any string value that does not contain spaces.",
"min" : 0,
"max" : "1",
"base" : {
"path" : "Element.id",
"min" : 0,
"max" : "1"
},
"type" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type",
"valueUrl" : "id"
}],
"code" : "http://hl7.org/fhirpath/System.String"
}],
"condition" : ["ele-1"],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "n/a"
}]
},
{
"id" : "Extension.extension:period.extension",
"path" : "Extension.extension.extension",
"slicing" : {
"discriminator" : [{
"type" : "value",
"path" : "url"
}],
"description" : "Extensions are always sliced by (at least) url",
"rules" : "open"
},
"short" : "Extension",
"definition" : "An Extension",
"min" : 0,
"max" : "0",
"base" : {
"path" : "Element.extension",
"min" : 0,
"max" : "*"
},
"type" : [{
"code" : "Extension"
}],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
},
{
"key" : "ext-1",
"severity" : "error",
"human" : "Must have either extensions or value[x], not both",
"expression" : "extension.exists() != value.exists()",
"source" : "http://hl7.org/fhir/StructureDefinition/Extension"
}],
"isModifier" : false,
"isSummary" : false
},
{
"id" : "Extension.extension:period.url",
"path" : "Extension.extension.url",
"representation" : ["xmlAttr"],
"short" : "identifies the meaning of the extension",
"definition" : "Source of the definition for the extension code - a logical name or a URL.",
"comment" : "The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.",
"min" : 1,
"max" : "1",
"base" : {
"path" : "Extension.url",
"min" : 1,
"max" : "1"
},
"type" : [{
"code" : "uri"
}],
"fixedUri" : "period",
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "N/A"
}]
},
{
"id" : "Extension.extension:period.value[x]",
"path" : "Extension.extension.value[x]",
"short" : "Value of extension",
"definition" : "Value of extension - must be one of a constrained set of the data types (see [Extensibility](http://hl7.org/fhir/R5/extensibility.html) for a list).",
"min" : 1,
"max" : "1",
"base" : {
"path" : "Extension.value[x]",
"min" : 0,
"max" : "1"
},
"type" : [{
"code" : "Period"
}],
"condition" : ["ext-1"],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
}],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "N/A"
}]
},
{
"id" : "Extension.url",
"path" : "Extension.url",
"representation" : ["xmlAttr"],
"short" : "identifies the meaning of the extension",
"definition" : "Source of the definition for the extension code - a logical name or a URL.",
"comment" : "The definition may point directly to a computable or human-readable definition of the extensibility codes, or it may be a logical URI as declared in some other specification. The definition SHALL be a URI for the Structure Definition defining the extension.",
"min" : 1,
"max" : "1",
"base" : {
"path" : "Extension.url",
"min" : 1,
"max" : "1"
},
"type" : [{
"extension" : [{
"url" : "http://hl7.org/fhir/StructureDefinition/structuredefinition-fhir-type",
"valueUrl" : "uri"
}],
"code" : "http://hl7.org/fhirpath/System.String"
}],
"fixedUri" : "http://hl7.org/fhir/StructureDefinition/patient-citizenship",
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "N/A"
}]
},
{
"id" : "Extension.value[x]",
"path" : "Extension.value[x]",
"short" : "Value of extension",
"definition" : "Value of extension - must be one of a constrained set of the data types (see [Extensibility](http://hl7.org/fhir/R5/extensibility.html) for a list).",
"min" : 0,
"max" : "0",
"base" : {
"path" : "Extension.value[x]",
"min" : 0,
"max" : "1"
},
"type" : [{
"code" : "base64Binary"
},
{
"code" : "boolean"
},
{
"code" : "canonical"
},
{
"code" : "code"
},
{
"code" : "date"
},
{
"code" : "dateTime"
},
{
"code" : "decimal"
},
{
"code" : "id"
},
{
"code" : "instant"
},
{
"code" : "integer"
},
{
"code" : "integer64"
},
{
"code" : "markdown"
},
{
"code" : "oid"
},
{
"code" : "positiveInt"
},
{
"code" : "string"
},
{
"code" : "time"
},
{
"code" : "unsignedInt"
},
{
"code" : "uri"
},
{
"code" : "url"
},
{
"code" : "uuid"
},
{
"code" : "Address"
},
{
"code" : "Age"
},
{
"code" : "Annotation"
},
{
"code" : "Attachment"
},
{
"code" : "CodeableConcept"
},
{
"code" : "CodeableReference"
},
{
"code" : "Coding"
},
{
"code" : "ContactPoint"
},
{
"code" : "Count"
},
{
"code" : "Distance"
},
{
"code" : "Duration"
},
{
"code" : "HumanName"
},
{
"code" : "Identifier"
},
{
"code" : "Money"
},
{
"code" : "Period"
},
{
"code" : "Quantity"
},
{
"code" : "Range"
},
{
"code" : "Ratio"
},
{
"code" : "RatioRange"
},
{
"code" : "Reference"
},
{
"code" : "SampledData"
},
{
"code" : "Signature"
},
{
"code" : "Timing"
},
{
"code" : "ContactDetail"
},
{
"code" : "DataRequirement"
},
{
"code" : "Expression"
},
{
"code" : "ParameterDefinition"
},
{
"code" : "RelatedArtifact"
},
{
"code" : "TriggerDefinition"
},
{
"code" : "UsageContext"
},
{
"code" : "Availability"
},
{
"code" : "ExtendedContactDetail"
},
{
"code" : "Dosage"
},
{
"code" : "Meta"
}],
"condition" : ["ext-1"],
"constraint" : [{
"key" : "ele-1",
"severity" : "error",
"human" : "All FHIR elements must have a @value or children",
"expression" : "hasValue() or (children().count() > id.count())",
"source" : "http://hl7.org/fhir/StructureDefinition/Element"
}],
"isModifier" : false,
"isSummary" : false,
"mapping" : [{
"identity" : "rim",
"map" : "N/A"
}]
}]
},
"differential" : {
"element" : [{
"id" : "Extension",
"path" : "Extension",
"short" : "Nation(s) where the patient claims citizenship",
"definition" : "The patient's legal status as citizen of a country.",
"min" : 0,
"max" : "*"
},
{
"id" : "Extension.extension:code",
"path" : "Extension.extension",
"sliceName" : "code",
"short" : "Nation code of citizenship",
"definition" : "Nation code representing the citizenship of patient.",
"min" : 0,
"max" : "1",
"type" : [{
"code" : "Extension"
}]
},
{
"id" : "Extension.extension:code.extension",
"path" : "Extension.extension.extension",
"max" : "0"
},
{
"id" : "Extension.extension:code.url",
"path" : "Extension.extension.url",
"type" : [{
"code" : "uri"
}],
"fixedUri" : "code"
},
{
"id" : "Extension.extension:code.value[x]",
"path" : "Extension.extension.value[x]",
"min" : 1,
"type" : [{
"code" : "CodeableConcept"
}]
},
{
"id" : "Extension.extension:period",
"path" : "Extension.extension",
"sliceName" : "period",
"short" : "Time period of citizenship",
"definition" : "Period when citizenship was effective.",
"min" : 0,
"max" : "1",
"type" : [{
"code" : "Extension"
}]
},
{
"id" : "Extension.extension:period.extension",
"path" : "Extension.extension.extension",
"max" : "0"
},
{
"id" : "Extension.extension:period.url",
"path" : "Extension.extension.url",
"type" : [{
"code" : "uri"
}],
"fixedUri" : "period"
},
{
"id" : "Extension.extension:period.value[x]",
"path" : "Extension.extension.value[x]",
"min" : 1,
"type" : [{
"code" : "Period"
}]
},
{
"id" : "Extension.url",
"path" : "Extension.url",
"fixedUri" : "http://hl7.org/fhir/StructureDefinition/patient-citizenship"
},
{
"id" : "Extension.value[x]",
"path" : "Extension.value[x]",
"min" : 0,
"max" : "0"
}]
}
}