ShEx EXTENDS For a Clincal Use Case

Following is a description of the use of EXTENDS for a clinical use case. It develops a shape hierarchy from <#Observation>, the most widely-used shape in any clinical informatics system. This use case shows how ShEx treates diamond inheritance.

Here, a <#PostureVital> extends a <#Vital>, which extends an <#Observation>. A <#ReclineVital> is a <#PostureVital> with a "reclined" posture. A <#BP> (blood pressure) and a <#Pulse> have posture and reclined posture flavors.

The left panel, EXTENDS, captures this using a proposed syntax for extends. The right panel, compiled-ish, attempts to capture this using ShEx 2.0 triple expression labels (e.g. $<#BP-TE>) injected into the appropriate shapes. This introduces a burden as the maintainer must:

The semantics of EXTENDS cater to extending schemas outside of one's administrative control. For instance, someone extending a posture shape to create a reclined shape may be importing the posture shape from another schema and have no way to add disjuncts into the closures or triple expression labels into shapes.

EXTENDS

PREFIX fhir: <http://hl7.org/ns/fhir>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

<#Observation> {
  fhir:code .? ;
  fhir:component {
    fhir:code . ;
    fhir:value .
  }*
}


# -- super-classes --
ABSTRACT <#Vital>
      EXTENDS @<#Observation> {}

ABSTRACT <#PostureVital>
      EXTENDS @<#Vital> EXTENDS @<#Posture> {}

ABSTRACT <#ReclinedVital>
      EXTENDS @<#PostureVital> {}
  AND EXTENDS @<#Reclined> {}


# -- BP --
<#BP> EXTENDS @<#Vital> {} AND {

  fhir:component { fhir:code ["systolic"] } ;
  fhir:component { fhir:code ["diastolic"] }

}

<#PostureBP>
      EXTENDS @<#BP> EXTENDS @<#PostureVital> { }



<#ReclinedBP>
      EXTENDS @<#BP> EXTENDS @<#ReclinedVital> { }




# -- Pulse --
<#Pulse> EXTENDS @<#Vital> {} AND {

  fhir:code ["pulse"]
}

<#PosturePulse>
      EXTENDS @<#Pulse> EXTENDS @<#PostureVital> { }



<#ReclinedPulse>
      EXTENDS @<#Pulse> EXTENDS @<#ReclinedVital> { }




# -- postures --
<#Posture> {

  fhir:component {
    fhir:code ["posture"]
  }
}

<#Reclined> @<#Posture> AND {

  fhir:component {
    fhir:code ["posture"] ;
    fhir:value ["reclined"]
  }
}

compiled-ish

PREFIX fhir: <http://hl7.org/ns/fhir>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>

<#Observation> {
  fhir:code .? ;
  fhir:component {
    fhir:code . ;
    fhir:value .
  }*
}


# -- super-classes --
<#Vital>
     @<#ReclinedBP> OR @<#PostureBP> OR @<#BP>
  OR @<#ReclinedPulse> OR @<#PosturePulse> OR @<#Pulse>
<#PostureVital>
     @<#ReclinedBP> OR @<#PostureBP>
  OR @<#ReclinedPulse> OR @<#PosturePulse>
<#ReclinedVital>
     @<#ReclinedBP>
  OR @<#ReclinedPulse>


# -- BP --
<#BP> @<#Observation> AND EXTRA fhir:component {
  $<#BP-TE> (
    fhir:component { fhir:code ["systolic"] } ;
    fhir:component { fhir:code ["diastolic"] }
  )
}

<#PostureBP> @<#Observation> AND {
 &<#BP-TE> ;
 &<#Posture-TE>
}

<#ReclinedBP> @<#Observation> AND {
 &<#BP-TE> ;
 &<#Reclined-TE>
}


# -- Pulse --
<#Pulse> @<#Observation> AND {
  $<#Pulse-TE>
    fhir:code ["pulse"]
}

<#PosturePulse> @<#Observation> AND {
 &<#Pulse-TE> ;
 &<#Posture-TE>
}

<#ReclinedPulse> @<#Observation> AND {
 &<#Pulse-TE> ;
 &<#Reclined-TE>
}


# -- postures --
<#Posture> EXTRA fhir:component {
  $<#Posture-TE>
    fhir:component {
      fhir:code ["posture"]
    }
}

<#Reclined> @<#Posture> AND EXTRA fhir:component {
  $<#Reclined-TE>
    fhir:component {
      fhir:code ["posture"] ;
      fhir:value ["reclined"]
    }
}