From 6532eb46c3ea85b91ebde355eff48427286a3b21 Mon Sep 17 00:00:00 2001 From: Bastian Schaffer Date: Tue, 10 Dec 2024 11:42:22 +0100 Subject: [PATCH] Minor Adjustments --- .../integration-test/basic-auth/Dockerfile | 2 +- .../basic-auth/docker-compose.yml | 6 +- .../evaluate-and-post-different-doc-ref.sh | 4 +- .../evaluate-and-post-report.sh | 4 +- .../evaluate-and-post-update.sh | 4 +- .github/integration-test/no-auth/Dockerfile | 2 +- .../no-auth/docker-compose.yml | 2 +- .github/integration-test/oauth/Dockerfile | 2 +- .../integration-test/oauth/docker-compose.yml | 8 +-- .github/workflows/build.yml | 6 +- README.md | 65 ++++++++++--------- docker/.env.default | 18 ++--- docker/docker-compose.yml | 18 ++--- docker/docker-entrypoint.sh | 2 +- .../fhir_data_evaluator/DataStore.java | 26 +++----- .../FhirDataEvaluatorApplication.java | 57 +++++++++------- src/main/resources/application.yml | 20 +++--- .../fhir_data_evaluator/DataStoreTest.java | 4 +- 18 files changed, 127 insertions(+), 123 deletions(-) diff --git a/.github/integration-test/basic-auth/Dockerfile b/.github/integration-test/basic-auth/Dockerfile index d3c6567..dfb6d1e 100644 --- a/.github/integration-test/basic-auth/Dockerfile +++ b/.github/integration-test/basic-auth/Dockerfile @@ -1,4 +1,4 @@ -# Image is uses as base for a dummy container from which curl can request data within the same network as the other containers +# Image is used as base for a dummy container from which curl can request data within the same network as the other containers FROM alpine RUN apk add --no-cache curl CMD ["sh", "-c", "while true; do sleep 3600; done"] diff --git a/.github/integration-test/basic-auth/docker-compose.yml b/.github/integration-test/basic-auth/docker-compose.yml index c9d7ccb..1094144 100644 --- a/.github/integration-test/basic-auth/docker-compose.yml +++ b/.github/integration-test/basic-auth/docker-compose.yml @@ -22,9 +22,9 @@ services: FHIR_SOURCE_SERVER: "http://proxy:8080/fhir" FHIR_SOURCE_USER: "test" FHIR_SOURCE_PASSWORD: "bar" - FHIR_DESTINATION_SERVER: "http://proxy:8080/fhir" - FHIR_DESTINATION_USER: "test" - FHIR_DESTINATION_PASSWORD: "bar" + FHIR_REPORT_SERVER: "http://proxy:8080/fhir" + FHIR_REPORT_USER: "test" + FHIR_REPORT_PASSWORD: "bar" SEND_REPORT_TO_SERVER: ${FDE_SEND_REPORT_TO_SERVER:-false} AUTHOR_IDENTIFIER_SYSTEM: ${FDE_AUTHOR_IDENTIFIER_SYSTEM:-} AUTHOR_IDENTIFIER_VALUE: ${FDE_AUTHOR_IDENTIFIER_VALUE:-} diff --git a/.github/integration-test/evaluate-and-post-different-doc-ref.sh b/.github/integration-test/evaluate-and-post-different-doc-ref.sh index 205502a..32b6acd 100755 --- a/.github/integration-test/evaluate-and-post-different-doc-ref.sh +++ b/.github/integration-test/evaluate-and-post-different-doc-ref.sh @@ -38,12 +38,12 @@ get_response() { -d 'grant_type=client_credentials' \ -d 'client_id=account' \ -d 'client_secret=test'") - FHIR_DESTINATION_BEARER_TOKEN=$(echo "$oauth_response" | jq -r '.access_token') + FHIR_REPORT_BEARER_TOKEN=$(echo "$oauth_response" | jq -r '.access_token') response=$(docker exec "$CURL_TESTER_ID" sh -c " curl -s 'https://secure-fhir-server:8443/fhir/$URL' \ -H 'Content-Type: application/fhir+json' \ - -H 'Authorization: Bearer $FHIR_DESTINATION_BEARER_TOKEN'") + -H 'Authorization: Bearer $FHIR_REPORT_BEARER_TOKEN'") echo "$response" fi diff --git a/.github/integration-test/evaluate-and-post-report.sh b/.github/integration-test/evaluate-and-post-report.sh index 95076a4..e5c5179 100755 --- a/.github/integration-test/evaluate-and-post-report.sh +++ b/.github/integration-test/evaluate-and-post-report.sh @@ -39,12 +39,12 @@ get_response() { -d 'grant_type=client_credentials' \ -d 'client_id=account' \ -d 'client_secret=test'") - FHIR_DESTINATION_BEARER_TOKEN=$(echo "$oauth_response" | jq -r '.access_token') + FHIR_REPORT_BEARER_TOKEN=$(echo "$oauth_response" | jq -r '.access_token') response=$(docker exec "$CURL_TESTER_ID" sh -c " curl -s 'https://secure-fhir-server:8443/fhir/$URL' \ -H 'Content-Type: application/fhir+json' \ - -H 'Authorization: Bearer $FHIR_DESTINATION_BEARER_TOKEN'") + -H 'Authorization: Bearer $FHIR_REPORT_BEARER_TOKEN'") echo "$response" fi diff --git a/.github/integration-test/evaluate-and-post-update.sh b/.github/integration-test/evaluate-and-post-update.sh index 51ca05a..ef97b9e 100755 --- a/.github/integration-test/evaluate-and-post-update.sh +++ b/.github/integration-test/evaluate-and-post-update.sh @@ -36,12 +36,12 @@ get_response() { -d 'grant_type=client_credentials' \ -d 'client_id=account' \ -d 'client_secret=test'") - FHIR_DESTINATION_BEARER_TOKEN=$(echo "$oauth_response" | jq -r '.access_token') + FHIR_REPORT_BEARER_TOKEN=$(echo "$oauth_response" | jq -r '.access_token') response=$(docker exec "$CURL_TESTER_ID" sh -c " curl -s 'https://secure-fhir-server:8443/fhir/$URL' \ -H 'Content-Type: application/fhir+json' \ - -H 'Authorization: Bearer $FHIR_DESTINATION_BEARER_TOKEN'") + -H 'Authorization: Bearer $FHIR_REPORT_BEARER_TOKEN'") echo "$response" fi diff --git a/.github/integration-test/no-auth/Dockerfile b/.github/integration-test/no-auth/Dockerfile index d3c6567..dfb6d1e 100644 --- a/.github/integration-test/no-auth/Dockerfile +++ b/.github/integration-test/no-auth/Dockerfile @@ -1,4 +1,4 @@ -# Image is uses as base for a dummy container from which curl can request data within the same network as the other containers +# Image is used as base for a dummy container from which curl can request data within the same network as the other containers FROM alpine RUN apk add --no-cache curl CMD ["sh", "-c", "while true; do sleep 3600; done"] diff --git a/.github/integration-test/no-auth/docker-compose.yml b/.github/integration-test/no-auth/docker-compose.yml index 2e0dd99..fe0bf30 100644 --- a/.github/integration-test/no-auth/docker-compose.yml +++ b/.github/integration-test/no-auth/docker-compose.yml @@ -15,7 +15,7 @@ services: environment: CONVERT_TO_CSV: ${FDE_CONVERT_TO_CSV:-true} FHIR_SOURCE_SERVER: "http://fhir-server:8080/fhir" - FHIR_DESTINATION_SERVER: "http://fhir-server:8080/fhir" + FHIR_REPORT_SERVER: "http://fhir-server:8080/fhir" SEND_REPORT_TO_SERVER: ${FDE_SEND_REPORT_TO_SERVER:-false} AUTHOR_IDENTIFIER_SYSTEM: ${FDE_AUTHOR_IDENTIFIER_SYSTEM:-} AUTHOR_IDENTIFIER_VALUE: ${FDE_AUTHOR_IDENTIFIER_VALUE:-} diff --git a/.github/integration-test/oauth/Dockerfile b/.github/integration-test/oauth/Dockerfile index d3c6567..dfb6d1e 100644 --- a/.github/integration-test/oauth/Dockerfile +++ b/.github/integration-test/oauth/Dockerfile @@ -1,4 +1,4 @@ -# Image is uses as base for a dummy container from which curl can request data within the same network as the other containers +# Image is used as base for a dummy container from which curl can request data within the same network as the other containers FROM alpine RUN apk add --no-cache curl CMD ["sh", "-c", "while true; do sleep 3600; done"] diff --git a/.github/integration-test/oauth/docker-compose.yml b/.github/integration-test/oauth/docker-compose.yml index fce3bff..8aa252c 100644 --- a/.github/integration-test/oauth/docker-compose.yml +++ b/.github/integration-test/oauth/docker-compose.yml @@ -111,10 +111,10 @@ services: FHIR_SOURCE_OAUTH_ISSUER_URI: "https://secure-keycloak:8443/realms/test" FHIR_SOURCE_OAUTH_CLIENT_ID: "account" FHIR_SOURCE_OAUTH_CLIENT_SECRET: "test" - FHIR_DESTINATION_SERVER: "https://secure-fhir-server:8443/fhir" - FHIR_DESTINATION_OAUTH_ISSUER_URI: "https://secure-keycloak:8443/realms/test" - FHIR_DESTINATION_OAUTH_CLIENT_ID: "account" - FHIR_DESTINATION_OAUTH_CLIENT_SECRET: "test" + FHIR_REPORT_SERVER: "https://secure-fhir-server:8443/fhir" + FHIR_REPORT_OAUTH_ISSUER_URI: "https://secure-keycloak:8443/realms/test" + FHIR_REPORT_OAUTH_CLIENT_ID: "account" + FHIR_REPORT_OAUTH_CLIENT_SECRET: "test" SEND_REPORT_TO_SERVER: ${FDE_SEND_REPORT_TO_SERVER:-false} AUTHOR_IDENTIFIER_SYSTEM: ${FDE_AUTHOR_IDENTIFIER_SYSTEM:-} AUTHOR_IDENTIFIER_VALUE: ${FDE_AUTHOR_IDENTIFIER_VALUE:-} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db7a234..037bb3e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -155,13 +155,13 @@ jobs: - name: Run Integration Test to check if it correctly exits when there are insufficient writing permissions run: .github/integration-test/missing-permissions-test.sh - - name: Run Integration Test for Posting the MeasureReport to the FHIR server + - name: Run Integration Test for Posting the MeasureReport to the Report FHIR server run: .github/integration-test/evaluate-and-post-report.sh ${{ matrix.test }} Test_PROJECT_Evaluation_1 - - name: Run Integration Test for Posting the MeasureReport to the FHIR server with the Same Project Identifier + - name: Run Integration Test for Posting the MeasureReport to the Report FHIR server with the Same Project Identifier run: .github/integration-test/evaluate-and-post-update.sh ${{ matrix.test }} Test_PROJECT_Evaluation_1 - - name: Run Integration Test for Posting the MeasureReport to the FHIR server with a Different Project Identifier + - name: Run Integration Test for Posting the MeasureReport to the Report FHIR server with a Different Project Identifier run: .github/integration-test/evaluate-and-post-different-doc-ref.sh ${{ matrix.test }} Test_PROJECT_Evaluation_2 - name: Remove Blaze volumes diff --git a/README.md b/README.md index 53cd115..3cef49a 100644 --- a/README.md +++ b/README.md @@ -31,8 +31,9 @@ For a more detailed Documentation see: * [Documentation](Documentation/Documenta ## Run -When running the Fhir Data Evaluator with Docker, it will require a Measure resource file as input and save the resulting -MeasureReport into a Directory named after the current date combined with the Measure's name (specified in the 'name' field). +When running the Fhir Data Evaluator with Docker, it will require a Measure resource file as input. The resulting +MeasureReport will be saved inside `/app/output/` of the Docker container into a new Directory named after the current +date combined with the Measure's name (specified in the 'name' field of the Measure). If specified, additional CSV files will be created that represent the MeasureReport. An example of a Measure can be found [here](Documentation/example-measures/example-measure-1.json). @@ -83,7 +84,7 @@ docker run -v :/app/measure.json -v :/ap ### Sending the MeasureReport to a FHIR Server -If `SEND_REPORT_TO_SERVER` is set to true, the MeasureReport is sent to the `FHIR_DESTINATION_SERVER` along with a +If `SEND_REPORT_TO_SERVER` is set to true, the MeasureReport is sent to the `FHIR_REPORT_SERVER` along with a DocumentReference that is configured with the following environment variables: * `AUTHOR_IDENTIFIER_SYSTEM` (example: `http://dsf.dev/sid/organization-identifier`) * `AUTHOR_IDENTIFIER_VALUE` (example: `Test_DIC1`) @@ -92,35 +93,35 @@ DocumentReference that is configured with the following environment variables: ## Environment Variables -| Name | Default | Description | -|:-------------------------------------|:--------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------| -| FHIR_SOURCE_SERVER | http://localhost:8080/fhir | The base URL of the FHIR server to use for downloading the resources. | -| FHIR_SOURCE_USER | | The username to use for HTTP Basic Authentication for the source FHIR server. | -| FHIR_SOURCE_PASSWORD | | The password to use for HTTP Basic Authentication for the source FHIR server. | -| FHIR_SOURCE_MAX_CONNECTIONS | 4 | The maximum number of connections to open towards the source FHIR server. | -| FHIR_SOURCE_MAX_QUEUE_SIZE | 500 | The maximum number FHIR server requests at the source FHIR server to queue before returning an error. | -| FHIR_SOURCE_PAGE_COUNT | 1000 | The number of resources per page to request from the source FHIR server. | -| FHIR_SOURCE_BEARER_TOKEN | | Bearer token for authentication for the source FHIR server. | -| FHIR_SOURCE_OAUTH_ISSUER_URI | | The issuer URI of the OpenID Connect provider for the source FHIR server. | -| FHIR_SOURCE_OAUTH_CLIENT_ID | | The client ID to use for authentication with OpenID Connect provider for the source FHIR server. | -| FHIR_SOURCE_OAUTH_CLIENT_SECRET | | The client secret to use for authentication with OpenID Connect provider for the source FHIR server. | -| FHIR_DESTINATION_SERVER | http://localhost:8080/fhir | The base URL of the FHIR server to use for (optionally) uploading the MeasureReport. | -| FHIR_DESTINATION_USER | | The username to use for HTTP Basic Authentication for the destination FHIR server. | -| FHIR_DESTINATION_PASSWORD | | The password to use for HTTP Basic Authentication for the destination FHIR server. | -| FHIR_DESTINATION_MAX_CONNECTIONS | 4 | The maximum number of connections to open towards the destination FHIR server. | -| FHIR_DESTINATION_MAX_QUEUE_SIZE | 500 | The maximum number FHIR server requests at the destination FHIR server to queue before returning an error. | -| FHIR_DESTINATION_BEARER_TOKEN | | Bearer token for authentication for the destination FHIR server. | -| FHIR_DESTINATION_OAUTH_ISSUER_URI | | The issuer URI of the OpenID Connect provider for the destination FHIR server. | -| FHIR_DESTINATION_OAUTH_CLIENT_ID | | The client ID to use for authentication with OpenID Connect provider for the destination FHIR server. | -| FHIR_DESTINATION_OAUTH_CLIENT_SECRET | | The client secret to use for authentication with OpenID Connect provider for the destination FHIR server. | -| MAX_IN_MEMORY_SIZE_MIB | 10 | The maximum in-memory buffer size for each webclient in MiB. | -| TZ | Europe/Berlin | The time zone used to create the output directory and set the date in the DocumentReference. | -| CONVERT_TO_CSV | false | Whether for the MeasureReport should be generated CSV files. | -| SEND_REPORT_TO_SERVER | false | Whether the MeasureReport should be sent to a FHIR server. | -| AUTHOR_IDENTIFIER_SYSTEM | http://dsf.dev/sid/organization-identifier | The system of the author organization used when uploading the report. | -| AUTHOR_IDENTIFIER_VALUE | | The code of the author organization used when uploading the report. | -| PROJECT_IDENTIFIER_SYSTEM | http://medizininformatik-initiative.de/sid/project-identifier | The system of the master identifier used when uploading the report. | -| PROJECT_IDENTIFIER_VALUE | | The value of the master identifier used when uploading the report. | +| Name | Default | Description | +|:--------------------------------|:--------------------------------------------------------------|:------------------------------------------------------------------------------------------------------| +| FHIR_SOURCE_SERVER | http://localhost:8080/fhir | The base URL of the FHIR server to use for downloading the resources. | +| FHIR_SOURCE_USER | | The username to use for HTTP Basic Authentication for the source FHIR server. | +| FHIR_SOURCE_PASSWORD | | The password to use for HTTP Basic Authentication for the source FHIR server. | +| FHIR_SOURCE_MAX_CONNECTIONS | 4 | The maximum number of connections to open towards the source FHIR server. | +| FHIR_SOURCE_MAX_QUEUE_SIZE | 500 | The maximum number FHIR server requests at the source FHIR server to queue before returning an error. | +| FHIR_SOURCE_PAGE_COUNT | 1000 | The number of resources per page to request from the source FHIR server. | +| FHIR_SOURCE_BEARER_TOKEN | | Bearer token for authentication for the source FHIR server. | +| FHIR_SOURCE_OAUTH_ISSUER_URI | | The issuer URI of the OpenID Connect provider for the source FHIR server. | +| FHIR_SOURCE_OAUTH_CLIENT_ID | | The client ID to use for authentication with OpenID Connect provider for the source FHIR server. | +| FHIR_SOURCE_OAUTH_CLIENT_SECRET | | The client secret to use for authentication with OpenID Connect provider for the source FHIR server. | +| FHIR_REPORT_SERVER | http://localhost:8080/fhir | The base URL of the FHIR server to use for (optionally) uploading the MeasureReport. | +| FHIR_REPORT_USER | | The username to use for HTTP Basic Authentication for the Report FHIR server. | +| FHIR_REPORT_PASSWORD | | The password to use for HTTP Basic Authentication for the Report FHIR server. | +| FHIR_REPORT_MAX_CONNECTIONS | 4 | The maximum number of connections to open towards the Report FHIR server. | +| FHIR_REPORT_MAX_QUEUE_SIZE | 500 | The maximum number FHIR server requests at the Report FHIR server to queue before returning an error. | +| FHIR_REPORT_BEARER_TOKEN | | Bearer token for authentication for the Report FHIR server. | +| FHIR_REPORT_OAUTH_ISSUER_URI | | The issuer URI of the OpenID Connect provider for the Report FHIR server. | +| FHIR_REPORT_OAUTH_CLIENT_ID | | The client ID to use for authentication with OpenID Connect provider for the Report FHIR server. | +| FHIR_REPORT_OAUTH_CLIENT_SECRET | | The client secret to use for authentication with OpenID Connect provider for the Report FHIR server. | +| MAX_IN_MEMORY_SIZE_MIB | 10 | The maximum in-memory buffer size for each webclient in MiB. | +| TZ | Europe/Berlin | The time zone used to create the output directory and set the date in the DocumentReference. | +| CONVERT_TO_CSV | false | Whether for the MeasureReport should be generated CSV files. | +| SEND_REPORT_TO_SERVER | false | Whether the MeasureReport should be sent to the FHIR Report server. | +| AUTHOR_IDENTIFIER_SYSTEM | http://dsf.dev/sid/organization-identifier | The system of the author organization used when uploading the report. | +| AUTHOR_IDENTIFIER_VALUE | | The code of the author organization used when uploading the report. | +| PROJECT_IDENTIFIER_SYSTEM | http://medizininformatik-initiative.de/sid/project-identifier | The system of the master identifier used when uploading the report. | +| PROJECT_IDENTIFIER_VALUE | | The value of the master identifier used when uploading the report. | ## Documentation diff --git a/docker/.env.default b/docker/.env.default index 7ff00c8..f5a95ca 100644 --- a/docker/.env.default +++ b/docker/.env.default @@ -9,15 +9,15 @@ FDE_FHIR_SOURCE_BEARER_TOKEN= FDE_FHIR_SOURCE_OAUTH_ISSUER_URI= FDE_FHIR_SOURCE_OAUTH_CLIENT_ID= FDE_FHIR_SOURCE_OAUTH_CLIENT_SECRET= -FDE_FHIR_DESTINATION_SERVER=http://localhost:8080/fhir -FDE_FHIR_DESTINATION_USER= -FDE_FHIR_DESTINATION_PASSWORD= -FDE_FHIR_DESTINATION_MAX_CONNECTIONS=4 -FDE_FHIR_DESTINATION_MAX_QUEUE_SIZE=500 -FDE_FHIR_DESTINATION_BEARER_TOKEN= -FDE_FHIR_DESTINATION_OAUTH_ISSUER_URI= -FDE_FHIR_DESTINATION_OAUTH_CLIENT_ID= -FDE_FHIR_DESTINATION_OAUTH_CLIENT_SECRET= +FDE_FHIR_REPORT_SERVER=http://localhost:8080/fhir +FDE_FHIR_REPORT_USER= +FDE_FHIR_REPORT_PASSWORD= +FDE_FHIR_REPORT_MAX_CONNECTIONS=4 +FDE_FHIR_REPORT_MAX_QUEUE_SIZE=500 +FDE_FHIR_REPORT_BEARER_TOKEN= +FDE_FHIR_REPORT_OAUTH_ISSUER_URI= +FDE_FHIR_REPORT_OAUTH_CLIENT_ID= +FDE_FHIR_REPORT_OAUTH_CLIENT_SECRET= FDE_MAX_IN_MEMORY_SIZE_MIB=10 FDE_INPUT_MEASURE=../Documentation/example-measures/example-measure-kds.json FDE_OUTPUT_DIR=../output diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 4a3dff9..154e90d 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -13,15 +13,15 @@ services: FHIR_SOURCE_OAUTH_ISSUER_URI: ${FDE_FHIR_SOURCE_OAUTH_ISSUER_URI:-} FHIR_SOURCE_OAUTH_CLIENT_ID: ${FDE_FHIR_SOURCE_OAUTH_CLIENT_ID:-} FHIR_SOURCE_OAUTH_CLIENT_SECRET: ${FDE_FHIR_SOURCE_OAUTH_CLIENT_SECRET:-} - FHIR_DESTINATION_SERVER: ${FDE_FHIR_DESTINATION_SERVER:-http://localhost:8080/fhir} - FHIR_DESTINATION_USER: ${FDE_FHIR_DESTINATION_USER:-} - FHIR_DESTINATION_PASSWORD: ${FDE_FHIR_DESTINATION_PASSWORD:-} - FHIR_DESTINATION_MAX_CONNECTIONS: ${FDE_FHIR_DESTINATION_MAX_CONNECTIONS:-4} - FHIR_DESTINATION_MAX_QUEUE_SIZE: ${FDE_FHIR_DESTINATION_MAX_QUEUE_SIZE:-500} - FHIR_DESTINATION_BEARER_TOKEN: ${FDE_FHIR_DESTINATION_BEARER_TOKEN:-} - FHIR_DESTINATION_OAUTH_ISSUER_URI: ${FDE_FHIR_DESTINATION_OAUTH_ISSUER_URI:-} - FHIR_DESTINATION_OAUTH_CLIENT_ID: ${FDE_FHIR_DESTINATION_OAUTH_CLIENT_ID:-} - FHIR_DESTINATION_OAUTH_CLIENT_SECRET: ${FDE_FHIR_DESTINATION_OAUTH_CLIENT_SECRET:-} + FHIR_REPORT_SERVER: ${FDE_FHIR_REPORT_SERVER:-http://localhost:8080/fhir} + FHIR_REPORT_USER: ${FDE_FHIR_REPORT_USER:-} + FHIR_REPORT_PASSWORD: ${FDE_FHIR_REPORT_PASSWORD:-} + FHIR_REPORT_MAX_CONNECTIONS: ${FDE_FHIR_REPORT_MAX_CONNECTIONS:-4} + FHIR_REPORT_MAX_QUEUE_SIZE: ${FDE_FHIR_REPORT_MAX_QUEUE_SIZE:-500} + FHIR_REPORT_BEARER_TOKEN: ${FDE_FHIR_REPORT_BEARER_TOKEN:-} + FHIR_REPORT_OAUTH_ISSUER_URI: ${FDE_FHIR_REPORT_OAUTH_ISSUER_URI:-} + FHIR_REPORT_OAUTH_CLIENT_ID: ${FDE_FHIR_REPORT_OAUTH_CLIENT_ID:-} + FHIR_REPORT_OAUTH_CLIENT_SECRET: ${FDE_FHIR_REPORT_OAUTH_CLIENT_SECRET:-} MAX_IN_MEMORY_SIZE_MIB: ${FDE_MAX_IN_MEMORY_SIZE_MIB:-10} SEND_REPORT_TO_SERVER: ${FDE_SEND_REPORT_TO_SERVER:-false} AUTHOR_IDENTIFIER_SYSTEM: ${FDE_AUTHOR_IDENTIFIER_SYSTEM:-http://dsf.dev/sid/organization-identifier} diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh index bcd3b9b..7e5cf89 100644 --- a/docker/docker-entrypoint.sh +++ b/docker/docker-entrypoint.sh @@ -1,7 +1,7 @@ #!/bin/bash -e if [ "${SEND_REPORT_TO_SERVER}" = true ]; then - vars_for_upload=(FHIR_DESTINATION_SERVER AUTHOR_IDENTIFIER_SYSTEM AUTHOR_IDENTIFIER_VALUE PROJECT_IDENTIFIER_SYSTEM PROJECT_IDENTIFIER_VALUE) + vars_for_upload=(FHIR_REPORT_SERVER AUTHOR_IDENTIFIER_SYSTEM AUTHOR_IDENTIFIER_VALUE PROJECT_IDENTIFIER_SYSTEM PROJECT_IDENTIFIER_VALUE) for var in "${vars_for_upload[@]}"; do if [[ -z "${!var}" ]]; then echo "In order to upload the MeasureReport to a FHIR server, all following environment variables must be set" \ diff --git a/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStore.java b/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStore.java index 7e76793..5a6291e 100644 --- a/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStore.java +++ b/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStore.java @@ -4,10 +4,8 @@ import ca.uhn.fhir.fhirpath.IFhirPath; import ca.uhn.fhir.parser.IParser; import org.hl7.fhir.r4.model.Bundle; -import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Flux; @@ -21,24 +19,18 @@ import static de.medizininformatikinitiative.fhir_data_evaluator.ResourceWithIncludes.processBundleIncludes; -@Component public class DataStore { - private final WebClient sourceClient; - private final WebClient destinationClient; + private final WebClient webClient; private final IParser parser; - private final int sourcePageCount; + private final int pageCount; private final FhirContext context; private final IFhirPath applicationFhirPathEngine; - public DataStore(WebClient sourceClient, WebClient destinationClient, IParser parser, - @Value("${fhir.source.pageCount}") int sourcePageCount, - FhirContext context, - IFhirPath fhirPathEngine) { - this.sourceClient = sourceClient; - this.destinationClient = destinationClient; + public DataStore(WebClient webClient, IParser parser, int pageCount, FhirContext context, IFhirPath fhirPathEngine) { + this.webClient = webClient; this.parser = parser; - this.sourcePageCount = sourcePageCount; + this.pageCount = pageCount; this.context = context; this.applicationFhirPathEngine = fhirPathEngine; } @@ -50,13 +42,13 @@ public DataStore(WebClient sourceClient, WebClient destinationClient, IParser pa * @return the resources found with the {@code query} */ public Flux getResources(String query) { - return sourceClient.get() + return webClient.get() .uri(appendPageCount(query)) .retrieve() .bodyToFlux(String.class) .map(response -> parser.parseResource(Bundle.class, response)) .expand(bundle -> Optional.ofNullable(bundle.getLink("next")) - .map(link -> fetchPage(sourceClient, link.getUrl())) + .map(link -> fetchPage(webClient, link.getUrl())) .orElse(Mono.empty())) .retryWhen(Retry.backoff(3, Duration.ofSeconds(1)) .filter(e -> e instanceof WebClientResponseException && @@ -72,7 +64,7 @@ public Flux getResources(String query) { * failure */ public Mono postReport(String bundle) { - return destinationClient.post() + return webClient.post() .contentType(MediaType.valueOf("application/fhir+json")) .bodyValue(bundle) .retrieve() @@ -99,7 +91,7 @@ private Mono fetchPage(WebClient client, String url) { } String appendPageCount(String query) { - return query.contains("?") ? query + "&_count=" + this.sourcePageCount : query + "?_count=" + this.sourcePageCount; + return query.contains("?") ? query + "&_count=" + this.pageCount : query + "?_count=" + this.pageCount; } } diff --git a/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/FhirDataEvaluatorApplication.java b/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/FhirDataEvaluatorApplication.java index 0502533..7c7ee00 100644 --- a/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/FhirDataEvaluatorApplication.java +++ b/src/main/java/de/medizininformatikinitiative/fhir_data_evaluator/FhirDataEvaluatorApplication.java @@ -72,8 +72,19 @@ public IFhirPath fhirPathEngine(FhirContext context) { } @Bean - public MeasureEvaluator measureEvaluator(DataStore dataStore, IFhirPath fhirPathEngine) { - return new MeasureEvaluator(dataStore, fhirPathEngine); + public DataStore sourceDataStore(WebClient sourceClient, IParser parser, @Value("${fhir.source.pageCount}") int sourcePageCount, + FhirContext context, IFhirPath fhirPathEngine) { + return new DataStore(sourceClient, parser, sourcePageCount, context, fhirPathEngine); + } + + @Bean + public DataStore reportDataStore(WebClient reportClient, IParser parser, FhirContext context, IFhirPath fhirPathEngine) { + return new DataStore(reportClient, parser, 100, context, fhirPathEngine); + } + + @Bean + public MeasureEvaluator measureEvaluator(DataStore sourceDataStore, IFhirPath fhirPathEngine) { + return new MeasureEvaluator(sourceDataStore, fhirPathEngine); } @Bean @@ -98,23 +109,23 @@ ExchangeFilterFunction sourceOauthExchangeFilterFunction( } @Bean - public WebClient destinationClient(@Value("${fhir.destination.server}") String fhirServer, - @Value("${fhir.destination.user}") String user, - @Value("${fhir.destination.password}") String password, - @Value("${fhir.destination.maxConnections}") int maxConnections, - @Value("${fhir.destination.maxQueueSize}") int maxQueueSize, - @Value("${fhir.destination.bearerToken}") String bearerToken, + public WebClient reportClient(@Value("${fhir.report.server}") String fhirServer, + @Value("${fhir.report.user}") String user, + @Value("${fhir.report.password}") String password, + @Value("${fhir.report.maxConnections}") int maxConnections, + @Value("${fhir.report.maxQueueSize}") int maxQueueSize, + @Value("${fhir.report.bearerToken}") String bearerToken, @Value("${maxInMemorySizeMib}") int maxInMemorySizeMib, - @Qualifier("destinationOauth") ExchangeFilterFunction oauthExchangeFilterFunction) { + @Qualifier("reportOauth") ExchangeFilterFunction oauthExchangeFilterFunction) { return getWebClient(fhirServer, user, password, maxConnections, maxQueueSize, bearerToken, maxInMemorySizeMib, oauthExchangeFilterFunction); } @Bean - @Qualifier("destinationOauth") - ExchangeFilterFunction destinationOauthExchangeFilterFunction( - @Value("${fhir.destination.oauth.issuer.uri}") String issuerUri, - @Value("${fhir.destination.oauth.client.id}") String clientId, - @Value("${fhir.destination.oauth.client.secret}") String clientSecret) { + @Qualifier("reportOauth") + ExchangeFilterFunction reportOauthExchangeFilterFunction( + @Value("${fhir.report.oauth.issuer.uri}") String issuerUri, + @Value("${fhir.report.oauth.client.id}") String clientId, + @Value("${fhir.report.oauth.client.secret}") String clientSecret) { return getExchangeFilterFunction(issuerUri, clientId, clientSecret); } @@ -179,7 +190,7 @@ public static void main(String[] args) { class EvaluationExecutor implements CommandLineRunner { private final static double NANOS_IN_SECOND = 1_000_000_000.0; - private final DataStore dataStore; + private final DataStore reportDataStore; private final Logger logger = LoggerFactory.getLogger(EvaluationExecutor.class); @Value("${measureFile}") @@ -196,8 +207,8 @@ class EvaluationExecutor implements CommandLineRunner { private String projectIdentifierSystem; @Value("${projectIdentifierValue}") private String projectIdentifierValue; - @Value("${fhir.destination.server}") - private String reportDestinationServer; + @Value("${fhir.report.server}") + private String reportServer; private final String TRANSACTION_BUNDLE_TEMPLATE_FILE = "/transaction-bundle-template.json"; private final MeasureEvaluator measureEvaluator; @@ -207,10 +218,10 @@ class EvaluationExecutor implements CommandLineRunner { .setSystem("http://unitsofmeasure.org") .setUnit("u"); - public EvaluationExecutor(MeasureEvaluator measureEvaluator, IParser parser, DataStore dataStore) { + public EvaluationExecutor(MeasureEvaluator measureEvaluator, IParser parser, DataStore reportDataStore) { this.measureEvaluator = measureEvaluator; this.parser = parser; - this.dataStore = dataStore; + this.reportDataStore = reportDataStore; } private String getMeasureFile() { @@ -245,7 +256,7 @@ private String getBundleTemplate() { } private String getDocRefId() { - var documentReferences = dataStore.getResources(reportDestinationServer + "/DocumentReference") + var documentReferences = reportDataStore.getResources(reportServer + "/DocumentReference") .map(r -> (DocumentReference)r.mainResource()).collectList().block(); var refsWithSameProjId = documentReferences.stream().filter(r -> @@ -311,10 +322,10 @@ public void run(String... args) { String parsedReport = parser.encodeResourceToString(measureReport); if(sendReportToServer) { - logger.info("Uploading MeasureReport to FHIR server at {}", reportDestinationServer); + logger.info("Uploading MeasureReport to FHIR Report server at {}", reportServer); try { - dataStore.postReport(createTransactionBundle(dateForBundle, parsedReport)) - .doOnSuccess(v -> logger.info("Successfully uploaded MeasureReport to FHIR server")) + reportDataStore.postReport(createTransactionBundle(dateForBundle, parsedReport)) + .doOnSuccess(v -> logger.info("Successfully uploaded MeasureReport to FHIR Report server")) .block(); } catch (RuntimeException e) { logger.error(e.getMessage()); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 7c6d018..0f53eee 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -13,19 +13,19 @@ fhir: client: id: ${FHIR_SOURCE_OAUTH_CLIENT_ID:} secret: ${FHIR_SOURCE_OAUTH_CLIENT_SECRET:} - destination: - server: ${FHIR_DESTINATION_SERVER:http://localhost:8080/fhir} - user: ${FHIR_DESTINATION_USER:} - password: ${FHIR_DESTINATION_PASSWORD:} - maxConnections: ${FHIR_DESTINATION_MAX_CONNECTIONS:4} - maxQueueSize: ${FHIR_DESTINATION_MAX_QUEUE_SIZE:500} - bearerToken: ${FHIR_DESTINATION_BEARER_TOKEN:} + report: + server: ${FHIR_REPORT_SERVER:http://localhost:8080/fhir} + user: ${FHIR_REPORT_USER:} + password: ${FHIR_REPORT_PASSWORD:} + maxConnections: ${FHIR_REPORT_MAX_CONNECTIONS:4} + maxQueueSize: ${FHIR_REPORT_MAX_QUEUE_SIZE:500} + bearerToken: ${FHIR_REPORT_BEARER_TOKEN:} oauth: issuer: - uri: ${FHIR_DESTINATION_OAUTH_ISSUER_URI:} + uri: ${FHIR_REPORT_OAUTH_ISSUER_URI:} client: - id: ${FHIR_DESTINATION_OAUTH_CLIENT_ID:} - secret: ${FHIR_DESTINATION_OAUTH_CLIENT_SECRET:} + id: ${FHIR_REPORT_OAUTH_CLIENT_ID:} + secret: ${FHIR_REPORT_OAUTH_CLIENT_SECRET:} maxInMemorySizeMib: ${MAX_IN_MEMORY_SIZE_MIB:10} measureFile: ${MEASURE_FILE:/app/measure.json} outputDir: ${OUTPUT_DIR:/app/output/} diff --git a/src/test/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStoreTest.java b/src/test/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStoreTest.java index 59fd9c0..260e62f 100644 --- a/src/test/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStoreTest.java +++ b/src/test/java/de/medizininformatikinitiative/fhir_data_evaluator/DataStoreTest.java @@ -45,7 +45,7 @@ void initialize() { .build(); FhirContext context = FhirContext.forR4(); IParser parser = context.newJsonParser(); - dataStore = new DataStore(client, null, parser, 1000, context, context.newFhirPath()); + dataStore = new DataStore(client, parser, 1000, context, context.newFhirPath()); } @ParameterizedTest @@ -110,7 +110,7 @@ void initialize() { .build(); FhirContext context = FhirContext.forR4(); IParser parser = context.newJsonParser(); - dataStore = new DataStore(null,client, parser, 1000, context, context.newFhirPath()); + dataStore = new DataStore(client, parser, 1000, context, context.newFhirPath()); } @Test