1
0
mirror of https://github.com/pcvolkmer/onco-analytics-monitor.git synced 2025-04-19 19:16:52 +00:00

feat: add interface for ConditionRepository methods

This commit is contained in:
Paul-Christian Volkmer 2024-08-07 20:06:51 +02:00
parent 3dc5d79808
commit 32ac53934f
9 changed files with 107 additions and 24 deletions

View File

@ -1,6 +1,6 @@
package dev.pcvolkmer.oncoanalytics.monitor package dev.pcvolkmer.oncoanalytics.monitor
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionInMemoryRepository import dev.pcvolkmer.oncoanalytics.monitor.conditions.InMemoryConditionRepository
import dev.pcvolkmer.oncoanalytics.monitor.conditions.Statistics import dev.pcvolkmer.oncoanalytics.monitor.conditions.Statistics
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication import org.springframework.boot.runApplication
@ -18,18 +18,18 @@ class OncoAnalyticsMonitorApplication {
} }
@Bean @Bean
fun obdsXmlConditionRepository(): ConditionInMemoryRepository { fun obdsXmlConditionRepository(): InMemoryConditionRepository {
return ConditionInMemoryRepository() return InMemoryConditionRepository()
} }
@Bean @Bean
fun fhirObdsConditionRepository(): ConditionInMemoryRepository { fun fhirObdsConditionRepository(): InMemoryConditionRepository {
return ConditionInMemoryRepository() return InMemoryConditionRepository()
} }
@Bean @Bean
fun fhirPseudonymizedConditionRepository(): ConditionInMemoryRepository { fun fhirPseudonymizedConditionRepository(): InMemoryConditionRepository {
return ConditionInMemoryRepository() return InMemoryConditionRepository()
} }
} }

View File

@ -0,0 +1,32 @@
package dev.pcvolkmer.oncoanalytics.monitor.conditions
/**
* Interface declaring a data repository to hold (latest) conditions
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
interface ConditionRepository {
/**
* Save condition if no newer condition (by id and version) is present
*
* @param condition The condition to be saved
* @return Will return true if successful
*/
fun saveIfNewerVersion(condition: Condition): Boolean
/**
* Save condition without any checks
*
* @param condition The condition to be saved
* @return Will return true if successful
*/
fun save(condition: Condition): Boolean
/**
* Return all saved conditions
*/
fun findAll(): List<Condition>
}

View File

