This is a proof-of-concept Web service commissioned by NHS Digital Code4Health that exposes HL7 FHIR operations (read
, search
, conformance
) from a choice of openEHR CDRs (Ehrscape compliant e.g. Marand Think!Ehr or Ripple EtherCis) for a small range of INTEROpen Care-Connect profiles, using the HAPI FHIR stack.
./mvnw clean package
(inside the project folder)
Copy fhir-adaptor.jar
from target
folder to your server
java -jar fhir-adaptor.jar --spring.profiles.active=marand
(will run on port 8082)
java -jar fhir-adaptor.jar --spring.profiles.active=ethercis
(will run on port 8083)
TBD
read
(all)
search by NHS Number
conformance
read
(all)
search by NHS Number
conformance
The intent was to create an extensible framework to support the creation of a FHIR API for any openEHR CDR that supports the EHRscape API - This includes the Marand and etherCIS CDRs used by Code4Health, with other CDR providers likely to follow suit.
The API was built using HAPI-FHIR, an open-source implementation of the FHIR specification in Java. HAPI-FHIR simplifies the building of a FHIR API on any data source and its use simplifies conformance with the FHIR standard as it has already be tested in a number of implementations. It was originally intended to base the project on FHIR DSTU2, but during development it became clear that STU3 was becoming preferred for current INTEROpen Care-connect and GP-Connect profile curation. This curation work is well advanced but not yet stable, so it is ecpected that further revisions ot the mappings will be required as stable, published versions emerge.
The following FHIR Interactions are supported
Read
Search
Conformance
However, the framework will allow the addition of support for other FHIR API interactions should use cases emerge that require these.
In order to make use of the framework. It was necessary to ensure that the underlying openEHR archetypes support the data-points in the INTEROPen profiles and provide mappings between these.
Currently of the 16 profiles proposed by INTEROPen, most if not all of the data points they contain are supported by existing openEHR archetypes, but should additional archetypes be required these will be created and made available as open-source artefacts via the UK Apperta CKM repository.
The Apperta 5-Nation CKM group is currently reviewing the related openEHR templates as fit-for-purpose for UK + Ireland use, including alignment with Care-Connect profiles.
The scope of this project was therefore limited to the essential data points in the profiles stable enough to allow clinically useful mappings and for which clear Search specifications are available:
- IDCR - Adverse Reaction List.v1| Adverse reaction list
- IDCR - Medication Statement List.v1| Medication Statement list
- IDCR - Problem List.v1| Problem list
- IDCR - Procedure list .v1| Procedure list
- openEHR AdverseReactionRisk to FHIR allergyIntolerance STU3 mappings
- openEHR Medication Order (as MedicationStatement) to FHIR MedicationStatement STU3 mappings
- openEHR ProblemDiagnosis to FHIR condition STU3 mappings
- openEHR Procedure to FHIR Procedure STU3 mappings
The general approach has been to construct openEHR Archetype Language (AQL) statements to retrieve appropriate data from target openEHR templates. The mappings have been built in java, with considerable use made of generic mapping functions, facilitated by the close alignment of many openEHR and FHIR datatypes.
For more on AQL see:
or the examples given in the guidance documents.
select
e/ehr_id/value as ehrId,
e/ehr_status/subject/external_ref/id/value as subjectId,
e/ehr_status/subject/external_ref/namespace as subjectNamespace,
a/uid/value as compositionId,
a/composer/name as composerName,
a/composer/external_ref/id/value as composerIdentifier,
a/composer/external_ref/namespace as composerNamespace,
a/context/start_time/value as compositionStartTime,
b_a/uid/value as entryId,
b_a/data[at0001]/items[at0002]/value as Causative_agent,
b_a/data[at0001]/items[at0063]/value/defining_code/code_string as Status_code,
b_a/data[at0001]/items[at0101]/value/defining_code/code_string as Criticality_code,
b_a/data[at0001]/items[at0120]/value/defining_code/code_string as Category_code,
b_a/data[at0001]/items[at0117]/value/value as Onset_of_last_reaction,
b_a/data[at0001]/items[at0058]/value/defining_code/code_string as Reaction_mechanism_code,
b_a/data[at0001]/items[at0006]/value/value as Comment,
b_a/protocol[at0042]/items[at0062]/value/value as Adverse_reaction_risk_Last_updated,
b_a/data[at0001]/items[at0009]/items[at0010]/value as Specific_substance,
b_a/data[at0001]/items[at0009]/items[at0021]/value/defining_code/code_string as Certainty_code,
b_a/data[at0001]/items[at0009]/items[at0011]/value as Manifestation,
b_a/data[at0001]/items[at0009]/items[at0012]/value/value as Reaction_description,
b_a/data[at0001]/items[at0009]/items[at0027]/value/value as Onset_of_reaction,
b_a/data[at0001]/items[at0009]/items[at0089]/value/defining_code/code_string as Severity_code,
b_a/data[at0001]/items[at0009]/items[at0106]/value as Route_of_exposure,
b_a/data[at0001]/items[at0009]/items[at0032]/value/value as Adverse_reaction_risk_Comment
from EHR e
contains COMPOSITION a[openEHR-EHR-COMPOSITION.adverse_reaction_list.v1]
contains EVALUATION b_a[openEHR-EHR-EVALUATION.adverse_reaction_risk.v1]
where a/name/value='Adverse reaction list'
-- Optional parameters, depending on FHIR search criteria
and e/ehr_id/value = '{{fhir.patient.id_param}}'
and e/ehr_status/subject/external_ref/id/value = '{{fhir.patient.identifier.value.param}}'
and e/ehr_status/subject/external_ref/namespace = '{{fhir.patient.identifier.system.param}}'
and b_a/data[at0001]/items[at0120]/value/defining_code_string = '{{fhir_category_params}}'
and b_a/protocol[at0042]/items[at0062]/value/value >= '{{fhir_date_param_min}}'
and b_a/protocol[at0042]/items[at0062]/value/value <= '{{fhir_date_param_max}}'
- Multiple occurrences on codeableConcept not supported.
- Update mappings as INTEROPen curations are published.
- Update mappings as Apperta 5N-CKM reviews progress.
- Add further Profiles, Immunisation, Observation.
- Add further operations (write).
- Improve low-level datatype mapping.
- Improve and extend search criteria.
- Adapt to replace the Ehrscape API with formal openEHR REST API.