From 6a3ee860b75327ffe42b7c89414f18f2df89a004 Mon Sep 17 00:00:00 2001 From: Paul-Christian Volkmer Date: Sun, 22 Jun 2025 12:52:42 +0200 Subject: [PATCH] feat: add display and system to diagnosis data --- .../onco/datamapper/PropertyCatalogue.java | 28 ++++- .../mapper/KpaDiagnosisDataMapper.java | 117 +++++++++++++++++- .../mapper/KpaTumorausbreitungDataMapper.java | 30 ++++- .../onco/datamapper/mapper/MtbDataMapper.java | 3 +- .../mapper/KpaDiagnosisDataMapperTest.java | 22 +++- .../KpaTumorausbreitungDataMapperTest.java | 7 +- 6 files changed, 192 insertions(+), 15 deletions(-) diff --git a/src/main/java/dev/pcvolkmer/onco/datamapper/PropertyCatalogue.java b/src/main/java/dev/pcvolkmer/onco/datamapper/PropertyCatalogue.java index 93a95d4..3cbade4 100644 --- a/src/main/java/dev/pcvolkmer/onco/datamapper/PropertyCatalogue.java +++ b/src/main/java/dev/pcvolkmer/onco/datamapper/PropertyCatalogue.java @@ -43,8 +43,16 @@ public class PropertyCatalogue { public Entry getByCodeAndVersion(String code, int version) { try { return this.jdbcTemplate.queryForObject( - "SELECT code, shortdesc, description FROM property_catalogue_version_entry WHERE code = ? AND property_version_id = ?", - (rs, rowNum) -> new Entry(rs.getString("code"), rs.getString("shortdesc"), rs.getString("description")), + "SELECT code, shortdesc, e.description, v.oid AS version_oid, v.description AS version_description FROM property_catalogue_version_entry e" + + " JOIN property_catalogue_version v ON (e.property_version_id = v.id)" + + " WHERE code = ? AND property_version_id = ?", + (rs, rowNum) -> new Entry( + rs.getString("code"), + rs.getString("shortdesc"), + rs.getString("description"), + rs.getString("version_oid"), + rs.getString("version_description") + ), code, version); } catch (RuntimeException e) { @@ -59,11 +67,19 @@ public class PropertyCatalogue { private final String code; private final String shortdesc; private final String description; + private final String versionOid; + private final String versionDescription; public Entry(String code, String shortdesc, String description) { + this(code, shortdesc, description, null, null); + } + + public Entry(String code, String shortdesc, String description, String versionOid, String versionDescription) { this.code = code; this.shortdesc = shortdesc; this.description = description; + this.versionOid = versionOid; + this.versionDescription = versionDescription; } public String getCode() { @@ -77,6 +93,14 @@ public class PropertyCatalogue { public String getShortdesc() { return shortdesc; } + + public String getVersionOid() { + return versionOid; + } + + public String getVersionDescription() { + return versionDescription; + } } } diff --git a/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapper.java b/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapper.java index fb01bb9..165d460 100644 --- a/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapper.java +++ b/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapper.java @@ -1,8 +1,16 @@ package dev.pcvolkmer.onco.datamapper.mapper; -import dev.pcvolkmer.mv64e.mtb.Coding; -import dev.pcvolkmer.mv64e.mtb.MtbDiagnosis; +import dev.pcvolkmer.mv64e.mtb.*; +import dev.pcvolkmer.onco.datamapper.PropertyCatalogue; import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue; +import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorausbreitungCatalogue; +import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorgradingCatalogue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; /** * Mapper class to load and map diagnosis data from database table 'dk_dnpm_kpa' @@ -13,9 +21,20 @@ import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue; public class KpaDiagnosisDataMapper implements DataMapper { private final KpaCatalogue kpaCatalogue; + private final TumorausbreitungCatalogue tumorausbreitungCatalogue; + private final TumorgradingCatalogue tumorgradingCatalogue; + private final PropertyCatalogue propertyCatalogue; - public KpaDiagnosisDataMapper(final KpaCatalogue kpaCatalogue) { + public KpaDiagnosisDataMapper( + final KpaCatalogue kpaCatalogue, + final TumorausbreitungCatalogue tumorausbreitungCatalogue, + final TumorgradingCatalogue tumorgradingCatalogue, + final PropertyCatalogue propertyCatalogue + ) { this.kpaCatalogue = kpaCatalogue; + this.tumorausbreitungCatalogue = tumorausbreitungCatalogue; + this.tumorgradingCatalogue = tumorgradingCatalogue; + this.propertyCatalogue = propertyCatalogue; } /** @@ -31,12 +50,102 @@ public class KpaDiagnosisDataMapper implements DataMapper { var builder = MtbDiagnosis.builder(); builder .id(data.getString("id")) + .patient(Reference.builder().id(data.getString("patient_id")).build()) .code( Coding.builder() .code(data.getString("icd10")) + .system("http://fhir.de/CodeSystem/bfarm/icd-10-gm") + .display(propertyCatalogue.getByCodeAndVersion(data.getString("icd10"), data.getInteger("icd10_propcat_version")).getShortdesc()) + .version(propertyCatalogue.getByCodeAndVersion(data.getString("icd10"), data.getInteger("icd10_propcat_version")).getVersionDescription()) .build() - ); + ) + .topography(Coding.builder().code(data.getString("icdo3localisation")).build()) + // Nicht in Onkostar erfasst + //.germlineCodes() + .guidelineTreatmentStatus( + getMtbDiagnosisGuidelineTreatmentStatusCoding(data.getString("leitlinienstatus"), data.getInteger("leitlinienstatus_propcat_version")) + ) + .grading(getGrading(id)) + .staging(getStaging(id)) + ; return builder.build(); } + private MtbDiagnosisGuidelineTreatmentStatusCoding getMtbDiagnosisGuidelineTreatmentStatusCoding(final String code, final int version) { + if (code == null || !Arrays.stream(MtbDiagnosisGuidelineTreatmentStatusCodingCode.values()).map(MtbDiagnosisGuidelineTreatmentStatusCodingCode::toValue).collect(Collectors.toSet()).contains(code)) { + return null; + } + + var resultBuilder = MtbDiagnosisGuidelineTreatmentStatusCoding.builder() + .display(propertyCatalogue.getByCodeAndVersion(code, version).getShortdesc()) + .system("dnpm-dip/mtb/diagnosis/guideline-treatment-status"); + try { + resultBuilder.code(MtbDiagnosisGuidelineTreatmentStatusCodingCode.forValue(code)); + } catch (IOException e) { + throw new IllegalStateException("No valid code found"); + } + + return resultBuilder.build(); + } + + private Grading getGrading(final int id) { + var all = tumorgradingCatalogue.getAllByParentId(id).stream() + .map(resultSet -> { + var builder = TumorGrading.builder() + .date(resultSet.getDate("zeitpunkt")); + + if (null != resultSet.getString("tumorgrading") && !resultSet.getString("tumorgrading").isBlank()) { + var propertyEntry = propertyCatalogue + .getByCodeAndVersion(resultSet.getString("tumorgrading"), resultSet.getInteger("tumorgrading_propcat_version")); + builder.codes( + List.of( + Coding.builder() + .code(resultSet.getString("tumorgrading")) + .system("https://www.basisdatensatz.de/feld/161/grading") + // TODO Annahme: "v1" ist Version 2025 + .version(propertyEntry.getVersionDescription().equals("v1") ? "2025" : null) + .display(propertyEntry.getShortdesc()) + .build() + ) + ); + return builder.build(); + } else if (null != resultSet.getString("whograd") && !resultSet.getString("whograd").isBlank()) { + var propertyEntry = propertyCatalogue + .getByCodeAndVersion(resultSet.getString("whograd"), resultSet.getInteger("whograd_propcat_version")); + builder.codes( + List.of( + Coding.builder() + .code(resultSet.getString("whograd")) + .system("dnpm-dip/mtb/who-grading-cns-tumors") + .version(propertyEntry.getVersionDescription()) + .display(propertyEntry.getShortdesc()) + .build() + ) + ); + return builder.build(); + } + + return null; + } + ).filter(Objects::nonNull).collect(Collectors.toList()); + + if (all.isEmpty()) { + return null; + } + + return Grading.builder().history(all).build(); + } + + private Staging getStaging(final int id) { + var subMapper = new KpaTumorausbreitungDataMapper(tumorausbreitungCatalogue); + + var all = tumorausbreitungCatalogue.getAllByParentId(id).stream() + .map(it -> subMapper.getById(it.getInteger("id"))) + .collect(Collectors.toList()); + if (all.isEmpty()) { + return null; + } + + return Staging.builder().history(all).build(); + } } diff --git a/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapper.java b/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapper.java index aa1c111..a270163 100644 --- a/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapper.java +++ b/src/main/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapper.java @@ -39,7 +39,14 @@ public class KpaTumorausbreitungDataMapper extends AbstractSubformDataMapper { var diagnosisDataMapper = new KpaDiagnosisDataMapper( kpaCatalogue, catalogueFactory.catalogue(TumorausbreitungCatalogue.class), - catalogueFactory.catalogue(TumorgradingCatalogue.class) + catalogueFactory.catalogue(TumorgradingCatalogue.class), + propertyCatalogue ); var prozedurMapper = new KpaProzedurDataMapper(catalogueFactory.catalogue(ProzedurCatalogue.class)); diff --git a/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapperTest.java b/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapperTest.java index 5b6f5c6..2310874 100644 --- a/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapperTest.java +++ b/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaDiagnosisDataMapperTest.java @@ -1,8 +1,11 @@ package dev.pcvolkmer.onco.datamapper.mapper; import dev.pcvolkmer.mv64e.mtb.MtbDiagnosis; +import dev.pcvolkmer.onco.datamapper.PropertyCatalogue; import dev.pcvolkmer.onco.datamapper.ResultSet; import dev.pcvolkmer.onco.datamapper.datacatalogues.KpaCatalogue; +import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorausbreitungCatalogue; +import dev.pcvolkmer.onco.datamapper.datacatalogues.TumorgradingCatalogue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -21,13 +24,24 @@ import static org.mockito.Mockito.doAnswer; class KpaDiagnosisDataMapperTest { KpaCatalogue kpaCatalogue; + TumorausbreitungCatalogue tumorausbreitungCatalogue; + TumorgradingCatalogue tumorgradingCatalogue; + PropertyCatalogue propertyCatalogue; KpaDiagnosisDataMapper dataMapper; @BeforeEach - void setUp(@Mock KpaCatalogue kpaCatalogue) { + void setUp( + @Mock KpaCatalogue kpaCatalogue, + @Mock TumorausbreitungCatalogue tumorausbreitungCatalogue, + @Mock TumorgradingCatalogue tumorgradingCatalogue, + @Mock PropertyCatalogue propertyCatalogue + ) { this.kpaCatalogue = kpaCatalogue; - this.dataMapper = new KpaDiagnosisDataMapper(kpaCatalogue); + this.tumorausbreitungCatalogue = tumorausbreitungCatalogue; + this.tumorgradingCatalogue = tumorgradingCatalogue; + this.propertyCatalogue = propertyCatalogue; + this.dataMapper = new KpaDiagnosisDataMapper(kpaCatalogue, tumorausbreitungCatalogue, tumorgradingCatalogue, propertyCatalogue); } @Test @@ -46,6 +60,10 @@ class KpaDiagnosisDataMapperTest { .when(kpaCatalogue) .getById(anyInt()); + doAnswer(invocationOnMock -> + new PropertyCatalogue.Entry("C00.0", "Bösartige Neubildung: Äußere Oberlippe", "Bösartige Neubildung: Äußere Oberlippe") + ).when(propertyCatalogue).getByCodeAndVersion(anyString(), anyInt()); + var actual = this.dataMapper.getById(1); assertThat(actual).isInstanceOf(MtbDiagnosis.class); assertThat(actual.getId()).isEqualTo("1"); diff --git a/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapperTest.java b/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapperTest.java index 9fa3496..8acb554 100644 --- a/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapperTest.java +++ b/src/test/java/dev/pcvolkmer/onco/datamapper/mapper/KpaTumorausbreitungDataMapperTest.java @@ -69,7 +69,12 @@ class KpaTumorausbreitungDataMapperTest { var actual = actualList.get(0); assertThat(actual).isInstanceOf(TumorStaging.class); assertThat(actual.getDate()).isEqualTo(new java.sql.Date(Date.from(Instant.parse("2000-01-01T12:00:00Z")).getTime())); - assertThat(actual.getMethod()).isEqualTo(TumorStagingMethodCoding.builder().code(TumorStagingMethodCodingCode.PATHOLOGIC).build()); + assertThat(actual.getMethod()).isEqualTo( + TumorStagingMethodCoding.builder() + .code(TumorStagingMethodCodingCode.PATHOLOGIC) + .system("dnpm-dip/mtb/tumor-staging/method") + .build() + ); assertThat(actual.getOtherClassifications()).hasSize(1); assertThat(actual.getOtherClassifications().get(0).getCode()).isEqualTo("tumor-free"); assertThat(actual.getTnmClassification().getTumor().getCode()).isEqualTo("p0");