Stream: cql
Topic: Using CQL execution framework to evaluate FHIR constraints
Kevin Olbrich (Jan 21 2018 at 01:44):
In theory it should be possible to generate code that reflects the constraints on resources as defined in the FHIR definition files. According to the documentation, the expressions are defined in FHIRPath, which is itself a subset of CQL. What I would like to do is use the CQL-to-ELM translator to generate an ELM tree for each of the constraints and then use that tree to generate code in a target language. By doing this we can automate code generation and make sure that it actually matches the definitions as much as possible. Has anyone tried this? Is this possible? Am I wasting my time?
Grahame Grieve (Jan 21 2018 at 03:08):
The build tool parses them all to an ast, and evaluates them, but doesn’t do any code generation. I don’t know of anyone who has done that. Btw, you can use the java ast if you want (if you’re using java)
Kevin Olbrich (Jan 21 2018 at 08:26):
@Grahame Grieve can you point me at the code the build tool uses to parse the constraints?
Grahame Grieve (Jan 21 2018 at 08:50):
org.hl7.fhir.r4.model.ExpressionNode and org.hl7.fhir.r4.utils.FHIRPathEngine
Kevin Olbrich (Jan 21 2018 at 22:37):
Weird... there are constraints that look like this hasValue() | (children().count() > id.count())
all over the place, but I can't find a definition of hasValue()
in the FHIRPath specification (http://hl7.org/fhirpath/).
Grahame Grieve (Jan 21 2018 at 22:53):
hmm. that's something we haven't quite figured out; it's technically a feature of the primitive types in FHIR
Kevin Olbrich (Jan 21 2018 at 22:55):
So is hasValue()
really just checking to see if the Element is a primitive?
Grahame Grieve (Jan 21 2018 at 22:57):
no. better to explain it in terms of an element
Grahame Grieve (Jan 21 2018 at 22:57):
<status value="active"/>
Grahame Grieve (Jan 21 2018 at 22:57):
hasValue() == true
Grahame Grieve (Jan 21 2018 at 22:57):
<status><extension url="balh"><valueCode value="blah"/></extension/></status>
Grahame Grieve (Jan 21 2018 at 22:58):
hasValue() == false
Kevin Olbrich (Jan 21 2018 at 23:34):
I see, there are a few things that aren't primitives, but do have a value
.
Kevin Olbrich (Jan 21 2018 at 23:39):
What would hasValue()
evaluate to for <extension url="foo"><valueCode="bar"/></extension>
?
Kevin Olbrich (Jan 21 2018 at 23:58):
Shouldn't that constraint be something like hasValue() or (children().count() > 0)
? What does the id.count()
have to do with it?
Grahame Grieve (Jan 22 2018 at 01:35):
hasValue() returns null on Extension because it's not a primitive
Grahame Grieve (Jan 22 2018 at 01:35):
what's the context of this constraint?
Kevin Olbrich (Jan 22 2018 at 04:53):
I'm talking about the ele-1
constraint from Element
(hasValue() | (children().count() > id.count())
). It's not clear to me why children().count() > id.count()
is used instead of children().count() > 0
.
Grahame Grieve (Jan 22 2018 at 04:55):
oh because it can have an id but that doesn't as content. So there must be at least one more child than the the count of id (which will be 0 or 1)
Kevin Olbrich (Jan 22 2018 at 15:06):
@Bryn Rhodes so if I wanted to use the cql-to-elm
translator to generate an ELM
tree for the ele-1
constraint, how would I go about doing it? --- (BTW... it took longer than I care to admit for me to realize that the ELM
here is not the elm
programming language)
Bryn Rhodes (Jan 22 2018 at 20:28):
Simplest way would be to take the ele-1 constraint and put it in a .cql file and call the command-line translator on it. There's context though, so you would need to set up a library to express the definition, something like this:
Bryn Rhodes (Jan 22 2018 at 20:29):
library "ele-1"
using FHIR version '3.0.0'
parameter Context Patient
define Constraint: <content of the ele-1 constraint>
Kevin Olbrich (Jan 22 2018 at 20:53):
I'll give that a try, thanks!
Kevin Olbrich (Jan 22 2018 at 21:03):
if I send this...
library "ele-1" using FHIR version '3.0.0' parameter Context Patient define Constraint: hasValue() | (children().count() > id.count())
To the cql-to-elm translator docker container I get this in response...
{ "library": { "annotation": [ { "startLine": 6, "startChar": 2, "endLine": 6, "endChar": 11, "message": "Could not resolve call to operator hasValue with signature ().", "errorType": "semantic", "errorSeverity": "error", "type": "CqlToElmError" } ], "identifier": { "id": "ele-1" }, "schemaIdentifier": { "id": "urn:hl7-org:elm", "version": "r1" }, "usings": { "def": [ { "localIdentifier": "System", "uri": "urn:hl7-org:elm-types:r1" }, { "localId": "1", "localIdentifier": "FHIR", "uri": "http://hl7.org/fhir", "version": "3.0.0" } ] }, "parameters": { "def": [ { "localId": "3", "name": "Context", "accessLevel": "Public", "parameterTypeSpecifier": { "localId": "2", "name": "{http://hl7.org/fhir}Patient", "type": "NamedTypeSpecifier" } } ] }, "statements": {...
Kevin Olbrich (Jan 23 2018 at 16:14):
@Bryn Rhodes looks like this doesn't work as expected. Any idea how to correct this? It seems like I'm just missing some definitions, but I have no idea where to find them.
Bryn Rhodes (Jan 23 2018 at 16:23):
Since it is a constraint, it needs to be evaluated in the context of the definition, so it needs a bit more setup:
Bryn Rhodes (Jan 23 2018 at 16:28):
I'll log this as an issue and get it running in the translator. hasValue() in particular it looks like is missing, I may need to add that to FHIR Helpers.
Kevin Olbrich (Jan 23 2018 at 16:28):
Awesome! Thanks!
Last updated: Apr 12 2022 at 19:14 UTC