diff options
Diffstat (limited to 'src/main/kotlin')
10 files changed, 76 insertions, 72 deletions
diff --git a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt index 3e88ffd..d780642 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/config/AppConfiguration.kt @@ -20,7 +20,6 @@ package dev.dnpm.etl.processor.config -import com.fasterxml.jackson.databind.ObjectMapper import dev.dnpm.etl.processor.consent.GicsConsentService import dev.dnpm.etl.processor.consent.GicsGetBroadConsentService import dev.dnpm.etl.processor.consent.IConsentService diff --git a/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt b/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt index a8b8fdb..1f867e8 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/consent/ConsentEvaluator.kt @@ -20,9 +20,9 @@ package dev.dnpm.etl.processor.consent -import dev.pcvolkmer.mv64e.mtb.ConsentProvision -import dev.pcvolkmer.mv64e.mtb.ModelProjectConsentPurpose -import dev.pcvolkmer.mv64e.mtb.Mtb +import dev.pcvolkmer.mv64e.model.ConsentProvisionType +import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose +import dev.pcvolkmer.mv64e.model.PatientRecord import org.springframework.stereotype.Service /** Evaluates consent using provided consent service and file based consent information */ @@ -30,8 +30,8 @@ import org.springframework.stereotype.Service class ConsentEvaluator( private val consentService: IConsentService, ) { - fun check(mtbFile: Mtb): ConsentEvaluation { - val ttpConsentStatus = consentService.getTtpBroadConsentStatus(mtbFile.patient.id) + fun check(mtbFile: PatientRecord): ConsentEvaluation { + val ttpConsentStatus = consentService.getTtpBroadConsentStatus(mtbFile.patient!!.id) val consentGiven = ttpConsentStatus == TtpConsentStatus.BROAD_CONSENT_GIVEN || ttpConsentStatus == TtpConsentStatus.GENOM_DE_CONSENT_SEQUENCING_PERMIT || @@ -39,7 +39,7 @@ class ConsentEvaluator( ttpConsentStatus == TtpConsentStatus.UNKNOWN_CHECK_FILE && mtbFile.metadata?.modelProjectConsent?.provisions?.any { it.purpose == ModelProjectConsentPurpose.SEQUENCING && - it.type == ConsentProvision.PERMIT + it.type == ConsentProvisionType.PERMIT } == true return ConsentEvaluation(ttpConsentStatus, consentGiven) 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 a126e07..51d093b 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/input/KafkaInputListener.kt @@ -26,7 +26,7 @@ import dev.dnpm.etl.processor.RequestId import dev.dnpm.etl.processor.consent.ConsentEvaluator import dev.dnpm.etl.processor.consent.TtpConsentStatus import dev.dnpm.etl.processor.services.RequestProcessor -import dev.pcvolkmer.mv64e.mtb.Mtb +import dev.pcvolkmer.mv64e.model.PatientRecord import org.apache.kafka.clients.consumer.ConsumerRecord import org.slf4j.LoggerFactory import org.springframework.http.MediaType @@ -72,8 +72,8 @@ class KafkaInputListener( private fun handleDnpmV2Message(record: ConsumerRecord<String, String>) { try { - val mtbFile = jsonMapper.readValue(record.value(), Mtb::class.java) - val patientId = PatientId(mtbFile.patient.id) + val mtbFile = jsonMapper.readValue(record.value(), PatientRecord::class.java) + val patientId = PatientId(mtbFile.patient!!.id) val firstRequestIdHeader = record.headers().headers("requestId")?.firstOrNull() val requestId = if (null != firstRequestIdHeader) { @@ -106,7 +106,7 @@ class KafkaInputListener( } } catch (e: Exception) { logger.error("Error while processing MtbFile", e) - requestProcessor.processMtbFile(Mtb.builder().build()) + requestProcessor.processMtbFile(PatientRecord.builder().build()) } } } 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 47f0766..7ab846a 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/input/MtbFileRestController.kt @@ -22,10 +22,9 @@ package dev.dnpm.etl.processor.input import dev.dnpm.etl.processor.CustomMediaType import dev.dnpm.etl.processor.PatientId -import dev.dnpm.etl.processor.consent.ConsentEvaluator import dev.dnpm.etl.processor.consent.TtpConsentStatus import dev.dnpm.etl.processor.services.RequestProcessor -import dev.pcvolkmer.mv64e.mtb.Mtb +import dev.pcvolkmer.mv64e.model.PatientRecord import org.slf4j.LoggerFactory import org.springframework.http.MediaType import org.springframework.http.ResponseEntity @@ -52,7 +51,7 @@ class MtbFileRestController( CustomMediaType.APPLICATION_VND_DNPM_V2_MTB_JSON_VALUE, ], ) - fun mtbFile(@RequestBody mtbFile: Mtb): ResponseEntity<Unit> { + fun mtbFile(@RequestBody mtbFile: PatientRecord): ResponseEntity<Unit> { logger.debug("Accepted MTB File (DNPM V2) for processing") if (requestProcessor.processMtbFile(mtbFile)) { return ResponseEntity.accepted().build() @@ -80,7 +79,7 @@ class MtbFileRestControllerAdvice( @ExceptionHandler(HttpMessageNotReadableException::class) fun handleMessageNotReadableException(e: Exception): ResponseEntity<Unit> { logger.error("Error while processing MtbFile", e) - requestProcessor.processMtbFile(Mtb.builder().build()) + requestProcessor.processMtbFile(PatientRecord.builder().build()) return ResponseEntity.badRequest().build() } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt index 8c20b7c..e198952 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/output/KafkaMtbFileSender.kt @@ -23,8 +23,8 @@ package dev.dnpm.etl.processor.output import dev.dnpm.etl.processor.CustomMediaType import dev.dnpm.etl.processor.config.KafkaProperties import dev.dnpm.etl.processor.monitoring.RequestStatus -import dev.pcvolkmer.mv64e.mtb.Mtb -import dev.pcvolkmer.mv64e.mtb.MvhMetadata +import dev.pcvolkmer.mv64e.model.MvhMetadata +import dev.pcvolkmer.mv64e.model.PatientRecord import org.apache.kafka.clients.producer.ProducerRecord import org.slf4j.LoggerFactory import org.springframework.kafka.core.KafkaTemplate @@ -75,7 +75,7 @@ class KafkaMtbFileSender( } override fun send(request: DeleteRequest): MtbFileSender.Response { - val dummyMtbFile = Mtb.builder().metadata(MvhMetadata()).build() + val dummyMtbFile = PatientRecord.builder().metadata(MvhMetadata()).build() return try { return retryTemplate.execute<MtbFileSender.Response, Exception> { @@ -114,7 +114,7 @@ class KafkaMtbFileSender( private fun key(request: MtbRequest): String = when (request) { - is DnpmV2MtbFileRequest -> "{\"pid\": \"${request.content.patient.id}\"}" + is DnpmV2MtbFileRequest -> "{\"pid\": \"${request.content.patient?.id}\"}" is DeleteRequest -> "{\"pid\": \"${request.patientId.value}\"}" else -> throw IllegalArgumentException("Unsupported request type: ${request::class.simpleName}") diff --git a/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt b/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt index 75401e6..e066d54 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/output/MtbRequest.kt @@ -22,7 +22,7 @@ package dev.dnpm.etl.processor.output import dev.dnpm.etl.processor.PatientPseudonym import dev.dnpm.etl.processor.RequestId -import dev.pcvolkmer.mv64e.mtb.Mtb +import dev.pcvolkmer.mv64e.model.PatientRecord interface MtbRequest { val requestId: RequestId @@ -37,9 +37,9 @@ sealed interface MtbFileRequest<out T> : MtbRequest { data class DnpmV2MtbFileRequest( override val requestId: RequestId, - override val content: Mtb, -) : MtbFileRequest<Mtb> { - override fun patientPseudonym(): PatientPseudonym = PatientPseudonym(content.patient.id) + override val content: PatientRecord, +) : MtbFileRequest<PatientRecord> { + override fun patientPseudonym(): PatientPseudonym = PatientPseudonym(content.patient!!.id) } data class DeleteRequest( diff --git a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt index 6615b35..21f3a7f 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/pseudonym/extensions.kt @@ -21,9 +21,9 @@ package dev.dnpm.etl.processor.pseudonym import dev.dnpm.etl.processor.PatientId -import dev.pcvolkmer.mv64e.mtb.ModelProjectConsent -import dev.pcvolkmer.mv64e.mtb.Mtb -import dev.pcvolkmer.mv64e.mtb.MvhMetadata +import dev.pcvolkmer.mv64e.model.MvhMetadata +import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsent +import dev.pcvolkmer.mv64e.model.PatientRecord import org.apache.commons.codec.digest.DigestUtils /** @@ -33,8 +33,8 @@ import org.apache.commons.codec.digest.DigestUtils * @return The MTB file containing patient pseudonymes * @since 0.11.0 */ -infix fun Mtb.pseudonymizeWith(pseudonymizeService: PseudonymizeService) { - val patientPseudonym = pseudonymizeService.patientPseudonym(PatientId(this.patient.id)).value +infix fun PatientRecord.pseudonymizeWith(pseudonymizeService: PseudonymizeService) { + val patientPseudonym = pseudonymizeService.patientPseudonym(PatientId(this.patient!!.id)).value this.episodesOfCare?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } this.carePlans?.filterNotNull()?.forEach { carePlan -> @@ -57,7 +57,7 @@ infix fun Mtb.pseudonymizeWith(pseudonymizeService: PseudonymizeService) { this.diagnoses?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } this.guidelineTherapies?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } this.guidelineProcedures?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } - this.patient.id = patientPseudonym + this.patient?.id = patientPseudonym this.claims?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } this.claimResponses?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } this.familyMemberHistories?.filterNotNull()?.forEach { it.patient?.id = patientPseudonym } @@ -116,7 +116,7 @@ infix fun Mtb.pseudonymizeWith(pseudonymizeService: PseudonymizeService) { * @return The MTB file containing rehashed content IDs * @since 0.11.0 */ -infix fun Mtb.anonymizeContentWith(pseudonymizeService: PseudonymizeService) { +infix fun PatientRecord.anonymizeContentWith(pseudonymizeService: PseudonymizeService) { val prefix = pseudonymizeService.prefix() fun anonymize(id: String): String { @@ -280,25 +280,25 @@ infix fun Mtb.anonymizeContentWith(pseudonymizeService: PseudonymizeService) { } } -fun Mtb.ensureMetaDataIsInitialized() { +fun PatientRecord.ensureMetaDataIsInitialized() { // init metadata if necessary if (this.metadata == null) { val mvhMetadata = MvhMetadata.builder().build() this.metadata = mvhMetadata } - if (this.metadata.researchConsents == null) { - this.metadata.researchConsents = mutableListOf() + if (this.metadata?.researchConsents == null) { + this.metadata?.researchConsents = mutableListOf() } - if (this.metadata.modelProjectConsent == null) { - this.metadata.modelProjectConsent = ModelProjectConsent() - this.metadata.modelProjectConsent.provisions = mutableListOf() - } else if (this.metadata.modelProjectConsent.provisions != null) { + if (this.metadata?.modelProjectConsent == null) { + this.metadata?.modelProjectConsent = MvhMetadataModelProjectConsent() + this.metadata?.modelProjectConsent?.provisions = mutableListOf() + } else if (this.metadata?.modelProjectConsent?.provisions != null) { // make sure list can be changed - this.metadata.modelProjectConsent.provisions = - this.metadata.modelProjectConsent.provisions.toMutableList() + this.metadata?.modelProjectConsent?.provisions = + this.metadata?.modelProjectConsent?.provisions?.toMutableList() } } -infix fun Mtb.addGenomDeTan(pseudonymizeService: PseudonymizeService) { - this.metadata?.transferTan = pseudonymizeService.genomDeTan(PatientId(this.patient.id)) +infix fun PatientRecord.addGenomDeTan(pseudonymizeService: PseudonymizeService) { + this.metadata?.transferTAN = pseudonymizeService.genomDeTan(PatientId(this.patient!!.id)) } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt index a95420a..15ccdc4 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/ConsentProcessor.kt @@ -28,7 +28,13 @@ import dev.dnpm.etl.processor.consent.ConsentDomain import dev.dnpm.etl.processor.consent.IConsentService import dev.dnpm.etl.processor.consent.MtbFileConsentService import dev.dnpm.etl.processor.pseudonym.ensureMetaDataIsInitialized -import dev.pcvolkmer.mv64e.mtb.* +import dev.pcvolkmer.mv64e.model.ConsentProvisionType +import dev.pcvolkmer.mv64e.model.ModelProjectConsentPurpose +import dev.pcvolkmer.mv64e.model.MvhMetadata +import dev.pcvolkmer.mv64e.model.MvhMetadataModelProjectConsentProvisionsInner +import dev.pcvolkmer.mv64e.model.MvhSubmissionType +import dev.pcvolkmer.mv64e.model.PatientRecord +import dev.pcvolkmer.mv64e.model.ResearchConsent import org.apache.commons.lang3.NotImplementedException import org.hl7.fhir.r4.model.* import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent @@ -65,7 +71,7 @@ class ConsentProcessor( * @param mtbFile File v2 (will be enriched with consent data) * @return true if consent is given */ - fun consentGatedCheckAndTryEmbedding(mtbFile: Mtb): Boolean { + fun consentGatedCheckAndTryEmbedding(mtbFile: PatientRecord): Boolean { mtbFile.ensureMetaDataIsInitialized() if (consentService is MtbFileConsentService) { @@ -73,7 +79,7 @@ class ConsentProcessor( return true } - val personIdentifierValue = mtbFile.patient.id + val personIdentifierValue = mtbFile.patient!!.id val requestDate = Date.from(Instant.now(Clock.systemUTC())) // 1. Broad consent Entry exists? @@ -129,7 +135,7 @@ class ConsentProcessor( return false } - fun embedBroadConsentResources(mtbFile: Mtb, broadConsent: Bundle) { + fun embedBroadConsentResources(mtbFile: PatientRecord, broadConsent: Bundle) { for (entry in broadConsent.entry) { val resource = entry.resource if (resource is Consent) { @@ -137,12 +143,12 @@ class ConsentProcessor( // we need another step to back to string, before we convert to object map val asJsonString = fhirContext.newJsonParser().encodeResourceToString(resource) try { - val mapOfJson: MvhMetadata.ResearchConsent? = + val mapOfJson: ResearchConsent? = jsonMapper.readValue( asJsonString, - MvhMetadata.ResearchConsent::class.java, + ResearchConsent::class.java, ) - mtbFile.metadata.researchConsents.add(mapOfJson) + mtbFile.metadata?.researchConsents?.add(mapOfJson) } catch (e: JsonProcessingException) { throw RuntimeException(e) } @@ -150,7 +156,7 @@ class ConsentProcessor( } } - fun addGenomeDbProvisions(mtbFile: Mtb, consentGnomeDe: Bundle) { + fun addGenomeDbProvisions(mtbFile: PatientRecord, consentGnomeDe: Bundle) { for (entry in consentGnomeDe.entry) { val resource = entry.resource if (resource !is Consent) { @@ -167,22 +173,22 @@ class ConsentProcessor( val provisionCode = getProvisionCode(provisionComponent) if (provisionCode != null) { try { - val modelProjectConsentPurpose = ModelProjectConsentPurpose.forValue(provisionCode) + val modelProjectConsentPurpose = ModelProjectConsentPurpose.fromValue(provisionCode) if (ModelProjectConsentPurpose.SEQUENCING == modelProjectConsentPurpose) { // CONVENTION: wrapping date is date of SEQUENCING consent - mtbFile.metadata.modelProjectConsent.date = resource.dateTime + mtbFile.metadata?.modelProjectConsent?.date = resource.dateTime } val provision = - Provision.builder() - .type(ConsentProvision.valueOf(provisionComponent.type.name)) + MvhMetadataModelProjectConsentProvisionsInner.builder() + .type(ConsentProvisionType.valueOf(provisionComponent.type.name)) .date(provisionComponent.period.start) .purpose(modelProjectConsentPurpose) .build() - mtbFile.metadata.modelProjectConsent.provisions.add(provision) - } catch (ioe: IOException) { + mtbFile.metadata?.modelProjectConsent?.provisions?.add(provision) + } catch (ioe: IllegalArgumentException) { logger.error( "Provision code '$provisionCode' is unknown and cannot be mapped.", ioe.toString(), @@ -190,8 +196,8 @@ class ConsentProcessor( } } - if (mtbFile.metadata.modelProjectConsent.provisions.isNotEmpty()) { - mtbFile.metadata.modelProjectConsent.version = gIcsConfigProperties.genomeDeConsentVersion + if (mtbFile.metadata?.modelProjectConsent?.provisions?.isNotEmpty() == true) { + mtbFile.metadata?.modelProjectConsent?.version = gIcsConfigProperties.genomeDeConsentVersion } } } @@ -207,15 +213,15 @@ class ConsentProcessor( return provisionCode } - private fun setGenomDeSubmissionType(mtbFile: Mtb) { + private fun setGenomDeSubmissionType(mtbFile: PatientRecord) { if (appConfigProperties.genomDeTestSubmission) { - mtbFile.metadata.type = MvhSubmissionType.TEST + mtbFile.metadata?.type = MvhSubmissionType.TEST logger.info("genomeDe submission mit TEST") } else { - mtbFile.metadata.type = - when (mtbFile.metadata.type) { + mtbFile.metadata?.type = + when (mtbFile.metadata?.type) { null -> MvhSubmissionType.INITIAL - else -> mtbFile.metadata.type + else -> mtbFile.metadata?.type } } } diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt index 4b7afff..c152d0f 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/RequestProcessor.kt @@ -32,8 +32,8 @@ import dev.dnpm.etl.processor.pseudonym.PseudonymizeService import dev.dnpm.etl.processor.pseudonym.addGenomDeTan import dev.dnpm.etl.processor.pseudonym.anonymizeContentWith import dev.dnpm.etl.processor.pseudonym.pseudonymizeWith -import dev.pcvolkmer.mv64e.mtb.Mtb -import dev.pcvolkmer.mv64e.mtb.MvhSubmissionType +import dev.pcvolkmer.mv64e.model.MvhSubmissionType +import dev.pcvolkmer.mv64e.model.PatientRecord import org.apache.commons.codec.binary.Base32 import org.apache.commons.codec.digest.DigestUtils import org.slf4j.Logger @@ -58,11 +58,11 @@ class RequestProcessor( private var logger: Logger = LoggerFactory.getLogger("RequestProcessor") - fun processMtbFile(mtbFile: Mtb): Boolean { + fun processMtbFile(mtbFile: PatientRecord): Boolean { return processMtbFile(mtbFile, randomRequestId()) } - fun processMtbFile(mtbFile: Mtb, requestId: RequestId): Boolean { + fun processMtbFile(mtbFile: PatientRecord, requestId: RequestId): Boolean { val isConsentOk = consentProcessor != null && consentProcessor.consentGatedCheckAndTryEmbedding(mtbFile) || consentProcessor == null @@ -127,7 +127,7 @@ class RequestProcessor( RequestType.MTB_FILE, submissionType, RequestStatus.BLOCKED_INITIAL, - Tan(request.content.metadata?.transferTan.orEmpty()) + Tan(request.content.metadata?.transferTAN.orEmpty()) ) ) // Exit - no further processing @@ -164,7 +164,7 @@ class RequestProcessor( RequestType.MTB_FILE, submissionType, RequestStatus.UNKNOWN, - Tan(request.content.metadata?.transferTan.orEmpty()), + Tan(request.content.metadata?.transferTAN.orEmpty()), ) ) @@ -229,7 +229,7 @@ class RequestProcessor( val patientPseudonym = when (pseudonymizedMtbFileRequest) { is DnpmV2MtbFileRequest -> - PatientPseudonym(pseudonymizedMtbFileRequest.content.patient.id) + PatientPseudonym(pseudonymizedMtbFileRequest.content.patient!!.id) } val lastMtbFileRequestForPatient = diff --git a/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt b/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt index 755e6b3..d6318ce 100644 --- a/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt +++ b/src/main/kotlin/dev/dnpm/etl/processor/services/TransformationService.kt @@ -22,16 +22,16 @@ package dev.dnpm.etl.processor.services import com.jayway.jsonpath.JsonPath import com.jayway.jsonpath.PathNotFoundException -import dev.pcvolkmer.mv64e.mtb.Mtb +import dev.pcvolkmer.mv64e.model.PatientRecord import tools.jackson.databind.json.JsonMapper class TransformationService( private val jsonMapper: JsonMapper, private val transformations: List<Transformation>, ) { - fun transform(mtbFile: Mtb): Mtb { + fun transform(mtbFile: PatientRecord): PatientRecord { val json = transform(jsonMapper.writeValueAsString(mtbFile)) - return jsonMapper.readValue(json, Mtb::class.java) + return jsonMapper.readValue(json, PatientRecord::class.java) } private fun transform(content: String): String { |
