These are Swift classes representing data models of 🔥 FHIR elements and resources, compatible with iOS 8 and OS X 10.9 and later.
This work is Apache licensed. FHIR® is the registered trademark of HL7 and is used with the permission of HL7.
Due to the complications of combining two volatile technologies, here's an overview of which version numbers use which Swift and FHIR versions.
- The
master
branch should always compile and is on (point releases of) these main versions. - The
develop
branch should be on versions corresponding to the latest freezes. - The
feature/latest-ci
branch is updated from time to time with the latest and greatest.
See tags/releases.
Version | Swift | FHIR | |
---|---|---|---|
3.0 | 3.0 | 3.0.0.11832 |
STU 3 |
2.10 | 3.0 | 1.8.0.10521 |
STU 3 Freeze, Jan 2017 |
2.9 | 3.0 | 1.6.0.9663 |
STU 3 Ballot, Sep 2016 |
2.8 | 3.0 | 1.0.2.7202 |
DSTU 2 (+ technical errata) |
2.4 | 2.2 | 1.6.0.9663 |
STU 3 Ballot, Sept 2016 |
2.3 | 2.3 | 1.0.2.7202 |
DSTU 2 (+ technical errata) |
2.2.3 | 2.2 | 1.0.2.7202 |
DSTU 2 (+ technical errata) |
2.2 | 2.0-2.2 | 1.0.2.7202 |
DSTU 2 (+ technical errata) |
2.1 | 2.0-2.2 | 1.0.1.7108 |
DSTU 2 |
2.0 | 2.0-2.2 | 0.5.0.5149 |
DSTU 2 Ballot, May 2015 |
1.0 | 1.2 | 0.5.0.5149 |
DSTU 2 Ballot, May 2015 |
0.2 | 1.1 | 0.5.0.5149 |
DSTU 2 Ballot, May 2015 |
0.1 | 1.0 | 0.0.81.2382 |
DSTU 1 |
The Swift-SMART framework utilizes these classes.
- Programming Guide with code examples
- Technical Documentation of classes, properties and methods
- Medication List sample app
Here's a rough list of what still needs to be done.
[ ] Remove _isSummaryResource workaround to STU-3's nMin/isSummary errors
[ ] More convenience methods to working with resources in code
[ ] Nice support for simple PATCH operations
[ ] Separate resource models from base models; needs untangling of
_owningResource, _owningBundle (easy), _resolved etc.
[ ] Handle resource versions nicely
[ ] Create a default behavior when a modifierExtension is detected
[ ] Update/modernize FHIRSearch
[ ] Search: report search parameters that the server ignored
Working, at least to some extent:
- Classes generated for FHIR's base resources
- Use custom structs for primitive types
- Use custom Date/Time/DateTime/Instant structs
- Generate enums for many closed ValueSets
- Create elements and resources programmatically
- Use a FHIR server protocol for REST interactions with a server
- Deserialize from JSON
- Tells you which mandatory properties were missing,
- which properties were not expected or
- which were of a wrong type
- Serialize to JSON
- Refuses to serialize incomplete elements
- Resolve contained/bundled/relative/absolute resource references
- Contain resources
- Create enums for
code
type properties - Construct searches with NoSQL-like statements (cf. fhir.js)
- Perform operations
- Use example resources for auto-created class unit tests
- Tests deserialization from file
- Tests serialization from deserialized instances
Standard Swift naming conventions apply.
Tabs are used for indentation and spaces for alignment – the best of both worlds.
Classes representing FHIR resources do not have a prefix.
Custom classes and protocols start with FHIR
to not make them clash with element or resource classes and make them easily distinguishable.
Classes are generated from FHIR resource definitions with our Python FHIR parser.
Swift is statically typed and introspection is very limited at the time. Therefore the generator needs to be a bit more verbose and create class-level serializers/deserializers, rather than looking at class properties at runtime and figure out how to serialize/deserialize.
Some data models have properties with a cardinality of a minimum of 1. While these can be enforced to never be nil in Swift by not making them Optionals, they are still optional to enable uniform initializers that only take a JSON dictionary. For classes representing models with non-optional properties, a convenience initializer is supplied to reflect the need to set those properties without enforcing it.
FHIR makes use of contained resources.
An extension on the Reference
class is included that adds method to handle reference resolving.
To resolve resource references, call resolve(ModelClass) { resource in }
on a reference property, which will return an instance of the referenced type in the callback if resolved successfully.
To contain a resource and receive a Reference
instance, call parent.containResource(contained)
// create a prescription with a contained medication
let order = MedicationRequest()
let medication = Medication()
medication.id = "med"
do {
order.medicationReference = try order.containResource(medication)
}
catch let error {
// failed to contain, either because no id or containing itself
}
// resolve the contained medication
order.medication?.resolve(Medication.self) { medication in
if let medication = medication {
// successfully resolved
}
}
The client supports the NoSQL-like approach proposed and used by fhir.js.
Search can be restricted to compartments, these however are not yet supported in the SMART server nor in these classes.
[ ] Patient/23/procedure?date=>2010-01-01&date=<2011-12-31
If search is restricted to a reference property, this applies:
- If the search token is merely an id, i.e. it does not contain a forward slash, a type restricted search is constructed based on which instance method is called:
GET {base-url}/Thing?referenced:InstanceType={id}
- If the search token does contain a forward slash it is assumed to be an absolute reference and no
:InstanceType
will be appended:
GET {base-url}/Thing?referenced={uri}
The full build of the framework will include all FHIR resources, which will result in a rather large binary.
Take a look at the package.py
script: provide one or more resource names when invoking the script from command line and it will output all the elements and resources that are needed for the desired resources.
You may then be able to remove unnecessary resources, which unfortunately is a tedious task and requires fumbling with the factory.
There is an experimental SwiftFHIRMin-iOS
build target which only includes a minimal set of resources.
The problem here is that the factory is excluded and hence dereferencing, bundles and contained resources won't be properly instantiated.