Using CQL with FHIR
2.0.0-ballot - STU2Ballot International flag

Using CQL with FHIR, published by HL7 International / Clinical Decision Support. This guide is not an authorized publication; it is the continuous build for version 2.0.0-ballot built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/HL7/cql-ig/ and changes regularly. See the Directory of published versions

Using ModelInfo

This topic specifies conformance requirements for the use of Model Information as part of FHIR Knowledge Artifacts that make use of Clinical Quality Language (CQL).

ModelInfo

To use CQL with FHIR, model information (ModelInfo) must be provided to the implementation environment. To create this ModelInfo FHIR StructureDefinition resources can be processed according to the following rules:

  1. For each StructureDefinition, if the kind is primitive-type, complex-type (except for types based on Extension), or resource (with no derivation or a derivation of specialization), a ClassInfo with the same name as the structure definition is created
    1. For each element:
      1. If the element is not a backbone element, a corresponding element with the name and type is added to the ClassInfo. If the maximum cardinality of the element is not "1", the element is created as a list type.
      2. If the element is a backbone element, a new ClassInfo is created with the child elements of the backbone element and a new element is added to the containing ClassInfo with the type of the ClassInfo. Note that this process is recursive and so may result in multiple levels of nested class creation. As such the name of the ClassInfo must include the name of all the parent classes as qualifiers in order to ensure uniqueness. This approach also supports the ability of FHIR elements to reference other element definitions, though a post-processing fixup step is typically needed to resolve these references.

If this process is run against the StructureDefinitions from the base FHIR specification, it produces a complete representation of all the FHIR Resources as classes in the ModelInfo. However, because FHIR primitive types actually have elements (e.g. value, id, and extension), this process produces classes in the ModelInfo for each of the FHIR primitive types, and only the value elements of these FHIR primitives are typed with the actual CQL primitive types. This means that to access the actual values of FHIR elements for comparison against CQL primitive values, the .value path must be used:

Patient.gender.value = 'female'

To facilitate comparison by authors, these primitives can be implicitly converted to CQL primitive types, and the FHIRHelpers library (generated alongside the ModelInfo) defines these implicit conversions. See the CQF Common implementation guide for a complete FHIR ModelInfo as well as FHIRHelpers library representing the FHIR specification.

To make use of these implicit conversions within a CQL library, include the FHIRHelpers library:

include FHIRHelpers version '4.0.1'

ModelInfo Libraries

Similar to CQL content, ModelInfo can be included in FHIR Library resources to facilitate distribution.

Conformance Requirement 6.1 (ModelInfo Libraries):

  1. Libraries used to package ModelInfo SHALL conform to the CQLModelInfo profile
  2. The identifying elements of a modelinfo SHALL conform to the following requirements:
    • Library.url SHALL be <CQL model namespace url>/Library/<CQL model name>-ModelInfo
    • Library.name SHALL be <CQL model name>
    • Library.version SHALL be <CQL model version>
  3. For model info libraries included in FHIR implementation guides, the CQL model namespace is defined by the implementation guide as follows:
    • CQL model namespace name SHALL be IG.packageId
    • CQL model namespace url SHALL be IG.canonicalBase
  4. To avoid issues with characters between web ids and names, CQL model names SHALL NOT have underscores.

The prohibition against underscores in CQL model names is required to ensure compliance with the canonical URL pattern (because URLs by convention should not use underscores). In addition, many publishing environments will use the canonical tail (i.e. the name of the library) as the logical id of the Library resource, which does not allow underscores per the FHIR specification.

Profile-informed ModelInfo

