summaryrefslogtreecommitdiff
path: root/src/main/kotlin/dev/dnpm
diff options
context:
space:
mode:
authorPaul-Christian Volkmer2025-04-06 13:36:30 +0200
committerGitHub2025-04-06 13:36:30 +0200
commit7d97365aea81391ae74d64c815261a059bb48c73 (patch)
tree766ab86b96ec12c7178efcdb0f528b4f3849951a /src/main/kotlin/dev/dnpm
parent48b1e62e2241db42b787ab192cdd695f6ac64601 (diff)
feat: add endpoint for DNPM-Datamodel V2 using content negotiation (#104)
This simply adds an REST endpoint without proper implementation. The goal is to accept DNPM V2 JSON data.
Diffstat (limited to 'src/main/kotlin/dev/dnpm')
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/extensions.kt35
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt37
-rw-r--r--src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt13
3 files changed, 78 insertions, 7 deletions
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/extensions.kt b/src/main/kotlin/dev/dnpm/etl/processor/extensions.kt
new file mode 100644
index 0000000..060ecb2
--- /dev/null
+++ b/src/main/kotlin/dev/dnpm/etl/processor/extensions.kt
@@ -0,0 +1,35 @@
+/*
+ * This file is part of ETL-Processor
+ *
+ * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package dev.dnpm.etl.processor
+
+import org.springframework.http.MediaType
+
+/**
+ * Custom MediaTypes
+ *
+ * @since 0.11.0
+ */
+object CustomMediaType {
+ val APPLICATION_VND_DNPM_V2_MTB_JSON = MediaType("application", "vnd.dnpm.v2.mtb+json")
+ const val APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE = "application/vnd.dnpm.v2.mtb+json"
+
+ val APPLICATION_VND_DNPM_V2_RD_JSON = MediaType("application", "vnd.dnpm.v2.rd+json")
+ const val APPLICATION_VND_DNPM_V2_RD_JSON_VALUE = "application/vnd.dnpm.v2.rd+json"
+}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt
index 2aff8cb..e797390 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt
@@ -1,7 +1,7 @@
/*
* This file is part of ETL-Processor
*
- * Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
+ * Copyright (c) 2025 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
@@ -22,11 +22,13 @@ package dev.dnpm.etl.processor.input
import com.fasterxml.jackson.databind.ObjectMapper
import de.ukw.ccc.bwhc.dto.Consent
import de.ukw.ccc.bwhc.dto.MtbFile
+import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.PatientId
import dev.dnpm.etl.processor.RequestId
import dev.dnpm.etl.processor.services.RequestProcessor
import org.apache.kafka.clients.consumer.ConsumerRecord
import org.slf4j.LoggerFactory
+import org.springframework.http.MediaType
import org.springframework.kafka.listener.MessageListener
class KafkaInputListener(
@@ -35,10 +37,29 @@ class KafkaInputListener(
) : MessageListener<String, String> {
private val logger = LoggerFactory.getLogger(KafkaInputListener::class.java)
- override fun onMessage(data: ConsumerRecord<String, String>) {
- val mtbFile = objectMapper.readValue(data.value(), MtbFile::class.java)
+ override fun onMessage(record: ConsumerRecord<String, String>) {
+ when (guessMimeType(record)) {
+ MediaType.APPLICATION_JSON_VALUE -> handleBwhcMessage(record)
+ CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE -> handleDnpmV2Message(record)
+ else -> {
+ /* ignore other messages */
+ }
+ }
+ }
+
+ private fun guessMimeType(record: ConsumerRecord<String, String>): String {
+ if (record.headers().headers("contentType").toList().isEmpty()) {
+ // Fallback if no contentType set (old behavior)
+ return MediaType.APPLICATION_JSON_VALUE
+ }
+
+ return record.headers().headers("contentType")?.firstOrNull()?.value().contentToString()
+ }
+
+ private fun handleBwhcMessage(record: ConsumerRecord<String, String>) {
+ val mtbFile = objectMapper.readValue(record.value(), MtbFile::class.java)
val patientId = PatientId(mtbFile.patient.id)
- val firstRequestIdHeader = data.headers().headers("requestId")?.firstOrNull()
+ val firstRequestIdHeader = record.headers().headers("requestId")?.firstOrNull()
val requestId = if (null != firstRequestIdHeader) {
RequestId(String(firstRequestIdHeader.value()))
} else {
@@ -61,4 +82,10 @@ class KafkaInputListener(
}
}
}
-} \ No newline at end of file
+
+ private fun handleDnpmV2Message(record: ConsumerRecord<String, String>) {
+ // Do not handle DNPM-V2 for now
+ logger.warn("Ignoring MTB File in DNPM V2 format: Not implemented yet")
+ }
+
+}
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt
index 123a84f..432711a 100644
--- a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt
+++ b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt
@@ -21,9 +21,13 @@ package dev.dnpm.etl.processor.input
import de.ukw.ccc.bwhc.dto.Consent
import de.ukw.ccc.bwhc.dto.MtbFile
+import dev.dnpm.etl.processor.CustomMediaType
import dev.dnpm.etl.processor.PatientId
import dev.dnpm.etl.processor.services.RequestProcessor
+import dev.pcvolkmer.mv64e.mtb.Mtb
import org.slf4j.LoggerFactory
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
@@ -40,7 +44,7 @@ class MtbFileRestController(
return ResponseEntity.ok("Test")
}
- @PostMapping
+ @PostMapping( consumes = [ MediaType.APPLICATION_JSON_VALUE ] )
fun mtbFile(@RequestBody mtbFile: MtbFile): ResponseEntity<Unit> {
if (mtbFile.consent.status == Consent.Status.ACTIVE) {
logger.debug("Accepted MTB File for processing")
@@ -53,6 +57,11 @@ class MtbFileRestController(
return ResponseEntity.accepted().build()
}
+ @PostMapping( consumes = [ CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE] )
+ fun mtbFile(@RequestBody mtbFile: Mtb): ResponseEntity<Unit> {
+ return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build()
+ }
+
@DeleteMapping(path = ["{patientId}"])
fun deleteData(@PathVariable patientId: String): ResponseEntity<Unit> {
logger.debug("Accepted patient ID to process deletion")
@@ -60,4 +69,4 @@ class MtbFileRestController(
return ResponseEntity.accepted().build()
}
-} \ No newline at end of file
+}