Stream: ibm
Topic: Validating custom resources
Matt Sargent (May 04 2020 at 19:29):
Does the IBM FHIR code provide support for validating custom resource definitions? Suppose I have MyPatient
which puts some extra constraints on the Patient
resource. Is it possible to leverage FHIRValidator
to validate this resource? If so, are there examples handy anywhere of how to accomplish this?
I've been trying to do something along the lines of
val profiles = ... // Seq(strings containing structure definitions)
val customResourceString = ... // String containing JSON representation of a custom resource
val parsedResource = FHIRParser.parser(Format.JSON).parse(IOUtils.toInputStream(resourceString, "UTF-8")).asInstanceOf[Resource]
FHIRValidator.validator().validate(resource, true, profiles: _*)
Depending on the 'resourceType' I use in the custom resource string, either the validator runs, but only appears to validate against the base Patient
resource, or if I try to use MyPatient
as the resourceType
then the FHIRParser chokes on the JSON.
If anyone has advice on how I should try to proceed I would greatly appreciate it. Thanks!
Lee Surprenant (May 04 2020 at 20:01):
Hi Matt. Did you have a look at https://ibm.github.io/FHIR/guides/FHIRValidationGuide ? Basically, you need to make your constraints available to the validator via conformance artifacts (StructureDefinition in your case) in the FHIRRegistry
Lee Surprenant (May 04 2020 at 20:03):
the validator will look them up from there by uri and version
Lee Surprenant (May 04 2020 at 20:06):
as for building those StructureDefinition, we don't really provide any tooling beyond the base fhir model, but there's lots of tools in the community
Matt Sargent (May 04 2020 at 20:28):
Thanks for the response. I'll have to dive in deeper to that example, but after a first pass it seems like validation is built with a FHIR server in mind? Is that correct? Or is it also possible to accomplish by hand, but I'd have to tie together the components called out on that page (fhir-model, fhir-validation, fhir-registry, etc.)?
Lee Surprenant (May 04 2020 at 21:03):
FHIR Validation is written as a standalone component (a set of modules). It uses a Java ServiceLoader pattern to find RegistryResourceProviders
when its initialized. In the webapp, that is initialized during server startup (via a ServletContextListener) so you'd need to do similar for your app.
Lee Surprenant (May 04 2020 at 21:07):
https://ibm.github.io/FHIR/guides/CreateFHIRValidationAssembly provides some guidance on building an assembly that contains the validator and all related pieces...although I've never actually gone through that part myself. Let us know if you hit any issues.
Matt Sargent (May 15 2020 at 18:24):
Thanks again Lee. Finally have time to circle back to this.
I'll let you know if I hit any technical issues. So far my main issue is trying to decipher what the actual steps are from the documentation, but they might make more sense once I start trying to code.
Matt Sargent (May 15 2020 at 21:39):
I worked with a teammate today to get a very simple validation program running with a custom profile. We were able to enforce that a Period was required, when normally it was optional.
Our next step is trying to also enforce that the mandatory Period contains a particular extension, but we have not been able to get that working yet.
Thanks again for the pointers.
Matt Sargent (May 18 2020 at 16:23):
@Lee Surprenant , does the FHIR validation support more than "one level" of validation? For example, should I be able to have a profile that specifies that a resource contains a Period, and that the Period itself contains a particular extension?
Paul Bastide (May 18 2020 at 18:04):
HI Matt yes absolutely
Lee Surprenant (May 18 2020 at 18:10):
Yes, what paul said. How are you creating the profiles today? Did you mention you were using FSH?
Lee Surprenant (May 18 2020 at 18:13):
Irregardless of which tools you are using to produce the profile, I think the result will be 3 structureDefinitions:
- The StructureDefinition of the extension you want to make mandatory on the Period (call it http://example.com/StructureDefinition/my-extension)
- The StructureDefinition of the profile for the Period datatype (call it http://example.com/StructureDefintion/period-with-extension
- The StructureDefinition of the profile for the resource type where you are making the Period required
Lee Surprenant (May 18 2020 at 18:14):
although #1 may be optional for what you're trying to accomplish
Matt Sargent (May 18 2020 at 19:03):
We are using FSH and sushi to generate profiles.
There are definitions covering items 2 and 3 from the list above, but I did not add a definition for the extension itself yet. I'll add that in and see if the result is any different.
Matt Sargent (May 18 2020 at 20:33):
(apologies ahead of time for this wall of text)
Here's a minimal cut of the FSH files in use.
Profile: MyCoverage
Parent: Coverage
Id: my-coverage
* period 1..1
* period only PeriodWithMyExtension
Profile: PeriodWithMyExtension
Parent: Period
Title: "Period with my extension"
Id: period-with-my-extension
* extension contains MyExtension named myExtension 1..1
Extension: MyExtension
Title: "My Extension"
Id: my-extension
Description: "An extension"
* value[x] only integer
I generated the structure definitions and added them to our project. I also updated .index.json to the following:
{
"index-version": 1,
"files": [
{
"filename": "my-coverage.json",
"resourceType": "StructureDefinition",
"id": "my-coverage",
"url": "http://myurl.org/my-coverage",
"version": "4.0.1",
"kind": "resource",
"type": "Coverage"
},
{
"filename": "my-extension.json",
"resourceType": "StructureDefinition",
"id": "my-extension",
"url": "http://myurl.org/my-extension",
"version": "4.0.1",
"kind": "complex-type",
"type": "Extension"
},
{
"filename": "period-with-my-extension.json",
"resourceType": "StructureDefinition",
"id": "period-with-my-extension",
"url": "http://myurl.org/period-with-my-extension",
"version": "4.0.1",
"kind": "complex-type",
"type": "Period"
}
]
}
Finally, I tried running this toy program:
package org.myurl.validation
import com.ibm.fhir.model.`type`.code.CoverageStatus
import com.ibm.fhir.model.`type`.{Canonical, Meta, Period, Reference, String => FHIRString, DateTime => FHIRDateTime}
import com.ibm.fhir.model.resource.Coverage
import com.ibm.fhir.validation.FHIRValidator
object FHIRValidationPgm {
val validator = FHIRValidator.validator()
def main(args: Array[String]): Unit = {
val coverage = Coverage.builder()
.status(CoverageStatus.ACTIVE)
.beneficiary(Reference.builder().reference(FHIRString.of("none")).build())
.payor(Reference.builder().reference(FHIRString.of("none")).build())
// .period(Period.builder().start(FHIRDateTime.of("2020-01-01")).end(FHIRDateTime.of("2020-01-31")).build())
.meta(Meta.builder()
.profile(Canonical.builder().value("http://myurl.org/my-coverage").build())
.build()
)
.build()
System.out.println(validator.validate(coverage))
}
}
With the period()
line commented out, I see that a constraint is violated in the output:
"text": "generated-my-coverage-1: Constraint violation: period.exists()"
However, when I include the Period line, there is no such complaint about a missing extension on the Period. Any thoughts on what might be going wrong? I'm wondering if I have a mistake all the way back in the FSH files, or if I am adding the structure definitions to the project incorrectly. Thanks for any help you can offer.
Lee Surprenant (May 18 2020 at 21:00):
Unfortunately, I'm not much good with FSH... is it possible for you to share your StructureDefinitions here (or via other means if sensitive at all)?
Lee Surprenant (May 18 2020 at 21:01):
@John Timm fyi ^
Lee Surprenant (May 18 2020 at 21:09):
specifically what i'm wondering is if * extension contains MyExtension named myExtension 1..1
is doing what you expect it to be doing. extension is a repeating field and so typically the way to "constrain" that is via a "slice"
Lee Surprenant (May 18 2020 at 21:10):
so is this line properly identifying that the profile must contain one (and only one) instance of myExtension in the list of extensions?
Matt Sargent (May 18 2020 at 21:18):
my-coverage.json my-extension.json period-with-my-extension.json
John Timm (May 18 2020 at 21:25):
We currently don't support the generation of constraints on complex data types that are specified in the way that FSH has generated for this example. We need to convince FSH to generate a structure definition that references the extension definition directly as opposed to doing it through an intermediate profiled complex data type (as you have done). For example:
Coverage.period
Coverage.period.extension
Coverage.period.extension:sliceName
John Timm (May 18 2020 at 21:36):
Here's what I think needs to happen:
- Figure out how to get FSH to generate what we do support
- Create an enhancement request to look into what it would take to expand what our constraint generator supports
John Timm (May 18 2020 at 21:46):
https://github.com/IBM/FHIR/issues/1117
Matt Sargent (May 18 2020 at 22:07):
Thanks John. Knowing that the FSH files are the place to start tweaking for now is helpful.
John Timm (May 19 2020 at 16:59):
@Matt Sargent An enhancement to the constraint generator was delivered with this PR:
https://github.com/IBM/FHIR/pull/1121
Matt Sargent (May 22 2020 at 21:09):
Initial testing with 4.2.2 is looking good so far. Thank you for such a quick turnaround on this new feature!
Last updated: Apr 12 2022 at 19:14 UTC