CQL can be used with a FHIR ModelInfo directly, as described above. However, FHIR profiles include a wealth of computable information about the intended structure of the clinical data involved in an exchange, including terminology bindings, constraints, descriptive metadata, slices and extensions. To facilitate authoring that can easily reference this information, the tooling to construct ModelInfo from the base FHIR StructureDefinitions has been enhanced to support building ModelInfo that is specific to an implementation guide:

  1. Each profile (StructureDefinition with derivation set to constraint) results in a new ClassInfo in the ModelInfo, derived from the ClassInfo for the baseDefinition of the profile
    1. namespace is set to the modelName
    2. name is set to the name element of the StructureDefinition
    3. baseType is set to the qualified name of the class corresponding to the baseDefinition
    4. identifier is set to the canonical url of the StructureDefinition
    5. label is set to the title of the StructureDefinition (unless overridden by the cqf-modelInfo-label extension)
    6. retrievable is set to true (unless overridden by the cqf-modelInfo-isRetrievable extension)
    7. primaryCodePath is set based on the cqf-modelInfo-primaryCodePath extenssion
  2. FHIR Primitive types are mapped to CQL types according to the above FHIR Type Mapping section.
  3. Extensions and slices defined in profiles are represented as first-class elements in the ClassInfo. Specifically, ClassInfo structures are created with elements as defined by the slice or extension definitions.
    1. For slices, a new ClassInfo is created derived from the ClassInfo corresponding to the element being sliced, and named based on the sliceName element of the slice definition. An element of this type and named with the sliceName is then added to the containing ClassInfo.
    2. For extensions, a new ClassInfo is created derived from the Extension ClassInfo and named based on the name of the extension definition. An element of this type and named with the extension sliceName is then added to the containing ClassInfo.
  4. If a terminology-valued element has a cqf-notDoneValueSet extension defined, the element is typed as a Choice of the terminology-value (CodeableConcept, Coding, or Code) and ValueSet, allowing retrieves to be performed against the ValueSet referenced by the cqf-notDoneValueSet extension

For example, consider the US Core Blood Pressure Profile. This profile has two slices of the component element, named systolic and diastolic. The resulting USCore ModelInfo has classes derived from the USCore.Observation.Component class:

  <typeInfo xsi:type="ClassInfo" namespace="USCore" name="Observation.Component.systolic" retrievable="false" baseType="USCore.Observation.Component"/>
  <typeInfo xsi:type="ClassInfo" namespace="USCore" name="Observation.Component.diastolic" retrievable="false" baseType="USCore.Observation.Component"/>

and then elements in the USCore.BloodPressureProfile class corresponding to these slices:

  <element name="systolic" elementType="USCore.Observation.Component.systolic"/>
  <element name="diastolic" elementType="USCore.Observation.Component.diastolic"/>

For extensions, consider the US Core Ethnicity Extension. This is a complex extension, and so the constructed ClassInfo has elements for each of the elements defined by the extension:

  <typeInfo xsi:type="ClassInfo" namespace="USCore" name="EthnicityExtension" identifier="http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity" label="US Core Ethnicity Extension" retrievable="false" baseType="USCore.Extension">
      <element name="ombCategory" elementType="System.Code"/>
      <element name="detailed">
          <elementTypeSpecifier xsi:type="ListTypeSpecifier" elementType="System.Code"/>
      </element>
      <element name="text" elementType="System.String"/>
      <element name="url" elementType="System.String"/>
  </typeInfo>

And the USCore.PatientProfile class then has an element named ethnicity of this type:

  <element name="ethnicity" elementType="USCore.EthnicityExtension"/>

NOTE: Importantly, with profile-informed modelinfo, each element in the modelinfo includes a target mapping that specifies an expansion to be performed by the translator so that access in the ELM is performed directly against the base FHIR resources, rather than requiring engines (and by extension runtime environments) to deal with data in terms of the profile definitions. As a result, the ELM output of CQL libraries using profile-informed authoring is in terms of the base FHIR resources. Note that for implementations that support profile-informed CQL, this means that the result of retrieve expressions must respect the profile stated in the templateId element of the retrieve. This is not to say that the FHIR resource must declare profiles to which they conform, only that with profile-informed authoring, there is an expectation that the ELM expects that FHIR resources returned through a retrieve will conform to the stated profiles. How that conformance is guaranteed is left up to implementations.

ModelInfo Settings

In addition, to support more fine-grained control over the process of producing ModelInfo from FHIR StructureDefinitions, this implementation guide defines several ModelInfo-related extensions:

  • cqf-modelInfo-isIncluded - Determines whether to create a ClassInfo for the profile or extension on which it appears
  • cqf-modelInfo-isRetrievable - Determines whether the ClassInfo for the profile on which it appears is marked retrievable (i.e. can appear as the target type of a Retrieve in CQL)
  • cqf-modelInfo-label - Specifies an author-friendly title for the ClassInfo (i.e. an alternate name by which the type can be referenced in CQL type specifiers)
  • cqf-modelInfo-primaryCodePath - Specifies the primary code path for the ClassInfo produced from the profile on which it appears (i.e. the default path for terminology-valued filters when the type is used in a Retrieve in CQL)
  • cqf-modelInfoSettings - Specifies additional settings used to produce the ModelInfo for profiles and extensions defined in the Implementation Guide on which it appears