-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add initial SystemischeTherapieMedicationStatementMapper (#170)
* feat: add initial SystemischeTherapieMedicationStatementMapper * add medication and bundle type * add missing subject, status and effective * change property "mii-pr-medication-statement" Co-authored-by: chgl <[email protected]> * set "partOf" * extract and change substance id generation from plain name * Revert "change property "mii-pr-medication-statement"" This reverts commit 71b87df. * use custom system for medical statement id --------- Co-authored-by: chgl <[email protected]>
- Loading branch information
Showing
7 changed files
with
304 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
...racum/streams/ume/obdstofhir/mapper/mii/SystemischeTherapieMedicationStatementMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package org.miracum.streams.ume.obdstofhir.mapper.mii; | ||
|
||
import com.google.common.hash.Hashing; | ||
import de.basisdatensatz.obds.v3.SYSTTyp; | ||
import de.basisdatensatz.obds.v3.SYSTTyp.Meldeanlass; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import org.apache.commons.lang3.Validate; | ||
import org.hl7.fhir.r4.model.Bundle; | ||
import org.hl7.fhir.r4.model.CodeableConcept; | ||
import org.hl7.fhir.r4.model.Coding; | ||
import org.hl7.fhir.r4.model.Enumerations.ResourceType; | ||
import org.hl7.fhir.r4.model.Identifier; | ||
import org.hl7.fhir.r4.model.MedicationStatement; | ||
import org.hl7.fhir.r4.model.Period; | ||
import org.hl7.fhir.r4.model.Reference; | ||
import org.miracum.streams.ume.obdstofhir.FhirProperties; | ||
import org.miracum.streams.ume.obdstofhir.mapper.ObdsToFhirMapper; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.util.StringUtils; | ||
|
||
@Service | ||
public class SystemischeTherapieMedicationStatementMapper extends ObdsToFhirMapper { | ||
|
||
private static final Logger LOG = | ||
LoggerFactory.getLogger(SystemischeTherapieProcedureMapper.class); | ||
|
||
public SystemischeTherapieMedicationStatementMapper(FhirProperties fhirProperties) { | ||
super(fhirProperties); | ||
} | ||
|
||
public Bundle map(SYSTTyp syst, Reference patient, Reference procedure) { | ||
Objects.requireNonNull(syst, "Systemtherapie must not be null"); | ||
Objects.requireNonNull(patient, "Reference to Patient must not be null"); | ||
Objects.requireNonNull(procedure, "Reference to Procedure must not be null"); | ||
|
||
Validate.notBlank(syst.getSYSTID(), "Required SYST_ID is unset"); | ||
Validate.isTrue( | ||
Objects.equals( | ||
patient.getReferenceElement().getResourceType(), ResourceType.PATIENT.toCode()), | ||
"The subject reference should point to a Patient resource"); | ||
Validate.isTrue( | ||
Objects.equals( | ||
procedure.getReferenceElement().getResourceType(), ResourceType.PROCEDURE.toCode()), | ||
"The subject reference should point to a Procedure resource"); | ||
|
||
var bundle = new Bundle(); | ||
bundle.setType(Bundle.BundleType.TRANSACTION); | ||
|
||
for (var substanz : syst.getMengeSubstanz().getSubstanz()) { | ||
var systMedicationStatement = new MedicationStatement(); | ||
systMedicationStatement | ||
.getMeta() | ||
.addProfile(fhirProperties.getProfiles().getMiiPrMedicationStatement()); | ||
|
||
if ((null != substanz.getATC() && StringUtils.hasText(substanz.getATC().getCode())) | ||
|| StringUtils.hasText(substanz.getBezeichnung())) { | ||
var substanzId = ""; | ||
if (null != substanz.getATC() && StringUtils.hasText(substanz.getATC().getCode())) { | ||
substanzId = substanz.getATC().getCode(); | ||
var atcCoding = | ||
new Coding( | ||
fhirProperties.getSystems().getAtcBfarm(), substanz.getATC().getCode(), ""); | ||
systMedicationStatement.setMedication(new CodeableConcept(atcCoding)); | ||
} else { | ||
substanzId = createSubstanzIdFromPlain(substanz.getBezeichnung()); | ||
systMedicationStatement.setMedication( | ||
new CodeableConcept().setText(substanz.getBezeichnung())); | ||
} | ||
|
||
// TODO: can we be sure that this SYST-ID is globally unqiue across all SYSTs? | ||
// if not we may instead need to construct the ID from the patient-id + others. | ||
var identifier = | ||
new Identifier() | ||
.setSystem( | ||
fhirProperties.getSystems().getSystemischeTherapieMedicationStatementId()) | ||
.setValue(String.format("%s_%s", syst.getSYSTID(), substanzId)); | ||
systMedicationStatement.addIdentifier(identifier); | ||
systMedicationStatement.setId(computeResourceIdFromIdentifier(identifier)); | ||
|
||
// Status / Effective | ||
var meldeanlass = syst.getMeldeanlass(); | ||
var period = new Period(); | ||
if (meldeanlass == Meldeanlass.BEHANDLUNGSENDE) { | ||
systMedicationStatement.setStatus( | ||
MedicationStatement.MedicationStatementStatus.COMPLETED); | ||
convertObdsDatumToDateTimeType(syst.getBeginn()) | ||
.ifPresent(start -> period.setStart(start.getValue(), start.getPrecision())); | ||
convertObdsDatumToDateTimeType(syst.getEnde()) | ||
.ifPresent(end -> period.setEnd(end.getValue(), end.getPrecision())); | ||
} else { | ||
systMedicationStatement.setStatus(MedicationStatement.MedicationStatementStatus.ACTIVE); | ||
convertObdsDatumToDateTimeType(syst.getBeginn()) | ||
.ifPresent(start -> period.setStart(start.getValue(), start.getPrecision())); | ||
} | ||
systMedicationStatement.setEffective(period); | ||
|
||
// Subject | ||
systMedicationStatement.setSubject(patient); | ||
|
||
// Part of | ||
systMedicationStatement.setPartOf(List.of(procedure)); | ||
|
||
bundle = addResourceAsEntryInBundle(bundle, systMedicationStatement); | ||
} | ||
} | ||
|
||
return bundle; | ||
} | ||
|
||
private String createSubstanzIdFromPlain(String plainName) { | ||
Validate.notBlank(plainName, "Required substance name is unset"); | ||
return String.format( | ||
"%s_%s", | ||
plainName.replaceAll("[^A-Za-z0-9]+", ""), | ||
Hashing.sha256().hashString(plainName, StandardCharsets.UTF_8).toString().substring(0, 4)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
...m/streams/ume/obdstofhir/mapper/mii/SystemischeTherapieMedicationStatementMapperTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package org.miracum.streams.ume.obdstofhir.mapper.mii; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import ca.uhn.fhir.context.FhirContext; | ||
import com.fasterxml.jackson.databind.DeserializationFeature; | ||
import com.fasterxml.jackson.dataformat.xml.XmlMapper; | ||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; | ||
import com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationModule; | ||
import de.basisdatensatz.obds.v3.OBDS; | ||
import java.io.IOException; | ||
import org.approvaltests.Approvals; | ||
import org.hl7.fhir.r4.model.Reference; | ||
import org.junit.jupiter.api.BeforeAll; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.miracum.streams.ume.obdstofhir.FhirProperties; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
import org.springframework.boot.test.context.SpringBootTest; | ||
|
||
@SpringBootTest(classes = {FhirProperties.class}) | ||
@EnableConfigurationProperties | ||
class SystemischeTherapieMedicationStatementMapperTest { | ||
private static SystemischeTherapieMedicationStatementMapper sut; | ||
|
||
@BeforeAll | ||
static void beforeAll(@Autowired FhirProperties fhirProps) { | ||
sut = new SystemischeTherapieMedicationStatementMapper(fhirProps); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({"Testpatient_1.xml", "Testpatient_2.xml", "Testpatient_3.xml"}) | ||
void map_withGivenObds_shouldCreateValidMedicationStatement(String sourceFile) | ||
throws IOException { | ||
final var resource = this.getClass().getClassLoader().getResource("obds3/" + sourceFile); | ||
assertThat(resource).isNotNull(); | ||
|
||
final var xmlMapper = | ||
XmlMapper.builder() | ||
.defaultUseWrapper(false) | ||
.addModule(new JakartaXmlBindAnnotationModule()) | ||
.addModule(new Jdk8Module()) | ||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) | ||
.build(); | ||
|
||
final var obds = xmlMapper.readValue(resource.openStream(), OBDS.class); | ||
|
||
var obdsPatient = obds.getMengePatient().getPatient().getFirst(); | ||
|
||
var patient = new Reference("Patient/any"); | ||
var procedure = new Reference("Procedure/any"); | ||
var systMeldung = | ||
obdsPatient.getMengeMeldung().getMeldung().stream() | ||
.filter(m -> m.getSYST() != null) | ||
.findFirst() | ||
.get(); | ||
var bundle = sut.map(systMeldung.getSYST(), patient, procedure); | ||
|
||
var fhirParser = FhirContext.forR4().newJsonParser().setPrettyPrint(true); | ||
var fhirJson = fhirParser.encodeResourceToString(bundle); | ||
|
||
Approvals.verify( | ||
fhirJson, Approvals.NAMES.withParameters(sourceFile).forFile().withExtension(".fhir.json")); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
...p_withGivenObds_shouldCreateValidMedicationStatement.Testpatient_1.xml.approved.fhir.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"resourceType": "Bundle", | ||
"type": "transaction", | ||
"entry": [ { | ||
"fullUrl": "MedicationStatement/050a031e5a9043c28c565c6b60550c3d34cd059bc2f24c195cdb807f099cd978", | ||
"resource": { | ||
"resourceType": "MedicationStatement", | ||
"id": "050a031e5a9043c28c565c6b60550c3d34cd059bc2f24c195cdb807f099cd978", | ||
"meta": { | ||
"profile": [ "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationStatement" ] | ||
}, | ||
"identifier": [ { | ||
"system": "https://bzkf.github.io/obds-to-fhir/identifiers/systemische-therapie-medication-statement-id", | ||
"value": "101_IN-1_L01FF05" | ||
} ], | ||
"partOf": [ { | ||
"reference": "Procedure/any" | ||
} ], | ||
"status": "completed", | ||
"medicationCodeableConcept": { | ||
"coding": [ { | ||
"system": "http://fhir.de/CodeSystem/bfarm/atc", | ||
"code": "L01FF05" | ||
} ] | ||
}, | ||
"subject": { | ||
"reference": "Patient/any" | ||
}, | ||
"effectivePeriod": { | ||
"start": "2020-05", | ||
"end": "2020-10-15" | ||
} | ||
}, | ||
"request": { | ||
"method": "PUT", | ||
"url": "MedicationStatement/050a031e5a9043c28c565c6b60550c3d34cd059bc2f24c195cdb807f099cd978" | ||
} | ||
} ] | ||
} |
35 changes: 35 additions & 0 deletions
35
...p_withGivenObds_shouldCreateValidMedicationStatement.Testpatient_2.xml.approved.fhir.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"resourceType": "Bundle", | ||
"type": "transaction", | ||
"entry": [ { | ||
"fullUrl": "MedicationStatement/e4b35c4756c9668e9c2b92f281667382020c401482e0a674566a695cd20a4cfa", | ||
"resource": { | ||
"resourceType": "MedicationStatement", | ||
"id": "e4b35c4756c9668e9c2b92f281667382020c401482e0a674566a695cd20a4cfa", | ||
"meta": { | ||
"profile": [ "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationStatement" ] | ||
}, | ||
"identifier": [ { | ||
"system": "https://bzkf.github.io/obds-to-fhir/identifiers/systemische-therapie-medication-statement-id", | ||
"value": "11_1_Innere.1_Bicalutamid_fa96" | ||
} ], | ||
"partOf": [ { | ||
"reference": "Procedure/any" | ||
} ], | ||
"status": "active", | ||
"medicationCodeableConcept": { | ||
"text": "Bicalutamid" | ||
}, | ||
"subject": { | ||
"reference": "Patient/any" | ||
}, | ||
"effectivePeriod": { | ||
"start": "2021-11-08" | ||
} | ||
}, | ||
"request": { | ||
"method": "PUT", | ||
"url": "MedicationStatement/e4b35c4756c9668e9c2b92f281667382020c401482e0a674566a695cd20a4cfa" | ||
} | ||
} ] | ||
} |
35 changes: 35 additions & 0 deletions
35
...p_withGivenObds_shouldCreateValidMedicationStatement.Testpatient_3.xml.approved.fhir.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"resourceType": "Bundle", | ||
"type": "transaction", | ||
"entry": [ { | ||
"fullUrl": "MedicationStatement/da9d78a5d066bba6acd32a9a903c8663ecc1421cb373dcb51566b6d23dd30df7", | ||
"resource": { | ||
"resourceType": "MedicationStatement", | ||
"id": "da9d78a5d066bba6acd32a9a903c8663ecc1421cb373dcb51566b6d23dd30df7", | ||
"meta": { | ||
"profile": [ "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationStatement" ] | ||
}, | ||
"identifier": [ { | ||
"system": "https://bzkf.github.io/obds-to-fhir/identifiers/systemische-therapie-medication-statement-id", | ||
"value": "12_1_Innere.1_Paclitaxel_a0a4" | ||
} ], | ||
"partOf": [ { | ||
"reference": "Procedure/any" | ||
} ], | ||
"status": "active", | ||
"medicationCodeableConcept": { | ||
"text": "Paclitaxel" | ||
}, | ||
"subject": { | ||
"reference": "Patient/any" | ||
}, | ||
"effectivePeriod": { | ||
"start": "2018-03-17" | ||
} | ||
}, | ||
"request": { | ||
"method": "PUT", | ||
"url": "MedicationStatement/da9d78a5d066bba6acd32a9a903c8663ecc1421cb373dcb51566b6d23dd30df7" | ||
} | ||
} ] | ||
} |