Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle Primaertumor_ICD_Version being unset or not matching regex #39

Merged
merged 4 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.hl7.fhir.r4.model.*;
import org.miracum.streams.ume.obdstofhir.FhirProperties;
import org.miracum.streams.ume.obdstofhir.lookup.*;
Expand All @@ -12,12 +13,16 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

@Configuration
public class ObdsConditionMapper extends ObdsToFhirMapper {

private static final Logger LOG = LoggerFactory.getLogger(ObdsConditionMapper.class);

private static final Pattern icdVersionPattern =
Pattern.compile("^(10 (?<versionYear>20\\d{2}) ((GM)|(WHO))|Sonstige)$");

@Value("${app.version}")
private String appVersion;

Expand Down Expand Up @@ -64,8 +69,12 @@ public Bundle mapOnkoResourcesToCondition(

ADT_GEKID.PrimaryConditionAbs primDia = meldung.getDiagnose();

// diagnose Tag ist only specified in meldeanlass 'diagnose', otherwise use tag 'Tumorzuordung'
if (primDia == null) {
// Diagnose Element is only fully specified in meldeanlass 'diagnose', otherwise use element
// 'Tumorzuordung'
// It's possible that 'Meldung.Diagnose' is set but 'Meldung.Diagnose.Primaertumor_*' is not,
// in that case also use the TumorZuordnung to construct the Condition.
var useTumorZuordnung = primDia == null || primDia.getPrimaertumor_ICD_Code() == null;
if (useTumorZuordnung) {
primDia = meldung.getTumorzuordnung();

if (primDia == null) {
Expand All @@ -80,6 +89,9 @@ public Bundle mapOnkoResourcesToCondition(
}

var conIdentifier = pid + "condition" + primDia.getTumor_ID();
if (useTumorZuordnung) {
conIdentifier += "-from-tumorzuordnung";
}

onkoCondition.setId(this.getHash(ResourceType.Condition, conIdentifier));

Expand All @@ -94,18 +106,26 @@ public Bundle mapOnkoResourcesToCondition(
.getMeta()
.setProfile(List.of(new CanonicalType(fhirProperties.getProfiles().getCondition())));

var coding = new Coding();
var icd10Version = primDia.getPrimaertumor_ICD_Version();
// Aufbau: "10 2021 GM"
String[] icdVersionArray = icd10Version.split(" ");

if (icdVersionArray.length == 3 && icdVersionArray[1].matches("^20\\d{2}$")) {
coding.setVersion(icdVersionArray[1]);
} // FIXME: else throw exception?
var coding =
new Coding()
.setCode(primDia.getPrimaertumor_ICD_Code())
.setSystem(fhirProperties.getSystems().getIcd10gm());

coding
.setCode(primDia.getPrimaertumor_ICD_Code())
.setSystem(fhirProperties.getSystems().getIcd10gm());
// Aufbau: "10 2021 GM"
var icd10Version = primDia.getPrimaertumor_ICD_Version();
if (StringUtils.hasLength(icd10Version)) {
var matcher = icdVersionPattern.matcher(icd10Version);
if (matcher.matches()) {
coding.setVersion(matcher.group("versionYear"));
} else {
LOG.warn(
"Primaertumor_ICD_Version doesn't match expected format. Expected: '{}', actual: '{}'",
icdVersionPattern.pattern(),
icd10Version);
}
} else {
LOG.warn("Primaertumor_ICD_Version is unset or contains only whitespaces");
}

var conditionCode = new CodeableConcept().addCoding(coding);
onkoCondition.setCode(conditionCode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import java.io.IOException;
import java.util.*;
import java.util.stream.Stream;
import org.apache.commons.lang3.tuple.Pair;
import org.approvaltests.Approvals;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Observation;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.miracum.streams.ume.obdstofhir.FhirProperties;
import org.miracum.streams.ume.obdstofhir.mapper.*;
Expand Down Expand Up @@ -194,4 +196,35 @@ void mapObservation_withGivenAdtXml(
.withExtension(".fhir.json"));
}
}

@ParameterizedTest
@CsvSource({"diagnosis_set.xml", "diagnosis_unset.xml"})
void mapObservation_withGivenObdsXml_shouldMatchSnapshot(String resourceXmlName)
throws IOException {

var meldungExportList =
buildMeldungExportList(List.of(new Tupel<String, Integer>(resourceXmlName, 1)));

var onkoProcessor =
new ObdsProcessor(
fhirProps,
onkoMedicationStatementMapper,
onkoObservationMapper,
onkoProcedureMapper,
onkoPatientMapper,
onkoConditionMapper);

var observResultBundle =
onkoProcessor.getOnkoToObservationBundleMapper().apply(meldungExportList);

var resultBundle =
onkoProcessor
.getOnkoToConditionBundleMapper()
.apply(Pair.of(meldungExportList, observResultBundle));

var fhirJson = fhirParser.encodeResourceToString(resultBundle);
Approvals.verify(
fhirJson,
Approvals.NAMES.withParameters(resourceXmlName).forFile().withExtension(".fhir.json"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected MeldungExportList buildMeldungExportList(List<Tupel<String, Integer>>
Map<String, Object> payloadOnkoRessource = new HashMap<>();
payloadOnkoRessource.put("ID", payloadId);
payloadOnkoRessource.put("REFERENZ_NUMMER", patId);
payloadOnkoRessource.put("LKR_MELDUNG", Integer.parseInt(meldungsId.replace(melderId, "")));
payloadOnkoRessource.put("LKR_MELDUNG", meldungsId.replace(melderId, ""));
payloadOnkoRessource.put("VERSIONSNUMMER", xmlTupel.getSecond());
payloadOnkoRessource.put("XML_DATEN", xmlContent);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [ {
"fullUrl": "Condition/04c8f27ca021b8fd87ffd3abbde1f4b907bb3d6921fd61c5d4b9a0a756b8d110",
"resource": {
"resourceType": "Condition",
"id": "04c8f27ca021b8fd87ffd3abbde1f4b907bb3d6921fd61c5d4b9a0a756b8d110",
"meta": {
"source": "KR7X825X.ONKOSTAR:obds-to-fhir:0.0.0-test",
"profile": [ "http://dktk.dkfz.de/fhir/StructureDefinition/onco-core-Condition-Primaerdiagnose" ]
},
"code": {
"coding": [ {
"system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"version": "2010",
"code": "C43.5"
} ]
},
"subject": {
"reference": "Patient/19cc75fbfb51266ac0149828ae2f8522106e3ba176ceac2b40acb3cb1c9365f9",
"identifier": {
"type": {
"coding": [ {
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR"
} ]
},
"system": "https://fhir.diz.uk-erlangen.de/identifiers/patient-id",
"value": "0001234567"
}
}
},
"request": {
"method": "PUT",
"url": "Condition/04c8f27ca021b8fd87ffd3abbde1f4b907bb3d6921fd61c5d4b9a0a756b8d110"
}
} ]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [ {
"fullUrl": "Condition/dd9844e53c6d877fb91a9059f1bc0a433e7e892cd272770caa84aad4e7b7189d",
"resource": {
"resourceType": "Condition",
"id": "dd9844e53c6d877fb91a9059f1bc0a433e7e892cd272770caa84aad4e7b7189d",
"meta": {
"source": "KR7X825X.ONKOSTAR:obds-to-fhir:0.0.0-test",
"profile": [ "http://dktk.dkfz.de/fhir/StructureDefinition/onco-core-Condition-Primaerdiagnose" ]
},
"code": {
"coding": [ {
"system": "http://fhir.de/CodeSystem/bfarm/icd-10-gm",
"version": "2019",
"code": "C43.2"
} ]
},
"bodySite": [ {
"coding": [ {
"system": "http://dktk.dkfz.de/fhir/onco/core/CodeSystem/SeitenlokalisationCS",
"code": "L",
"display": "links"
}, {
"system": "http://snomed.info/sct",
"code": "7771000",
"display": "Left"
} ]
} ],
"subject": {
"reference": "Patient/19cc75fbfb51266ac0149828ae2f8522106e3ba176ceac2b40acb3cb1c9365f9",
"identifier": {
"type": {
"coding": [ {
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
"code": "MR"
} ]
},
"system": "https://fhir.diz.uk-erlangen.de/identifiers/patient-id",
"value": "0001234567"
}
},
"onsetDateTime": "2019-08-21"
},
"request": {
"method": "PUT",
"url": "Condition/dd9844e53c6d877fb91a9059f1bc0a433e7e892cd272770caa84aad4e7b7189d"
}
} ]
}
110 changes: 110 additions & 0 deletions src/test/resources/diagnosis_set.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8"?>
<ADT_GEKID xmlns="http://www.gekid.de/namespace" Schema_Version="2.2.3">
<Absender Absender_ID="KR7X825X" Software_ID="ONKOSTAR" Installations_ID="2030">
<Absender_Bezeichnung>UKI</Absender_Bezeichnung>
<Absender_Ansprechpartner>Chef</Absender_Ansprechpartner>
<Absender_Anschrift>Irgendwo-Straße 1, 12345 Phantasieland</Absender_Anschrift>
</Absender>
<Menge_Patient>
<Patient>
<Patienten_Stammdaten Patient_ID="0001234567">
<KrankenversichertenNr>privatversichert</KrankenversichertenNr>
<KrankenkassenNr>1234567890</KrankenkassenNr>
<Patienten_Nachname>TestpatientEnzensperger</Patienten_Nachname>
<Patienten_Titel></Patienten_Titel>
<Patienten_Vornamen>Horst</Patienten_Vornamen>
<Patienten_Geburtsname></Patienten_Geburtsname>
<Patienten_Geschlecht>M</Patienten_Geschlecht>
<Patienten_Geburtsdatum>01.01.1950</Patienten_Geburtsdatum>
<Menge_Adresse>
<Adresse>
<Patienten_Strasse>Irgendwo-Straße 2</Patienten_Strasse>
<Patienten_Hausnummer>2</Patienten_Hausnummer>
<Patienten_Land>DE</Patienten_Land>
<Patienten_PLZ>12345</Patienten_PLZ>
<Patienten_Ort>Phantasieland</Patienten_Ort>
</Adresse>
</Menge_Adresse>
</Patienten_Stammdaten>
<Menge_Meldung>
<Meldung Meldung_ID="000000B2-KR7X825X" Melder_ID="KR7X825X">
<Meldedatum>30.01.2024</Meldedatum>
<Meldebegruendung>D</Meldebegruendung>
<Meldeanlass>histologie_zytologie</Meldeanlass>
<Tumorzuordnung Tumor_ID="1">
<Primaertumor_ICD_Code>C43.2</Primaertumor_ICD_Code>
<Primaertumor_ICD_Version>10 2019 GM</Primaertumor_ICD_Version>
<Diagnosedatum>21.08.2019</Diagnosedatum>
<Seitenlokalisation>L</Seitenlokalisation>
</Tumorzuordnung>
<Diagnose Tumor_ID="1">
<Primaertumor_ICD_Code>C43.5</Primaertumor_ICD_Code>
<Primaertumor_ICD_Version>10 2010 GM</Primaertumor_ICD_Version>
<Primaertumor_Diagnosetext>Bösartiges Melanom des Rumpfes</Primaertumor_Diagnosetext>
<Menge_Histologie>
<Histologie Histologie_ID="1234567">
<Tumor_Histologiedatum>21.08.2019</Tumor_Histologiedatum>
<Histologie_EinsendeNr>p 21557-19</Histologie_EinsendeNr>
<Morphologie_Code>8720/3</Morphologie_Code>
<Morphologie_ICD_O_Version>33</Morphologie_ICD_O_Version>
</Histologie>
</Menge_Histologie>
<Modul_Allgemein>
<DatumStudienrekrutierung>
<NU>N</NU>
</DatumStudienrekrutierung>
</Modul_Allgemein>
<Anmerkung> *** Pathobericht</Anmerkung>
</Diagnose>
<Menge_Zusatzitem>
<Zusatzitem>
<Art>Einsender_Vorname</Art>
<Wert>Sepp</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_Nachname</Art>
<Wert>Prof. Dr. Doof</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_Titel</Art>
<Wert>-</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_Strasse</Art>
<Wert>Irgendwo-Straße</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_Hausnummer</Art>
<Wert>1</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_Ort</Art>
<Wert>Phantasieland</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_PLZ</Art>
<Wert>12345</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_Einrichtung</Art>
<Wert>Prof. Dr. Doof, UKI, HG</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_BSNR</Art>
<Wert>-</Wert>
</Zusatzitem>
<Zusatzitem>
<Art>Einsender_LANR</Art>
<Wert>-</Wert>
</Zusatzitem>
</Menge_Zusatzitem>
</Meldung>
</Menge_Meldung>
</Patient>
</Menge_Patient>
<Menge_Melder>
<Melder Melder_ID="KR7X825X">
<Meldende_Stelle>KR7X825X</Meldende_Stelle>
</Melder>
</Menge_Melder>
</ADT_GEKID>
Loading
Loading