@ -2,6 +2,12 @@ package dev.pcvolkmer.oncoanalytics.monitor.conditions
import org.apache.commons.codec.digest.DigestUtils import org.apache.commons.codec.digest.DigestUtils
/**
* Type to be used for the condition ID
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
@JvmInline @JvmInline
value class ConditionId(val value: String) { value class ConditionId(val value: String) {
companion object { companion object {
@ -11,13 +17,30 @@ value class ConditionId(val value: String) {
} }
} }
/**
* A condition
*
* @property id The conditions unique ID
* @property icd10 The ICD10 code of the related diagnosis
* @property version (if present) The version of the related oBDS message or zero
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
data class Condition(val id: ConditionId, val icd10: String, val version: Int = 0) data class Condition(val id: ConditionId, val icd10: String, val version: Int = 0)
class ConditionInMemoryRepository { /**
* In memory implementation of a ConditionRepository
*
* @author Paul-Christian Volkmer
* @since 0.1.0
* @see ConditionRepository
*/
class InMemoryConditionRepository : ConditionRepository {
private val conditions = mutableMapOf<ConditionId, Condition>() private val conditions = mutableMapOf<ConditionId, Condition>()
fun saveIfNewerVersion(condition: Condition): Boolean { override fun saveIfNewerVersion(condition: Condition): Boolean {
if ((this.conditions[condition.id]?.version ?: 0) < condition.version) { if ((this.conditions[condition.id]?.version ?: 0) < condition.version) {
this.conditions[condition.id] = condition this.conditions[condition.id] = condition
return true return true
@ -25,12 +48,12 @@ class ConditionInMemoryRepository {
return false return false
} }
fun save(condition: Condition): Boolean { override fun save(condition: Condition): Boolean {
this.conditions[condition.id] = condition this.conditions[condition.id] = condition
return true return true
} }
fun findAll(): List<Condition> { override fun findAll(): List<Condition> {
return conditions.values.toList() return conditions.values.toList()
} }

View File

@ -1,8 +1,26 @@
package dev.pcvolkmer.oncoanalytics.monitor.conditions package dev.pcvolkmer.oncoanalytics.monitor.conditions
/**
* A statistics summary
*
* @property name The name of the statistics e.g. the source of data
* @property entries A list of entries containing information for each ICD10 code group
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
data class Statistics( data class Statistics(
val name: String, val name: String,
val entries: List<StatisticsEntry> val entries: List<StatisticsEntry>
) )
/**
* A statistics entry
*
* @property name The name of the ICD10 code group
* @property count Number of recognized oBDS or FHIR messages for the OCD10 code group
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
data class StatisticsEntry(val name: String, val count: Int) data class StatisticsEntry(val name: String, val count: Int)

View File

@ -1,6 +1,6 @@
package dev.pcvolkmer.oncoanalytics.monitor package dev.pcvolkmer.oncoanalytics.monitor
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionInMemoryRepository import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionRepository
import dev.pcvolkmer.oncoanalytics.monitor.conditions.Statistics import dev.pcvolkmer.oncoanalytics.monitor.conditions.Statistics
import dev.pcvolkmer.oncoanalytics.monitor.conditions.StatisticsEntry import dev.pcvolkmer.oncoanalytics.monitor.conditions.StatisticsEntry
@ -32,7 +32,15 @@ val allKeys = listOf(
"Other" "Other"
) )
fun fetchStatistics(name: String, source: ConditionInMemoryRepository): Statistics { /**
* Fetch statistics using given ConditionRepository
*
* @see ConditionRepository
*
* @author Paul-Christian Volkmer
* @since 0.1.0
*/
fun fetchStatistics(name: String, source: ConditionRepository): Statistics {
fun mapIcd10Code(code: String): String { fun mapIcd10Code(code: String): String {
val c = when (code) { val c = when (code) {
"D39.1", "D09.0", "D41.4" -> code "D39.1", "D09.0", "D41.4" -> code
@ -72,5 +80,7 @@ fun fetchStatistics(name: String, source: ConditionInMemoryRepository): Statisti
.groupBy { mapIcd10Code(it.icd10) } .groupBy { mapIcd10Code(it.icd10) }
.mapValues { it.value.size } .mapValues { it.value.size }
return Statistics(name, allKeys.map { StatisticsEntry(it, 0) }.map { StatisticsEntry(it.name, entries.getOrDefault(it.name, 0)) }) return Statistics(
name,
allKeys.map { StatisticsEntry(it, 0) }.map { StatisticsEntry(it.name, entries.getOrDefault(it.name, 0)) })
} }

View File

@ -4,7 +4,7 @@ import ca.uhn.fhir.context.FhirContext
import dev.pcvolkmer.oncoanalytics.monitor.StatisticsSink import dev.pcvolkmer.oncoanalytics.monitor.StatisticsSink
import dev.pcvolkmer.oncoanalytics.monitor.conditions.Condition import dev.pcvolkmer.oncoanalytics.monitor.conditions.Condition
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionId import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionId
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionInMemoryRepository import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionRepository
import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics
import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.Bundle
import org.springframework.beans.factory.annotation.Qualifier import org.springframework.beans.factory.annotation.Qualifier
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component
@Component @Component
class FhirObdsTopicMonitor( class FhirObdsTopicMonitor(
@Qualifier("fhirObdsConditionRepository") @Qualifier("fhirObdsConditionRepository")
private val conditionRepository: ConditionInMemoryRepository, private val conditionRepository: ConditionRepository,
statisticsEventProducer: StatisticsSink, statisticsEventProducer: StatisticsSink,
) : TopicMonitor(statisticsEventProducer) { ) : TopicMonitor(statisticsEventProducer) {

View File

@ -4,7 +4,7 @@ import ca.uhn.fhir.context.FhirContext
import dev.pcvolkmer.oncoanalytics.monitor.StatisticsSink import dev.pcvolkmer.oncoanalytics.monitor.StatisticsSink
import dev.pcvolkmer.oncoanalytics.monitor.conditions.Condition import dev.pcvolkmer.oncoanalytics.monitor.conditions.Condition
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionId import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionId
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionInMemoryRepository import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionRepository
import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics
import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.Bundle
import org.springframework.beans.factory.annotation.Qualifier import org.springframework.beans.factory.annotation.Qualifier
@ -17,7 +17,7 @@ import org.springframework.stereotype.Component
@Component @Component
class FhirPseudonymizedTopicMonitor( class FhirPseudonymizedTopicMonitor(
@Qualifier("fhirPseudonymizedConditionRepository") @Qualifier("fhirPseudonymizedConditionRepository")
private val conditionRepository: ConditionInMemoryRepository, private val conditionRepository: ConditionRepository,
statisticsEventProducer: StatisticsSink, statisticsEventProducer: StatisticsSink,
) : TopicMonitor(statisticsEventProducer) { ) : TopicMonitor(statisticsEventProducer) {

View File

@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import dev.pcvolkmer.oncoanalytics.monitor.StatisticsSink import dev.pcvolkmer.oncoanalytics.monitor.StatisticsSink
import dev.pcvolkmer.oncoanalytics.monitor.conditions.Condition import dev.pcvolkmer.oncoanalytics.monitor.conditions.Condition
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionId import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionId
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionInMemoryRepository import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionRepository
import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics
import org.springframework.beans.factory.annotation.Qualifier import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.kafka.annotation.KafkaListener import org.springframework.kafka.annotation.KafkaListener
@ -22,7 +22,7 @@ import javax.xml.xpath.XPathFactory
@Component @Component
class ObdsXmlTopicMonitor( class ObdsXmlTopicMonitor(
@Qualifier("obdsXmlConditionRepository") @Qualifier("obdsXmlConditionRepository")
private val conditionRepository: ConditionInMemoryRepository, private val conditionRepository: ConditionRepository,
private val objectMapper: ObjectMapper, private val objectMapper: ObjectMapper,
statisticsEventProducer: StatisticsSink, statisticsEventProducer: StatisticsSink,
) : TopicMonitor(statisticsEventProducer) { ) : TopicMonitor(statisticsEventProducer) {

View File

@ -1,6 +1,6 @@
package dev.pcvolkmer.oncoanalytics.monitor.web package dev.pcvolkmer.oncoanalytics.monitor.web
import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionInMemoryRepository import dev.pcvolkmer.oncoanalytics.monitor.conditions.ConditionRepository
import dev.pcvolkmer.oncoanalytics.monitor.conditions.Statistics import dev.pcvolkmer.oncoanalytics.monitor.conditions.Statistics
import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics import dev.pcvolkmer.oncoanalytics.monitor.fetchStatistics
import org.springframework.beans.factory.annotation.Qualifier import org.springframework.beans.factory.annotation.Qualifier
@ -12,11 +12,11 @@ import org.springframework.web.bind.annotation.RestController
@RequestMapping(path = ["/statistics"]) @RequestMapping(path = ["/statistics"])
class StatisticsController( class StatisticsController(
@Qualifier("obdsXmlConditionRepository") @Qualifier("obdsXmlConditionRepository")
private val obdsXmlConditionRepository: ConditionInMemoryRepository, private val obdsXmlConditionRepository: ConditionRepository,
@Qualifier("fhirObdsConditionRepository") @Qualifier("fhirObdsConditionRepository")
private val fhirObdsConditionRepository: ConditionInMemoryRepository, private val fhirObdsConditionRepository: ConditionRepository,
@Qualifier("fhirPseudonymizedConditionRepository") @Qualifier("fhirPseudonymizedConditionRepository")
private val fhirPseudonymizedConditionRepository: ConditionInMemoryRepository, private val fhirPseudonymizedConditionRepository: ConditionRepository,
) { ) {
@GetMapping(path = ["obdsxml"]) @GetMapping(path = ["obdsxml"])