Add support for a pattern value constraint with the FHIR String data type #3970
Description
Describe the bug
The ConstraintGenerator class does not currently support pattern value constraints when the data type is FHIR String.
For example, the below GraphDefinition resource, introduces a set of slices on GraphDefinition.link.
The slices are unordered and Open, and can be differentiated using the following discriminators: pattern @ path
GraphDefinition.link supports two types of slices: link:location and link:formulary
{
"resourceType": "GraphDefinition",
"id": "PayerInsurancePlanGraphDefinition",
"meta": {
"profile": [
"http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-PayerInsurancePlanBulkDataGraphDefinition"
]
},
"text": {
"status": "empty",
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Redacted for size</div>"
},
"url": "http://hl7.org/fhir/us/davinci-drug-formulary/GraphDefinition/PayerInsurancePlanGraphDefinition",
"version": "2.0.0",
"name": "PayerInsurancePlanGraphDefinition",
"status": "active",
"date": "2022-08-25T13:12:25+00:00",
"publisher": "HL7 Pharmacy Working Group",
"contact": [
{
"name": "HL7 Pharmacy Working Group",
"telecom": [
{
"system": "url",
"value": "http://www.hl7.org/Special/committees/medication"
},
{
"system": "email",
"value": "pharmacy@lists.HL7.org"
}
]
}
],
"jurisdiction": [
{
"coding": [
{
"system": "urn:iso:std:iso:3166",
"code": "US"
}
]
}
],
"start": "InsurancePlan",
"profile": "http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-PayerInsurancePlan",
"link": [
{
"path": "InsurancePlan.coverageArea",
"target": [
{
"type": "Location",
"profile": "http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-InsurancePlanLocation"
}
]
},
{
"path": "InsurancePlan.coverage.extension.where(url=http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyReference-extension).valueReference",
"target": [
{
"type": "InsurancePlan",
"profile": "http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-Formulary",
"link": [
{
"target": [
{
"type": "Basic",
"params": "formulary={ref}",
"profile": "http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyItem",
"link": [
{
"path": "Basic.subject",
"target": [
{
"type": "MedicationKnowledge",
"profile": "http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyDrug"
}
]
}
]
}
]
}
]
}
]
}
]
}
The existing constraint generated for link:location is
"link.where(path).exists() implies (link.where(path).count() >= 1 and link.where(path).all(path.exists() and (target.exists() implies (target.count() >= 1 and target.all(type = 'Location' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-InsurancePlanLocation')))))))"
which also validating the link:formulary node because of the missing pattern value in the generated constraint.
The existing constraint generated for link:formulary is
"link.where(path).exists() implies (link.where(path).count() >= 1 and link.where(path).all(path.exists() and (target.exists() implies (target.count() >= 1 and target.all(type = 'InsurancePlan' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-Formulary')) and (link.exists() implies (link.count() >= 1 and link.all((target.exists() implies (target.count() >= 1 and target.all(type = 'Basic' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyItem')) and (link.exists() implies (link.count() >= 1 and link.all((target.exists() implies (target.count() >= 1 and target.all(type = 'MedicationKnowledge' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyDrug')))))))))))))))))))"
which also validating the link:formulary node because of the missing pattern value in the generated constraint.
.
This is because pattern value in GraphDefinition is of data type FHIR String and the ConstraintGenerator class does not currently support pattern value constraints when the data type is FHIR String.
Information on GraphDefinition.link : https://build.fhir.org/ig/HL7/davinci-pdex-formulary/StructureDefinition-usdf-PayerInsurancePlanBulkDataGraphDefinition-definitions.html
Information on slicing: https://build.fhir.org/profiling.html#slicing
Environment
Which version of LinuxForHealth FHIR Server? 5.0
To Reproduce
Steps to reproduce the behavior:
- Go to 'FHIR/conformance/fhir-ig-davinci-pdex-formulary/src/test/java/org/linuxforhealth/fhir/ig/davinci/pdex/formulary/test/ExamplesValidationTest.java'
- Change the example JSON in main method to "200/GraphDefinition-PayerInsurancePlanGraphDefinition.json"
new ExamplesValidationTest(EXAMPLES_PATH + "GraphDefinition-PayerInsurancePlanGraphDefinition.json") .testDaVinciFormularyValidation();
- Run ExamplesValidationTest as a Java application.
- See error
src/test/resources/examples/200/GraphDefinition-PayerInsurancePlanGraphDefinition.json {
"severity": "error",
"code": "invariant",
"details": {
"text": "generated-usdf-PayerInsurancePlanBulkDataGraphDefinition-4: Constraint violation: link.where(path).exists() implies (link.where(path).count() >= 1 and link.where(path).all(path.exists() and (target.exists() implies (target.count() >= 1 and target.all(type = 'Location' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-InsurancePlanLocation')))))))"
},
"diagnostics": "Caused by: [[expression: type = 'Location', result: false, location: GraphDefinition.link[1].target[0]]]",
"expression": [
"GraphDefinition"
]
}
src/test/resources/examples/200/GraphDefinition-PayerInsurancePlanGraphDefinition.json {
"severity": "error",
"code": "invariant",
"details": {
"text": "generated-usdf-PayerInsurancePlanBulkDataGraphDefinition-5: Constraint violation: link.where(path).exists() implies (link.where(path).count() >= 1 and link.where(path).all(path.exists() and (target.exists() implies (target.count() >= 1 and target.all(type = 'InsurancePlan' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-Formulary')) and (link.exists() implies (link.count() >= 1 and link.all((target.exists() implies (target.count() >= 1 and target.all(type = 'Basic' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyItem')) and (link.exists() implies (link.count() >= 1 and link.all((target.exists() implies (target.count() >= 1 and target.all(type = 'MedicationKnowledge' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-FormularyDrug')))))))))))))))))))"
},
"diagnostics": "Caused by: [[expression: type = 'InsurancePlan', result: false, location: GraphDefinition.link[0].target[0]]]",
"expression": [
"GraphDefinition"
]
}
Expected behavior
The ConstraintGenerator class does not currently support pattern value constraints when the data type is FHIR String. The above Graph Definition resource is valid and the validation should PASS without any issues with "severity": "error"
After the fix the constraint generated for link:location should be like
"link.where(path = 'InsurancePlan.coverageArea').exists() implies (link.where(path = 'InsurancePlan.coverageArea').count() >= 1 and link.where(path = 'InsurancePlan.coverageArea').all(path = 'InsurancePlan.coverageArea' and (target.exists() implies (target.count() >= 1 and target.all(type = 'Location' and (profile.exists() implies (profile = 'http://hl7.org/fhir/us/davinci-drug-formulary/StructureDefinition/usdf-InsurancePlanLocation')))))))"