Monday, August 3, 2020

Validating Constraints imposed by Definition Resources

One of my outstanding action items related to SANER is to propose a mechanism by which constraints imposed by definition resources can be applied to a FHIR Resource for validation.

A definition resource is one which defines content allowed in a resource referencing that definition.

For example, for MeasureReport, the definition is Measure, for QuestionnaireResponse, the definition is Questionnaire, and for CarePlan, the definition is CarePlanDefinition.

The challenge here is that the invariants imposed by a definition resource require access to that resource in order to be implemented, and they aren't stated in the specifications either on the resource, or on the definition resource in a machine readable format.

Since the definition resource is what actually applies them, and creators of the definition resource are who's basically creating the rules, what is needed here is a different kind of invariant statement.  The invariant is stated in the definition resource, but applies to the defined resource.

Typically invariants are written in the context of the resource to which they apply. However, the invariants implied by the use of a definition need to be written in the context of the defined resource, and the context of that resource's definition need to be available.

Let's have a look at Measure and MeasureReport (this is my first take):
FieldDescriptionConstraint with respect to %def = resolve(MeasureReport.measure)
subjectThe subject is compatible with %def.subjectCodeableConceptnot(%def.subjectCodeableConcept.exists()) or 
  subject.resolve().exists(
    ofType(
      %def.subjectCodeableConcept.where(
        system =
         'http://hl7.org/fhir/resource-types'
      ).code
    )
  )
subjectThe subject is compatible with %def.subjectReference.typenot(%def.subjectReference) or 
resolve(%def.subjectReference).exists(
  (type = 'person' and
     %resource.subject.where(
       ofType('Patient') or ofType('Practitioner') or ofType('RelatedPerson')
     )
  ) or
  (type = 'animal' and 
     %resource.subject.where(ofType('Patient'))
  ) or
  (type = 'practitioner' and 
     %resource.subject.where(ofType('Practitioner')
  ) or
  (type = 'device' and 
     %resource.subject.where(ofType('Device'))
 
)
  // Don't need to worry about medication or substance, as Measure doesn't allow these
)
periodPeriod is in the effectivePeriod for the measure.not(%def.effectivePeriod.exists()) or (
  period.start >= %def.effectivePeriod.start and
  period.end <= %def.effectivePeriod.end
)
improvementNotationimprovementNotation is compatible with %def.improvementNotationnot(%def.improvementNotation) or %def.improvementNotation ~ improvementNotation
groupMeasureReport will contain one group of data for each group specified in the corresponding Measure%def.group.all(
  $this.code ~ %resource.group[$index].code
)
group.populationconsisting of a set of population elements, one for each criteria defined in each group.%def.group.population.all(
  $this.code ~
    (%resource.group.population)[$index].code

)
group.stratifierIn addition, each group will contain stratifiers with a value stratum for each value defined by the stratifier criteria, for each criteria defined in the measure.%def.group.stratifier.all(
  $this.code ~ 
    (%resource.group.stratifier)[$index].code

)
and
%def.group.stratifier.component.all(
  $this.code ~ 
    (%resource.group.stratifier.stratum
       .component)[$index].code

)

What was really challenging in this was a limitation of FHIRPath.  FHIRPath provides the $this and $index variables to define the current position within the evaluated context.  It works very much like "." does within XPath expressions.  Unfortunately, FHIR has no way to assign $this or $index to a variable so that it can be used with the same values in subexpressions contained inside the initial expression.

Fortunately, [index: Integer] is defined as an operation, which means we can use [$index] to select the $indexth item of a collection, but figuring that out was a royal pain.

What seems to be needed in FHIRPath is a way to define a variable, e.g.: let that = $this (which would resolve to this), so that one could write some more complex correlation validations.


3 comments:

  1. Al Nahr Company provides you with all the services related to cleaning, pest control, pesticide spraying, and termite control, all at prices that suit you and with trained workers. For this do not hesitate and contact us as we provide you with protection from harmful insects, cleaning both related to mosques, homes, companies, hotels, restaurants, apartments, boards, and carpets
    شركة النهر خدمات عامة
    <a

    ReplyDelete
  2. I read your blog it is very good and you are doing a great job for helping others. I really appreciate what content you are giving to your viewers.
    All Best Blog

    ReplyDelete