mirror of
https://github.com/pcvolkmer/etl-processor.git
synced 2025-07-01 22:22:53 +00:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
d49671f0d4 | |||
3a19212a78 | |||
e95fa2fb12 | |||
1bcc8c13de | |||
2fc3299543 | |||
5575867632 | |||
87658bfa58 | |||
99efd6c98a | |||
e42d11f125 | |||
8b194e7212 | |||
070100eba0 | |||
ce1489d9a1 | |||
ca1e73a0b5 | |||
041bf459ef | |||
c922e27758 | |||
4d5c0ce1fb | |||
bb0bbf5a28 | |||
1b4585d601 | |||
dad3ea80ee | |||
01446bdece | |||
43660a4dcb | |||
8313420de5 | |||
1651f446fe | |||
056a087065 | |||
a730ce2a53 |
8
.github/workflows/deploy.yml
vendored
8
.github/workflows/deploy.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@ -30,6 +30,6 @@ jobs:
|
|||||||
- name: Execute image build and push
|
- name: Execute image build and push
|
||||||
run: |
|
run: |
|
||||||
./gradlew bootBuildImage
|
./gradlew bootBuildImage
|
||||||
docker tag ghcr.io/ccc-mf/etl-processor ghcr.io/ccc-mf/etl-processor:${{ github.ref_name }}
|
docker tag ghcr.io/${{ github.repository }} ghcr.io/${{ github.repository }}:${{ github.ref_name }}
|
||||||
docker push ghcr.io/ccc-mf/etl-processor
|
docker push ghcr.io/${{ github.repository }}
|
||||||
docker push ghcr.io/ccc-mf/etl-processor:${{ github.ref_name }}
|
docker push ghcr.io/${{ github.repository }}:${{ github.ref_name }}
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
@ -27,7 +27,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
|
@ -4,23 +4,23 @@ import org.springframework.boot.gradle.tasks.bundling.BootBuildImage
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
war
|
war
|
||||||
id("org.springframework.boot") version "3.2.3"
|
id("org.springframework.boot") version "3.2.12"
|
||||||
id("io.spring.dependency-management") version "1.1.4"
|
id("io.spring.dependency-management") version "1.1.5"
|
||||||
kotlin("jvm") version "1.9.22"
|
kotlin("jvm") version "1.9.24"
|
||||||
kotlin("plugin.spring") version "1.9.22"
|
kotlin("plugin.spring") version "1.9.24"
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "de.ukw.ccc"
|
group = "dev.dnpm"
|
||||||
version = "0.9.1"
|
version = "0.9-SNAPSHOT"
|
||||||
|
|
||||||
var versions = mapOf(
|
var versions = mapOf(
|
||||||
"bwhc-dto-java" to "0.2.0",
|
"bwhc-dto-java" to "0.3.0",
|
||||||
"hapi-fhir" to "6.10.2",
|
"hapi-fhir" to "6.10.5",
|
||||||
"httpclient5" to "5.2.1",
|
"httpclient5" to "5.2.3",
|
||||||
"mockito-kotlin" to "5.2.1",
|
"mockito-kotlin" to "5.3.1",
|
||||||
// Webjars
|
// Webjars
|
||||||
"echarts" to "5.4.3",
|
"echarts" to "5.4.3",
|
||||||
"htmx.org" to "1.9.10"
|
"htmx.org" to "1.9.12"
|
||||||
)
|
)
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@ -70,7 +70,7 @@ dependencies {
|
|||||||
implementation("ca.uhn.hapi.fhir:hapi-fhir-structures-r4:${versions["hapi-fhir"]}")
|
implementation("ca.uhn.hapi.fhir:hapi-fhir-structures-r4:${versions["hapi-fhir"]}")
|
||||||
implementation("org.apache.httpcomponents.client5:httpclient5:${versions["httpclient5"]}")
|
implementation("org.apache.httpcomponents.client5:httpclient5:${versions["httpclient5"]}")
|
||||||
implementation("com.jayway.jsonpath:json-path")
|
implementation("com.jayway.jsonpath:json-path")
|
||||||
implementation("org.webjars:webjars-locator:0.50")
|
implementation("org.webjars:webjars-locator:0.52")
|
||||||
implementation("org.webjars.npm:echarts:${versions["echarts"]}")
|
implementation("org.webjars.npm:echarts:${versions["echarts"]}")
|
||||||
implementation("org.webjars.npm:htmx.org:${versions["htmx.org"]}")
|
implementation("org.webjars.npm:htmx.org:${versions["htmx.org"]}")
|
||||||
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
|
runtimeOnly("org.mariadb.jdbc:mariadb-java-client")
|
||||||
@ -85,6 +85,8 @@ dependencies {
|
|||||||
testImplementation("org.mockito.kotlin:mockito-kotlin:${versions["mockito-kotlin"]}")
|
testImplementation("org.mockito.kotlin:mockito-kotlin:${versions["mockito-kotlin"]}")
|
||||||
integrationTestImplementation("org.testcontainers:junit-jupiter")
|
integrationTestImplementation("org.testcontainers:junit-jupiter")
|
||||||
integrationTestImplementation("org.testcontainers:postgresql")
|
integrationTestImplementation("org.testcontainers:postgresql")
|
||||||
|
// Override dependency version from org.testcontainers:junit-jupiter - CVE-2024-26308, CVE-2024-25710
|
||||||
|
integrationTestImplementation("org.apache.commons:commons-compress:1.26.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinCompile> {
|
tasks.withType<KotlinCompile> {
|
||||||
@ -111,7 +113,7 @@ task<Test>("integrationTest") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.named<BootBuildImage>("bootBuildImage") {
|
tasks.named<BootBuildImage>("bootBuildImage") {
|
||||||
imageName.set("ghcr.io/ccc-mf/etl-processor")
|
imageName.set("ghcr.io/pcvolkmer/etl-processor")
|
||||||
|
|
||||||
// Binding for CA Certs
|
// Binding for CA Certs
|
||||||
bindings.set(listOf(
|
bindings.set(listOf(
|
||||||
@ -121,7 +123,7 @@ tasks.named<BootBuildImage>("bootBuildImage") {
|
|||||||
environment.set(environment.get() + mapOf(
|
environment.set(environment.get() + mapOf(
|
||||||
// Enable this line to embed CA Certs into image on build time
|
// Enable this line to embed CA Certs into image on build time
|
||||||
//"BP_EMBED_CERTS" to "true",
|
//"BP_EMBED_CERTS" to "true",
|
||||||
"BP_OCI_SOURCE" to "https://github.com/CCC-MF/etl-processor",
|
"BP_OCI_SOURCE" to "https://github.com/pcvolkmer/etl-processor",
|
||||||
"BP_OCI_LICENSES" to "AGPLv3",
|
"BP_OCI_LICENSES" to "AGPLv3",
|
||||||
"BP_OCI_DESCRIPTION" to "ETL Processor for bwHC MTB files"
|
"BP_OCI_DESCRIPTION" to "ETL Processor for bwHC MTB files"
|
||||||
))
|
))
|
||||||
|
@ -57,6 +57,7 @@ class ReportService(
|
|||||||
data class Issue(val severity: Severity, val message: String)
|
data class Issue(val severity: Severity, val message: String)
|
||||||
|
|
||||||
enum class Severity(@JsonValue val value: String) {
|
enum class Severity(@JsonValue val value: String) {
|
||||||
|
FATAL("fatal"),
|
||||||
ERROR("error"),
|
ERROR("error"),
|
||||||
WARNING("warning"),
|
WARNING("warning"),
|
||||||
INFO("info")
|
INFO("info")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of ETL-Processor
|
* This file is part of ETL-Processor
|
||||||
*
|
*
|
||||||
* Copyright (c) 2023 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
|
* Copyright (c) 2024 Comprehensive Cancer Center Mainfranken, Datenintegrationszentrum Philipps-Universität Marburg and Contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published
|
||||||
@ -31,31 +31,31 @@ import org.apache.commons.codec.digest.DigestUtils
|
|||||||
infix fun MtbFile.pseudonymizeWith(pseudonymizeService: PseudonymizeService) {
|
infix fun MtbFile.pseudonymizeWith(pseudonymizeService: PseudonymizeService) {
|
||||||
val patientPseudonym = pseudonymizeService.patientPseudonym(this.patient.id)
|
val patientPseudonym = pseudonymizeService.patientPseudonym(this.patient.id)
|
||||||
|
|
||||||
this.episode.patient = patientPseudonym
|
this.episode?.patient = patientPseudonym
|
||||||
this.carePlans.forEach { it.patient = patientPseudonym }
|
this.carePlans?.forEach { it.patient = patientPseudonym }
|
||||||
this.patient.id = patientPseudonym
|
this.patient.id = patientPseudonym
|
||||||
this.claims.forEach { it.patient = patientPseudonym }
|
this.claims?.forEach { it.patient = patientPseudonym }
|
||||||
this.consent.patient = patientPseudonym
|
this.consent?.patient = patientPseudonym
|
||||||
this.claimResponses.forEach { it.patient = patientPseudonym }
|
this.claimResponses?.forEach { it.patient = patientPseudonym }
|
||||||
this.diagnoses.forEach { it.patient = patientPseudonym }
|
this.diagnoses?.forEach { it.patient = patientPseudonym }
|
||||||
this.ecogStatus.forEach { it.patient = patientPseudonym }
|
this.ecogStatus?.forEach { it.patient = patientPseudonym }
|
||||||
this.familyMemberDiagnoses.forEach { it.patient = patientPseudonym }
|
this.familyMemberDiagnoses?.forEach { it.patient = patientPseudonym }
|
||||||
this.geneticCounsellingRequests.forEach { it.patient = patientPseudonym }
|
this.geneticCounsellingRequests?.forEach { it.patient = patientPseudonym }
|
||||||
this.histologyReevaluationRequests.forEach { it.patient = patientPseudonym }
|
this.histologyReevaluationRequests?.forEach { it.patient = patientPseudonym }
|
||||||
this.histologyReports.forEach {
|
this.histologyReports?.forEach {
|
||||||
it.patient = patientPseudonym
|
it.patient = patientPseudonym
|
||||||
it.tumorMorphology.patient = patientPseudonym
|
it.tumorMorphology?.patient = patientPseudonym
|
||||||
}
|
}
|
||||||
this.lastGuidelineTherapies.forEach { it.patient = patientPseudonym }
|
this.lastGuidelineTherapies?.forEach { it.patient = patientPseudonym }
|
||||||
this.molecularPathologyFindings.forEach { it.patient = patientPseudonym }
|
this.molecularPathologyFindings?.forEach { it.patient = patientPseudonym }
|
||||||
this.molecularTherapies.forEach { molecularTherapy -> molecularTherapy.history.forEach { it.patient = patientPseudonym } }
|
this.molecularTherapies?.forEach { molecularTherapy -> molecularTherapy.history.forEach { it.patient = patientPseudonym } }
|
||||||
this.ngsReports.forEach { it.patient = patientPseudonym }
|
this.ngsReports?.forEach { it.patient = patientPseudonym }
|
||||||
this.previousGuidelineTherapies.forEach { it.patient = patientPseudonym }
|
this.previousGuidelineTherapies?.forEach { it.patient = patientPseudonym }
|
||||||
this.rebiopsyRequests.forEach { it.patient = patientPseudonym }
|
this.rebiopsyRequests?.forEach { it.patient = patientPseudonym }
|
||||||
this.recommendations.forEach { it.patient = patientPseudonym }
|
this.recommendations?.forEach { it.patient = patientPseudonym }
|
||||||
this.responses.forEach { it.patient = patientPseudonym }
|
this.responses?.forEach { it.patient = patientPseudonym }
|
||||||
this.studyInclusionRequests.forEach { it.patient = patientPseudonym }
|
this.studyInclusionRequests?.forEach { it.patient = patientPseudonym }
|
||||||
this.specimens.forEach { it.patient = patientPseudonym }
|
this.specimens?.forEach { it.patient = patientPseudonym }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,7 +134,6 @@ class StatisticsRestController(
|
|||||||
@GetMapping(path = ["events"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
|
@GetMapping(path = ["events"], produces = [MediaType.TEXT_EVENT_STREAM_VALUE])
|
||||||
fun updater(): Flux<ServerSentEvent<Any>> {
|
fun updater(): Flux<ServerSentEvent<Any>> {
|
||||||
return statisticsUpdateProducer.asFlux().flatMap {
|
return statisticsUpdateProducer.asFlux().flatMap {
|
||||||
println(it)
|
|
||||||
Flux.fromIterable(
|
Flux.fromIterable(
|
||||||
listOf(
|
listOf(
|
||||||
ServerSentEvent.builder<Any>()
|
ServerSentEvent.builder<Any>()
|
||||||
|
@ -55,6 +55,7 @@
|
|||||||
<td th:if="${issue.severity.value == 'info'}" class="bg-blue"><small>[[ ${issue.severity} ]]</small></td>
|
<td th:if="${issue.severity.value == 'info'}" class="bg-blue"><small>[[ ${issue.severity} ]]</small></td>
|
||||||
<td th:if="${issue.severity.value == 'warning'}" class="bg-yellow"><small>[[ ${issue.severity} ]]</small></td>
|
<td th:if="${issue.severity.value == 'warning'}" class="bg-yellow"><small>[[ ${issue.severity} ]]</small></td>
|
||||||
<td th:if="${issue.severity.value == 'error'}" class="bg-red"><small>[[ ${issue.severity} ]]</small></td>
|
<td th:if="${issue.severity.value == 'error'}" class="bg-red"><small>[[ ${issue.severity} ]]</small></td>
|
||||||
|
<td th:if="${issue.severity.value == 'fatal'}" class="bg-red"><small>[[ ${issue.severity} ]]</small></td>
|
||||||
<td>[[ ${issue.message} ]]</td>
|
<td>[[ ${issue.message} ]]</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -134,4 +134,65 @@ class ExtensionsTest {
|
|||||||
.isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098")
|
.isEqualTo("TESTDOMAIN44e20a53bbbf9f3ae39626d05df7014dcd77d6098")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldNotThrowExceptionOnNullValues(@Mock pseudonymizeService: PseudonymizeService) {
|
||||||
|
doAnswer {
|
||||||
|
it.arguments[0]
|
||||||
|
"PSEUDO-ID"
|
||||||
|
}.whenever(pseudonymizeService).patientPseudonym(ArgumentMatchers.anyString())
|
||||||
|
|
||||||
|
doAnswer {
|
||||||
|
"TESTDOMAIN"
|
||||||
|
}.whenever(pseudonymizeService).prefix()
|
||||||
|
|
||||||
|
val mtbFile = MtbFile.builder()
|
||||||
|
.withPatient(
|
||||||
|
Patient.builder()
|
||||||
|
.withId("1")
|
||||||
|
.withBirthDate("2000-08-08")
|
||||||
|
.withGender(Patient.Gender.MALE)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withConsent(
|
||||||
|
Consent.builder()
|
||||||
|
.withId("1")
|
||||||
|
.withStatus(Consent.Status.ACTIVE)
|
||||||
|
.withPatient("123")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withEpisode(
|
||||||
|
Episode.builder()
|
||||||
|
.withId("1")
|
||||||
|
.withPatient("1")
|
||||||
|
.withPeriod(PeriodStart("2023-08-08"))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.withClaims(null)
|
||||||
|
.withDiagnoses(null)
|
||||||
|
.withCarePlans(null)
|
||||||
|
.withClaimResponses(null)
|
||||||
|
.withEcogStatus(null)
|
||||||
|
.withFamilyMemberDiagnoses(null)
|
||||||
|
.withGeneticCounsellingRequests(null)
|
||||||
|
.withHistologyReevaluationRequests(null)
|
||||||
|
.withHistologyReports(null)
|
||||||
|
.withLastGuidelineTherapies(null)
|
||||||
|
.withMolecularPathologyFindings(null)
|
||||||
|
.withMolecularTherapies(null)
|
||||||
|
.withNgsReports(null)
|
||||||
|
.withPreviousGuidelineTherapies(null)
|
||||||
|
.withRebiopsyRequests(null)
|
||||||
|
.withRecommendations(null)
|
||||||
|
.withResponses(null)
|
||||||
|
.withStudyInclusionRequests(null)
|
||||||
|
.withSpecimens(null)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
mtbFile.pseudonymizeWith(pseudonymizeService)
|
||||||
|
mtbFile.anonymizeContentWith(pseudonymizeService)
|
||||||
|
|
||||||
|
|
||||||
|
assertThat(mtbFile.episode.id).isNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -43,20 +43,23 @@ class ReportServiceTest {
|
|||||||
"issues": [
|
"issues": [
|
||||||
{ "severity": "info", "message": "Info Message" },
|
{ "severity": "info", "message": "Info Message" },
|
||||||
{ "severity": "warning", "message": "Warning Message" },
|
{ "severity": "warning", "message": "Warning Message" },
|
||||||
{ "severity": "error", "message": "Error Message" }
|
{ "severity": "error", "message": "Error Message" },
|
||||||
|
{ "severity": "fatal", "message": "Fatal Message" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
val actual = this.reportService.deserialize(json)
|
val actual = this.reportService.deserialize(json)
|
||||||
|
|
||||||
assertThat(actual).hasSize(3)
|
assertThat(actual).hasSize(4)
|
||||||
assertThat(actual[0].severity).isEqualTo(ReportService.Severity.ERROR)
|
assertThat(actual[0].severity).isEqualTo(ReportService.Severity.FATAL)
|
||||||
assertThat(actual[0].message).isEqualTo("Error Message")
|
assertThat(actual[0].message).isEqualTo("Fatal Message")
|
||||||
assertThat(actual[1].severity).isEqualTo(ReportService.Severity.WARNING)
|
assertThat(actual[1].severity).isEqualTo(ReportService.Severity.ERROR)
|
||||||
assertThat(actual[1].message).isEqualTo("Warning Message")
|
assertThat(actual[1].message).isEqualTo("Error Message")
|
||||||
assertThat(actual[2].severity).isEqualTo(ReportService.Severity.INFO)
|
assertThat(actual[2].severity).isEqualTo(ReportService.Severity.WARNING)
|
||||||
assertThat(actual[2].message).isEqualTo("Info Message")
|
assertThat(actual[2].message).isEqualTo("Warning Message")
|
||||||
|
assertThat(actual[3].severity).isEqualTo(ReportService.Severity.INFO)
|
||||||
|
assertThat(actual[3].message).isEqualTo("Info Message")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Reference in New Issue
Block a user