-
Notifications
You must be signed in to change notification settings - Fork 20
3. Add new mapping
After seting up and running the FHIR-Bridge (as explained here) a mapping can be added by following the steps explained beyond. All steps are explained following the example of implementing a mapping for body temperature.
Each change to the FHIR bridge should have a ticket created, explaining the change. Create a new feature branch with
ticket number like: feature/123_mapping_body_temperature
, where 123
stands for the issue number
# optional: make a new checkout
#git clone https://github.com/ehrbase/fhir-bridge.git
git clone [email protected]:ehrbase/fhir-bridge.git
# default:
cd fhir-bridge
git checkout -b feature/123_mapping_body_temperature
# At the first push:
git push -u origin feature/123_mapping_body_temperature
# For later pushes:
git push
# start docker, if it is not already running (analog to readme)
cd fhir-bridge/docker
docker-compose -f docker-compose-light.yml up
# build everything initially
cd fhir-bridge # bzw. 'cd ..' , wenn der vorherige Befehl ausgeführt wurde
mvn clean install
- visit http://88.198.146.13/ckm/projects/1246.152.26/resourcecentre
- download the
Körpertemperatur.opt
by clicking on it - add the file to the directory
fhir-bridge/src/main/resources/opt
- Optional: Check the OPT in Pablos Tool: toolkit.cabolabs.com
- leave the fhir-bridge folder
- clone the following project with
git clone https://github.com/ehrbase/openEHR_SDK
- enter the directory and execute
mvn clean install
- execute
java -jar YOUR_OPENEHR-SDK_PATH/generator/target/generator-1.0.0.jar -opt YOUR_FHIR-BRIDGE_PATH/src/main/resources/opt/Körpertemperatur.opt -out YOUR_FHIR-BRIDGE_PATH/src/main/java/ -package org.ehrbase.fhirbridge.ehr.opt
This serializes Java classes for the Body temp Composition. - Make class
fhir-bridge/src/main/java/org/ehrbase/fhirbridge/ehr/opt/YOUR-COMP/YOUR-COMP-Composition
implement the Composition interface. Troubleshooting: In case IntelliJ can not resolve basic imports anymore, e.g. java.xxxx, close the project. Delete the ".idea" folder and open project again.
- visit https://simplifier.net/ForschungsnetzCovid-19/~resources?fhirVersion=R4&sortBy=RankScore_desc
- search for Body Temperature (Profile)
- click on the Profile and Download a Snapshot as XML
- move the Downloaded XML into the directory
fhir-bridge/src/main/resources/profiles
Note: If your Profile includes extensions, don't forget to download and add them, too.
To later test the implemented mapping, an example of the profile also needs to be provided
- visit https://simplifier.net/ForschungsnetzCovid-19/~resources?fhirVersion=R4&sortBy=RankScore_desc
- search for Body Temperature (Example)
- click on the Example and Download it as JSON
- open the JSON and search for the value of the field
¨resourceType¨
, in this case it is an Observation - move it to
fhir-bridge/src/test/resources/Observation
- rename it to
create-body-temp.json
- open the file and replace the JSON object
subject
with the following lines:
"subject": {
"identifier": {
"system": "urn:ietf:rfc:4122",
"value": "{{patientId}}"
}
},
Note: Step 7 depends on the resource type, e.g. for Patient it's just the identifier part that needs to be included.
To add a mapping to the fhir-bridge, the routing for the input has to be defined. Since the basic functionality is already provided only two classes need to be edited.
- open
fhir-bridge/src/main/java/org/ehrbase/fhir-bridge/fhir/common/Profile.java
- add the line
BODY_TEMP(Observation.class, "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/body-temperature"),
to the enum class e.g.:
public enum Profile {
PATIENT(Patient.class, "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/Patient"),
BODY_TEMP(Observation.class, "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/body-temperature"),
BODY_WEIGHT(Observation.class, "https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/body-weight");
The values entered here derive from your fhir resource you want to map. In case of our example, body temperature is a Observation. This may vary depending on the resourceType of your fhir resource! The URL contained as the second parameter is found in your fhir JSON example within the JSON object meta e.g.:
"meta": {
"profile": [
"https://www.netzwerk-universitaetsmedizin.de/fhir/StructureDefinition/body-temperature"
]
},
- open
fhir-bridge/src/main/org/ehrbase/fhirbridge/ehr/converter/CompositionConverterResolver.java
- go to the method afterPropertiesSet()
- add
profiles.put(Profile.BODY_TEMP, new BodyTemperatureCompositionConverter());
to the method. Result should look like that :
@Override
public void afterPropertiesSet() {
profiles.put(Profile.DIAGNOSTIC_REPORT_LAB, new DiagnosticReportLabCompositionConverter());
profiles.put(Profile.BODY_HEIGHT, new BodyHeightCompositionConverter());
profiles.put(Profile.BLOOD_PRESSURE, new BloodPressureCompositionConverter());
profiles.put(Profile.BODY_TEMP, new BodyTemperatureCompositionConverter());
Hereby camel can route the input of an BodyTemp to the BodyTemperatureCompositionConverter where the mapping logic is to be contained.
- create the class
BodyTemperatureCompositionConverter
infhir-bridge/src/main/java/org/ehrbase/fhirbridge/ehr/converter/
(for example with pressingAlt
+Enter
while your cursor is in IntelliJ on the red highlighted converter class name, you just wrote) - this class needs to implement the CompositionConverter interface using the KoerpertermperaturComposition and Observation (remember body temp is an Observation). Example:
public class BodyTemperatureCompositionConverter implements CompositionConverter<KoerpertemperaturComposition, Observation>
- the CompositionConverter interface has two methods that needs to be set for each mappings that is done, the
toComposition
andfromComposition
methods. The first one maps fhir into the openEHR composition, the latter one the composition into fhir. In our example, the methodtoComposition
would look something like that:
@Override
public KoerpertemperaturComposition toComposition(Observation observation) {
// your mapping code
// return the mapped KoerpertemperaturComposition of Koerpertemperatur
}
and fromComposition:
@Override
public Observation fromComposition(KoerpertemperaturComposition composition) {
//your mapping code
// return the mapped Observation of body temp
}
- download the following graphic
- open draw.io
- import the graphic (file -> open from -> device)
- Go to Simplifier and open the resource you want to map (not the example !) e.g. body temp
- compare the fields with the ones of the template, to do so open this link, search your template and click "View template"
- add this value mappings to the grapic (see examples, also in the left top corner is a legend)
(Final file can be added to the Wiki under "Fertige Dokus")
To see all fields of the template you can use better designer instead of ckm. Therefore, you have to:
- Open the "Gecco Core Project" in ckm
- Export the project as zip
- Sign in with github-Account (https://tools.openehr.org/designer/#/)[https://tools.openehr.org/designer/#/]
- Create a new repository
- Import the zip into the repositry ("import", "upload", wait, "close")
In the next step the mapping needs to be implemented in your new CompositionConverter, in our case BodyTemperatureCompositionConverter.
To run what you implemented:
- Be sure, docker is running
(base) birgit@birgit-Latitude-7390:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
308cf2833064 ehrbase/ehrbase:next "/bin/sh -c ./docker…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp docker_ehrbase_1
71abf5d575ae ehrbase/ehrbase-postgres:latest "docker-entrypoint.s…" 3 minutes ago Up 2 minutes 0.0.0.0:5432->5432/tcp docker_ehrbase-db_1
- Start your local fhir-bridge by clicking 'Maven' in the upper right corner of IntelliJ. Then navigate to 'FHIR Bridge | Plugins | spring-boot ' und start the 'spring-boot:run' command
- Run the Junit tests of interest. If you just implemented your mapping you probably want to continue reading first ;-)
Troubleshooting for Windows user in IntelliJ: If "command line command is to long" error occurs. IntelliJ will already propose how to fix it (first option). If not: Run, Edit Configurations, testclass-name (e.g. ObservationIT). If you don't see the "Shorten command line". Click on arrow next to Modify options on right side and activate "Shorten command line". Now select "@argfile ...". Now it should run.
Afterwards POST the example fhir json to the fhir-bridge ({base_url/fhir/Observation}). Within the log of the fhir-bridge server, the composition version uid is returned. Copy this uid and send an request to ehrbase to return this composition. Retrieve related composition from ehrbase via an AQL query, i.e.
POST {{ehrbase_url}}/query/aql
Content-Type: application/json
Authorization: Basic bXl1c2VyOm15UGFzc3dvcmQ0MzI=
# body/payload
{
"q": "SELECT c FROM EHR e [ehr_id/value='{{ehr_id}}'] CONTAINS COMPOSITION c"
}
#or
{
"q": "SELECT c FROM EHR e CONTAINS COMPOSITION c ORDER BY c/context/start_time DESC"
}
Check if the composition contains all the values as intended.
- open Postman
- import
config/postman/fhir-bridge.postman_collection.json
- check, that the fhir-bridge environment exists Issue 113
- run
Ehrbase -> Create EHR
- run
Patient -> Create Patient
- then post your composition
Tests shall cover the following cases:
- In
fhir-bridge/src/test/java/org/ehrbase/fhirbridge/fhir
create a new testfile for your mapping within the proper package, e.g.observation
. The new class itself must end withIT
, e.g.observation/BodyTempIT.java
. - Add the getJavers()-method. To do this you copy the method from another test-class. 2a. Add every openEHR Observation, Composition, Element etc. included in your mapping as a ValueObject. The Composition has to include a location string, used to ignore the location when comparing object (example). Implementation hint: When running the mapping that uses javers, the class that is not comparable will be thrown in the error stack, copy this class name and add it to the getJavers() method.
- In order to provide an object that the mapping test can be validated against, the output of your current one is to be used. It is crucial that you manually check this Composition and ensure its validity (your latest mapping can be found in src/main/resources/MappingOutput.json).
- copy this json and add it to test/resources/fhir/yourPackage
- write the mapping test using this file for the specific fhir input, do the same for all other valid testfiles. Example:
@Test
void mapBodyTemp() throws IOException, IntrospectionException, InvocationTargetException, IllegalAccessException {
String resource = IOUtils.toString(new ClassPathResource("observation/create-body-temp.json").getInputStream(), StandardCharsets.UTF_8);
IParser parser = context.newJsonParser();
BodyTempResource bodyTempResource = parser.parseResource(BodyTempFhirProfile.class, resource);
BodyTempCompositionConverter bodyTempCompositionConverter = new BodyTempCompositionConverter();
BodyTempComposition mappedBodyTempComposition = bodyTempCompositionConverter.toComposition(bodyTempResource);
Diff diff = compareCompositions(getJavers(), "observation/BodyTempComposition.json", mappedBodyTempComposition);
assertEquals(diff.getChanges().size(), 0);
}
- add one more test that mapps a resource and sends it to the ehrbase (entire workflow).
- If there are some exceptions you added that are not covered yet, add tests for those.