diff --git a/.github/integration-test/ontology/dse/profile_tree.json b/.github/integration-test/ontology/dse/profile_tree.json
index 718c85e4..0011dc10 100644
--- a/.github/integration-test/ontology/dse/profile_tree.json
+++ b/.github/integration-test/ontology/dse/profile_tree.json
@@ -1,63 +1,135 @@
{
- "name": "Root",
- "module": "no-module",
- "url": "no-url",
- "children": [
+ "name": "Root",
+ "module": "no-module",
+ "url": "no-url",
+ "children": [
+ {
+ "id": "e5dbef02-a690-4f5a-b1b9-081302aff04d",
+ "name": "modul-medikation",
+ "display": {
+ "original": "Medikation",
+ "translations": [
+ {
+ "language": "de-DE",
+ "value": "Medikation"
+ },
+ {
+ "language": "en-US",
+ "value": "Medication"
+ }
+ ]
+ },
+ "url": "modul-medikation",
+ "module": "modul-medikation",
+ "selectable": false,
+ "leaf": false,
+ "children": [
{
- "id": "de5c2903-00aa-4d64-92e5-2161d56e3daf",
- "children": [
- {
- "id": "69f4718f-1767-4517-90f8-6c079f627eed",
- "name": "MII_PR_Medikation_MedicationStatement",
- "display": "MII PR Medikation MedicationStatement",
- "module": "modul-medikation",
- "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationStatement",
- "leaf": true,
- "selectable": true
- },
- {
- "id": "83b4d6be-b3e1-451a-adf2-c307477e7b97",
- "name": "MII_PR_Medikation_Medikationsliste",
- "display": "MII PR Medikation Medikationsliste",
- "module": "modul-medikation",
- "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/medikationsliste",
- "leaf": true,
- "selectable": true
- },
- {
- "id": "fd375ed9-b3cd-414f-8a56-c70e10bb9609",
- "name": "MII_PR_Medikation_MedicationRequest",
- "display": "MII PR Medikation MedicationRequest",
- "module": "modul-medikation",
- "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationRequest",
- "leaf": true,
- "selectable": true
- },
- {
- "id": "323a3ad1-1c10-45f5-848a-2dc5fb100c47",
- "name": "MII_PR_Medikation_Medication",
- "display": "MII PR Medikation Medication",
- "module": "modul-medikation",
- "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/Medication",
- "leaf": true,
- "selectable": true
- },
- {
- "id": "81ed0f03-1d77-49c9-8391-d4c25702652c",
- "name": "MII_PR_Medikation_MedicationAdministration",
- "display": "MII PR Medikation MedicationAdministration",
- "module": "modul-medikation",
- "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationAdministration",
- "leaf": true,
- "selectable": true
- }
- ],
- "name": "modul-medikation",
- "display": "Medikation",
- "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationStatement",
- "module": "modul-medikation",
- "selectable": true,
- "leaf": false
+ "id": "5486577b-430b-4a42-a3c8-28c6d6eaf4e8",
+ "name": "MII_PR_Medikation_MedicationStatement",
+ "display": {
+ "original": "MII PR Medikation MedicationStatement",
+ "translations": [
+ {
+ "language": "de-DE",
+ "value": ""
+ },
+ {
+ "language": "en-US",
+ "value": "MII PR Medikation MedicationStatement"
+ }
+ ]
+ },
+ "module": "modul-medikation",
+ "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationStatement",
+ "leaf": true,
+ "selectable": true
+ },
+ {
+ "id": "491759f1-8afc-4a35-9a35-34642211f02a",
+ "name": "MII_PR_Medikation_Medikationsliste",
+ "display": {
+ "original": "MII PR Medikation Medikationsliste",
+ "translations": [
+ {
+ "language": "de-DE",
+ "value": ""
+ },
+ {
+ "language": "en-US",
+ "value": "MII PR Medikation Medicationlist"
+ }
+ ]
+ },
+ "module": "modul-medikation",
+ "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/medikationsliste",
+ "leaf": true,
+ "selectable": true
+ },
+ {
+ "id": "9d1fe081-3964-4951-b743-716d1b60d779",
+ "name": "MII_PR_Medikation_MedicationRequest",
+ "display": {
+ "original": "MII PR Medikation MedicationRequest",
+ "translations": [
+ {
+ "language": "de-DE",
+ "value": ""
+ },
+ {
+ "language": "en-US",
+ "value": "MII PR Medikation MedicationRequest"
+ }
+ ]
+ },
+ "module": "modul-medikation",
+ "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationRequest",
+ "leaf": true,
+ "selectable": true
+ },
+ {
+ "id": "1026f31f-78ec-4e20-9b40-c5b02b857bc3",
+ "name": "MII_PR_Medikation_Medication",
+ "display": {
+ "original": "MII PR Medikation Medication",
+ "translations": [
+ {
+ "language": "de-DE",
+ "value": ""
+ },
+ {
+ "language": "en-US",
+ "value": "MII PR Medikation Medication"
+ }
+ ]
+ },
+ "module": "modul-medikation",
+ "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/Medication",
+ "leaf": true,
+ "selectable": true
+ },
+ {
+ "id": "d8affe77-892f-45b5-8747-b5ca5400d1be",
+ "name": "MII_PR_Medikation_MedicationAdministration",
+ "display": {
+ "original": "MII PR Medikation MedicationAdministration",
+ "translations": [
+ {
+ "language": "de-DE",
+ "value": ""
+ },
+ {
+ "language": "en-US",
+ "value": "MII PR Medikation MedicationAdministration"
+ }
+ ]
+ },
+ "module": "modul-medikation",
+ "url": "https://www.medizininformatik-initiative.de/fhir/core/modul-medikation/StructureDefinition/MedicationAdministration",
+ "leaf": true,
+ "selectable": true
}
- ]
+ ]
+ }
+ ]
}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9a7ec987..d146abe4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,4 +56,6 @@ googleCodeStyle.xml
result.log
ontology
+update-availability/*
+!update-availability/README.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 32f2ca2a..7379ee0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+## [UNRELEASED] - yyyy-mm-dd
+
+### Added
+### Changed
+### Deprecated
+### Removed
+### Fixed
+### Security
+
+## [6.0.0-alpha.3] - 2024-10-21
+
+### Changed
+- Allow empty search
+- Change structure of dse profile and details for new translation structure
+
## [6.0.0-alpha.2] - 2024-09-04
### Added
diff --git a/docker-compose.yml b/docker-compose.yml
index 8468c98f..7fada739 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -139,7 +139,7 @@ services:
condition: service_healthy
environment:
ELASTIC_HOST: http://dataportal-elastic:9200
- ELASTIC_GIT_TAG: v3.0.0-test.2
+ ELASTIC_GIT_TAG: v3.0.0-alpha
ELASTIC_FILEPATH: https://github.com/medizininformatik-initiative/fhir-ontology-generator/raw/TAGPLACEHOLDER/example/fdpg-ontology/
ELASTIC_FILENAME: elastic.zip
# if set to false, existing indices are not overridden.
diff --git a/elastic-update-availability.sh b/elastic-update-availability.sh
new file mode 100755
index 00000000..5c8bfdcc
--- /dev/null
+++ b/elastic-update-availability.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+set -e
+
+BASE_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit 1 ; pwd -P )"
+ES_BASE_URL=${ES_BASE_URL:-http://localhost:9200}
+ES_INDEX=${ES_INDEX:-ontology}
+
+FILES=("$BASE_DIR"/update-availability/*)
+for availUpdateBundle in "${FILES[@]}"; do
+ if [[ $(basename "$availUpdateBundle") == *.json ]]; then
+ echo "Sending Availability Update bundle $availUpdateBundle ..."
+ response=$(curl --write-out "%{http_code}" -s --output /dev/null -XPOST -H 'Content-Type: application/json' --data-binary @"$availUpdateBundle" "$ES_BASE_URL/$ES_INDEX/_bulk")
+ echo "$response"
+ else
+ echo "Skipping $availUpdateBundle (not a .json file)"
+ fi
+done
diff --git a/pom.xml b/pom.xml
index fa82226f..d4ad56e1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,13 +6,13 @@
org.springframework.boot
spring-boot-starter-parent
- 3.3.3
+ 3.3.4
de.medizininformatik-initiative
DataportalBackend
- 6.0.0-alpha.2
+ 6.0.0-alpha.3
Dataportal Backend
Backend of the Dataportal
@@ -27,7 +27,7 @@
17
4.10.0
4.10.0
- v3.0.0-test.2
+ v3.0.0-alpha
@@ -49,17 +49,17 @@
io.undertow
undertow-core
- 2.3.16.Final
+ 2.3.17.Final
io.undertow
undertow-servlet
- 2.3.16.Final
+ 2.3.17.Final
io.undertow
undertow-websockets-jsr
- 2.3.16.Final
+ 2.3.17.Final
@@ -141,7 +141,7 @@
org.springdoc
springdoc-openapi-starter-webmvc-ui
- 2.0.4
+ 2.6.0
@@ -198,6 +198,12 @@
6.6.2
+
+ ca.uhn.hapi.fhir
+ org.hl7.fhir.utilities
+ 6.3.26
+
+
com.bucket4j
bucket4j-core
@@ -237,7 +243,7 @@
de.medizininformatik-initiative
sq2cql
- 0.3.0
+ v0.5.0-alpha.1
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/config/WebSecurityConfig.java b/src/main/java/de/numcodex/feasibility_gui_backend/config/WebSecurityConfig.java
index 6c0896d9..1f6982de 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/config/WebSecurityConfig.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/config/WebSecurityConfig.java
@@ -51,7 +51,7 @@ public class WebSecurityConfig {
public static final String PATH_DSE = "/dse";
public static final String PATH_CODEABLE_CONCEPT = "/codeable-concept";
public static final String PATH_SWAGGER_UI = "/swagger-ui/**";
- public static final String PATH_SWAGGER_CONFIG = "/v4/api-docs/**";
+ public static final String PATH_SWAGGER_CONFIG = "/v3/api-docs/**";
@Value("${app.keycloakAllowedRole}")
private String keycloakAllowedRole;
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DisplayEntry.java b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DisplayEntry.java
new file mode 100644
index 00000000..2fae710f
--- /dev/null
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DisplayEntry.java
@@ -0,0 +1,15 @@
+package de.numcodex.feasibility_gui_backend.dse.api;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+
+import java.util.List;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Builder
+public record DisplayEntry(
+ @JsonProperty String original,
+ @JsonProperty List translations
+ ) {
+}
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfile.java b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfile.java
index 649b0234..0ff50e78 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfile.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfile.java
@@ -10,7 +10,7 @@
@Builder
public record DseProfile(
@JsonProperty String url,
- @JsonProperty String display,
+ @JsonProperty DisplayEntry display,
@JsonProperty List fields,
@JsonProperty List filters,
@JsonProperty String errorCode,
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfileTreeNode.java b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfileTreeNode.java
index 93c954a5..4e8f9192 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfileTreeNode.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/DseProfileTreeNode.java
@@ -12,7 +12,7 @@ public record DseProfileTreeNode(
@JsonProperty String id,
@JsonProperty List children,
@JsonProperty String name,
- @JsonProperty String display,
+ @JsonProperty DisplayEntry display,
@JsonProperty String module,
@JsonProperty String url,
@JsonProperty boolean leaf,
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/Field.java b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/Field.java
index 4ca0b3b4..a9312877 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/Field.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/Field.java
@@ -10,8 +10,8 @@
@Builder
public record Field(
@JsonProperty String id,
- @JsonProperty String display,
- @JsonProperty String name,
+ @JsonProperty DisplayEntry display,
+ @JsonProperty DisplayEntry description,
@JsonProperty String type,
@JsonProperty List children
) {
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/LocalizedValue.java b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/LocalizedValue.java
new file mode 100644
index 00000000..e2edf722
--- /dev/null
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/dse/api/LocalizedValue.java
@@ -0,0 +1,13 @@
+package de.numcodex.feasibility_gui_backend.dse.api;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Builder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Builder
+public record LocalizedValue(
+ @JsonProperty String language,
+ @JsonProperty String value
+) {
+}
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/query/QueryHandlerService.java b/src/main/java/de/numcodex/feasibility_gui_backend/query/QueryHandlerService.java
index 802573ac..2bfccdec 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/query/QueryHandlerService.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/query/QueryHandlerService.java
@@ -203,6 +203,7 @@ private Query convertQueryToApi(de.numcodex.feasibility_gui_backend.query.persis
.content(jsonUtil.readValue(in.getQueryContent().getQueryContent(), StructuredQuery.class))
.label(savedQuery.get().getLabel())
.comment(savedQuery.get().getComment())
+ .totalNumberOfPatients(savedQuery.get().getResultSize())
.build();
} else {
return Query.builder()
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/query/api/Query.java b/src/main/java/de/numcodex/feasibility_gui_backend/query/api/Query.java
index afd5e2a2..853859ab 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/query/api/Query.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/query/api/Query.java
@@ -11,7 +11,8 @@ public record Query(
@JsonProperty long id,
@JsonProperty StructuredQuery content,
@JsonProperty String label,
- @JsonProperty String comment
+ @JsonProperty String comment,
+ @JsonProperty long totalNumberOfPatients
) {
}
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/query/translation/QueryTranslatorSpringConfig.java b/src/main/java/de/numcodex/feasibility_gui_backend/query/translation/QueryTranslatorSpringConfig.java
index de1d42dd..6f246e41 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/query/translation/QueryTranslatorSpringConfig.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/query/translation/QueryTranslatorSpringConfig.java
@@ -5,7 +5,8 @@
import de.numcodex.sq2cql.Translator;
import de.numcodex.sq2cql.model.Mapping;
import de.numcodex.sq2cql.model.MappingContext;
-import de.numcodex.sq2cql.model.TermCodeNode;
+import de.numcodex.sq2cql.model.MappingTreeBase;
+import de.numcodex.sq2cql.model.MappingTreeModuleRoot;
import org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
@@ -18,6 +19,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@@ -78,35 +80,47 @@ QueryTranslationComponent createQueryTranslationService(@Qualifier("json") Query
@Bean
Translator createCqlTranslator(@Qualifier("translation") ObjectMapper jsonUtil) throws IOException {
var mappings = jsonUtil.readValue(new File(mappingsFile), Mapping[].class);
- var conceptTree = jsonUtil.readValue(new File(conceptTreeFile), TermCodeNode.class);
+ var mappingTreeBase = new MappingTreeBase(Arrays.stream(jsonUtil.readValue(new File(conceptTreeFile), MappingTreeModuleRoot[].class)).toList());
+
return Translator.of(MappingContext.of(
Stream.of(mappings)
.collect(Collectors.toMap(Mapping::key, Function.identity(), (a, b) -> a)),
- conceptTree,
- Map.ofEntries(entry("http://fhir.de/CodeSystem/bfarm/icd-10-gm", "icd10"),
- entry("mii.abide", "abide"),
- entry("http://fhir.de/CodeSystem/bfarm/ops", "ops"),
- entry("http://dicom.nema.org/resources/ontology/DCM", "dcm"),
- entry("https://www.medizininformatik-initiative.de/fhir/core/modul-person/CodeSystem/Vitalstatus", "vitalstatus"),
- entry("http://loinc.org", "loinc"),
- entry("https://fhir.bbmri.de/CodeSystem/SampleMaterialType", "sample"),
- entry("http://fhir.de/CodeSystem/bfarm/atc", "atc"),
- entry("http://snomed.info/sct", "snomed"),
- entry("http://terminology.hl7.org/CodeSystem/condition-ver-status", "cvs"),
- entry("http://hl7.org/fhir/administrative-gender", "gender"),
- entry("urn:oid:1.2.276.0.76.5.409", "urn409"),
- entry(
- "https://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/ecrf-parameter-codes",
- "numecrf"),
- entry("urn:iso:std:iso:3166", "iso3166"),
- entry("https://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/frailty-score",
- "frailtyscore"),
- entry("http://terminology.hl7.org/CodeSystem/consentcategorycodes", "consentcategory"),
- entry("urn:oid:2.16.840.1.113883.3.1937.777.24.5.3", "consent"),
- entry("http://hl7.org/fhir/sid/icd-o-3", "icdo3"),
- entry("http://hl7.org/fhir/consent-provision-type", "provisiontype"))));
+ mappingTreeBase,
+ Map.ofEntries(entry("http://fhir.de/CodeSystem/bfarm/icd-10-gm", "icd10"),
+ entry("mii.abide", "abide"),
+ entry("http://fhir.de/CodeSystem/bfarm/ops", "ops"),
+ entry("http://dicom.nema.org/resources/ontology/DCM", "dcm"),
+ entry("https://www.medizininformatik-initiative.de/fhir/core/modul-person/CodeSystem/Vitalstatus", "vitalstatus"),
+ entry("http://loinc.org", "loinc"),
+ entry("https://fhir.bbmri.de/CodeSystem/SampleMaterialType", "sample"),
+ entry("http://fhir.de/CodeSystem/bfarm/atc", "atc"),
+ entry("http://snomed.info/sct", "snomed"),
+ entry("http://terminology.hl7.org/CodeSystem/condition-ver-status", "cvs"),
+ entry("http://hl7.org/fhir/administrative-gender", "gender"),
+ entry("urn:oid:1.2.276.0.76.5.409", "urn409"),
+ entry(
+ "https://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/ecrf-parameter-codes",
+ "numecrf"),
+ entry("urn:iso:std:iso:3166", "iso3166"),
+ entry("https://www.netzwerk-universitaetsmedizin.de/fhir/CodeSystem/frailty-score",
+ "frailtyscore"),
+ entry("http://terminology.hl7.org/CodeSystem/consentcategorycodes", "consentcategory"),
+ entry("urn:oid:2.16.840.1.113883.3.1937.777.24.5.3", "consent"),
+ entry("http://hl7.org/fhir/sid/icd-o-3", "icdo3"),
+ entry("fdpg.mii.cds", "fdpgmiicds"),
+ entry("http://fhir.de/CodeSystem/bfarm/alpha-id", "alphaid"),
+ entry("urn:iso:std:iso:11073:10101", "ISO11073"),
+ entry("http://terminology.hl7.org/CodeSystem/icd-o-3", "icdo3"),
+ entry("http://fhir.de/CodeSystem/dkgev/Fachabteilungsschluessel", "fachabteilungsschluessel"),
+ entry("http://terminology.hl7.org/CodeSystem/v3-ActCode", "v3actcode"),
+ entry("http://fhir.de/CodeSystem/dkgev/Fachabteilungsschluessel-erweitert", "fachabteilungsschluesselerweitert"),
+ entry("http://fhir.de/CodeSystem/kontaktart-de", "kontaktart"),
+ entry("http://hl7.org/fhir/sid/icd-10", "sidicd10"),
+ entry("http://fhir.de/CodeSystem/Kontaktebene", "kontaktebene"),
+ entry("http://hl7.org/fhir/consent-provision-type", "provisiontype"))));
}
+
@Qualifier("cql")
@Lazy
@Bean
diff --git a/src/main/java/de/numcodex/feasibility_gui_backend/query/v4/QueryHandlerRestController.java b/src/main/java/de/numcodex/feasibility_gui_backend/query/v4/QueryHandlerRestController.java
index b84a1e37..055d9bbc 100644
--- a/src/main/java/de/numcodex/feasibility_gui_backend/query/v4/QueryHandlerRestController.java
+++ b/src/main/java/de/numcodex/feasibility_gui_backend/query/v4/QueryHandlerRestController.java
@@ -309,6 +309,7 @@ public ResponseEntity