Tips and Tricks
Specifying Additional Resource Paths
Sometimes authors may wish to put predefined resources in folders other than the normally supported input
sub-folders. To support this, SUSHI now recognizes the ImplementationGuide parameter path-resource
. Authors can include this parameter in sushi-config.yaml
to specify relative paths to additional folders that contain predefined resources. For example, the following can now be used in sushi-config.yaml
to include resources from the sub-folder predefined-resources
:
parameters:
path-resource:
- input/predefined-resources
Note that the value of path-resource
is an array (or sequence) formatted in the standard YAML style.
For SUSHI users who manage their own ImplementationGuide resource (i.e. FSHOnly IGs), SUSHI will use the parameter from the ImplementationGuide resource:
"parameter": [
{
"code": "path-resource",
"value": "input/predefined-resource"
}
]
Support for contentReference Elements
Content references allow ElementDefinitions to refer to be defined in terms of other elements. A typical application of a content reference is to prevent infinite regress in elements such as Questionnaire.item.item
, whose the definition refers back to Questionnaire.item
via a content reference.
Content references are supported in AddElementRules
by way of the contentReference
keyword. This feature applies to Logical Models and custom Resources. To define an element of type contentReference
, include contentReference <url-to-referenced-element>
in the AddElementRule
where the type
would typically go. For example, the following AddElementRule
will create an element section.section
that is a contentReference to the element found at http://example.org/StructureDefinition/Report#Report.section
.
* section.section 0..1 contentReference http://example.org/StructureDefinition/Report#Report.section "A sub-section"
Inferred Choice Path
When assigning values to choice elements (e.g., value[x]) on an Instance, type-specific elements (e.g., valueBoolean) should always be used in assignment rules. However, if the choice element has been constrained to a single type, SUSHI will infer the correct type-specific element.
For example, SUSHI will infer the last line is to be interpreted as * valueBoolean = true
as the Instance
is exported. Authors are encouraged to not depend on this behavior, and use type-specific elements in instances.
Profile: BooleanObservation
Parent: Observation
* value[x] only boolean
Instance: MyObservation
InstanceOf: BooleanObservation
* status = #final
* code = http://example#somecode
* value[x] = true
Referencing the Canonical URL of the ImplementationGuide
There may be cases where an author needs to refer to the canonical URL of the ImplementationGuide resource they are creating. SUSHI now supports using the Canonical
keyword with the IG’s id
, packageId
, or name
that is specified in sushi-config.yaml
. For example, when creating a CapabilityStatement
, the following Assignment Rule can be added:
* implementationGuide = Canonical(my-package-id)
Extensions for Representing Elements From Other Versions of FHIR
The FHIR specification defines behavior for a feature they refer to as extensions for converting between versions (also known as “implied extensions”). This feature allows authors to represent specific elements from past and future versions of FHIR using a specific extension URL format (as described in the spec linked above). These extensions are not available in any physical package, but rather, are understood and processed conceptually.
To use this feature in SUSHI, authors must specify a dependency on a package using an id and version of the form hl7.fhir.extensions.<extension-version>: <package-version>
, where valid extension-versions are r2
, r3
, r4
, and r5
. As an example, if an author wanted to represent the Patient.animal.species
element as defined in STU3, the dependencies should be specified as:
dependencies:
hl7.fhir.extensions.r3: 4.0.1
An author can then reference the extension using a URL following the format defined in the FHIR specification linked above. For example, the extension referring to the R3 Patient.animal.species
element would be: http://hl7.org/fhir/3.0/StructureDefinition/extension-Patient.animal.species
.
See the following documentation for additional details:
- Dependencies from the FSH School SUSHI documentation
- Extensions for Converting Between Versions from the current FHIR specification
Extension for Profiling BackboneElements
The profile-element
extension can be used to profile a BackboneElement by pointing at another BackboneElement defined elsewhere. This is typically used to indicate that constraints on the target of a contentReference should be applied to all the references as well. For example, the following snippet indicates that all recursive references to Questionnaire.item
(e.g., Questionnaire.item.item
) should conform to the same constraints as the original Questionnaire.item
in this profile:
Profile: MyQuestionnaire
Parent: Questionnaire
* item ^type.profile = "http://example.org/StructureDefinition/MyQuestionnaire"
* item ^type.profile.extension.url = "http://hl7.org/fhir/StructureDefinition/elementdefinition-profile-element"
* item ^type.profile.extension.valueString = "Questionnaire.item"
// ...
See the following documentation for additional details:
- Extension: profile-element from the FHIR specification
- Clarification on contentReference discussion on Zulip
Instances of Logical Models
The IG Publisher supports including instances of logical models as binary resources. This feature was announced and discussed in a Logical Model Examples thread on chat.fhir.org.
Authors can use Instance:
to create instances of logical models and instances of logical model profiles in the same way as all other FSH instances. These instances are exported using standard JSON serialization and automatically receive id
and meta.profile
values when the logical model and SUSHI configuration support those elements. These instances have filenames starting with Binary-
and will be auto-encoded as part of the publishing process.
Alternatively, authors can provide their own instances of logical models without defining them in FSH. The basic steps an author needs to take in order to manually include logical model examples in a SUSHI project are:
- Add the example to the
input/resources
orinput/examples
folder- The file name of the example should be
Binary-{id}.json
orBinary-{id}.xml
(substituting{id}
for the real id)
- The file name of the example should be
- Add an entry for the example in the
sushi-config.yaml
resources
property- Specify a
name
- Specify
exampleCanonical
pointing to the canonical of your logical model - Add an extension w/ the proper resource format (
application/fhir+json
orapplication/xml
)
- Specify a
For example, given the following simple logical model definition in an IG w/ IG canonical root http://example.org
:
Logical: MyLM
Id: MyLM
Title: "My LM"
Description: "This is mine"
* id 1..1 SU id "Identifier for the logical model"
* important 1..1 SU boolean "Is this logical model important"
Create the file input/examples/Binary-my-logical-example.json
:
{
"resourceType": "http://example.org/StructureDefinition/MyLM",
"id": "my-logical-example",
"important": true
}
And add the following in your sushi-config.yaml
:
resources:
Binary/my-logical-example:
extension:
- url: http://hl7.org/fhir/tools/StructureDefinition/implementationguide-resource-format
valueCode: application/fhir+json
name: Example of LM
exampleCanonical: http://example.org/StructureDefinition/MyLM
Both approaches will result in your logical model example being listed and displayed as a proper example of the logical model.
If the logical model does not have resourceType
or id
, the same steps as above can be used with a few small adjustments:
- In step 1, the file name of the example can be any valid file name (e.g.
hook-example.json
) - In step 2, the key in the resources list should be
Binary/{filename}
, where{filename}
matches the the file name of the example without the file extension (e.g.Binary/hook-example
)
Manual Slice Ordering
Authors can exercise full manual control over the ordering of slice elements within Instances. Previous versions of SUSHI allowed for partial control of slice element ordering, but some ordering was determined by SUSHI’s implementation and could not be affected by an author. In the current version of SUSHI (v3.0.0
or later), authors can configure their FSH projects to manually control slice ordering. When using manual slice ordering, authors should use soft indexing and avoid using hard numeric indices.
Manual slice ordering follows the following rules:
- slices appear on an Instance in the order of FSH rules
- any required slices (
1..*
) that are not referenced in a FSH rule on the Instance appear after all referenced slices in the order in which they are defined on the Instance’s StructureDefinition (the instance’sInstanceOf
) - a rule that references a sliced element should reference it using the slice name
- to reference multiple items in a slice, use hard or soft indices after the slice name (e.g.,
component[myslice][0]
) - when rule paths use only a soft index (instead of a slice name), the resolved numeric index will take into account named slices that have already been referenced by previous rule paths. This should only be used to add items that do not belong to a defined slice.
- Note: when manual slice ordering is enabled, it is not possible to refer to an element with a slice name by soft numeric index only. If hard numeric indices are used (not recommended), they may still directly access previously referenced named slices. This may lead to undesired output.
To use this ordering, add the following to sushi-config.yaml
:
instanceOptions:
manualSliceOrdering: true
Examples
Profile: ExampleBPObservation
Parent: Observation
// slicing rules for component omitted for brevity
* component contains systolicBP 1..1 MS and diastolicBP 1..1 MS
When using this profile without manual slice ordering, the systolicBP
slice will always be the first entry in the component
element, and the diastolicBP
slice will always be the second entry in the component
element. So, the following two instances would have the same component
elements:
Instance: ExampleByName
InstanceOf: ExampleBPObservation
// some required elements omitted for brevity
* component[systolicBP].valueQuantity = 108 'mm[Hg]'
* component[diastolicBP].valueQuantity = 45 'mm[Hg]'
Instance: ExampleByNumber
InstanceOf: ExampleBPObservation
// some required elements omitted for brevity
* component[0].valueQuantity = 108 'mm[Hg]'
* component[1].valueQuantity = 45 'mm[Hg]'
When manual slice ordering is enabled, rules that set values on the systolicBP
or diastolicBP
slices must use the slice name. With this option enabled, the ExampleByName
instance would produce the same entries in component
, but the ExampleByNumber
instance would contain four entries in the component
list: two entries that are not part of a named slice, followed by the systolicBP
slice, and finally the diastolicBP
slice.
When manual slice ordering is enabled, if any required slices with required assigned values are not present in an instance’s list of rules, they will be added in the order in which they are defined. If you want these slices to appear in a different order on the instance without adding any new information to the slices, add rules on the instance that reassign the existing values:
Alias: $ObservationCategoryCodes = http://terminology.hl7.org/CodeSystem/observation-category
Profile: ExampleObservation
Parent: Observation
// slicing rules for category omitted for brevity
* category contains CategoryA 1..1 and CategoryB 1..1
* category[CategoryA] = $ObservationCategoryCodes#vital-signs
* category[CategoryB] = $ObservationCategoryCodes#survey
Instance: ReorderedExample
InstanceOf: ExampleObservation
// some required elements omitted for brevity
* category[CategoryB] = $ObservationCategoryCodes#survey
* category[CategoryA] = $ObservationCategoryCodes#vital-signs
This instance’s category
element will have the survey
code as the first entry and the vital-signs
code as the second entry.
Soft index resolution will account for named slices that have been referenced in previous rules:
Instance: SoftIndexExample
InstanceOf: ExampleObservation
// some required elements omitted for brevity
* category[+] = $ObservationCategoryCodes#laboratory // this + will resolve to index 0
* category[CategoryB] = $ObservationCategoryCodes#survey
* category[+] = $ObservationCategoryCodes#exam // this + will resolve to index 2, since the CategoryB slice occupies index 1
* category[CategoryA] = $ObservationCategoryCodes#vital-signs
This instance’s category
element will have four entries in the order specified: laboratory
, survey
, exam
, vital-signs
.
Link References
SUSHI creates the fsh-generated/includes/fsh-link-references.md file to make it easier to create links to resource definitions in other markdown pages. This file’s contents are a list of markdown link definitions, with one link for each resource in your ImplementationGuide.json file. This will include resources defined in FSH, the resources
configuration property, and predefined resources. For example:
[MyPatient]: StructureDefinition-MyPatient.html
[MyExtension]: StructureDefinition-MyExtension.html
The rules for determining what the link text will be for a given resource are as follows:
- For resources defined in FSH:
- Non-instance resources use the name of the resource.
- Instances use the id of the resource.
- For predefined resources:
- Resources in the
input/examples
folder use the id of the resource. - Resources in other sub-folders of
input
attempt to use the name of the resource if this is a string value, and otherwise use the id of the resource.
- Resources in the
- For resources that are manually configured in
sushi-config.yaml
:- The name of the resource is used, if available.
- Otherwise, the id of the resource is used.
To use these generated links, include fsh-generated-links.md
in your custom markdown pages. This can be done by including the following line at the bottom of your custom markdown page:
{% include fsh-link-references.md %}
Then, you can create links by including the resource’s link text within square brackets. For example, if you had a Profile named MyPatient
, your custom markdown file could look like this:
## Patients
This IG provides [MyPatient] for patient information.
{% include fsh-link-references.md %}
Choosing a SNOMED CT edition
To specify a certain edition of SNOMED CT - for example to ensure terminology validation works correctly - do the following:
- Add or modify the
parameters
section in yoursushi-config.yaml
to specify apath-expansion-params
parameter.
parameters:
path-expansion-params: Parameters-expansion.json
- Create an
input/fsh/expansion.fsh
file and define an instance ofParameters
with the idexpansion
. Within the Parameters instance, specify asystem-version
parameter. For example, if you’d like to use the US edition of SNOMED, add this definition:
Instance: expansion
InstanceOf: Parameters
Description: "SNOMED CT expansion parameter"
Usage: #definition
* parameter[+].name = "system-version"
* parameter[=].valueCanonical = "http://snomed.info/sct|http://snomed.info/sct/731000124108"
If you’d like to use another language, such as Swedish, choose this:
Instance: expansion
InstanceOf: Parameters
Description: "SNOMED CT Swedish expansion parameter"
Usage: #definition
* parameter[+].name = "displayLanguage"
* parameter[=].valueCode = urn:ietf:bcp:47#se
* parameter[+].name = "system-version"
* parameter[=].valueCanonical = "http://snomed.info/sct|http://snomed.info/sct/45991000052106"
Note: The system-version
and displayLanguage
parameters correspond to the parameters of the same name in FHIR’s $expand operation.