Creating (and finding) FHIR Extension definitions
November 4, 2015 2 Comments
We’ve talked on quite a few occasions about profiling in FHIR, and creating extensions when we need to represent elements that aren’t in the core resources. At Orion Health, we’re putting a fair amount of effort into FHIR (as are all forward looking vendors in this space) so we needed a way to more easily manage the extensions we need to create. Forge is an option – but our extensions are quite simple. clinFHIR has always been able to create extensions, but the process is klunky and we needed a better way. So I’ve added an ‘Extension Editor’ to make this a bit easier.
I do need to point out that the capabilities of clinFHIR are limited compared to the official tool Forge from Furore – it manages only a subset of the capabilities FHIR offers and will only edit Extensions that were originally authored through the tool.
First, a bit of background.
Broadly, there are 2 aspects to ‘profiling’ resources in FHIR (we’re just talking about altering resources at the moment – profiling is a large topic).
- Creating extensions, which is used to add new properties to resources. As we’ve discussed before, this process is a fundamental part of FHIR – there is no stigma to using extensions, and they have the same capabilities as ‘native’ elements. Our belief is that most real implementations will use them.
- Constraining resources, which is where we take the core resource and alter the defined elements. Possibilities include:
- Mark some as required and other as not used (within some limits)
- ‘Slicing’ to refine elements supporting multiple values
- Change the terminology binding of coded elements
- Prescribe systems for Identifiers
Both of these are performed using the StructureDefinition resource. For example, we might define an extension for ‘Eye Colour’ to be represented as a string and used in a Patient resource. (We could alternatively use a CodeableConcept as the datatype, which might be a better choice if we wanted to report on the prevalence of eye colour within a population, but I digress…)
Given that another fundamental part of FHIR is discoverability – where a resource instance with an extension must refer to its definition (ie the StructureDefinition resource), it begs the question of where to store these definition in a way that they can be found by any recipient – and in a way that is Internet Scalable.
There are 2 parts to this.
First, all StructureDefinitions (SD) have a globally unique ‘url’ property. Strictly this is a URI, though the spec recommends that it should be ‘resolvable’ – eg entering it into a web browser should download the StructureDefinition. However, this is not required – it only has to be globally unique. There are different ways to create this url – for example an organization could manually assign it based on a web domain it controls – for example www.clinfhir.com/StructureDefinition/myExtension – or it could let the server hosting it create it. It is even possible that the SD is stored as a file in, say, gitHub and referenced from there.
If the url doesn’t HAVE to be resolvable, it follows that there must be some way of storing it somewhere, and searching for it based on its unique url. This is the role of a registry – a FHIR server that is focused on storing and returning SD’s based on the url. Pretty much any FHIR server can do this, but it makes sense that there are some ‘well known’ registries for this purpose – such as the ‘simplifier’ registry hosted by Furore on behalf of HL7 and accessible at http://foundry.furore.com/. Using such registries means that a client has a place to go to find SD’s that won’t resolve – or just using it as a matter of course. We can refer to this registry as a Conformance Server – as it stores conformance resources , of which there are a half dozen or so (see the list in the spec)
It’s very much up to the community as to how this all works out in practice – as a ‘platform’ spec FHIR doesn’t dictates how an implementation should work – it just establishes the ground rules.
So, with that background, let’s see how to use clinFHIR to create and manage Extensions (or more correctly the StructureDefinitions that define extensions). For clarity we will refer to them as ‘Definitions’ – but they are really just StructureDefinition resources.
First, navigate to clinFHIR (http://clinfhir.com/) and select the Extensions Editor from the list of components on the left. This will open the editor in a separate window. Here’s what it looks like (I really need to create some better extension definitions for the front window!)
The app automatically loads all of the definitions that clinFHIR has created and generates a list from which you can select one to view and potentially edit. To do so, it needs to connect to a registry (Conformance server) as described above. You can configure this server using the ‘Show Servers’ link on the top right – Grahames server tends to have the most up to date list, but HAPI and Furore also have a good selection. (Eventually simplifier will be the default – but the REST interface isn’t quite ready)
The tool can show any definition on the server (though not necessarily all the details of that definition at the moment). To do this you can search the server using criteria at the top left of the screen. Search options include:
- Publisher – all definitions where the publisher field contains the search string.
- Name – all definitions where the name field contains the search string.
- Description – all definitions where the description field contains the search string.
- Identifier – if you add an identifier to the SD then you can use this option to search on them. This is a handy way to further group SD’s – say all of those created by a specific team within an organization – or any other purpose for that matter.
- Resource – this displays a list of resource types. Select one of them and clinFHIR will display all the extensions that are designed to work with that resource type. The ‘*’ option displays those extensions that work with any resource type.
(click the magnifying lens icon to perform the search).
Here’s a query of all definitions that apply to the Observation resource, with the ‘AllelicState’ definition selected. Note that the right hand side shows some of the details of the definition (and an option to view the json representation of the complete resource). These include:
- The URL. This is the unique uri for the definition as described above.
- The Status. This can be draft, active & retired. For definitions authored though clinFHIR this can be altered using the edit extension screen – described below.
- The Name and Description of the definition. (Note how thorough the Genomics folk are!)
- The context type – or where the extension can be applied. Mostly you’ll apply an extension to a resource or resource element, but it’s also possible to create an extension definition for a datatype as well (eg a HumanName datatype may have extensions needed for non-english countries)
- The specific context of use. This is related to the context type, but assuming that this is a resource, then the context is the actual resource type where this extension should be used. There can be multiple types and also path’s within the resource. For an example of the latter, search for definitions on Patient, then the ‘Time of Day of Birth’. The context here is Patient.birthDate – indicating that the extension is specific to the date of birth.
- DataType of the extension. Clocking the ‘eye’ icon will display the datatype definition in the spec. If the datatype is coded, and there is a Binding defined then the Binding strength and URL of the ValueSet is displayed, and another eye icon to explore the ValueSet appears.
- Publisher – a string
- Whether multiple instances of this extension can appear in a single resource instance.
Other items that may appear if defined are
- Identifier, if one has been defined
- Contacts
At the bottom of the screen is an edit button. Clicking this will bring up a modal that displays the existing data – and if authored by clinFHIR, allows changes to be made. (Definitions from other tools are read only, as the capabilities of the clinFHIR editor is fairly basic at present).
The form is self-explanatory – when used in this ‘edit’ mode, the name cannot be changed as it is used by the tool to generate the unique url.
To create a new definition, click the ‘New Extension’ button at the top right. This displays the same modal window, but this time the name field can (and should) be edited. Enter a name for the definition (and note how both the server and the Url update). ClinFHIR creates the url for you based on the server location and the name. When you’ve finished entering the name, move out of the field and clinFHIR will check that the url is unique. If it is not then you’ll get a warning – you can choose to overwrite the definition if you wish – but you should be sure that is what you want to do.
So what’s happening under the hood? (Warning: techie stuff ahead!)
Well, when defining resources, FHIR describes a hierarchy of ‘entities’ that ‘inherit’ from a Base entity (very similar in concept to Object Orientated programming). The nature of the change to entities as you move ‘down’ the tree is described by the StructureDefintion resource.
So start with the base Resource entity (like the Object in OO). This has an Id, some metadata and a couple of other elements. A DomainResource extends Resource to add elements like text, a holder for contained resources and extensions. Then a ‘business’ resource – like Condition – extends DomainResource and adds the elements specific to that resource. Each of these entities is described by a StructureDefinition which has (amongst other elements) the base (that it is refining), a differential list (which represents the changes from the base – used for tooling) and a snapshot (which is a list of all the elements in that particular entity).
You can see this quite nicely in the spec as well – start with a Condition and click on the DomainResource type. You can continue to move ‘up’ the hierarchy in this way.
So what we’re doing when we create an Extension definition is altering the Extension resource – our definition will be an ExtensionDefinition that has a base that is the Extension object, and uses the snapshot & differential elements to record the specific changes we are making. ClinFhir keeps it simple – the extensions always have a base of Extension (And you can see the resource that is created by clicking on the Json tab in the detail window), but more complex tools such as forge and the specification tooling allow the hierarchy to continue to be extended.
That’s a really high level description of what’s happening – refer to the specification for more details – or read the Furore blog for various in-depth articles.
In this post we’ve confined our discussion on how to use the StructureDefinition to create extension definitions. You also use the StructureDefinition to constrain a resource – and to link the constrained resource to extensions definitions. Another post perhaps…
I should also emphasize that ‘best practice’ is to search for existing definitions before creating a new one – as that increases the chances that a recipient will understand it. Ideally too, an extension can be used in multiple resources (assuming that makes sense). Tooling to do this kind of searching is very much a work in progress – this tool is one option, and the furore registry is another. It is very likely that the two will converge over time.
Some limitations:
- Currently the tool only works with ‘simple’ extension definitions. It’s possible to define inherited extensions and extensions that are nested within other ones. Support for this will follow. (If you do select on of these more complex extensions, the Json tab will display the StructureDefinition, but the Details tab and modal window will be incomplete, and editing disabled.
Great stuff, David! Do you see a need to have a ‘scope’ property to differentiate extensions that might be globally applicable (e.g. a clinical property) with those only applicable to a certain jurisdiction (e.g. the NZ NHI Number)?
Although the url property (of the SD resource) is of data type uri, the description of this property in the DSTU2 spec does say “Absolute URL used to reference this StructureDefinition”. I appreciate that this is not a mandatory requirement, but I’d like to understand more about use cases when it would be appropriate to place a URI in this property.
BTW…”If the url doesn’t HAVE to be resolvable, it follows that there must be some way of storing it somewhere, and searching for it based on its unique url.” Shouldn’t this read ‘unique URI’ ?
Pingback: Slicing extensions with FHIR | Hay on FHIR