diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
new file mode 100644
index 000000000..125e89012
--- /dev/null
+++ b/.github/workflows/maven.yml
@@ -0,0 +1,20 @@
+# This workflow will build a Java project with Maven
+# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
+
+name: Java CI with Maven
+
+on: [push, pull_request]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: 11
+ - name: Build with Maven
+ run: mvn -B package --file pom.xml
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100755
index 901eabbd4..000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-language: java
-jdk:
-- openjdk11
-- oraclejdk11
-install: mvn install -DskipTests=true -Dmaven.javadoc.skip=true -Dgpg.skip -B -V
\ No newline at end of file
diff --git a/README.md b/README.md
index fca706734..322349b73 100755
--- a/README.md
+++ b/README.md
@@ -1,17 +1,20 @@
# HiGHmed Data Sharing Framework (HiGHmed DSF)
-[![Build Status](https://travis-ci.org/highmed/highmed-dsf.svg?branch=master)](https://travis-ci.org/highmed/highmed-dsf)
+[![Java CI with Maven status](https://github.com/highmed/highmed-dsf/workflows/Java%20CI%20with%20Maven/badge.svg)](https://github.com/highmed/highmed-dsf/actions?query=workflow%3A"Java+CI+with+Maven")
The HiGHmed Data Sharing Framework (HiGHmed DSF) implements a distributed process engine based on the BPMN 2.0 and FHIR R4 standards. Within the HiGHmed medical informatics consortium, the DSF is used to support biomedical research with routine data. Every participating site runs a FHIR endpoint (dsf-fhir) accessible by other sites and a business process engine (dsf-bpe) in the local secured network. Authentication between sites is handled using X.509 client/server certificates. The process engines execute BPMN processes in order to coordinate local and remote steps necessary to enable cross-site data sharing and feasibility analyses. This includes access to local data repositories, use-and-access-committee decision support, consent filtering, and privacy preserving record-linkage and pseudonymization.
-## Introduction
-An introduction to the HiGHmed data sharing architecture can be found on [YouTube](http://www.youtube.com/watch?v=YPcryul5occ) (German).
+## Development
+Branching follows the git-flow model, for the latest development version see branch [develop](https://github.com/highmed/highmed-dsf/tree/develop).
+
+## License
+All code from the HiGHmed Data Sharing Framework is published under the [Apache-2.0 License](LICENSE).
## Wiki
-The Wiki with the full documentation can be found [here](https://github.com/highmed/highmed-dsf/wiki).
+A full documentation can be found in the [Wiki](https://github.com/highmed/highmed-dsf/wiki).
## Manual Integration Testing (local with Docker)
-Prerequisite: Java 11, Maven 3.6, Docker 18
+Prerequisite: Java 11, Maven >= 3.6, Docker >= 18
* Build the entire project from the root directory of this repository
```
diff --git a/dsf-bpe/dsf-bpe-process-base/pom.xml b/dsf-bpe/dsf-bpe-process-base/pom.xml
index 33d120a20..a5b67a2d8 100755
--- a/dsf-bpe/dsf-bpe-process-base/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-base/pom.xml
@@ -1,5 +1,5 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
dsf-bpe-process-base
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
@@ -28,5 +28,11 @@
org.camunda.bpm
camunda-engine
+
+
+ de.hs-heilbronn.mi
+ log4j2-utils
+ test
+
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java
index a723033c2..945287256 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java
@@ -12,11 +12,14 @@ public interface Constants
// String VARIABLE_CORRELATION_KEY = "correlationKey";
String VARIABLE_MULTI_INSTANCE_TARGET = "multiInstanceTarget";
String VARIABLE_MULTI_INSTANCE_TARGETS = "multiInstanceTargets";
+ String VARIABLE_BLOOM_FILTER_CONFIG = "bloomFilterConfig";
String VARIABLE_QUERY_RESULTS = "queryResults";
+ String VARIABLE_FINAL_QUERY_RESULTS = "finalQueryResults";
String VARIABLE_TASK = "task";
String VARIABLE_LEADING_TASK = "leadingTask";
String VARIABLE_RESEARCH_STUDY = "researchStudy";
String VARIABLE_COHORTS = "cohorts";
+ String VARIABLE_TTP_IDENTIFIER = "ttp";
String VARIABLE_QUERIES = "queries";
String VARIABLE_QUERY_PARAMETERS = "queryParameters";
String VARIABLE_BUNDLE_ID = "bundleId";
@@ -24,14 +27,8 @@ public interface Constants
String VARIABLE_NEEDS_RECORD_LINKAGE = "needsRecordLinkage";
/**
- * Stores a List<{@link org.highmed.dsf.bpe.variables.FinalSimpleFeasibilityResult}> of the final results of
- * a multi medic simple cohort size query. Do not override, only add new entries to the list.
- */
- String VARIABLE_SIMPLE_COHORT_SIZE_QUERY_FINAL_RESULT = "simpleCohortSizeQueryFinalResult";
-
- /**
- * Stores a List<{@link org.highmed.dsf.fhir.variables.Outputs}> >of outputs that have to be written to a
- * task resource after the process terminates. Do not override, only add new entries to the list.
+ * Stores a List<{@link org.highmed.dsf.fhir.variables.Outputs}> >of outputs that have to be written to a task
+ * resource after the process terminates. Do not override, only add new entries to the list.
*/
String VARIABLE_PROCESS_OUTPUTS = "outputs";
@@ -54,13 +51,16 @@ public interface Constants
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY = "medic-correlation-key";
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK = "needs-consent-check";
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE = "needs-record-linkage";
+ String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG = "bloom-filter-configuration";
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT = "single-medic-result";
+ String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE = "single-medic-result-reference";
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT = "participating-medics";
+ String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NOT_ENOUGH_PARTICIPATION = "not-enough-participation";
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT = "multi-medic-result";
String CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE = "research-study-reference";
String CODESYSTEM_HIGHMED_UPDATE_WHITELIST = "http://highmed.org/fhir/CodeSystem/update-whitelist";
- String CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST = "HiGHmed_white_list";
+ String CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST = "highmed_whitelist";
String PROCESS_URI_BASE = "http://highmed.org/bpe/Process/";
@@ -69,6 +69,7 @@ public interface Constants
String ENDPOINT_IDENTIFIER_SYSTEM = "http://highmed.org/fhir/NamingSystem/endpoint-identifier";
String EXTENSION_PARTICIPATING_MEDIC_URI = "http://highmed.org/fhir/StructureDefinition/participating-medic";
+ String EXTENSION_PARTICIPATING_TTP_URI = "http://highmed.org/fhir/StructureDefinition/participating-ttp";
String EXTENSION_QUERY_URI = "http://highmed.org/fhir/StructureDefinition/query";
String EXTENSION_GROUP_ID_URI = "http://highmed.org/fhir/StructureDefinition/group-id";
@@ -81,4 +82,6 @@ public interface Constants
CodeType AQL_QUERY_TYPE = new CodeType("application/x-aql-query")
.setSystem("http://highmed.org/fhir/CodeSystem/query-type");
+
+ String OPENEHR_MIMETYPE_JSON = "application/json";
}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/delegate/AbstractServiceDelegate.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/delegate/AbstractServiceDelegate.java
index b04f378b6..16654602d 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/delegate/AbstractServiceDelegate.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/delegate/AbstractServiceDelegate.java
@@ -73,7 +73,7 @@ public final void execute(DelegateExecution execution) throws Exception
task = taskHelper.addOutputs(task, outputs);
task.setStatus(Task.TaskStatus.FAILED);
- webserviceClient.update(task);
+ webserviceClient.withMinimalReturn().update(task);
execution.getProcessEngine().getRuntimeService()
.deleteProcessInstance(execution.getProcessInstanceId(), exception.getMessage());
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/AbstractTaskMessageSend.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/AbstractTaskMessageSend.java
index b1f72cd19..bdd591856 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/AbstractTaskMessageSend.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/AbstractTaskMessageSend.java
@@ -74,12 +74,12 @@ public void doExecute(DelegateExecution execution) throws Exception
}
catch (Exception e)
{
- String errorMessage =
- "Error while sending Task (process: " + processDefinitionKey + ", version: " + versionTag
- + ", message-name: " + messageName + ", business-key: " + businessKey
- + ", correlation-key: " + target.getCorrelationKey() + ") to organization with identifier "
- + target.getTargetOrganizationIdentifierValue() + ": " + e.getMessage();
+ String errorMessage = "Error while sending Task (process: " + processDefinitionKey + ", version: "
+ + versionTag + ", message-name: " + messageName + ", business-key: " + businessKey
+ + ", correlation-key: " + target.getCorrelationKey() + ") to organization with identifier "
+ + target.getTargetOrganizationIdentifierValue() + ": " + e.getMessage();
logger.warn(errorMessage);
+ logger.debug("Error while sending Task", e);
Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
outputs.addErrorOutput(errorMessage);
@@ -96,7 +96,8 @@ public void doExecute(DelegateExecution execution) throws Exception
* Override this method to set a different multiinstance target then the one defined in the process variable
* {@link Constants#VARIABLE_MULTI_INSTANCE_TARGET}
*
- * @param execution the delegate execution of this process instance
+ * @param execution
+ * the delegate execution of this process instance
* @return {@link MultiInstanceTarget} that should receive the message
*/
protected MultiInstanceTarget getMultiInstanceTarget(DelegateExecution execution)
@@ -136,26 +137,26 @@ protected void sendTask(String targetOrganizationIdentifierValue, String process
// http://highmed.org/bpe/Process/processDefinitionKey
// http://highmed.org/bpe/Process/processDefinitionKey/versionTag
- String instantiatesUri =
- Constants.PROCESS_URI_BASE + processDefinitionKey + (versionTag != null && !versionTag.isEmpty() ?
- ("/" + versionTag) :
- "");
+ String instantiatesUri = Constants.PROCESS_URI_BASE + processDefinitionKey
+ + (versionTag != null && !versionTag.isEmpty() ? ("/" + versionTag) : "");
task.setInstantiatesUri(instantiatesUri);
- ParameterComponent messageNameInput = new ParameterComponent(new CodeableConcept(
- new Coding(Constants.CODESYSTEM_HIGHMED_BPMN, Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME,
- null)), new StringType(messageName));
+ ParameterComponent messageNameInput = new ParameterComponent(
+ new CodeableConcept(new Coding(Constants.CODESYSTEM_HIGHMED_BPMN,
+ Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME, null)),
+ new StringType(messageName));
task.getInput().add(messageNameInput);
- ParameterComponent businessKeyInput = new ParameterComponent(new CodeableConcept(
- new Coding(Constants.CODESYSTEM_HIGHMED_BPMN, Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY,
- null)), new StringType(businessKey));
+ ParameterComponent businessKeyInput = new ParameterComponent(
+ new CodeableConcept(new Coding(Constants.CODESYSTEM_HIGHMED_BPMN,
+ Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY, null)),
+ new StringType(businessKey));
task.getInput().add(businessKeyInput);
if (correlationKey != null)
{
- ParameterComponent correlationKeyInput = new ParameterComponent(new CodeableConcept(
- new Coding(Constants.CODESYSTEM_HIGHMED_BPMN,
+ ParameterComponent correlationKeyInput = new ParameterComponent(
+ new CodeableConcept(new Coding(Constants.CODESYSTEM_HIGHMED_BPMN,
Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY, null)),
new StringType(correlationKey));
task.getInput().add(correlationKeyInput);
@@ -170,7 +171,7 @@ protected void sendTask(String targetOrganizationIdentifierValue, String process
client.getBaseUrl());
logger.trace("Task resource to send: {}", fhirContext.newJsonParser().encodeResourceToString(task));
- client.create(task);
+ client.withMinimalReturn().create(task);
}
private FhirWebserviceClient getFhirClient(Task task, String targetOrganizationIdentifierValue)
@@ -183,9 +184,8 @@ private FhirWebserviceClient getFhirClient(Task task, String targetOrganizationI
else
{
logger.trace("Using remote webservice client");
- return getFhirWebserviceClientProvider()
- .getRemoteWebserviceClient(organizationProvider.getDefaultIdentifierSystem(),
- targetOrganizationIdentifierValue);
+ return getFhirWebserviceClientProvider().getRemoteWebserviceClient(
+ organizationProvider.getDefaultIdentifierSystem(), targetOrganizationIdentifierValue);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/TaskHelper.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/TaskHelper.java
index 62c263301..aa307ac93 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/TaskHelper.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/task/TaskHelper.java
@@ -6,6 +6,8 @@
import org.highmed.dsf.fhir.variables.Outputs;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.ParameterComponent;
+import org.hl7.fhir.r4.model.Task.TaskOutputComponent;
import org.hl7.fhir.r4.model.UrlType;
public interface TaskHelper
@@ -24,17 +26,27 @@ public interface TaskHelper
Optional getFirstInputParameterUrlValue(Task task, String system, String code);
- Stream getInputParameterWithExtension(Task task, String system, String code, String url);
-
Stream getInputParameterUrlValues(Task task, String system, String code);
- Task.ParameterComponent createInput(String system, String code, String value);
+ Optional getFirstInputParameterByteValue(Task task, String system, String code);
+
+ Stream getInputParameterWithExtension(Task task, String system, String code, String url);
+
+ ParameterComponent createInput(String system, String code, String value);
+
+ ParameterComponent createInput(String system, String code, boolean value);
+
+ ParameterComponent createInput(String system, String code, Reference reference);
+
+ ParameterComponent createInput(String system, String code, byte[] bytes);
+
+ ParameterComponent createInputUnsignedInt(String system, String code, int value);
- Task.ParameterComponent createInput(String system, String code, boolean value);
+ ParameterComponent createInput(String system, String code, int value);
- Task.ParameterComponent createInput(String system, String code, Reference reference);
+ TaskOutputComponent createOutput(String system, String code, String value);
- Task.TaskOutputComponent createOutput(String system, String code, String value);
+ TaskOutputComponent createOutputUnsignedInt(String system, String code, int value);
Task addOutputs(Task task, Outputs outputs);
}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfig.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfig.java
new file mode 100644
index 000000000..051677144
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfig.java
@@ -0,0 +1,103 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.security.Key;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+public class BloomFilterConfig
+{
+ private static final int SEED_LENGTH = 8;
+ private static final int HMAC_SHA2_KEY_LENGTH = 32;
+ private static final int HMAC_SHA3_KEY_LENGTH = 32;
+
+ private final long permutationSeed;
+
+ @JsonDeserialize(using = KeyDeserializer.class)
+ @JsonSerialize(using = KeySerializer.class)
+ private final Key hmacSha2Key;
+
+ @JsonDeserialize(using = KeyDeserializer.class)
+ @JsonSerialize(using = KeySerializer.class)
+ private final Key hmacSha3Key;
+
+ public static BloomFilterConfig fromBytes(byte[] bytes)
+ {
+ if (bytes.length != SEED_LENGTH + HMAC_SHA2_KEY_LENGTH + HMAC_SHA3_KEY_LENGTH)
+ throw new IllegalArgumentException(
+ "bytes.length = " + (SEED_LENGTH + HMAC_SHA2_KEY_LENGTH + HMAC_SHA3_KEY_LENGTH)
+ + " expected, but got " + bytes.length);
+
+ byte[] seed = new byte[SEED_LENGTH];
+ byte[] key1 = new byte[HMAC_SHA2_KEY_LENGTH];
+ byte[] key2 = new byte[HMAC_SHA3_KEY_LENGTH];
+
+ System.arraycopy(bytes, 0, seed, 0, seed.length);
+ System.arraycopy(bytes, seed.length, key1, 0, key1.length);
+ System.arraycopy(bytes, seed.length + key1.length, key2, 0, key2.length);
+
+ long permutationSeed = bigEndianToLong(seed);
+ Key hmacSha2Key = new SecretKeySpec(key1, "HmacSHA256");
+ Key hmacSha3Key = new SecretKeySpec(key2, "HmacSHA3-256");
+
+ return new BloomFilterConfig(permutationSeed, hmacSha2Key, hmacSha3Key);
+ }
+
+ @JsonCreator
+ public BloomFilterConfig(@JsonProperty("permutationSeed") long permutationSeed,
+ @JsonProperty("hmacSha2Key") Key hmacSha2Key, @JsonProperty("hmacSha3Key") Key hmacSha3Key)
+ {
+ this.permutationSeed = permutationSeed;
+ this.hmacSha2Key = hmacSha2Key;
+ this.hmacSha3Key = hmacSha3Key;
+ }
+
+ public long getPermutationSeed()
+ {
+ return permutationSeed;
+ }
+
+ public Key getHmacSha2Key()
+ {
+ return hmacSha2Key;
+ }
+
+ public Key getHmacSha3Key()
+ {
+ return hmacSha3Key;
+ }
+
+ @JsonIgnore
+ public byte[] toBytes()
+ {
+ byte[] bytes = new byte[SEED_LENGTH + HMAC_SHA2_KEY_LENGTH + HMAC_SHA3_KEY_LENGTH];
+
+ byte[] seed = longToBigEndian(permutationSeed);
+ byte[] key1 = hmacSha2Key.getEncoded();
+ byte[] key2 = hmacSha3Key.getEncoded();
+
+ System.arraycopy(seed, 0, bytes, 0, seed.length);
+ System.arraycopy(key1, 0, bytes, SEED_LENGTH, key1.length);
+ System.arraycopy(key2, 0, bytes, SEED_LENGTH + HMAC_SHA2_KEY_LENGTH, key2.length);
+
+ return bytes;
+ }
+
+ private static byte[] longToBigEndian(long l)
+ {
+ return new byte[] { (byte) (l >>> 56), (byte) (l >>> 48), (byte) (l >>> 40), (byte) (l >>> 32),
+ (byte) (l >>> 24), (byte) (l >>> 16), (byte) (l >>> 8), (byte) (l >>> 0) };
+ }
+
+ private static long bigEndianToLong(byte[] b)
+ {
+ return (((long) b[0] << 56) + ((long) (b[1] & 255) << 48) + ((long) (b[2] & 255) << 40)
+ + ((long) (b[3] & 255) << 32) + ((long) (b[4] & 255) << 24) + ((b[5] & 255) << 16) + ((b[6] & 255) << 8)
+ + ((b[7] & 255) << 0));
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfigSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfigSerializer.java
new file mode 100644
index 000000000..372d24c25
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfigSerializer.java
@@ -0,0 +1,70 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.io.IOException;
+import java.util.Objects;
+
+import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer;
+import org.camunda.bpm.engine.impl.variable.serializer.ValueFields;
+import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl;
+import org.highmed.dsf.fhir.variables.BloomFilterConfigValues.BloomFilterConfigValue;
+import org.springframework.beans.factory.InitializingBean;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class BloomFilterConfigSerializer extends PrimitiveValueSerializer
+ implements InitializingBean
+{
+ private final ObjectMapper objectMapper;
+
+ public BloomFilterConfigSerializer(ObjectMapper objectMapper)
+ {
+ super(BloomFilterConfigValues.VALUE_TYPE);
+
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ Objects.requireNonNull(objectMapper, "objectMapper");
+ }
+
+ @Override
+ public void writeValue(BloomFilterConfigValue value, ValueFields valueFields)
+ {
+ BloomFilterConfig target = value.getValue();
+ try
+ {
+ if (target != null)
+ valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(target));
+ }
+ catch (JsonProcessingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public BloomFilterConfigValue convertToTypedValue(UntypedValueImpl untypedValue)
+ {
+ return BloomFilterConfigValues.create((BloomFilterConfig) untypedValue.getValue());
+ }
+
+ @Override
+ public BloomFilterConfigValue readValue(ValueFields valueFields, boolean asTransientValue)
+ {
+ byte[] bytes = valueFields.getByteArrayValue();
+
+ try
+ {
+ BloomFilterConfig target = (bytes == null || bytes.length <= 0) ? null
+ : objectMapper.readValue(bytes, BloomFilterConfig.class);
+ return BloomFilterConfigValues.create(target);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfigValues.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfigValues.java
new file mode 100644
index 000000000..a38d71162
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/BloomFilterConfigValues.java
@@ -0,0 +1,54 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.util.Map;
+
+import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl;
+import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl;
+import org.camunda.bpm.engine.variable.type.PrimitiveValueType;
+import org.camunda.bpm.engine.variable.value.PrimitiveValue;
+import org.camunda.bpm.engine.variable.value.TypedValue;
+
+public class BloomFilterConfigValues
+{
+ public static interface BloomFilterConfigValue extends PrimitiveValue
+ {
+ }
+
+ private static class BloomFilterConfigValueImpl extends PrimitiveTypeValueImpl
+ implements BloomFilterConfigValues.BloomFilterConfigValue
+ {
+ private static final long serialVersionUID = 1L;
+
+ public BloomFilterConfigValueImpl(BloomFilterConfig value, PrimitiveValueType type)
+ {
+ super(value, type);
+ }
+ }
+
+ public static class BloomFilterConfigValueTypeImpl extends PrimitiveValueTypeImpl
+ {
+ private static final long serialVersionUID = 1L;
+
+ private BloomFilterConfigValueTypeImpl()
+ {
+ super(BloomFilterConfig.class);
+ }
+
+ @Override
+ public TypedValue createValue(Object value, Map valueInfo)
+ {
+ return new BloomFilterConfigValues.BloomFilterConfigValueImpl((BloomFilterConfig) value, VALUE_TYPE);
+ }
+ }
+
+ public static final PrimitiveValueType VALUE_TYPE = new BloomFilterConfigValues.BloomFilterConfigValueTypeImpl();
+
+ private BloomFilterConfigValues()
+ {
+ }
+
+ public static BloomFilterConfigValues.BloomFilterConfigValue create(BloomFilterConfig value)
+ {
+ return new BloomFilterConfigValues.BloomFilterConfigValueImpl(value, VALUE_TYPE);
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResult.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResult.java
index eca10b8e4..5558a7680 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResult.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResult.java
@@ -1,6 +1,9 @@
package org.highmed.dsf.fhir.variables;
+import org.highmed.openehr.model.structure.ResultSet;
+
import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
public class FeasibilityQueryResult
@@ -8,16 +11,37 @@ public class FeasibilityQueryResult
private final String organizationIdentifier;
private final String cohortId;
private final int cohortSize;
+ private final ResultSet resultSet;
+ private final String resultSetUrl;
+
+ public static FeasibilityQueryResult countResult(String organizationIdentifier, String cohortId, int cohortSize)
+ {
+ if (cohortSize < 0)
+ throw new IllegalArgumentException("cohortSize >= 0 expected");
+
+ return new FeasibilityQueryResult(organizationIdentifier, cohortId, cohortSize, null, null);
+ }
+
+ public static FeasibilityQueryResult idResult(String organizationIdentifier, String cohortId, ResultSet resultSet)
+ {
+ return new FeasibilityQueryResult(organizationIdentifier, cohortId, -1, resultSet, null);
+ }
+
+ public static FeasibilityQueryResult idResult(String organizationIdentifier, String cohortId, String resultSetUrl)
+ {
+ return new FeasibilityQueryResult(organizationIdentifier, cohortId, -1, null, resultSetUrl);
+ }
@JsonCreator
- public FeasibilityQueryResult(
- @JsonProperty("organizationIdentifier") String organizationIdentifier,
- @JsonProperty("groupId") String groupId,
- @JsonProperty("groupSize") int groupSize)
+ public FeasibilityQueryResult(@JsonProperty("organizationIdentifier") String organizationIdentifier,
+ @JsonProperty("cohortId") String cohortId, @JsonProperty("cohortSize") int cohortSize,
+ @JsonProperty("resultSet") ResultSet resultSet, @JsonProperty("resultSetUrl") String resultSetUrl)
{
this.organizationIdentifier = organizationIdentifier;
- this.cohortId = groupId;
- this.cohortSize = groupSize;
+ this.cohortId = cohortId;
+ this.cohortSize = cohortSize;
+ this.resultSet = resultSet;
+ this.resultSetUrl = resultSetUrl;
}
public String getOrganizationIdentifier()
@@ -34,4 +58,32 @@ public int getCohortSize()
{
return cohortSize;
}
+
+ public ResultSet getResultSet()
+ {
+ return resultSet;
+ }
+
+ public String getResultSetUrl()
+ {
+ return resultSetUrl;
+ }
+
+ @JsonIgnore
+ public boolean isCohortSizeResult()
+ {
+ return resultSet == null && resultSetUrl == null;
+ }
+
+ @JsonIgnore
+ public boolean isIdResultSetResult()
+ {
+ return resultSet != null && resultSetUrl == null;
+ }
+
+ @JsonIgnore
+ public boolean isIdResultSetUrlResult()
+ {
+ return resultSet == null && resultSetUrl != null;
+ }
}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java
index 1d139ce93..591946001 100644
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java
@@ -33,11 +33,11 @@ public void afterPropertiesSet() throws Exception
@Override
public void writeValue(FeasibilityQueryResultValue value, ValueFields valueFields)
{
- FeasibilityQueryResult target = value.getValue();
+ FeasibilityQueryResult result = value.getValue();
try
{
- if (target != null)
- valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(target));
+ if (result != null)
+ valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(result));
}
catch (JsonProcessingException e)
{
@@ -52,15 +52,15 @@ public FeasibilityQueryResultValue convertToTypedValue(UntypedValueImpl untypedV
}
@Override
- public FeasibilityQueryResultValue readValue(ValueFields valueFields)
+ public FeasibilityQueryResultValue readValue(ValueFields valueFields, boolean asTransientValue)
{
byte[] bytes = valueFields.getByteArrayValue();
try
{
- FeasibilityQueryResult target = (bytes == null || bytes.length <= 0) ? null
+ FeasibilityQueryResult result = (bytes == null || bytes.length <= 0) ? null
: objectMapper.readValue(bytes, FeasibilityQueryResult.class);
- return FeasibilityQueryResultValues.create(target);
+ return FeasibilityQueryResultValues.create(result);
}
catch (IOException e)
{
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java
index 347d814a0..d7b8afe31 100644
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java
@@ -33,11 +33,11 @@ public void afterPropertiesSet() throws Exception
@Override
public void writeValue(FeasibilityQueryResultsValue value, ValueFields valueFields)
{
- FeasibilityQueryResults targets = value.getValue();
+ FeasibilityQueryResults results = value.getValue();
try
{
- if (targets != null)
- valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(targets));
+ if (results != null)
+ valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(results));
}
catch (JsonProcessingException e)
{
@@ -52,15 +52,15 @@ public FeasibilityQueryResultsValue convertToTypedValue(UntypedValueImpl untyped
}
@Override
- public FeasibilityQueryResultsValue readValue(ValueFields valueFields)
+ public FeasibilityQueryResultsValue readValue(ValueFields valueFields, boolean asTransientValue)
{
byte[] bytes = valueFields.getByteArrayValue();
try
{
- FeasibilityQueryResults targets = (bytes == null || bytes.length <= 0) ? null
+ FeasibilityQueryResults results = (bytes == null || bytes.length <= 0) ? null
: objectMapper.readValue(bytes, FeasibilityQueryResults.class);
- return FeasibilityQueryResultsValues.create(targets);
+ return FeasibilityQueryResultsValues.create(results);
}
catch (IOException e)
{
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java
index 04e187b85..bdc7c8241 100644
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java
@@ -66,7 +66,7 @@ public FhirResourceValue convertToTypedValue(UntypedValueImpl untypedValue)
}
@Override
- public FhirResourceValue readValue(ValueFields valueFields)
+ public FhirResourceValue readValue(ValueFields valueFields, boolean asTransientValue)
{
String className = valueFields.getTextValue();
byte[] bytes = valueFields.getByteArrayValue();
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java
index bf430e970..3298df9a7 100644
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java
@@ -58,7 +58,7 @@ public FhirResourcesListValue convertToTypedValue(UntypedValueImpl untypedValue)
}
@Override
- public FhirResourcesListValue readValue(ValueFields valueFields)
+ public FhirResourcesListValue readValue(ValueFields valueFields, boolean asTransientValue)
{
String className = valueFields.getTextValue();
byte[] bytes = valueFields.getByteArrayValue();
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResult.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResult.java
new file mode 100644
index 000000000..6e19c49b1
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResult.java
@@ -0,0 +1,35 @@
+package org.highmed.dsf.fhir.variables;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class FinalFeasibilityQueryResult
+{
+ private final String cohortId;
+ private final int participatingMedics;
+ private final int cohortSize;
+
+ @JsonCreator
+ public FinalFeasibilityQueryResult(@JsonProperty("cohortId") String cohortId,
+ @JsonProperty("participatingMedics") int participatingMedics, @JsonProperty("cohortSize") int cohortSize)
+ {
+ this.cohortId = cohortId;
+ this.participatingMedics = participatingMedics;
+ this.cohortSize = cohortSize;
+ }
+
+ public String getCohortId()
+ {
+ return cohortId;
+ }
+
+ public int getParticipatingMedics()
+ {
+ return participatingMedics;
+ }
+
+ public int getCohortSize()
+ {
+ return cohortSize;
+ }
+}
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultSerializer.java
new file mode 100644
index 000000000..c67dcd212
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultSerializer.java
@@ -0,0 +1,70 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.io.IOException;
+import java.util.Objects;
+
+import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer;
+import org.camunda.bpm.engine.impl.variable.serializer.ValueFields;
+import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResultValues.FinalFeasibilityQueryResultValue;
+import org.springframework.beans.factory.InitializingBean;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class FinalFeasibilityQueryResultSerializer extends PrimitiveValueSerializer
+ implements InitializingBean
+{
+ private final ObjectMapper objectMapper;
+
+ public FinalFeasibilityQueryResultSerializer(ObjectMapper objectMapper)
+ {
+ super(FinalFeasibilityQueryResultValues.VALUE_TYPE);
+
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ Objects.requireNonNull(objectMapper, "objectMapper");
+ }
+
+ @Override
+ public void writeValue(FinalFeasibilityQueryResultValue value, ValueFields valueFields)
+ {
+ FinalFeasibilityQueryResult result = value.getValue();
+ try
+ {
+ if (result != null)
+ valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(result));
+ }
+ catch (JsonProcessingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public FinalFeasibilityQueryResultValue convertToTypedValue(UntypedValueImpl untypedValue)
+ {
+ return FinalFeasibilityQueryResultValues.create((FinalFeasibilityQueryResult) untypedValue.getValue());
+ }
+
+ @Override
+ public FinalFeasibilityQueryResultValue readValue(ValueFields valueFields, boolean asTransientValue)
+ {
+ byte[] bytes = valueFields.getByteArrayValue();
+
+ try
+ {
+ FinalFeasibilityQueryResult result = (bytes == null || bytes.length <= 0) ? null
+ : objectMapper.readValue(bytes, FinalFeasibilityQueryResult.class);
+ return FinalFeasibilityQueryResultValues.create(result);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultValues.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultValues.java
new file mode 100644
index 000000000..8c29c6a51
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultValues.java
@@ -0,0 +1,57 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.util.Map;
+
+import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl;
+import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl;
+import org.camunda.bpm.engine.variable.type.PrimitiveValueType;
+import org.camunda.bpm.engine.variable.value.PrimitiveValue;
+import org.camunda.bpm.engine.variable.value.TypedValue;
+
+public class FinalFeasibilityQueryResultValues
+{
+ public static interface FinalFeasibilityQueryResultValue extends PrimitiveValue
+ {
+ }
+
+ private static class FinalFeasibilityQueryResultValueImpl
+ extends PrimitiveTypeValueImpl
+ implements FinalFeasibilityQueryResultValues.FinalFeasibilityQueryResultValue
+ {
+ private static final long serialVersionUID = 1L;
+
+ public FinalFeasibilityQueryResultValueImpl(FinalFeasibilityQueryResult value, PrimitiveValueType type)
+ {
+ super(value, type);
+ }
+ }
+
+ public static class FinalFeasibilityQueryResultValueTypeImpl extends PrimitiveValueTypeImpl
+ {
+ private static final long serialVersionUID = 1L;
+
+ private FinalFeasibilityQueryResultValueTypeImpl()
+ {
+ super(FinalFeasibilityQueryResult.class);
+ }
+
+ @Override
+ public TypedValue createValue(Object value, Map valueInfo)
+ {
+ return new FinalFeasibilityQueryResultValues.FinalFeasibilityQueryResultValueImpl(
+ (FinalFeasibilityQueryResult) value, VALUE_TYPE);
+ }
+ }
+
+ public static final PrimitiveValueType VALUE_TYPE = new FinalFeasibilityQueryResultValues.FinalFeasibilityQueryResultValueTypeImpl();
+
+ private FinalFeasibilityQueryResultValues()
+ {
+ }
+
+ public static FinalFeasibilityQueryResultValues.FinalFeasibilityQueryResultValue create(
+ FinalFeasibilityQueryResult value)
+ {
+ return new FinalFeasibilityQueryResultValues.FinalFeasibilityQueryResultValueImpl(value, VALUE_TYPE);
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResults.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResults.java
new file mode 100644
index 000000000..16fd822f8
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResults.java
@@ -0,0 +1,38 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class FinalFeasibilityQueryResults
+{
+ private final List results = new ArrayList<>();
+
+ @JsonCreator
+ public FinalFeasibilityQueryResults(@JsonProperty("results") Collection extends FinalFeasibilityQueryResult> results)
+ {
+ if (results != null)
+ this.results.addAll(results);
+ }
+
+ public void add(FinalFeasibilityQueryResult newResult)
+ {
+ if (newResult != null)
+ results.add(newResult);
+ }
+
+ public void addAll(Collection results)
+ {
+ if (results != null)
+ this.results.addAll(results);
+ }
+
+ public List getResults()
+ {
+ return Collections.unmodifiableList(results);
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultsSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultsSerializer.java
new file mode 100644
index 000000000..ba0eee54b
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultsSerializer.java
@@ -0,0 +1,70 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.io.IOException;
+import java.util.Objects;
+
+import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer;
+import org.camunda.bpm.engine.impl.variable.serializer.ValueFields;
+import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResultsValues.FinalFeasibilityQueryResultsValue;
+import org.springframework.beans.factory.InitializingBean;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class FinalFeasibilityQueryResultsSerializer extends PrimitiveValueSerializer
+ implements InitializingBean
+{
+ private final ObjectMapper objectMapper;
+
+ public FinalFeasibilityQueryResultsSerializer(ObjectMapper objectMapper)
+ {
+ super(FinalFeasibilityQueryResultsValues.VALUE_TYPE);
+
+ this.objectMapper = objectMapper;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ Objects.requireNonNull(objectMapper, "objectMapper");
+ }
+
+ @Override
+ public void writeValue(FinalFeasibilityQueryResultsValue value, ValueFields valueFields)
+ {
+ FinalFeasibilityQueryResults results = value.getValue();
+ try
+ {
+ if (results != null)
+ valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(results));
+ }
+ catch (JsonProcessingException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public FinalFeasibilityQueryResultsValue convertToTypedValue(UntypedValueImpl untypedValue)
+ {
+ return FinalFeasibilityQueryResultsValues.create((FinalFeasibilityQueryResults) untypedValue.getValue());
+ }
+
+ @Override
+ public FinalFeasibilityQueryResultsValue readValue(ValueFields valueFields, boolean asTransientValue)
+ {
+ byte[] bytes = valueFields.getByteArrayValue();
+
+ try
+ {
+ FinalFeasibilityQueryResults results = (bytes == null || bytes.length <= 0) ? null
+ : objectMapper.readValue(bytes, FinalFeasibilityQueryResults.class);
+ return FinalFeasibilityQueryResultsValues.create(results);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultsValues.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultsValues.java
new file mode 100644
index 000000000..ac6b1eae8
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalFeasibilityQueryResultsValues.java
@@ -0,0 +1,57 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.util.Map;
+
+import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl;
+import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl;
+import org.camunda.bpm.engine.variable.type.PrimitiveValueType;
+import org.camunda.bpm.engine.variable.value.PrimitiveValue;
+import org.camunda.bpm.engine.variable.value.TypedValue;
+
+public class FinalFeasibilityQueryResultsValues
+{
+ public static interface FinalFeasibilityQueryResultsValue extends PrimitiveValue
+ {
+ }
+
+ private static class FinalFeasibilityQueryResultsValueImpl
+ extends PrimitiveTypeValueImpl
+ implements FinalFeasibilityQueryResultsValues.FinalFeasibilityQueryResultsValue
+ {
+ private static final long serialVersionUID = 1L;
+
+ public FinalFeasibilityQueryResultsValueImpl(FinalFeasibilityQueryResults value, PrimitiveValueType type)
+ {
+ super(value, type);
+ }
+ }
+
+ public static class FinalFeasibilityQueryResultsValueTypeImpl extends PrimitiveValueTypeImpl
+ {
+ private static final long serialVersionUID = 1L;
+
+ private FinalFeasibilityQueryResultsValueTypeImpl()
+ {
+ super(FinalFeasibilityQueryResults.class);
+ }
+
+ @Override
+ public TypedValue createValue(Object value, Map valueInfo)
+ {
+ return new FinalFeasibilityQueryResultsValues.FinalFeasibilityQueryResultsValueImpl(
+ (FinalFeasibilityQueryResults) value, VALUE_TYPE);
+ }
+ }
+
+ public static final PrimitiveValueType VALUE_TYPE = new FinalFeasibilityQueryResultsValues.FinalFeasibilityQueryResultsValueTypeImpl();
+
+ private FinalFeasibilityQueryResultsValues()
+ {
+ }
+
+ public static FinalFeasibilityQueryResultsValues.FinalFeasibilityQueryResultsValue create(
+ FinalFeasibilityQueryResults value)
+ {
+ return new FinalFeasibilityQueryResultsValues.FinalFeasibilityQueryResultsValueImpl(value, VALUE_TYPE);
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalSimpleFeasibilityResult.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalSimpleFeasibilityResult.java
deleted file mode 100644
index 40b369d6c..000000000
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FinalSimpleFeasibilityResult.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.highmed.dsf.fhir.variables;
-
-public class FinalSimpleFeasibilityResult
-{
- private final String cohortId;
- private final long participatingMedics;
- private final long cohortSize;
-
- public FinalSimpleFeasibilityResult(String cohortId, long participatingMedics, long cohortSize)
- {
- this.cohortId = cohortId;
- this.participatingMedics = participatingMedics;
- this.cohortSize = cohortSize;
- }
-
- public String getCohortId()
- {
- return cohortId;
- }
-
- public long getParticipatingMedics()
- {
- return participatingMedics;
- }
-
- public long getCohortSize()
- {
- return cohortSize;
- }
-}
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/KeyDeserializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/KeyDeserializer.java
new file mode 100644
index 000000000..8961869a4
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/KeyDeserializer.java
@@ -0,0 +1,27 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.io.IOException;
+import java.security.Key;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.TreeNode;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.node.TextNode;
+
+public class KeyDeserializer extends JsonDeserializer
+{
+ @Override
+ public Key deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException
+ {
+ TreeNode node = p.getCodec().readTree(p);
+
+ String algorithm = ((TextNode) node.get("algorithm")).textValue();
+ byte[] value = ((TextNode) node.get("value")).binaryValue();
+
+ return new SecretKeySpec(value, algorithm);
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/KeySerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/KeySerializer.java
new file mode 100644
index 000000000..9b104277a
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/KeySerializer.java
@@ -0,0 +1,24 @@
+package org.highmed.dsf.fhir.variables;
+
+import java.io.IOException;
+import java.security.Key;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+public class KeySerializer extends JsonSerializer
+{
+ @Override
+ public void serialize(Key value, JsonGenerator jgen, SerializerProvider provider)
+ throws IOException, JsonGenerationException
+ {
+ jgen.writeStartObject();
+ jgen.writeFieldName("algorithm");
+ jgen.writeString(value.getAlgorithm());
+ jgen.writeFieldName("value");
+ jgen.writeBinary(value.getEncoded());
+ jgen.writeEndObject();
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetSerializer.java
index 48934830d..7993c0ed0 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetSerializer.java
@@ -52,7 +52,7 @@ public MultiInstanceTargetValue convertToTypedValue(UntypedValueImpl untypedValu
}
@Override
- public MultiInstanceTargetValue readValue(ValueFields valueFields)
+ public MultiInstanceTargetValue readValue(ValueFields valueFields, boolean asTransientValue)
{
byte[] bytes = valueFields.getByteArrayValue();
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetsSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetsSerializer.java
index c7493ddaf..add2f433f 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetsSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/MultiInstanceTargetsSerializer.java
@@ -52,7 +52,7 @@ public MultiInstanceTargetsValue convertToTypedValue(UntypedValueImpl untypedVal
}
@Override
- public MultiInstanceTargetsValue readValue(ValueFields valueFields)
+ public MultiInstanceTargetsValue readValue(ValueFields valueFields, boolean asTransientValue)
{
byte[] bytes = valueFields.getByteArrayValue();
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputSerializer.java
index e1a0d5aa2..de5034b6c 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputSerializer.java
@@ -51,7 +51,7 @@ public OutputValue convertToTypedValue(UntypedValueImpl untypedValue)
}
@Override
- public OutputValue readValue(ValueFields valueFields)
+ public OutputValue readValue(ValueFields valueFields, boolean asTransientValue)
{
byte[] bytes = valueFields.getByteArrayValue();
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputsSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputsSerializer.java
index 196854ea4..24fa29cb0 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputsSerializer.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OutputsSerializer.java
@@ -51,7 +51,7 @@ public OutputsValue convertToTypedValue(UntypedValueImpl untypedValue)
}
@Override
- public OutputsValue readValue(ValueFields valueFields)
+ public OutputsValue readValue(ValueFields valueFields, boolean asTransientValue)
{
byte[] bytes = valueFields.getByteArrayValue();
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/SerializerPlugin.java
old mode 100755
new mode 100644
similarity index 71%
rename from dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java
rename to dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/SerializerPlugin.java
index 55950dda5..ead6dfb0b
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/SerializerPlugin.java
@@ -8,22 +8,26 @@
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.camunda.bpm.engine.impl.variable.serializer.TypedValueSerializer;
-public class FhirPlugin implements ProcessEnginePlugin
+public class SerializerPlugin implements ProcessEnginePlugin
{
@SuppressWarnings("rawtypes")
private final List serializer;
- public FhirPlugin(FhirResourceSerializer fhirResourceSerializer,
+ public SerializerPlugin(FhirResourceSerializer fhirResourceSerializer,
FhirResourcesListSerializer fhirResourcesListSerializer,
MultiInstanceTargetSerializer multiInstanceTargetSerializer,
MultiInstanceTargetsSerializer multiInstanceTargetsSerializer,
FeasibilityQueryResultSerializer feasibilityQueryResultSerializer,
- FeasibilityQueryResultsSerializer feasibilityQueryResultsSerializer, OutputSerializer outputSerializer,
+ FeasibilityQueryResultsSerializer feasibilityQueryResultsSerializer,
+ FinalFeasibilityQueryResultSerializer finalFeasibilityQueryResultSerializer,
+ FinalFeasibilityQueryResultsSerializer finalFeasibilityQueryResultsSerializer,
+ BloomFilterConfigSerializer bloomFilterConfigSerializer, OutputSerializer outputSerializer,
OutputsSerializer outputsSerializer)
{
serializer = Arrays.asList(fhirResourceSerializer, fhirResourcesListSerializer, multiInstanceTargetSerializer,
multiInstanceTargetsSerializer, feasibilityQueryResultSerializer, feasibilityQueryResultsSerializer,
- outputSerializer, outputsSerializer);
+ finalFeasibilityQueryResultSerializer, finalFeasibilityQueryResultsSerializer,
+ bloomFilterConfigSerializer, outputSerializer, outputsSerializer);
}
@Override
diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/openehr/client/OpenEhrWebserviceClientProvider.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/openehr/client/OpenEhrWebserviceClientProvider.java
index fdf7b7ed1..9757924da 100755
--- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/openehr/client/OpenEhrWebserviceClientProvider.java
+++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/openehr/client/OpenEhrWebserviceClientProvider.java
@@ -1,10 +1,10 @@
package org.highmed.dsf.openehr.client;
-import org.highmed.openehr.client.OpenehrWebserviceClient;
+import org.highmed.openehr.client.OpenEhrWebserviceClient;
public interface OpenEhrWebserviceClientProvider
{
String getBaseUrl();
- OpenehrWebserviceClient getWebserviceClient();
+ OpenEhrWebserviceClient getWebserviceClient();
}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/test/java/org/highmed/dsf/fhir/variables/BloomFilterConfigTest.java b/dsf-bpe/dsf-bpe-process-base/src/test/java/org/highmed/dsf/fhir/variables/BloomFilterConfigTest.java
new file mode 100644
index 000000000..a7a6d141d
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/test/java/org/highmed/dsf/fhir/variables/BloomFilterConfigTest.java
@@ -0,0 +1,61 @@
+package org.highmed.dsf.fhir.variables;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Base64;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class BloomFilterConfigTest
+{
+ private static final Logger logger = LoggerFactory.getLogger(BloomFilterConfigTest.class);
+
+ private static final byte[] b1 = Base64.getDecoder().decode("KLhuuy3lDSmo8A/mcYBBZJ+Xu+ok30qDGM4L0magwyY=");
+ private static final byte[] b2 = Base64.getDecoder().decode("VALdwRisuEsUBIXaqJ01L9lk0jJUSGm5ZBE+Ha5bm8c=");
+ private static final long l = -9139328758761390867L;
+
+ @Test
+ public void testReadWriteJson() throws Exception
+ {
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ BloomFilterConfig bfc = new BloomFilterConfig(l, new SecretKeySpec(b1, "HmacSHA256"),
+ new SecretKeySpec(b2, "HmacSHA3-256"));
+
+ String value = objectMapper.writeValueAsString(bfc);
+
+ logger.debug("BloomFilterConfig: {}", value);
+
+ BloomFilterConfig readBfc = objectMapper.readValue(value, BloomFilterConfig.class);
+
+ assertNotNull(readBfc);
+ assertEquals(bfc.getPermutationSeed(), readBfc.getPermutationSeed());
+ assertEquals(bfc.getHmacSha2Key(), readBfc.getHmacSha2Key());
+ assertEquals(bfc.getHmacSha3Key(), readBfc.getHmacSha3Key());
+ }
+
+ @Test
+ public void testReadWriteBytes() throws Exception
+ {
+ BloomFilterConfig bfc = new BloomFilterConfig(l, new SecretKeySpec(b1, "HmacSHA256"),
+ new SecretKeySpec(b2, "HmacSHA3-256"));
+
+ byte[] bytes = bfc.toBytes();
+
+ logger.debug("BloomFilterConfig: {}", Base64.getEncoder().encodeToString(bytes));
+
+ BloomFilterConfig fromBytes = BloomFilterConfig.fromBytes(bytes);
+
+ assertNotNull(fromBytes);
+ assertEquals(bfc.getPermutationSeed(), fromBytes.getPermutationSeed());
+ assertEquals(bfc.getHmacSha2Key(), fromBytes.getHmacSha2Key());
+ assertEquals(bfc.getHmacSha3Key(), fromBytes.getHmacSha3Key());
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-base/src/test/resources/log4j2.xml b/dsf-bpe/dsf-bpe-process-base/src/test/resources/log4j2.xml
new file mode 100644
index 000000000..f1afe81dc
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-base/src/test/resources/log4j2.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/pom.xml b/dsf-bpe/dsf-bpe-process-feasibility/pom.xml
index e3d119997..3e9caa823 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-feasibility/pom.xml
@@ -1,6 +1,6 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
dsf-bpe-process-feasibility
@@ -8,7 +8,7 @@
dsf-bpe-pom
org.highmed.dsf
- 0.1.0
+ 0.2.0
@@ -16,6 +16,20 @@
org.highmed.dsf
dsf-bpe-process-base
+
+ org.highmed.dsf
+ dsf-pseudonymization-medic
+
+
+ org.highmed.dsf
+ dsf-pseudonymization-ttp
+
+
+
+ org.highmed.dsf
+ dsf-mpi-client
+
+
de.hs-heilbronn.mi
log4j2-utils
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java
index 3e93d09de..131ef178e 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java
@@ -8,10 +8,11 @@
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.AbstractTaskMessageSend;
import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.BloomFilterConfig;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.ResearchStudy;
-import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.ParameterComponent;
import ca.uhn.fhir.context.FhirContext;
@@ -24,26 +25,39 @@ public SendMedicRequest(FhirWebserviceClientProvider clientProvider, TaskHelper
}
@Override
- protected Stream getAdditionalInputParameters(DelegateExecution execution)
+ protected Stream getAdditionalInputParameters(DelegateExecution execution)
{
ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(Constants.VARIABLE_RESEARCH_STUDY);
- IdType type = new IdType(getFhirWebserviceClientProvider().getLocalBaseUrl() + "/" + researchStudy.getId());
+ IdType researchStudyId = new IdType(
+ getFhirWebserviceClientProvider().getLocalBaseUrl() + "/" + researchStudy.getId());
- Task.ParameterComponent inputResearchStudyReference = getTaskHelper()
- .createInput(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE,
- new Reference().setReference(type.getValueAsString()));
+ ParameterComponent inputResearchStudyReference = getTaskHelper().createInput(
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE,
+ new Reference().setReference(researchStudyId.toVersionless().getValueAsString()));
boolean needsConsentCheck = (boolean) execution.getVariable(Constants.VARIABLE_NEEDS_CONSENT_CHECK);
- Task.ParameterComponent inputNeedsConsentCheck = getTaskHelper()
- .createInput(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck);
+ ParameterComponent inputNeedsConsentCheck = getTaskHelper().createInput(
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck);
boolean needsRecordLinkage = (boolean) execution.getVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE);
- Task.ParameterComponent inputNeedsRecordLinkage = getTaskHelper()
- .createInput(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage);
-
- return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck, inputNeedsRecordLinkage);
+ ParameterComponent inputNeedsRecordLinkage = getTaskHelper().createInput(
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage);
+
+ if (needsRecordLinkage)
+ {
+ BloomFilterConfig bloomFilterConfig = (BloomFilterConfig) execution
+ .getVariable(Constants.VARIABLE_BLOOM_FILTER_CONFIG);
+ ParameterComponent inputBloomFilterConfig = getTaskHelper().createInput(
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG, bloomFilterConfig.toBytes());
+
+ return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck, inputNeedsRecordLinkage,
+ inputBloomFilterConfig);
+ }
+ else
+ return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck, inputNeedsRecordLinkage);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java
index a236c53f3..244ceb7c8 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java
@@ -8,10 +8,11 @@
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.AbstractTaskMessageSend;
import org.highmed.dsf.fhir.task.TaskHelper;
-import org.highmed.dsf.fhir.variables.Outputs;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResults;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Reference;
-import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.ParameterComponent;
import ca.uhn.fhir.context.FhirContext;
@@ -24,19 +25,30 @@ public SendMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHe
}
@Override
- protected Stream getAdditionalInputParameters(DelegateExecution execution)
+ protected Stream getAdditionalInputParameters(DelegateExecution execution)
{
- Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
+ FinalFeasibilityQueryResults results = (FinalFeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_FINAL_QUERY_RESULTS);
- return outputs.getOutputs().stream().map(output -> {
- Task.ParameterComponent component = getTaskHelper()
- .createInput(output.getSystem(), output.getCode(), output.getValue());
+ return results.getResults().stream().flatMap(this::toInputs);
+ }
+
+ private Stream toInputs(FinalFeasibilityQueryResult result)
+ {
+ ParameterComponent input1 = getTaskHelper().createInputUnsignedInt(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT, result.getCohortSize());
+ input1.addExtension(createCohortIdExtension(result.getCohortId()));
- if (output.hasExtension())
- component.addExtension(
- new Extension(output.getExtensionUrl(), new Reference(output.getExtensionValue())));
+ ParameterComponent input2 = getTaskHelper().createInputUnsignedInt(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT,
+ result.getParticipatingMedics());
+ input2.addExtension(createCohortIdExtension(result.getCohortId()));
- return component;
- });
+ return Stream.of(input1, input2);
+ }
+
+ private Extension createCohortIdExtension(String cohortId)
+ {
+ return new Extension(Constants.EXTENSION_GROUP_ID_URI, new Reference(cohortId));
}
-}
+}
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java
index 9d49413bd..78ac4f00a 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java
@@ -8,15 +8,21 @@
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.AbstractTaskMessageSend;
import org.highmed.dsf.fhir.task.TaskHelper;
-import org.highmed.dsf.fhir.variables.Outputs;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.ParameterComponent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import ca.uhn.fhir.context.FhirContext;
public class SendSingleMedicResults extends AbstractTaskMessageSend
{
+ private static final Logger logger = LoggerFactory.getLogger(SendSingleMedicResults.class);
+
public SendSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
OrganizationProvider organizationProvider, FhirContext fhirContext)
{
@@ -26,14 +32,41 @@ public SendSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskH
@Override
protected Stream getAdditionalInputParameters(DelegateExecution execution)
{
- Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
- return outputs.getOutputs().stream().map(o -> {
- Task.ParameterComponent component = getTaskHelper().createInput(o.getSystem(), o.getCode(), o.getValue());
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
+
+ return results.getResults().stream().map(result -> toInput(result));
+ }
- if (o.hasExtension())
- component.addExtension(new Extension(o.getExtensionUrl(), new Reference(o.getExtensionValue())));
+ private Task.ParameterComponent toInput(FeasibilityQueryResult result)
+ {
+ if (result.isCohortSizeResult())
+ {
+ ParameterComponent input = getTaskHelper().createInputUnsignedInt(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT, result.getCohortSize());
+ input.addExtension(createCohortIdExtension(result.getCohortId()));
+ return input;
+ }
+ else if (result.isIdResultSetUrlResult())
+ {
+ ParameterComponent input = getTaskHelper().createInput(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE,
+ new Reference(result.getResultSetUrl()));
+ input.addExtension(createCohortIdExtension(result.getCohortId()));
+ return input;
+ }
+ else
+ {
+ logger.warn("Unexpected result (not a cohort-size or ResultSet URL result) for cohort with ID "
+ + result.getCohortId());
+ throw new RuntimeException(
+ "Unexpected result (not a cohort-size or ResultSet URL result) for cohort with ID "
+ + result.getCohortId());
+ }
+ }
- return component;
- });
+ private Extension createCohortIdExtension(String cohortId)
+ {
+ return new Extension(Constants.EXTENSION_GROUP_ID_URI, new Reference(cohortId));
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java
index f0828ce7c..1ac5d42ba 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java
@@ -32,16 +32,11 @@ protected Stream getAdditionalInputParameters(DelegateE
Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY,
target.getCorrelationKey()));
- boolean needsConsentCheck = (boolean) execution.getVariable(Constants.VARIABLE_NEEDS_CONSENT_CHECK);
- Task.ParameterComponent inputNeedsConsentCheck = getTaskHelper()
- .createInput(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck);
-
boolean needsRecordLinkage = (boolean) execution.getVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE);
Task.ParameterComponent inputNeedsRecordLinkage = getTaskHelper()
.createInput(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE , needsRecordLinkage);
- return Stream.concat(inputTargets, Stream.of(inputNeedsConsentCheck, inputNeedsRecordLinkage));
+ return Stream.concat(inputTargets, Stream.of(inputNeedsRecordLinkage));
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java
index 249fbd0ce..24acc480b 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java
@@ -1,6 +1,7 @@
package org.highmed.dsf.bpe.service;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
import org.camunda.bpm.engine.delegate.DelegateExecution;
@@ -10,8 +11,9 @@
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
-import org.highmed.dsf.fhir.variables.FinalSimpleFeasibilityResult;
-import org.highmed.dsf.fhir.variables.Outputs;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResultsValues;
public class CalculateMultiMedicResults extends AbstractServiceDelegate
{
@@ -21,44 +23,35 @@ public CalculateMultiMedicResults(FhirWebserviceClientProvider clientProvider, T
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
-
- List locationBasedResults = ((FeasibilityQueryResults) execution
+ List results = ((FeasibilityQueryResults) execution
.getVariable(Constants.VARIABLE_QUERY_RESULTS)).getResults();
- List finalResults = calculateResults(locationBasedResults);
// TODO: add percentage filter over result
+ List finalResults = calculateResults(results);
- Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
- addResultsToOutput(outputs, finalResults);
-
- execution.setVariable(Constants.VARIABLE_PROCESS_OUTPUTS, outputs);
+ execution.setVariable(Constants.VARIABLE_FINAL_QUERY_RESULTS,
+ FinalFeasibilityQueryResultsValues.create(new FinalFeasibilityQueryResults(finalResults)));
}
- private List calculateResults(List results)
+ private List calculateResults(List results)
{
- return results.stream().map(FeasibilityQueryResult::getCohortId).distinct().map(groupId -> {
- long participatingMedics = results.stream().filter(resultEntry -> resultEntry.getCohortId().equals(groupId))
- .count();
- long result = results.stream().filter(resultEntry -> resultEntry.getCohortId().equals(groupId))
- .mapToInt(FeasibilityQueryResult::getCohortSize).sum();
- return new FinalSimpleFeasibilityResult(groupId, participatingMedics, result);
- }).collect(Collectors.toUnmodifiableList());
+ Map> byCohortId = results.stream()
+ .collect(Collectors.groupingBy(FeasibilityQueryResult::getCohortId));
+
+ return byCohortId.entrySet().stream()
+ .map(e -> new FinalFeasibilityQueryResult(e.getKey(),
+ toInt(e.getValue().stream().filter(r -> r.getCohortSize() > 0).count()),
+ toInt(e.getValue().stream().mapToLong(FeasibilityQueryResult::getCohortSize).sum())))
+ .collect(Collectors.toList());
}
- private void addResultsToOutput(Outputs outputs, List finalResults)
+ private int toInt(long l)
{
- finalResults.forEach(result -> {
- outputs.add(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT,
- String.valueOf(result.getCohortSize()), Constants.EXTENSION_GROUP_ID_URI, result.getCohortId());
- ;
-
- outputs.add(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT,
- String.valueOf(result.getParticipatingMedics()), Constants.EXTENSION_GROUP_ID_URI,
- result.getCohortId());
- });
+ if (l > Integer.MAX_VALUE)
+ throw new IllegalArgumentException("long > " + Integer.MAX_VALUE);
+ else
+ return (int) l;
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java
index 2bd78ebad..2ff059c82 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java
@@ -23,7 +23,7 @@ public CheckFeasibilityResources(FhirWebserviceClientProvider clientProvider, Ta
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(Constants.VARIABLE_RESEARCH_STUDY);
@@ -31,28 +31,39 @@ public void doExecute(DelegateExecution execution) throws Exception
.getResourcesAndCast();
checkNumberOfParticipatingMedics(researchStudy);
+ checkFullyQualifiedCohortIds(cohorts);
checkNumberOfCohortDefinitions(cohorts);
}
private void checkNumberOfParticipatingMedics(ResearchStudy researchStudy)
{
- long medics = researchStudy.getExtension().stream()
- .filter(e -> e.getUrl().equals(Constants.EXTENSION_PARTICIPATING_MEDIC_URI))
- .map(extension -> ((Reference) extension.getValue()).getReference()).distinct().count();
+ long medics = researchStudy.getExtensionsByUrl(Constants.EXTENSION_PARTICIPATING_MEDIC_URI).stream()
+ .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
+ .map(r -> r.getIdentifier())
+ .filter(i -> "http://highmed.org/fhir/NamingSystem/organization-identifier".equals(i.getSystem()))
+ .map(i -> i.getValue()).distinct().count();
if (medics < MIN_PARTICIPATING_MEDICS)
{
- throw new IllegalStateException(
+ throw new RuntimeException(
"Number of distinct participanting MeDICs is < " + MIN_PARTICIPATING_MEDICS + ", got " + medics);
}
}
+ private void checkFullyQualifiedCohortIds(List cohorts)
+ {
+ if (cohorts.stream().anyMatch(g -> !g.getIdElement().hasBaseUrl()))
+ {
+ throw new RuntimeException("Not all cohorts have fully qualified ids (containing server base url)");
+ }
+ }
+
private void checkNumberOfCohortDefinitions(List cohorts)
{
int size = cohorts.size();
if (size < MIN_COHORT_DEFINITIONS)
{
- throw new IllegalStateException(
+ throw new RuntimeException(
"Number of defined cohorts is < " + MIN_COHORT_DEFINITIONS + ", got " + cohorts.size());
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java
index e15c0e97b..44c2c8f7e 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java
@@ -1,13 +1,21 @@
package org.highmed.dsf.bpe.service;
+import java.util.List;
+import java.util.stream.Collectors;
+
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
-import org.highmed.dsf.fhir.variables.Outputs;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResults;
+import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.ParameterComponent;
+import org.hl7.fhir.r4.model.Task.TaskOutputComponent;
+import org.hl7.fhir.r4.model.UnsignedIntType;
public class CheckMultiMedicResults extends AbstractServiceDelegate
{
@@ -17,27 +25,77 @@ public CheckMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskH
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
- Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
+ // Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
+
+ FinalFeasibilityQueryResults results = readFinalFeasibilityQueryResults(task);
+ results = checkResults(results);
+
+ Task leadingTask = (Task) execution.getVariable(Constants.VARIABLE_LEADING_TASK);
+ addOutputs(leadingTask, results);
+ }
+
+ private FinalFeasibilityQueryResults readFinalFeasibilityQueryResults(Task task)
+ {
+ List results = task.getInput().stream()
+ .filter(in -> in.hasType() && in.getType().hasCoding()
+ && Constants.CODESYSTEM_HIGHMED_FEASIBILITY.equals(in.getType().getCodingFirstRep().getSystem())
+ && Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT
+ .equals(in.getType().getCodingFirstRep().getCode()))
+ .map(in -> toResult(task, in)).collect(Collectors.toList());
+ return new FinalFeasibilityQueryResults(results);
+ }
+
+ private FinalFeasibilityQueryResult toResult(Task task, ParameterComponent in)
+ {
+ String cohortId = ((Reference) in.getExtensionByUrl(Constants.EXTENSION_GROUP_ID_URI).getValue())
+ .getReference();
+ int participatingMedics = getParticipatingMedicsCountByCohortId(task, cohortId);
+ int cohortSize = ((UnsignedIntType) in.getValue()).getValue();
+ return new FinalFeasibilityQueryResult(cohortId, participatingMedics, cohortSize);
+ }
- // TODO implement check for results with filter
- // - check resulting cohort sizes is not an exact number
- // - check participating medics is > 3
- // - other criterias tbd
+ private int getParticipatingMedicsCountByCohortId(Task task, String cohortId)
+ {
+ return task.getInput().stream().filter(in -> in.hasType() && in.getType().hasCoding()
+ && Constants.CODESYSTEM_HIGHMED_FEASIBILITY.equals(in.getType().getCodingFirstRep().getSystem())
+ && Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT
+ .equals(in.getType().getCodingFirstRep().getCode())
+ && cohortId.equals(
+ ((Reference) in.getExtensionByUrl(Constants.EXTENSION_GROUP_ID_URI).getValue()).getReference()))
+ .mapToInt(in -> ((UnsignedIntType) in.getValue()).getValue()).findFirst().getAsInt();
+ }
+
+ protected FinalFeasibilityQueryResults checkResults(FinalFeasibilityQueryResults results)
+ {
+ // TODO implement check for results
+ // - criterias tbd
+ return results;
+ }
+
+ private void addOutputs(Task leadingTask, FinalFeasibilityQueryResults results)
+ {
+ results.getResults().forEach(result -> addOutput(leadingTask, result));
+ }
+
+ private void addOutput(Task leadingTask, FinalFeasibilityQueryResult result)
+ {
+ TaskOutputComponent output1 = getTaskHelper().createOutputUnsignedInt(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT, result.getCohortSize());
+ output1.addExtension(createCohortIdExtension(result.getCohortId()));
+ leadingTask.addOutput(output1);
- transformAndAddToTaskOutput(outputs, task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT);
- transformAndAddToTaskOutput(outputs, task,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT);
+ TaskOutputComponent output2 = getTaskHelper().createOutputUnsignedInt(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT,
+ result.getParticipatingMedics());
+ output2.addExtension(createCohortIdExtension(result.getCohortId()));
+ leadingTask.addOutput(output2);
}
- private void transformAndAddToTaskOutput(Outputs outputs, Task task, String code)
+ private Extension createCohortIdExtension(String cohortId)
{
- getTaskHelper().getInputParameterWithExtension(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, code,
- Constants.EXTENSION_GROUP_ID_URI).forEach(result -> outputs
- .add(Constants.CODESYSTEM_HIGHMED_FEASIBILITY, code, result.getValue().primitiveValue(),
- Constants.EXTENSION_GROUP_ID_URI,
- ((Reference) result.getExtension().get(0).getValue()).getReference()));
+ return new Extension(Constants.EXTENSION_GROUP_ID_URI, new Reference(cohortId));
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java
index 6b8fd1fda..3816011c7 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java
@@ -42,7 +42,7 @@ public void afterPropertiesSet() throws Exception
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
List cohorts = ((FhirResourcesList) execution.getVariable(Constants.VARIABLE_COHORTS))
@@ -50,17 +50,17 @@ public void doExecute(DelegateExecution execution) throws Exception
Map queries = new HashMap<>();
- cohorts.forEach(group ->
- {
+ cohorts.forEach(group -> {
String aqlQuery = groupHelper.extractAqlQuery(group).toLowerCase();
String groupId = group.getId();
if (!aqlQuery.startsWith(SIMPLE_FEASIBILITY_QUERY_PREFIX))
{
- String errorMessage = "Initial single medic feasibility query check failed, wrong format for query of group with id '"
- + groupId + "', expected query to start with '" + SIMPLE_FEASIBILITY_QUERY_PREFIX
- + "' but got '" + aqlQuery + "'";
+ String errorMessage =
+ "Initial single medic feasibility query check failed, wrong format for query of group with id '"
+ + groupId + "', expected query to start with '" + SIMPLE_FEASIBILITY_QUERY_PREFIX
+ + "' but got '" + aqlQuery + "'";
logger.info(errorMessage);
outputs.addErrorOutput(errorMessage);
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java
index 5632c4958..51dcfaa4e 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java
@@ -1,8 +1,8 @@
package org.highmed.dsf.bpe.service;
+import java.util.ArrayList;
import java.util.List;
-import java.util.function.Predicate;
-import java.util.stream.Stream;
+import java.util.Optional;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
@@ -11,8 +11,8 @@
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
import org.highmed.dsf.fhir.variables.Outputs;
-import org.highmed.dsf.fhir.variables.OutputsValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,63 +26,48 @@ public CheckSingleMedicResults(FhirWebserviceClientProvider clientProvider, Task
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
- List results = ((FeasibilityQueryResults) execution
- .getVariable(Constants.VARIABLE_QUERY_RESULTS)).getResults();
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
- Stream positiveResults = checkQueryResults(results, getFilter());
- Stream negativeResults = checkQueryResults(results, getNegativeFilter());
+ List filteredResults = filterErronesResultsAndAddErrorsToOutput(results, outputs);
- addSuccessfulResultsToOutputs(positiveResults, outputs);
- addErroneousResultsToOutputs(negativeResults, outputs);
-
- execution.setVariable(Constants.VARIABLE_PROCESS_OUTPUTS, OutputsValues.create(outputs));
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(filteredResults)));
}
- private Stream checkQueryResults(List queryResults,
- Predicate filter)
+ private List filterErronesResultsAndAddErrorsToOutput(FeasibilityQueryResults results,
+ Outputs outputs)
{
- return queryResults.stream().filter(filter);
+ List filteredResults = new ArrayList<>();
+ for (FeasibilityQueryResult result : results.getResults())
+ {
+ Optional errorReason = testResultAndReturnErrorReason(result);
+ if (errorReason.isPresent())
+ addError(outputs, result.getCohortId(), errorReason.get());
+ else
+ filteredResults.add(result);
+ }
+
+ return filteredResults;
}
- private Predicate getFilter()
+ protected Optional testResultAndReturnErrorReason(FeasibilityQueryResult result)
{
// TODO: implement check
- // cohort size > 0
- // other filter criteria tbd
-
- return result -> true;
- }
-
- private Predicate getNegativeFilter()
- {
- // TODO: implement check, should match the opposite criteria of getFilter()
-
- return result -> false;
+ // cohort size > 0
+ // other filter criteria tbd
+ return Optional.empty();
}
- private void addErroneousResultsToOutputs(Stream erroneousResults, Outputs outputs)
+ private void addError(Outputs outputs, String cohortId, String error)
{
- erroneousResults.forEach(result -> {
- String errorMessage =
- "Final single medic feasibility query result check failed for group with id '" + result
- .getCohortId() + "', reason unknown";
-
- logger.info(errorMessage);
- outputs.addErrorOutput(errorMessage);
- });
+ String errorMessage = "Feasibility query result check failed for group with id '" + cohortId + "': " + error;
- }
-
- private void addSuccessfulResultsToOutputs(Stream successfulResults, Outputs outputs)
- {
- successfulResults.forEach(result -> {
- outputs.add(Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT,
- String.valueOf(result.getCohortSize()), Constants.EXTENSION_GROUP_ID_URI, result.getCohortId());
- });
+ logger.info(errorMessage);
+ outputs.addErrorOutput(errorMessage);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java
index e8044c1ce..8a4f1f94a 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java
@@ -1,22 +1,24 @@
package org.highmed.dsf.bpe.service;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
-import javax.ws.rs.WebApplicationException;
-
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.BloomFilterConfig;
+import org.highmed.dsf.fhir.variables.BloomFilterConfigValues;
+import org.highmed.dsf.fhir.variables.FhirResourceValues;
import org.highmed.dsf.fhir.variables.FhirResourcesListValues;
-import org.highmed.dsf.fhir.variables.Outputs;
-import org.highmed.dsf.fhir.variables.OutputsValues;
import org.highmed.fhir.client.FhirWebserviceClient;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Group;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Reference;
@@ -26,8 +28,6 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
-import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
-
public class DownloadFeasibilityResources extends AbstractServiceDelegate implements InitializingBean
{
private static final Logger logger = LoggerFactory.getLogger(DownloadFeasibilityResources.class);
@@ -49,26 +49,35 @@ public void afterPropertiesSet() throws Exception
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
IdType researchStudyId = getResearchStudyId(task);
FhirWebserviceClient client = getWebserviceClient(researchStudyId);
- ResearchStudy researchStudy = getResearchStudy(researchStudyId, client);
- execution.setVariable(Constants.VARIABLE_RESEARCH_STUDY, researchStudy);
+ Bundle bundle = getResearchStudyAndCohortDefinitions(researchStudyId, client);
- Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
+ ResearchStudy researchStudy = (ResearchStudy) bundle.getEntryFirstRep().getResource();
+ execution.setVariable(Constants.VARIABLE_RESEARCH_STUDY, FhirResourceValues.create(researchStudy));
- List cohortDefinitions = getCohortDefinitions(researchStudy, outputs, client);
+ List cohortDefinitions = getCohortDefinitions(bundle, client.getBaseUrl());
execution.setVariable(Constants.VARIABLE_COHORTS, FhirResourcesListValues.create(cohortDefinitions));
- execution.setVariable(Constants.VARIABLE_PROCESS_OUTPUTS, OutputsValues.create(outputs));
+
+ String ttpIdentifier = getTtpIdentifier(researchStudy, client);
+ execution.setVariable(Constants.VARIABLE_TTP_IDENTIFIER, ttpIdentifier);
boolean needsConsentCheck = getNeedsConsentCheck(task);
execution.setVariable(Constants.VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck);
boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task);
execution.setVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage);
+
+ if (needsRecordLinkage)
+ {
+ BloomFilterConfig bloomFilterConfig = getBloomFilterConfig(task);
+ execution.setVariable(Constants.VARIABLE_BLOOM_FILTER_CONFIG,
+ BloomFilterConfigValues.create(bloomFilterConfig));
+ }
}
private IdType getResearchStudyId(Task task)
@@ -76,7 +85,7 @@ private IdType getResearchStudyId(Task task)
Reference researchStudyReference = getTaskHelper()
.getInputParameterReferenceValues(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE)
- .collect(Collectors.toList()).get(0);
+ .findFirst().get();
return new IdType(researchStudyReference.getReference());
}
@@ -94,47 +103,57 @@ private FhirWebserviceClient getWebserviceClient(IdType researchStudyId)
}
}
- private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceClient client)
+ private Bundle getResearchStudyAndCohortDefinitions(IdType researchStudyId, FhirWebserviceClient client)
{
try
{
- return client.read(ResearchStudy.class, researchStudyid.getIdPart());
+ Bundle bundle = client.searchWithStrictHandling(ResearchStudy.class,
+ Map.of("_id", Collections.singletonList(researchStudyId.getIdPart()), "_include",
+ Collections.singletonList("ResearchStudy:enrollment")));
+
+ if (bundle.getEntry().size() < 2)
+ {
+ throw new RuntimeException("Returned search-set contained less then two entries");
+ }
+ else if (!bundle.getEntryFirstRep().hasResource()
+ || !(bundle.getEntryFirstRep().getResource() instanceof ResearchStudy))
+ {
+ throw new RuntimeException("Returned search-set did not contain ResearchStudy at index == 0");
+ }
+ else if (bundle.getEntry().stream().skip(1).map(c -> c.hasResource() && c.getResource() instanceof Group)
+ .filter(b -> !b).findAny().isPresent())
+ {
+ throw new RuntimeException("Returned search-set contained unexpected resource at index >= 1");
+ }
+
+ return bundle;
}
- catch (WebApplicationException e)
+ catch (Exception e)
{
- throw new ResourceNotFoundException("Error while reading ResearchStudy with id "
- + researchStudyid.getIdPart() + " from " + client.getBaseUrl());
+ logger.warn("Error while reading ResearchStudy with id {} including Groups from {}: {}",
+ researchStudyId.getIdPart(), client.getBaseUrl(), e.getMessage());
+ throw e;
}
}
- private List getCohortDefinitions(ResearchStudy researchStudy, Outputs outputs, FhirWebserviceClient client)
+ private List getCohortDefinitions(Bundle bundle, String baseUrl)
{
- List cohortDefinitions = new ArrayList<>();
- List cohortDefinitionReferences = researchStudy.getEnrollment();
-
- cohortDefinitionReferences.forEach(reference ->
+ return bundle.getEntry().stream().skip(1).map(e ->
{
- try
- {
- IdType type = new IdType(reference.getReference());
- Group group = client.read(Group.class, type.getIdPart());
-
- IdType groupId = new IdType(group.getId());
- group.setId(client.getBaseUrl() + groupId.getResourceType() + "/" + groupId.getIdPart());
-
- cohortDefinitions.add(group);
- }
- catch (WebApplicationException e)
- {
- String errorMessage = "Error while reading cohort definition with id " + reference.getReference()
- + " from " + client.getBaseUrl();
-
- logger.info(errorMessage);
- outputs.addErrorOutput(errorMessage);
- }
- });
+ Group group = (Group) e.getResource();
+ IdType oldId = group.getIdElement();
+ group.setIdElement(
+ new IdType(baseUrl, oldId.getResourceType(), oldId.getIdPart(), oldId.getVersionIdPart()));
+ return group;
+ }).collect(Collectors.toList());
+ }
- return cohortDefinitions;
+ private String getTtpIdentifier(ResearchStudy researchStudy, FhirWebserviceClient client)
+ {
+ Extension ext = researchStudy
+ .getExtensionByUrl("http://highmed.org/fhir/StructureDefinition/participating-ttp");
+ Reference ref = (Reference) ext.getValue();
+ return ref.getIdentifier().getValue();
}
private boolean getNeedsConsentCheck(Task task)
@@ -155,4 +174,13 @@ private boolean getNeedsRecordLinkageCheck(Task task)
() -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='"
+ task.getId() + "', this error should " + "have been caught by resource validation"));
}
+
+ private BloomFilterConfig getBloomFilterConfig(Task task)
+ {
+ return BloomFilterConfig.fromBytes(getTaskHelper()
+ .getFirstInputParameterByteValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG)
+ .orElseThrow(() -> new IllegalArgumentException("BloomFilterConfig byte[] is not set in task with id='"
+ + task.getId() + "', this error should " + "have been caught by resource validation")));
+ }
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java
index 7217585e6..cd182f022 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java
@@ -1,43 +1,55 @@
package org.highmed.dsf.bpe.service;
-import javax.ws.rs.WebApplicationException;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
+import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.ResearchStudy;
import org.hl7.fhir.r4.model.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
-import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
-
public class DownloadResearchStudyResource extends AbstractServiceDelegate implements InitializingBean
{
- public DownloadResearchStudyResource(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
+ private static final Logger logger = LoggerFactory.getLogger(DownloadResearchStudyResource.class);
+
+ private final OrganizationProvider organizationProvider;
+
+ public DownloadResearchStudyResource(OrganizationProvider organizationProvider,
+ FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
{
super(clientProvider, taskHelper);
+
+ this.organizationProvider = organizationProvider;
}
@Override
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
+
+ Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
IdType researchStudyId = getResearchStudyId(task);
FhirWebserviceClient client = getFhirWebserviceClientProvider().getLocalWebserviceClient();
ResearchStudy researchStudy = getResearchStudy(researchStudyId, client);
-
+ researchStudy = addMissingOrganizations(researchStudy, client);
execution.setVariable(Constants.VARIABLE_RESEARCH_STUDY, researchStudy);
boolean needsConsentCheck = getNeedsConsentCheck(task);
@@ -45,12 +57,6 @@ public void doExecute(DelegateExecution execution) throws Exception
boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task);
execution.setVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage);
-
- // TODO: remove when implemented
- if (needsConsentCheck || needsRecordLinkage)
- {
- throw new UnsupportedOperationException("Consent Check and Record Linkage not yet supported.");
- }
}
private IdType getResearchStudyId(Task task)
@@ -71,10 +77,50 @@ private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceCli
{
return client.read(ResearchStudy.class, researchStudyid.getIdPart());
}
- catch (WebApplicationException e)
+ catch (Exception e)
+ {
+ logger.warn("Error while reading ResearchStudy with id {} from {}", researchStudyid.getIdPart(),
+ client.getBaseUrl());
+ throw e;
+ }
+ }
+
+ private ResearchStudy addMissingOrganizations(ResearchStudy researchStudy, FhirWebserviceClient client)
+ {
+ List identifiers = organizationProvider.getOrganizationsByType("MeDIC")
+ .flatMap(o -> o.getIdentifier().stream())
+ .filter(i -> "http://highmed.org/fhir/NamingSystem/organization-identifier".equals(i.getSystem()))
+ .map(i -> i.getValue()).collect(Collectors.toList());
+
+ List existingIdentifiers = researchStudy.getExtensionsByUrl(Constants.EXTENSION_PARTICIPATING_MEDIC_URI)
+ .stream().filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
+ .map(r -> r.getIdentifier().getValue()).collect(Collectors.toList());
+
+ identifiers.removeAll(existingIdentifiers);
+
+ if (!identifiers.isEmpty())
+ {
+ identifiers.forEach(identifier -> researchStudy.addExtension(Constants.EXTENSION_PARTICIPATING_MEDIC_URI,
+ new Reference().getIdentifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier")
+ .setValue(identifier)));
+
+ return update(researchStudy, client);
+ }
+ else
+ return researchStudy;
+ }
+
+ private ResearchStudy update(ResearchStudy researchStudy, FhirWebserviceClient client)
+ {
+ try
+ {
+ return client.update(researchStudy);
+ }
+ catch (Exception e)
{
- throw new ResourceNotFoundException("Error while reading ResearchStudy with id "
- + researchStudyid.getIdPart() + " from " + client.getBaseUrl());
+ logger.warn("Error while updating ResearchStudy resoruce: " + e.getMessage(), e);
+ throw e;
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResultSets.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResultSets.java
new file mode 100644
index 000000000..5a698117f
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResultSets.java
@@ -0,0 +1,103 @@
+package org.highmed.dsf.bpe.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import javax.ws.rs.core.MediaType;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.highmed.dsf.bpe.Constants;
+import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
+import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
+import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
+import org.highmed.fhir.client.FhirWebserviceClient;
+import org.highmed.openehr.model.structure.ResultSet;
+import org.hl7.fhir.r4.model.IdType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class DownloadResultSets extends AbstractServiceDelegate
+{
+ private static final Logger logger = LoggerFactory.getLogger(DownloadResultSets.class);
+
+ private final ObjectMapper openEhrObjectMapper;
+
+ public DownloadResultSets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
+ ObjectMapper openEhrObjectMapper)
+ {
+ super(clientProvider, taskHelper);
+
+ this.openEhrObjectMapper = openEhrObjectMapper;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ super.afterPropertiesSet();
+
+ Objects.requireNonNull(openEhrObjectMapper, "openEhrObjectMapper");
+ }
+
+ @Override
+ protected void doExecute(DelegateExecution execution) throws Exception
+ {
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
+
+ List resultsWithResultSets = download(results);
+
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(resultsWithResultSets)));
+ }
+
+ private List download(FeasibilityQueryResults results)
+ {
+ return results.getResults().stream().map(r -> download(r)).collect(Collectors.toList());
+ }
+
+ private FeasibilityQueryResult download(FeasibilityQueryResult result)
+ {
+ IdType id = new IdType(result.getResultSetUrl());
+ FhirWebserviceClient client = getFhirWebserviceClientProvider().getRemoteWebserviceClient(id.getBaseUrl());
+
+ InputStream binary = readBinaryResource(client, id.getIdPart());
+ ResultSet resultSet = deserializeResultSet(binary);
+
+ return FeasibilityQueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), resultSet);
+ }
+
+ private InputStream readBinaryResource(FhirWebserviceClient client, String id)
+ {
+ try
+ {
+ logger.info("Reading binary from {} with id {}", client.getBaseUrl(), id);
+ return client.readBinary(id, MediaType.valueOf(Constants.OPENEHR_MIMETYPE_JSON));
+ }
+ catch (Exception e)
+ {
+ logger.warn("Error while reading Binary resoruce: " + e.getMessage(), e);
+ throw e;
+ }
+ }
+
+ private ResultSet deserializeResultSet(InputStream content)
+ {
+ try (content)
+ {
+ return openEhrObjectMapper.readValue(content, ResultSet.class);
+ }
+ catch (IOException e)
+ {
+ logger.warn("Error while deserializing ResultSet: " + e.getMessage(), e);
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteEpiLink.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteEpiLink.java
deleted file mode 100644
index 77778a046..000000000
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteEpiLink.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.highmed.dsf.bpe.service;
-
-import org.camunda.bpm.engine.delegate.DelegateExecution;
-import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
-import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
-import org.highmed.dsf.fhir.task.TaskHelper;
-
-public class ExecuteEpiLink extends AbstractServiceDelegate
-{
- public ExecuteEpiLink(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
- {
- super(clientProvider, taskHelper);
- }
-
- @Override
- protected void doExecute(DelegateExecution execution) throws Exception
- {
- // TODO: implement
- }
-}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java
index fce9046cd..1354255c2 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java
@@ -1,63 +1,94 @@
package org.highmed.dsf.bpe.service;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
+import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
-import org.highmed.openehr.client.OpenehrWebserviceClient;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
+import org.highmed.openehr.client.OpenEhrWebserviceClient;
+import org.highmed.openehr.model.datatypes.StringRowElement;
+import org.highmed.openehr.model.structure.Column;
+import org.highmed.openehr.model.structure.ResultSet;
+import org.highmed.openehr.model.structure.RowElement;
import org.springframework.beans.factory.InitializingBean;
public class ExecuteQueries extends AbstractServiceDelegate implements InitializingBean
{
- private final OpenehrWebserviceClient openehrWebserviceClient;
+ private final OpenEhrWebserviceClient openehrWebserviceClient;
+ private final OrganizationProvider organizationProvider;
- public ExecuteQueries(FhirWebserviceClientProvider clientProvider, OpenehrWebserviceClient openehrWebserviceClient,
- TaskHelper taskHelper)
+ public ExecuteQueries(FhirWebserviceClientProvider clientProvider, OpenEhrWebserviceClient openehrWebserviceClient,
+ TaskHelper taskHelper, OrganizationProvider organizationProvider)
{
super(clientProvider, taskHelper);
+
this.openehrWebserviceClient = openehrWebserviceClient;
+ this.organizationProvider = organizationProvider;
}
@Override
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
+
Objects.requireNonNull(openehrWebserviceClient, "openehrWebserviceClient");
+ Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
- @SuppressWarnings("unchecked")
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
//
+ @SuppressWarnings("unchecked")
Map queries = (Map) execution.getVariable(Constants.VARIABLE_QUERIES);
- List results = queries.entrySet().stream().map(entry -> {
- int result = executeQuery(entry.getValue());
- return new FeasibilityQueryResult(null, entry.getKey(), result);
- }).collect(Collectors.toList());
+ Boolean needsConsentCheck = (Boolean) execution.getVariable(Constants.VARIABLE_NEEDS_CONSENT_CHECK);
+ Boolean needsRecordLinkage = (Boolean) execution.getVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE);
+ boolean idQuery = Boolean.TRUE.equals(needsConsentCheck) || Boolean.TRUE.equals(needsRecordLinkage);
+
+ List results = queries.entrySet().stream()
+ .map(entry -> executeQuery(entry.getKey(), entry.getValue(), idQuery)).collect(Collectors.toList());
- execution.setVariable(Constants.VARIABLE_QUERY_RESULTS, new FeasibilityQueryResults(results));
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(results)));
}
- private int executeQuery(String query)
+ private FeasibilityQueryResult executeQuery(String cohortId, String cohortQuery, boolean idQuery)
{
// TODO We might want to introduce a more complex result type to represent a count,
- // errors and possible meta-data.
+ // errors and possible meta-data.
- // ResultSet result = openehrWebserviceClient.query(query, null);
- // int count = ((DvCount) result.getRow(0).get(0)).getValue();
+ // ResultSet result = openehrWebserviceClient.query(query, null);
+ // int count = ((DvCount) result.getRow(0).get(0)).getValue();
// TODO: remove dummy result
- return 15;
- }
+ if (idQuery)
+ {
+ List> rows = IntStream.range(0, 15)
+ .mapToObj(id -> Collections. singletonList(new StringRowElement(String.valueOf(id))))
+ .collect(Collectors.toList());
+ ResultSet resultSet = new ResultSet(null, null, cohortQuery,
+ Collections.singleton(new Column("EHRID", "/ehr_id/value")), rows);
+
+ // returns ResultSet with EHRIDs 0, 1, ..., 14
+ return FeasibilityQueryResult.idResult(organizationProvider.getLocalIdentifierValue(), cohortId, resultSet);
+ }
+ else
+ {
+ // returns 15
+ return FeasibilityQueryResult.countResult(organizationProvider.getLocalIdentifierValue(), cohortId, 15);
+ }
+ }
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java
new file mode 100644
index 000000000..d5aea4513
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java
@@ -0,0 +1,98 @@
+package org.highmed.dsf.bpe.service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.highmed.dsf.bpe.Constants;
+import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
+import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
+import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResultsValues;
+import org.highmed.pseudonymization.domain.PersonWithMdat;
+import org.highmed.pseudonymization.domain.impl.MatchedPersonImpl;
+import org.highmed.pseudonymization.recordlinkage.FederatedMatcherImpl;
+import org.highmed.pseudonymization.recordlinkage.MatchedPerson;
+import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicRbfOnly;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ExecuteRecordLink extends AbstractServiceDelegate
+{
+ private static final Logger logger = LoggerFactory.getLogger(ExecuteRecordLink.class);
+
+ private final ResultSetTranslatorFromMedicRbfOnly translator;
+
+ public ExecuteRecordLink(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
+ ResultSetTranslatorFromMedicRbfOnly translator)
+ {
+ super(clientProvider, taskHelper);
+
+ this.translator = translator;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ super.afterPropertiesSet();
+
+ Objects.requireNonNull(translator, "translator");
+ }
+
+ @Override
+ protected void doExecute(DelegateExecution execution) throws Exception
+ {
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
+
+ Map> byCohortId = results.getResults().stream()
+ .collect(Collectors.groupingBy(FeasibilityQueryResult::getCohortId));
+
+ FederatedMatcherImpl matcher = createMatcher();
+
+ List matchedResults = byCohortId.entrySet().stream()
+ .map(e -> match(matcher, e.getKey(), e.getValue())).collect(Collectors.toList());
+
+ execution.setVariable(Constants.VARIABLE_FINAL_QUERY_RESULTS,
+ FinalFeasibilityQueryResultsValues.create(new FinalFeasibilityQueryResults(matchedResults)));
+ }
+
+ private FinalFeasibilityQueryResult match(FederatedMatcherImpl matcher, String cohortId,
+ List results)
+ {
+ logger.debug("Matching results for cohort {}", cohortId);
+
+ List> persons = results.stream().map(this::translate).collect(Collectors.toList());
+
+ Set> matchedPersons = matcher.matchPersons(persons);
+
+ return new FinalFeasibilityQueryResult(cohortId,
+ toInt(persons.stream().mapToInt(r -> r.size()).filter(cohortSize -> cohortSize > 0).count()),
+ toInt(matchedPersons.size()));
+ }
+
+ private List translate(FeasibilityQueryResult result)
+ {
+ return translator.translate(result.getOrganizationIdentifier(), result.getResultSet());
+ }
+
+ protected FederatedMatcherImpl createMatcher()
+ {
+ return new FederatedMatcherImpl<>(MatchedPersonImpl::new);
+ }
+
+ private int toInt(long l)
+ {
+ if (l > Integer.MAX_VALUE)
+ throw new IllegalArgumentException("long > " + Integer.MAX_VALUE);
+ else
+ return (int) l;
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java
index 09f7c1d9e..56e92380e 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java
@@ -1,9 +1,17 @@
package org.highmed.dsf.bpe.service;
+import java.util.List;
+import java.util.stream.Collectors;
+
import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
+import org.highmed.openehr.model.structure.ResultSet;
public class FilterQueryResultsByConsent extends AbstractServiceDelegate
{
@@ -15,6 +23,30 @@ public FilterQueryResultsByConsent(FhirWebserviceClientProvider clientProvider,
@Override
protected void doExecute(DelegateExecution execution) throws Exception
{
- // TODO: implement
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
+
+ List filteredResults = filterResults(results.getResults());
+
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(filteredResults)));
+ }
+
+ private List filterResults(List results)
+ {
+ return results.stream().map(this::filterResult).collect(Collectors.toList());
+ }
+
+ protected FeasibilityQueryResult filterResult(FeasibilityQueryResult result)
+ {
+ return FeasibilityQueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(),
+ filterResultSet(result.getResultSet()));
+ }
+
+ private ResultSet filterResultSet(ResultSet resultSet)
+ {
+ // TODO implement
+
+ return resultSet;
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java
index acaa8b233..4a9f4e4b2 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java
@@ -1,20 +1,171 @@
package org.highmed.dsf.bpe.service;
+import java.security.Key;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.BloomFilterConfig;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
+import org.highmed.mpi.client.MasterPatientIndexClient;
+import org.highmed.openehr.model.structure.ResultSet;
+import org.highmed.pseudonymization.bloomfilter.BloomFilterGenerator;
+import org.highmed.pseudonymization.bloomfilter.RecordBloomFilterGenerator;
+import org.highmed.pseudonymization.bloomfilter.RecordBloomFilterGeneratorImpl;
+import org.highmed.pseudonymization.bloomfilter.RecordBloomFilterGeneratorImpl.FieldBloomFilterLengths;
+import org.highmed.pseudonymization.bloomfilter.RecordBloomFilterGeneratorImpl.FieldWeights;
+import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpRbfOnly;
+import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpRbfOnlyImpl;
+import org.hl7.fhir.r4.model.Binary;
+import org.hl7.fhir.r4.model.IdType;
+import org.hl7.fhir.r4.model.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import ca.uhn.fhir.context.FhirContext;
public class GenerateBloomFilters extends AbstractServiceDelegate
{
- public GenerateBloomFilters(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
+ private static final Logger logger = LoggerFactory.getLogger(GenerateBloomFilters.class);
+
+ private static final int RBF_LENGTH = 3000;
+ private static final FieldWeights FBF_WEIGHTS = new FieldWeights(0.1, 0.1, 0.1, 0.2, 0.05, 0.1, 0.05, 0.2, 0.1);
+ private static final FieldBloomFilterLengths FBF_LENGTHS = new FieldBloomFilterLengths(500, 500, 250, 50, 500, 250,
+ 500, 500, 500);
+
+ private final MasterPatientIndexClient masterPatientIndexClient;
+ private final ObjectMapper openEhrObjectMapper;
+ private final BouncyCastleProvider bouncyCastleProvider;
+
+ public GenerateBloomFilters(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
+ MasterPatientIndexClient masterPatientIndexClient, ObjectMapper openEhrObjectMapper,
+ BouncyCastleProvider bouncyCastleProvider)
{
super(clientProvider, taskHelper);
+
+ this.masterPatientIndexClient = masterPatientIndexClient;
+ this.openEhrObjectMapper = openEhrObjectMapper;
+ this.bouncyCastleProvider = bouncyCastleProvider;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ super.afterPropertiesSet();
+
+ Objects.requireNonNull(masterPatientIndexClient, "masterPatientIndexClient");
+ Objects.requireNonNull(openEhrObjectMapper, "openEhrObjectMapper");
+ Objects.requireNonNull(bouncyCastleProvider, "bouncyCastleProvider");
}
@Override
protected void doExecute(DelegateExecution execution) throws Exception
{
- // TODO: implement
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
+
+ String ttpIdentifier = (String) execution.getVariable(Constants.VARIABLE_TTP_IDENTIFIER);
+
+ BloomFilterConfig bloomFilterConfig = (BloomFilterConfig) execution
+ .getVariable(Constants.VARIABLE_BLOOM_FILTER_CONFIG);
+
+ ResultSetTranslatorToTtpRbfOnly resultSetTranslator = createResultSetTranslator(bloomFilterConfig);
+
+ List translatedResults = results.getResults().stream()
+ .map(result -> translateAndCreateBinary(resultSetTranslator, result, ttpIdentifier))
+ .collect(Collectors.toList());
+
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(translatedResults)));
+ }
+
+ protected ResultSetTranslatorToTtpRbfOnly createResultSetTranslator(BloomFilterConfig bloomFilterConfig)
+ {
+ return new ResultSetTranslatorToTtpRbfOnlyImpl(
+ createRecordBloomFilterGenerator(bloomFilterConfig.getPermutationSeed(),
+ bloomFilterConfig.getHmacSha2Key(), bloomFilterConfig.getHmacSha3Key()),
+ masterPatientIndexClient);
+ }
+
+ protected RecordBloomFilterGenerator createRecordBloomFilterGenerator(long permutationSeed, Key hmacSha2Key,
+ Key hmacSha3Key)
+ {
+ return new RecordBloomFilterGeneratorImpl(RBF_LENGTH, permutationSeed, FBF_WEIGHTS, FBF_LENGTHS,
+ () -> new BloomFilterGenerator.HmacSha2HmacSha3BiGramHasher(hmacSha2Key, hmacSha3Key,
+ bouncyCastleProvider));
+ }
+
+ private FeasibilityQueryResult translateAndCreateBinary(ResultSetTranslatorToTtpRbfOnly resultSetTranslator,
+ FeasibilityQueryResult result, String ttpIdentifier)
+ {
+ ResultSet translatedResultSet = translate(resultSetTranslator, result.getResultSet());
+ String resultSetUrl = saveResultSetAsBinaryForTtp(translatedResultSet, ttpIdentifier);
+
+ return FeasibilityQueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), resultSetUrl);
+ }
+
+ private ResultSet translate(ResultSetTranslatorToTtpRbfOnly resultSetTranslator, ResultSet resultSet)
+ {
+ try
+ {
+ return resultSetTranslator.translate(resultSet);
+ }
+ catch (Exception e)
+ {
+ logger.warn("Error while translating ResultSet: " + e.getMessage(), e);
+ throw e;
+ }
+ }
+
+ protected String saveResultSetAsBinaryForTtp(ResultSet resultSet, String ttpIdentifier)
+ {
+ byte[] content = serializeResultSet(resultSet);
+ Reference securityContext = new Reference();
+ securityContext.setType("Organization").getIdentifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue(ttpIdentifier);
+ Binary binary = new Binary().setContentType(Constants.OPENEHR_MIMETYPE_JSON).setSecurityContext(securityContext)
+ .setData(content);
+
+ IdType created = createBinaryResource(binary);
+ return new IdType(getFhirWebserviceClientProvider().getLocalBaseUrl(), "Binary", created.getIdPart(),
+ created.getVersionIdPart()).getValue();
+ }
+
+ private byte[] serializeResultSet(ResultSet resultSet)
+ {
+ try
+ {
+ return openEhrObjectMapper.writeValueAsBytes(resultSet);
+ }
+ catch (JsonProcessingException e)
+ {
+ logger.warn("Error while serializing ResultSet: " + e.getMessage(), e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private IdType createBinaryResource(Binary binary)
+ {
+ try
+ {
+ return getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().create(binary);
+ }
+ catch (Exception e)
+ {
+ logger.debug("Binary to create {}", FhirContext.forR4().newJsonParser().encodeResourceToString(binary));
+ logger.warn("Error while creating Binary resoruce: " + e.getMessage(), e);
+ throw e;
+ }
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java
index 3cbb3c780..ca7e8b7d6 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java
@@ -1,9 +1,16 @@
package org.highmed.dsf.bpe.service;
+import java.util.List;
+import java.util.stream.Collectors;
+
import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
public class GenerateCountFromIds extends AbstractServiceDelegate
{
@@ -15,6 +22,23 @@ public GenerateCountFromIds(FhirWebserviceClientProvider clientProvider, TaskHel
@Override
protected void doExecute(DelegateExecution execution) throws Exception
{
- // TODO: implement
+ FeasibilityQueryResults results = (FeasibilityQueryResults) execution
+ .getVariable(Constants.VARIABLE_QUERY_RESULTS);
+
+ List filteredResults = count(results.getResults());
+
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(filteredResults)));
+ }
+
+ private List count(List results)
+ {
+ return results.stream().map(this::count).collect(Collectors.toList());
+ }
+
+ protected FeasibilityQueryResult count(FeasibilityQueryResult result)
+ {
+ return FeasibilityQueryResult.countResult(result.getOrganizationIdentifier(), result.getCohortId(),
+ result.getResultSet().getRows().size());
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java
index 44b7b331d..0d56cfd42 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java
@@ -1,6 +1,11 @@
package org.highmed.dsf.bpe.service;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
import org.camunda.bpm.engine.delegate.DelegateExecution;
+import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
@@ -15,6 +20,33 @@ public ModifyQueries(FhirWebserviceClientProvider clientProvider, TaskHelper tas
@Override
protected void doExecute(DelegateExecution execution) throws Exception
{
- // TODO: implement
+ Boolean needsConsentCheck = (Boolean) execution.getVariable(Constants.VARIABLE_NEEDS_CONSENT_CHECK);
+ Boolean needsRecordLinkage = (Boolean) execution.getVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE);
+ boolean idQuery = Boolean.TRUE.equals(needsConsentCheck) || Boolean.TRUE.equals(needsRecordLinkage);
+
+ if (idQuery)
+ {
+ //
+ @SuppressWarnings("unchecked")
+ Map queries = (Map) execution.getVariable(Constants.VARIABLE_QUERIES);
+ Map modifiedQueries = modifyQueries(queries);
+ execution.setVariable(Constants.VARIABLE_QUERIES, modifiedQueries);
+ }
+ }
+
+ private Map modifyQueries(Map queries)
+ {
+ Map modifiedQueries = new HashMap<>();
+
+ for (Entry entry : queries.entrySet())
+ modifiedQueries.put(entry.getKey(), replaceSelectCountWithSelectMpiId(entry.getValue()));
+
+ return modifiedQueries;
+ }
+
+ protected String replaceSelectCountWithSelectMpiId(String value)
+ {
+ // TODO Implement correct replacement for default id query
+ return value.replace("SELECT COUNT(e)", "SELECT e/ehr_id/value as EHRID");
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java
index 9d1cd27dc..82ed1a3c7 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java
@@ -1,35 +1,56 @@
package org.highmed.dsf.bpe.service;
+import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Objects;
+import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;
+import javax.crypto.KeyGenerator;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
+import org.highmed.dsf.fhir.variables.BloomFilterConfig;
+import org.highmed.dsf.fhir.variables.BloomFilterConfigValues;
import org.highmed.dsf.fhir.variables.MultiInstanceTarget;
import org.highmed.dsf.fhir.variables.MultiInstanceTargetValues;
import org.highmed.dsf.fhir.variables.MultiInstanceTargets;
import org.highmed.dsf.fhir.variables.MultiInstanceTargetsValues;
-import org.hl7.fhir.r4.model.IdType;
-import org.hl7.fhir.r4.model.Identifier;
-import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.ResearchStudy;
public class SelectRequestTargets extends AbstractServiceDelegate
{
+ private static final Random random = new Random();
+
private final OrganizationProvider organizationProvider;
+ private final KeyGenerator hmacSha2Generator;
+ private final KeyGenerator hmacSha3Generator;
public SelectRequestTargets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
- OrganizationProvider organizationProvider)
+ OrganizationProvider organizationProvider, BouncyCastleProvider bouncyCastleProvider)
{
super(clientProvider, taskHelper);
+
this.organizationProvider = organizationProvider;
+
+ try
+ {
+ Objects.requireNonNull(bouncyCastleProvider, "bouncyCastleProvider");
+
+ hmacSha2Generator = KeyGenerator.getInstance("HmacSHA256", bouncyCastleProvider);
+ hmacSha3Generator = KeyGenerator.getInstance("HmacSHA3-256", bouncyCastleProvider);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new RuntimeException(e);
+ }
}
@Override
@@ -40,42 +61,46 @@ public void afterPropertiesSet() throws Exception
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
- {
- setMedicTargets(execution);
- setTtpTarget(execution);
- }
-
- private void setMedicTargets(DelegateExecution execution)
+ protected void doExecute(DelegateExecution execution) throws Exception
{
ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(Constants.VARIABLE_RESEARCH_STUDY);
- List targetReferences = researchStudy.getExtension().stream()
- .filter(extension -> extension.getUrl().equals(Constants.EXTENSION_PARTICIPATING_MEDIC_URI))
- .map(extension -> ((Reference) extension.getValue()).getReference()).collect(Collectors.toList());
+ execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGETS,
+ MultiInstanceTargetsValues.create(getMedicTargets(researchStudy)));
- List targets = targetReferences.stream()
- .flatMap(reference -> organizationProvider.getIdentifier(new IdType(reference)).stream())
- .map(identifier -> new MultiInstanceTarget(identifier.getValue(), UUID.randomUUID().toString()))
- .collect(Collectors.toList());
+ execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGET,
+ MultiInstanceTargetValues.create(getTtpTarget(researchStudy)));
- execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGETS,
- MultiInstanceTargetsValues.create(new MultiInstanceTargets(targets)));
+ Boolean needsRecordLinkage = (Boolean) execution.getVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE);
+ if (Boolean.TRUE.equals(needsRecordLinkage))
+ {
+ execution.setVariable(Constants.VARIABLE_BLOOM_FILTER_CONFIG,
+ BloomFilterConfigValues.create(createBloomFilterConfig()));
+ }
}
- private void setTtpTarget(DelegateExecution execution)
+ private BloomFilterConfig createBloomFilterConfig()
{
- // TODO implement ttp selection strategy, if there are multiple TTPs available
+ return new BloomFilterConfig(random.nextLong(), hmacSha2Generator.generateKey(),
+ hmacSha3Generator.generateKey());
+ }
- Organization ttp = organizationProvider.getOrganizationsByType("TTP").findFirst().orElseThrow(
- () -> new IllegalArgumentException("No organization of type TTP could be found, aborting request"));
+ private MultiInstanceTargets getMedicTargets(ResearchStudy researchStudy)
+ {
+ List targets = researchStudy
+ .getExtensionsByUrl(Constants.EXTENSION_PARTICIPATING_MEDIC_URI).stream()
+ .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
+ .map(r -> new MultiInstanceTarget(r.getIdentifier().getValue(), UUID.randomUUID().toString()))
+ .collect(Collectors.toList());
- Identifier ttpIdentifier = ttp.getIdentifier().stream()
- .filter(identifier -> identifier.getSystem().equals(Constants.ORGANIZATION_IDENTIFIER_SYSTEM))
- .findFirst().orElseThrow(() -> new IllegalArgumentException(
- "No organization identifier of type TTP could be found, aborting request"));
+ return new MultiInstanceTargets(targets);
+ }
- MultiInstanceTarget ttpTarget = new MultiInstanceTarget(ttpIdentifier.getValue(), UUID.randomUUID().toString());
- execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGET, MultiInstanceTargetValues.create(ttpTarget));
+ private MultiInstanceTarget getTtpTarget(ResearchStudy researchStudy)
+ {
+ return researchStudy.getExtensionsByUrl(Constants.EXTENSION_PARTICIPATING_TTP_URI).stream()
+ .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
+ .map(r -> new MultiInstanceTarget(r.getIdentifier().getValue(), UUID.randomUUID().toString()))
+ .findFirst().get();
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java
index 547c5a963..06dc58c07 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java
@@ -10,8 +10,6 @@
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.MultiInstanceTarget;
import org.highmed.dsf.fhir.variables.MultiInstanceTargetValues;
-import org.hl7.fhir.r4.model.IdType;
-import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Task;
import org.springframework.beans.factory.InitializingBean;
@@ -36,21 +34,18 @@ public void afterPropertiesSet() throws Exception
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
Task task = (Task) execution.getVariable(Constants.VARIABLE_LEADING_TASK);
String correlationKey = getTaskHelper()
.getFirstInputParameterStringValue(task, Constants.CODESYSTEM_HIGHMED_BPMN,
- Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).orElseThrow(
- () -> new IllegalStateException(
- "No correlation key found, this error should have been caught by resource validation"));
-
- Identifier medicIdentifier = organizationProvider.getIdentifier(new IdType(task.getRequester().getReference()))
+ Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY)
.orElseThrow(() -> new IllegalStateException(
- "Organization with id " + task.getRequester().getReference() + " not found"));
+ "No correlation key found, this error should have been caught by resource validation"));
- MultiInstanceTarget medicTarget = new MultiInstanceTarget(medicIdentifier.getValue(), correlationKey);
+ MultiInstanceTarget medicTarget = new MultiInstanceTarget(task.getRequester().getIdentifier().getValue(),
+ correlationKey);
execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGET, MultiInstanceTargetValues.create(medicTarget));
}
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java
index 31bcf1095..68528df24 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java
@@ -10,8 +10,6 @@
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.MultiInstanceTarget;
import org.highmed.dsf.fhir.variables.MultiInstanceTargetValues;
-import org.hl7.fhir.r4.model.Identifier;
-import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Task;
import org.springframework.beans.factory.InitializingBean;
@@ -23,7 +21,6 @@ public SelectResponseTargetTtp(FhirWebserviceClientProvider clientProvider, Task
OrganizationProvider organizationProvider)
{
super(clientProvider, taskHelper);
-
this.organizationProvider = organizationProvider;
}
@@ -31,42 +28,27 @@ public SelectResponseTargetTtp(FhirWebserviceClientProvider clientProvider, Task
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
-
Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
- Identifier ttpIdentifier = getTtpIdentifier(execution);
+ String ttpIdentifier = (String) execution.getVariable(Constants.VARIABLE_TTP_IDENTIFIER);
String correlationKey = getCorrelationKey(execution);
- MultiInstanceTarget ttpTarget = new MultiInstanceTarget(ttpIdentifier.getValue(), correlationKey);
+ MultiInstanceTarget ttpTarget = new MultiInstanceTarget(ttpIdentifier, correlationKey);
execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGET, MultiInstanceTargetValues.create(ttpTarget));
}
- private Identifier getTtpIdentifier(DelegateExecution execution)
- {
- // TODO implement ttp selection strategy, if there are multiple TTPs available
- // has to mach the selection strategy from the service SelectRequestTarget,
- // because this sends the Query results for record linkage to the TTP
-
- Organization ttp = organizationProvider.getOrganizationsByType("TTP").findFirst().orElseThrow(
- () -> new IllegalArgumentException("No organization of type TTP could be found, aborting request"));
-
- return ttp.getIdentifier().stream()
- .filter(identifier -> identifier.getSystem().equals(Constants.ORGANIZATION_IDENTIFIER_SYSTEM))
- .findFirst().orElseThrow(() -> new IllegalArgumentException(
- "No organization identifier of type TTP could be found, aborting request"));
- }
-
private String getCorrelationKey(DelegateExecution execution)
{
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
- return getTaskHelper().getFirstInputParameterStringValue(task, Constants.CODESYSTEM_HIGHMED_BPMN,
- Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).orElseThrow(() -> new IllegalStateException(
- "No correlation key found, this error should have been caught by resource validation"));
+ return getTaskHelper()
+ .getFirstInputParameterStringValue(task, Constants.CODESYSTEM_HIGHMED_BPMN,
+ Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY)
+ .orElseThrow(() -> new IllegalStateException(
+ "No correlation key found, this error should have been caught by resource validation"));
}
-
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java
index 1ba17e01c..5263de7fb 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java
@@ -35,22 +35,11 @@ protected void doExecute(DelegateExecution execution) throws Exception
execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGETS,
MultiInstanceTargetsValues.create(new MultiInstanceTargets(targets)));
- boolean needsConsentCheck = getNeedsConsentCheck(task);
- execution.setVariable(Constants.VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck);
-
boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task);
execution.setVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage);
- execution.setVariable(Constants.VARIABLE_QUERY_RESULTS, FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(null)));
- }
-
- private boolean getNeedsConsentCheck(Task task)
- {
- return getTaskHelper().getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK).orElseThrow(
- () -> new IllegalArgumentException(
- "NeedsConsentCheck boolean is not set in task with id='" + task.getId()
- + "', this error should " + "have been caught by resource validation"));
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(null)));
}
private boolean getNeedsRecordLinkageCheck(Task task)
@@ -61,5 +50,4 @@ private boolean getNeedsRecordLinkageCheck(Task task)
"NeedsRecordLinkage boolean is not set in task with id='" + task.getId()
+ "', this error should " + "have been caught by resource validation"));
}
-
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java
index 1e6c1af5e..1ab36d60a 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java
@@ -1,5 +1,6 @@
package org.highmed.dsf.bpe.service;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -12,8 +13,10 @@
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResult;
import org.highmed.dsf.fhir.variables.FeasibilityQueryResults;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.UnsignedIntType;
import org.springframework.beans.factory.InitializingBean;
public class StoreResults extends AbstractServiceDelegate implements InitializingBean
@@ -32,30 +35,60 @@ public StoreResults(FhirWebserviceClientProvider clientProvider, TaskHelper task
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
+
Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
- public void doExecute(DelegateExecution execution) throws Exception
+ protected void doExecute(DelegateExecution execution) throws Exception
{
FeasibilityQueryResults results = (FeasibilityQueryResults) execution
.getVariable(Constants.VARIABLE_QUERY_RESULTS);
+ boolean needsRecordLinkage = Boolean.TRUE
+ .equals((Boolean) execution.getVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE));
+
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
- String requester = task.getRequester().getReference();
- List resultInputs = getTaskHelper()
- .getInputParameterWithExtension(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
- Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT,
- Constants.EXTENSION_GROUP_ID_URI).map(input -> {
- String groupId = ((Reference) input.getExtension().get(0).getValue()).getReference();
- int groupSize = Integer.parseInt(input.getValue().primitiveValue());
- return new FeasibilityQueryResult(requester, groupId, groupSize);
- }).collect(Collectors.toList());
+ List extendedResults = new ArrayList<>();
+ extendedResults.addAll(results.getResults());
+ extendedResults.addAll(getResults(task, needsRecordLinkage));
+
+ execution.setVariable(Constants.VARIABLE_QUERY_RESULTS,
+ FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(extendedResults)));
+ }
+
+ private List getResults(Task task, boolean needsRecordLinkage)
+ {
+ TaskHelper taskHelper = getTaskHelper();
+ Reference requester = task.getRequester();
+
+ if (needsRecordLinkage)
+ {
+ return taskHelper.getInputParameterWithExtension(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE,
+ Constants.EXTENSION_GROUP_ID_URI).map(input ->
+ {
+ String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference();
+ String resultSetUrl = ((Reference) input.getValue()).getReference();
- results.addAll(resultInputs);
+ return FeasibilityQueryResult.idResult(requester.getIdentifier().getValue(), cohortId,
+ resultSetUrl);
+ }).collect(Collectors.toList());
+ }
+ else
+ {
+ return taskHelper.getInputParameterWithExtension(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY,
+ Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT,
+ Constants.EXTENSION_GROUP_ID_URI).map(input ->
+ {
+ String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference();
+ int cohortSize = ((UnsignedIntType) input.getValue()).getValue();
- // race conditions are not possible, since tasks are received sequentially over the websocket connection
- execution.setVariable(Constants.VARIABLE_QUERY_RESULTS, results);
+ return FeasibilityQueryResult.countResult(requester.getIdentifier().getValue(), cohortId,
+ cohortSize);
+ }).collect(Collectors.toList());
+ }
}
+
}
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java
index 4e860416c..e5c376d99 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java
@@ -1,5 +1,6 @@
package org.highmed.dsf.bpe.spring.config;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.highmed.dsf.bpe.message.SendMedicRequest;
import org.highmed.dsf.bpe.message.SendMultiMedicResults;
@@ -13,8 +14,9 @@
import org.highmed.dsf.bpe.service.CheckSingleMedicResults;
import org.highmed.dsf.bpe.service.DownloadFeasibilityResources;
import org.highmed.dsf.bpe.service.DownloadResearchStudyResource;
-import org.highmed.dsf.bpe.service.ExecuteEpiLink;
+import org.highmed.dsf.bpe.service.DownloadResultSets;
import org.highmed.dsf.bpe.service.ExecuteQueries;
+import org.highmed.dsf.bpe.service.ExecuteRecordLink;
import org.highmed.dsf.bpe.service.FilterQueryResultsByConsent;
import org.highmed.dsf.bpe.service.GenerateBloomFilters;
import org.highmed.dsf.bpe.service.GenerateCountFromIds;
@@ -29,9 +31,16 @@
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.openehr.client.OpenEhrWebserviceClientProvider;
+import org.highmed.mpi.client.MasterPatientIndexClient;
+import org.highmed.mpi.client.MasterPatientIndexClientFactory;
+import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicRbfOnly;
+import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicRbfOnlyImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
import ca.uhn.fhir.context.FhirContext;
@@ -44,6 +53,9 @@ public class FeasibilityConfig
@Autowired
private OpenEhrWebserviceClientProvider openehrClientProvider;
+ @Autowired
+ private MasterPatientIndexClientFactory masterPatientIndexClientFactory;
+
@Autowired
private OrganizationProvider organizationProvider;
@@ -56,6 +68,12 @@ public class FeasibilityConfig
@Autowired
private FhirContext fhirContext;
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @Autowired
+ private Environment environment;
+
@Bean
public ProcessEnginePlugin feasibilityPlugin()
{
@@ -69,13 +87,13 @@ public ProcessEnginePlugin feasibilityPlugin()
@Bean
public DownloadResearchStudyResource downloadResearchStudyResource()
{
- return new DownloadResearchStudyResource(fhirClientProvider, taskHelper);
+ return new DownloadResearchStudyResource(organizationProvider, fhirClientProvider, taskHelper);
}
@Bean
public SelectRequestTargets selectRequestTargets()
{
- return new SelectRequestTargets(fhirClientProvider, taskHelper, organizationProvider);
+ return new SelectRequestTargets(fhirClientProvider, taskHelper, organizationProvider, bouncyCastleProvider());
}
@Bean
@@ -127,7 +145,8 @@ public ModifyQueries modifyQueries()
@Bean
public ExecuteQueries executeQueries()
{
- return new ExecuteQueries(fhirClientProvider, openehrClientProvider.getWebserviceClient(), taskHelper);
+ return new ExecuteQueries(fhirClientProvider, openehrClientProvider.getWebserviceClient(), taskHelper,
+ organizationProvider);
}
@Bean
@@ -136,16 +155,29 @@ public FilterQueryResultsByConsent filterQueryResultsByConsent()
return new FilterQueryResultsByConsent(fhirClientProvider, taskHelper);
}
+ @Bean
+ public GenerateCountFromIds generateCountFromIds()
+ {
+ return new GenerateCountFromIds(fhirClientProvider, taskHelper);
+ }
+
+ @Bean
+ public MasterPatientIndexClient masterPatientIndexClient()
+ {
+ return masterPatientIndexClientFactory.createClient(environment::getProperty);
+ }
+
@Bean
public GenerateBloomFilters generateBloomFilters()
{
- return new GenerateBloomFilters(fhirClientProvider, taskHelper);
+ return new GenerateBloomFilters(fhirClientProvider, taskHelper, masterPatientIndexClient(), objectMapper,
+ bouncyCastleProvider());
}
@Bean
- public GenerateCountFromIds generateCountFromIds()
+ public BouncyCastleProvider bouncyCastleProvider()
{
- return new GenerateCountFromIds(fhirClientProvider, taskHelper);
+ return new BouncyCastleProvider();
}
@Bean
@@ -183,9 +215,21 @@ public StoreResults storeResults()
}
@Bean
- public ExecuteEpiLink executeEpiLink()
+ public DownloadResultSets downloadResultSets()
+ {
+ return new DownloadResultSets(fhirClientProvider, taskHelper, objectMapper);
+ }
+
+ @Bean
+ public ResultSetTranslatorFromMedicRbfOnly resultSetTranslatorFromMedicRbfOnly()
+ {
+ return new ResultSetTranslatorFromMedicRbfOnlyImpl();
+ }
+
+ @Bean
+ public ExecuteRecordLink executeRecordLink()
{
- return new ExecuteEpiLink(fhirClientProvider, taskHelper);
+ return new ExecuteRecordLink(fhirClientProvider, taskHelper, resultSetTranslatorFromMedicRbfOnly());
}
@Bean
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn
index 8d9ce9c61..fbd448eb5 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn
@@ -1,6 +1,6 @@
-
+
SequenceFlow_1lfe4wr
SequenceFlow_0xxpamp
@@ -29,8 +29,8 @@
- SequenceFlow_1lu3gr1
- SequenceFlow_0ru8qx9
+ SequenceFlow_0t4lx4v
+ SequenceFlow_155t66x
SequenceFlow_0h3to47
@@ -46,15 +46,14 @@
requestSimpleFeasibility
- http://highmed.org/fhir/StructureDefinition/highmed-task-result-multi-medic-simple-feasibility
- 0.1.0
+ http://highmed.org/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility
+ 0.2.0
resultMultiMedicSimpleFeasibilityMessage
SequenceFlow_0brvdlv
-
@@ -65,37 +64,38 @@
-
+
${needsRecordLinkage == false}
-
+
${needsRecordLinkage == true}
-
- SequenceFlow_0calilw
+
+ SequenceFlow_0zp76kj
SequenceFlow_02zmrer
-
-
- SequenceFlow_02zmrer
- SequenceFlow_1sevjlz
-
+
- SequenceFlow_0t4lx4v
- SequenceFlow_1sevjlz
+ SequenceFlow_02zmrer
+ SequenceFlow_155t66x
SequenceFlow_1lu3gr1
-
-
+
SequenceFlow_01pjftq
SequenceFlow_1lfe4wr
- SequenceFlow_0ru8qx9
+ SequenceFlow_1lu3gr1
SequenceFlow_0brvdlv
+
+
+ SequenceFlow_0calilw
+ SequenceFlow_0zp76kj
+
+
@@ -106,7 +106,7 @@
-
+
@@ -145,15 +145,11 @@
-
+
-
+
-
-
-
-
@@ -176,50 +172,54 @@
-
+
-
+
-
+
-
+
-
-
+
+
-
-
+
+
-
-
-
-
+
-
-
-
-
-
-
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn
index 826722289..b69df3fcc 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn
@@ -1,6 +1,6 @@
-
+
SequenceFlow_0q803rh
SequenceFlow_04ouilq
@@ -25,9 +25,9 @@
resultSingleMedicSimpleFeasibilityMessage
- 0.1.0
+ 0.2.0
computeSimpleFeasibility
- http://highmed.org/fhir/StructureDefinition/highmed-task-result-single-medic-simple-feasibility
+ http://highmed.org/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility
SequenceFlow_0ascyjc
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn
index 9a78de695..386c043ad 100755
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn
@@ -1,6 +1,6 @@
-
+
SequenceFlow_11k77gx
@@ -13,7 +13,7 @@
executeSimpleFeasibility
- 0.1.0
+ 0.2.0
executeSimpleFeasibilityMessage
http://highmed.org/fhir/StructureDefinition/highmed-task-execute-simple-feasibility
@@ -42,7 +42,7 @@
computeSimpleFeasibility
- 0.1.0
+ 0.2.0
computeSimpleFeasibilityMessage
http://highmed.org/fhir/StructureDefinition/highmed-task-compute-simple-feasibility
diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java
index 70c5e175a..2526b6349 100644
--- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java
+++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java
@@ -12,7 +12,8 @@
import javax.ws.rs.WebApplicationException;
import org.highmed.dsf.bpe.Constants;
-import org.highmed.dsf.fhir.service.ReferenceExtractor;
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
+import org.highmed.dsf.fhir.service.ReferenceCleanerImpl;
import org.highmed.dsf.fhir.service.ReferenceExtractorImpl;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.highmed.fhir.client.FhirWebserviceClientJersey;
@@ -27,8 +28,6 @@
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Narrative;
import org.hl7.fhir.r4.model.OperationOutcome;
-import org.hl7.fhir.r4.model.Practitioner;
-import org.hl7.fhir.r4.model.PractitionerRole;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.ResearchStudy;
import org.hl7.fhir.r4.model.ResearchStudy.ResearchStudyStatus;
@@ -53,18 +52,16 @@ public static void main(String[] args)
KeyStore trustStore = CertificateHelper.extractTrust(keyStore);
FhirContext context = FhirContext.forR4();
- ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl();
+ ReferenceCleaner referenceCleaner = new ReferenceCleanerImpl(new ReferenceExtractorImpl());
FhirWebserviceClient client = new FhirWebserviceClientJersey("https://medic1/fhir/", trustStore, keyStore,
- keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor);
+ keyStorePassword, null, null, null, 0, 0, null, context, referenceCleaner);
try
{
Group group1 = createGroup("Group 1");
Group group2 = createGroup("Group 2");
- Practitioner practitioner = createPractitioner();
- PractitionerRole practitionerRole = createPractitionerRole(practitioner);
- ResearchStudy researchStudy = createResearchStudy(group1, group2, practitioner);
- Task task = createTask(practitioner, researchStudy);
+ ResearchStudy researchStudy = createResearchStudy(group1, group2);
+ Task task = createTask(researchStudy);
Bundle bundle = new Bundle();
bundle.setType(BundleType.TRANSACTION);
@@ -72,16 +69,12 @@ public static void main(String[] args)
.setMethod(HTTPVerb.POST).setUrl("Group");
bundle.addEntry().setResource(group2).setFullUrl(group2.getIdElement().getIdPart()).getRequest()
.setMethod(HTTPVerb.POST).setUrl("Group");
- bundle.addEntry().setResource(practitioner).setFullUrl(practitioner.getIdElement().getIdPart()).getRequest()
- .setMethod(HTTPVerb.POST).setUrl("Practitioner");
- bundle.addEntry().setResource(practitionerRole).setFullUrl(practitionerRole.getIdElement().getIdPart())
- .getRequest().setMethod(HTTPVerb.POST).setUrl("PractitionerRole");
bundle.addEntry().setResource(researchStudy).setFullUrl(researchStudy.getIdElement().getIdPart())
.getRequest().setMethod(HTTPVerb.POST).setUrl("ResearchStudy");
bundle.addEntry().setResource(task).setFullUrl(task.getIdElement().getIdPart()).getRequest()
.setMethod(HTTPVerb.POST).setUrl("Task");
- client.postBundle(bundle);
+ client.withMinimalReturn().postBundle(bundle);
}
catch (WebApplicationException e)
{
@@ -105,7 +98,7 @@ private static Group createGroup(String name)
group.getText().getDiv().addText("This is the description");
group.getText().setStatus(Narrative.NarrativeStatus.ADDITIONAL);
group.setType(GroupType.PERSON);
- group.setActual(true);
+ group.setActual(false);
group.setActive(true);
group.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/query").setValue(new Expression()
.setLanguageElement(Constants.AQL_QUERY_TYPE).setExpression("SELECT COUNT(e) FROM EHR e"));
@@ -114,72 +107,51 @@ private static Group createGroup(String name)
return group;
}
- private static Practitioner createPractitioner()
- {
- Practitioner practitioner = new Practitioner();
- practitioner.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString()));
- practitioner.setActive(true);
-
- practitioner.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-practitioner");
- practitioner.getNameFirstRep().setFamily("HiGHmed").addGiven("Test");
-
- return practitioner;
- }
-
- private static PractitionerRole createPractitionerRole(Practitioner practitioner)
- {
- PractitionerRole practitionerRole = new PractitionerRole();
- practitionerRole.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString()));
- practitionerRole.setActive(true);
-
- practitioner.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role");
- practitionerRole.getPractitioner().setReference(practitioner.getIdElement().getIdPart());
- practitionerRole.getOrganization().setType("Organization").getIdentifier()
- .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1");
-
- return practitionerRole;
- }
-
- private static ResearchStudy createResearchStudy(Group group1, Group group2, Practitioner practitioner)
+ private static ResearchStudy createResearchStudy(Group group1, Group group2)
{
ResearchStudy researchStudy = new ResearchStudy();
researchStudy.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString()));
- researchStudy.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-research-study");
+ researchStudy.getMeta()
+ .addProfile("http://highmed.org/fhir/StructureDefinition/highmed-research-study-feasibility");
researchStudy.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/research-study-identifier")
.setValue(UUID.randomUUID().toString());
- researchStudy.setTitle("Research Study Test");
researchStudy.setStatus(ResearchStudyStatus.ACTIVE);
- researchStudy.setDescription(
- "This is a test research study based on the highmed profile. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.");
researchStudy.addEnrollment().setReference(group1.getIdElement().getIdPart());
researchStudy.addEnrollment().setReference(group2.getIdElement().getIdPart());
- researchStudy.getPrincipalInvestigator().setReference(practitioner.getIdElement().getIdPart());
researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic")
- .setValue(new Reference().setType("Organization").setIdentifier(new Identifier()
- .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1")));
+ .setValue(new Reference().setType("Organization")
+ .setIdentifier(new Identifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier")
+ .setValue("Test_MeDIC_1")));
researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic")
- .setValue(new Reference().setType("Organization").setIdentifier(new Identifier()
- .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_2")));
+ .setValue(new Reference().setType("Organization")
+ .setIdentifier(new Identifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier")
+ .setValue("Test_MeDIC_2")));
researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic")
- .setValue(new Reference().setType("Organization").setIdentifier(new Identifier()
- .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_3")));
+ .setValue(new Reference().setType("Organization")
+ .setIdentifier(new Identifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier")
+ .setValue("Test_MeDIC_3")));
researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-ttp")
- .setValue(new Reference().setType("Organization").setIdentifier(new Identifier()
- .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP")));
+ .setValue(new Reference().setType("Organization")
+ .setIdentifier(new Identifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier")
+ .setValue("Test_TTP")));
return researchStudy;
}
- private static Task createTask(Practitioner practitioner, ResearchStudy researchStudy)
+ private static Task createTask(ResearchStudy researchStudy)
{
Task task = new Task();
task.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString()));
task.getMeta()
.addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-request-simple-feasibility");
- task.setInstantiatesUri("http://highmed.org/bpe/Process/requestSimpleFeasibility/0.1.0");
+ task.setInstantiatesUri("http://highmed.org/bpe/Process/requestSimpleFeasibility/0.2.0");
task.setStatus(TaskStatus.REQUESTED);
task.setIntent(TaskIntent.ORDER);
task.setAuthoredOn(new Date());
@@ -195,9 +167,9 @@ private static Task createTask(Practitioner practitioner, ResearchStudy research
new Reference().setReference(researchStudy.getIdElement().getIdPart()).setType("ResearchStudy"))
.getType().addCoding().setSystem("http://highmed.org/fhir/CodeSystem/feasibility")
.setCode("research-study-reference");
- task.addInput().setValue(new BooleanType(false)).getType().addCoding()
+ task.addInput().setValue(new BooleanType(true)).getType().addCoding()
.setSystem("http://highmed.org/fhir/CodeSystem/feasibility").setCode("needs-record-linkage");
- task.addInput().setValue(new BooleanType(false)).getType().addCoding()
+ task.addInput().setValue(new BooleanType(true)).getType().addCoding()
.setSystem("http://highmed.org/fhir/CodeSystem/feasibility").setCode("needs-consent-check");
return task;
diff --git a/dsf-bpe/dsf-bpe-process-ping/pom.xml b/dsf-bpe/dsf-bpe-process-ping/pom.xml
index 83eff334b..87cd08048 100755
--- a/dsf-bpe/dsf-bpe-process-ping/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-ping/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPing.java b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPing.java
index 98e1ac565..3adfaf1ae 100755
--- a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPing.java
+++ b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPing.java
@@ -1,15 +1,10 @@
package org.highmed.dsf.bpe.service;
-import java.util.Objects;
-
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
-import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
-import org.hl7.fhir.r4.model.IdType;
-import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,22 +13,9 @@ public class LogPing extends AbstractServiceDelegate
{
private static final Logger logger = LoggerFactory.getLogger(LogPing.class);
- private final OrganizationProvider organizationProvider;
-
- public LogPing(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
- OrganizationProvider organizationProvider)
+ public LogPing(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
{
super(clientProvider, taskHelper);
-
- this.organizationProvider = organizationProvider;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception
- {
- super.afterPropertiesSet();
-
- Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
@@ -45,9 +27,6 @@ public void doExecute(DelegateExecution execution) throws Exception
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
- String organization = organizationProvider.getIdentifier(new IdType(task.getRequester().getReference()))
- .map(Identifier::getValue).orElse(task.getRequester().getReference());
-
- logger.info("PING from {}", organization);
+ logger.info("PING from {}", task.getRequester().getIdentifier().getValue());
}
}
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java
index 7430e24d2..fcf49ee58 100755
--- a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java
+++ b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java
@@ -1,15 +1,10 @@
package org.highmed.dsf.bpe.service;
-import java.util.Objects;
-
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
-import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
-import org.hl7.fhir.r4.model.IdType;
-import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,22 +13,9 @@ public class LogPong extends AbstractServiceDelegate
{
private static final Logger logger = LoggerFactory.getLogger(LogPong.class);
- private final OrganizationProvider organizationProvider;
-
- public LogPong(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
- OrganizationProvider organizationProvider)
+ public LogPong(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
{
super(clientProvider, taskHelper);
-
- this.organizationProvider = organizationProvider;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception
- {
- super.afterPropertiesSet();
-
- Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
@@ -45,9 +27,6 @@ public void doExecute(DelegateExecution execution) throws Exception
Task task = (Task) execution.getVariable(Constants.VARIABLE_TASK);
- String organization = organizationProvider.getIdentifier(new IdType(task.getRequester().getReference()))
- .map(Identifier::getValue).orElse(task.getRequester().getReference());
-
- logger.info("PONG from {}", organization);
+ logger.info("PONG from {}", task.getRequester().getIdentifier().getValue());
}
}
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java
index ec9060a02..b7dbaa96e 100755
--- a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java
+++ b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java
@@ -1,16 +1,12 @@
package org.highmed.dsf.bpe.service;
-import java.util.Objects;
-
import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.highmed.dsf.bpe.Constants;
import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
-import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.variables.MultiInstanceTarget;
import org.highmed.dsf.fhir.variables.MultiInstanceTargetValues;
-import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
@@ -21,22 +17,9 @@ public class SelectPongTarget extends AbstractServiceDelegate implements Initial
{
private static final Logger logger = LoggerFactory.getLogger(SelectPingTargets.class);
- private final OrganizationProvider organizationProvider;
-
- public SelectPongTarget(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper,
- OrganizationProvider organizationProvider)
+ public SelectPongTarget(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper)
{
super(clientProvider, taskHelper);
-
- this.organizationProvider = organizationProvider;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception
- {
- super.afterPropertiesSet();
-
- Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@Override
@@ -50,11 +33,7 @@ public void doExecute(DelegateExecution execution) throws Exception
String correlationKey = getTaskHelper().getFirstInputParameterStringValue(task,
Constants.CODESYSTEM_HIGHMED_BPMN, Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).get();
-
- Identifier targetOrganizationIdentifier = organizationProvider
- .getIdentifier(new IdType(task.getRequester().getReference()))
- .orElseThrow(() -> new IllegalStateException(
- "Organization with id " + task.getRequester().getReference() + " not found"));
+ Identifier targetOrganizationIdentifier = task.getRequester().getIdentifier();
execution.setVariable(Constants.VARIABLE_MULTI_INSTANCE_TARGET, MultiInstanceTargetValues
.create(new MultiInstanceTarget(targetOrganizationIdentifier.getValue(), correlationKey)));
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java
index 79de26b42..932fbdfe6 100755
--- a/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java
+++ b/dsf-bpe/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java
@@ -53,13 +53,13 @@ public SendPong sendPong()
@Bean
public LogPing logPing()
{
- return new LogPing(clientProvider, taskHelper, organizationProvider);
+ return new LogPing(clientProvider, taskHelper);
}
@Bean
public LogPong logPong()
{
- return new LogPong(clientProvider, taskHelper, organizationProvider);
+ return new LogPong(clientProvider, taskHelper);
}
@Bean
@@ -71,6 +71,6 @@ public SelectPingTargets selectPingTargets()
@Bean
public SelectPongTarget selectPongTarget()
{
- return new SelectPongTarget(clientProvider, taskHelper, organizationProvider);
+ return new SelectPongTarget(clientProvider, taskHelper);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn
index 4b064775d..a68c15eb4 100755
--- a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn
+++ b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn
@@ -1,6 +1,6 @@
-
+
@@ -11,7 +11,7 @@
pong
- 0.1.0
+ 0.2.0
pingMessage
http://highmed.org/fhir/StructureDefinition/highmed-task-ping
@@ -50,7 +50,7 @@
SequenceFlow_01v9yzp
- PT5S
+ PT5M
@@ -66,17 +66,30 @@
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -86,52 +99,39 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn
index d13a47ae0..5af4b7e5a 100755
--- a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn
+++ b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn
@@ -1,6 +1,6 @@
-
+
SequenceFlow_07w11cw
@@ -10,7 +10,7 @@
pongMessage
- 0.1.0
+ 0.2.0
ping
http://highmed.org/fhir/StructureDefinition/highmed-task-pong
diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java
index 182ffc78c..3896bc12d 100644
--- a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java
+++ b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java
@@ -8,7 +8,8 @@
import java.security.cert.CertificateException;
import java.util.Date;
-import org.highmed.dsf.fhir.service.ReferenceExtractor;
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
+import org.highmed.dsf.fhir.service.ReferenceCleanerImpl;
import org.highmed.dsf.fhir.service.ReferenceExtractorImpl;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.highmed.fhir.client.FhirWebserviceClientJersey;
@@ -33,13 +34,13 @@ public static void main(String[] args)
KeyStore trustStore = CertificateHelper.extractTrust(keyStore);
FhirContext context = FhirContext.forR4();
- ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl();
+ ReferenceCleaner referenceCleaner = new ReferenceCleanerImpl(new ReferenceExtractorImpl());
FhirWebserviceClient client = new FhirWebserviceClientJersey("https://ttp/fhir/", trustStore, keyStore,
- keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor);
+ keyStorePassword, null, null, null, 0, 0, null, context, referenceCleaner);
Task task = new Task();
- task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process");
- task.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0");
+ task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-ping-process");
+ task.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.2.0");
task.setStatus(TaskStatus.REQUESTED);
task.setIntent(TaskIntent.ORDER);
task.setAuthoredOn(new Date());
@@ -48,9 +49,9 @@ public static void main(String[] args)
task.getRestriction().addRecipient().setType("Organization").getIdentifier()
.setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP");
- task.addInput().setValue(new StringType("startProcessMessage")).getType().addCoding()
+ task.addInput().setValue(new StringType("startPingProcessMessage")).getType().addCoding()
.setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name");
- client.create(task);
+ client.withMinimalReturn().create(task);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-child/pom.xml b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-child/pom.xml
index 800f31492..0efeac384 100644
--- a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-child/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-child/pom.xml
@@ -8,7 +8,7 @@
dsf-bpe-process-plugin-example
org.highmed.dsf
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/pom.xml b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/pom.xml
index d5e911885..9cc236e41 100644
--- a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/pom.xml
@@ -8,7 +8,7 @@
dsf-bpe-process-plugin-example
org.highmed.dsf
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/java/org/highmed/dsf/bpe/start/PluginSubprocessExampleStarter.java b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/java/org/highmed/dsf/bpe/start/PluginSubprocessExampleStarter.java
new file mode 100644
index 000000000..57d63e481
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/java/org/highmed/dsf/bpe/start/PluginSubprocessExampleStarter.java
@@ -0,0 +1,58 @@
+package org.highmed.dsf.bpe.start;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Date;
+
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
+import org.highmed.dsf.fhir.service.ReferenceCleanerImpl;
+import org.highmed.dsf.fhir.service.ReferenceExtractorImpl;
+import org.highmed.fhir.client.FhirWebserviceClient;
+import org.highmed.fhir.client.FhirWebserviceClientJersey;
+import org.hl7.fhir.r4.model.StringType;
+import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.TaskIntent;
+import org.hl7.fhir.r4.model.Task.TaskStatus;
+
+import ca.uhn.fhir.context.FhirContext;
+
+import de.rwh.utils.crypto.CertificateHelper;
+import de.rwh.utils.crypto.io.CertificateReader;
+
+public class PluginSubprocessExampleStarter
+{
+ public static void main(String[] args)
+ throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException
+ {
+ char[] keyStorePassword = "password".toCharArray();
+ KeyStore keyStore = CertificateReader.fromPkcs12(Paths.get(
+ "../../dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"),
+ keyStorePassword);
+ KeyStore trustStore = CertificateHelper.extractTrust(keyStore);
+
+ FhirContext context = FhirContext.forR4();
+ ReferenceCleaner referenceCleaner = new ReferenceCleanerImpl(new ReferenceExtractorImpl());
+ FhirWebserviceClient client = new FhirWebserviceClientJersey("https://medic1/fhir/", trustStore, keyStore,
+ keyStorePassword, null, null, null, 0, 0, null, context, referenceCleaner);
+
+ Task task = new Task();
+ task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-parent-plugin");
+ task.setInstantiatesUri("http://highmed.org/bpe/Process/parentPlugin/0.2.0");
+ task.setStatus(TaskStatus.REQUESTED);
+ task.setIntent(TaskIntent.ORDER);
+ task.setAuthoredOn(new Date());
+ task.getRequester().setType("Organization").getIdentifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP");
+ task.getRestriction().addRecipient().setType("Organization").getIdentifier()
+ .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1");
+
+ task.addInput().setValue(new StringType("parentPluginMessage")).getType().addCoding()
+ .setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name");
+
+ client.create(task);
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-service-overwrite/pom.xml b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-service-overwrite/pom.xml
index 5e8693cba..595307b8f 100644
--- a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-service-overwrite/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-service-overwrite/pom.xml
@@ -8,7 +8,7 @@
dsf-bpe-process-plugin-example
org.highmed.dsf
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/pom.xml b/dsf-bpe/dsf-bpe-process-plugin-example/pom.xml
index c9a65ec6a..23eda8da5 100644
--- a/dsf-bpe/dsf-bpe-process-plugin-example/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-plugin-example/pom.xml
@@ -7,7 +7,7 @@
dsf-bpe-pom
org.highmed.dsf
- 0.1.0
+ 0.2.0
dsf-bpe-process-plugin-example
diff --git a/dsf-bpe/dsf-bpe-process-update-resources/pom.xml b/dsf-bpe/dsf-bpe-process-update-resources/pom.xml
index 4b58e1d19..e7ca984d9 100755
--- a/dsf-bpe/dsf-bpe-process-update-resources/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-update-resources/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/UpdateResources.java b/dsf-bpe/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/UpdateResources.java
index 57757af39..8705695fb 100755
--- a/dsf-bpe/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/UpdateResources.java
+++ b/dsf-bpe/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/UpdateResources.java
@@ -58,14 +58,17 @@ public void doExecute(DelegateExecution execution) throws Exception
Bundle bundle;
try
{
- bundle = requesterClient.read(Bundle.class, bundleId.getIdPart());
+ if (bundleId.hasVersionIdPart())
+ bundle = requesterClient.read(Bundle.class, bundleId.getIdPart(), bundleId.getVersionIdPart());
+ else
+ bundle = requesterClient.read(Bundle.class, bundleId.getIdPart());
}
catch (WebApplicationException e)
{
- logger.error("Error while reading Bundle with id {} from organization {}", bundleId.getValue(),
- task.getRequester().getReference());
+ logger.error("Error while reading Bundle with id {} from organization {}: {}", bundleId.getValue(),
+ task.getRequester().getReference(), e.getMessage());
throw new RuntimeException("Error while reading Bundle with id " + bundleId.getValue()
- + " from organization " + task.getRequester().getReference(), e);
+ + " from organization " + task.getRequester().getReference() + ", " + e.getMessage(), e);
}
if (!EnumSet.of(BundleType.TRANSACTION, BundleType.BATCH).contains(bundle.getType()))
@@ -77,14 +80,14 @@ public void doExecute(DelegateExecution execution) throws Exception
try
{
logger.debug("Posting bundle to local endpoint: {}", context.newXmlParser().encodeResourceToString(bundle));
- getFhirWebserviceClientProvider().getLocalWebserviceClient().postBundle(bundle);
+ getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().postBundle(bundle);
}
catch (Exception e)
{
- logger.error("Error while executing read Bundle with id {} from organization {} locally",
- bundleId.getValue(), task.getRequester().getReference());
- throw new RuntimeException("Error while executing read Bundle with id " + bundleId.getValue()
- + " from organization " + task.getRequester().getReference() + " locally", e);
+ logger.error("Error while executing Bundle with id {} from organization {} locally: {}",
+ bundleId.getValue(), task.getRequester().getReference(), e.getMessage());
+ throw new RuntimeException("Error while executing Bundle with id " + bundleId.getValue()
+ + " from organization " + task.getRequester().getReference() + " locally, " + e.getMessage(), e);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn
index 7b323f8d6..a9ae8427a 100755
--- a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn
+++ b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn
@@ -1,6 +1,6 @@
-
+
SequenceFlow_0djh0eg
@@ -28,7 +28,7 @@
-
+
@@ -41,11 +41,11 @@
-
+
-
+
diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn
index 5fe0830b9..c4a320cc6 100755
--- a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn
+++ b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn
@@ -1,6 +1,6 @@
-
+
@@ -11,7 +11,7 @@
executeUpdateResources
- 0.1.0
+ 0.2.0
executeUpdateResourcesMessage
http://highmed.org/fhir/StructureDefinition/highmed-task-execute-update-resources
diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java
index 3b9f4c732..57c4bb701 100644
--- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java
+++ b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java
@@ -10,11 +10,13 @@
import java.util.Date;
import java.util.Map;
-import org.highmed.dsf.fhir.service.ReferenceExtractor;
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
+import org.highmed.dsf.fhir.service.ReferenceCleanerImpl;
import org.highmed.dsf.fhir.service.ReferenceExtractorImpl;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.highmed.fhir.client.FhirWebserviceClientJersey;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.Task;
@@ -37,19 +39,21 @@ public static void main(String[] args)
KeyStore trustStore = CertificateHelper.extractTrust(keyStore);
FhirContext context = FhirContext.forR4();
- ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl();
+ ReferenceCleaner referenceCleaner = new ReferenceCleanerImpl(new ReferenceExtractorImpl());
FhirWebserviceClient client = new FhirWebserviceClientJersey("https://ttp/fhir/", trustStore, keyStore,
- keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor);
+ keyStorePassword, null, null, null, 0, 0, null, context, referenceCleaner);
- Bundle searchResult = client.search(Bundle.class, Map.of("identifier",
- Collections.singletonList("http://highmed.org/fhir/CodeSystem/update-whitelist|HiGHmed_white_list")));
+ Bundle searchResult = client.searchWithStrictHandling(Bundle.class, Map.of("identifier",
+ Collections.singletonList("http://highmed.org/fhir/CodeSystem/update-whitelist|highmed_whitelist")));
if (searchResult.getTotal() != 1 && searchResult.getEntryFirstRep().getResource() instanceof Bundle)
throw new IllegalStateException("Expected a single White-List Bundle");
Bundle whiteList = (Bundle) searchResult.getEntryFirstRep().getResource();
+ System.out.println(context.newXmlParser().encodeResourceToString(whiteList));
+
Task task = new Task();
task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-request-update-resources");
- task.setInstantiatesUri("http://highmed.org/bpe/Process/requestUpdateResources/0.1.0");
+ task.setInstantiatesUri("http://highmed.org/bpe/Process/requestUpdateResources/0.2.0");
task.setStatus(TaskStatus.REQUESTED);
task.setIntent(TaskIntent.ORDER);
task.setAuthoredOn(new Date());
@@ -61,13 +65,16 @@ public static void main(String[] args)
task.addInput().setValue(new StringType("requestUpdateResourcesMessage")).getType().addCoding()
.setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name");
- task.addInput().setValue(new Reference("Bundle/" + whiteList.getIdElement().getIdPart())).getType().addCoding()
- .setSystem("http://highmed.org/fhir/CodeSystem/update-resources").setCode("bundle-reference");
+ task.addInput()
+ .setValue(new Reference(new IdType("Bundle", whiteList.getIdElement().getIdPart(),
+ whiteList.getIdElement().getVersionIdPart())))
+ .getType().addCoding().setSystem("http://highmed.org/fhir/CodeSystem/update-resources")
+ .setCode("bundle-reference");
- task.addInput().setValue(new StringType("http://highmed.org/fhir/NamingSystem/organization-identifier|")).getType()
- .addCoding().setSystem("http://highmed.org/fhir/CodeSystem/update-resources")
+ task.addInput().setValue(new StringType("http://highmed.org/fhir/NamingSystem/organization-identifier|"))
+ .getType().addCoding().setSystem("http://highmed.org/fhir/CodeSystem/update-resources")
.setCode("organization-identifier-search-parameter");
- client.create(task);
+ client.withMinimalReturn().create(task);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/pom.xml b/dsf-bpe/dsf-bpe-process-update-whitelist/pom.xml
index dc67e38e0..c985297f5 100755
--- a/dsf-bpe/dsf-bpe-process-update-whitelist/pom.xml
+++ b/dsf-bpe/dsf-bpe-process-update-whitelist/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/plugin/UpdateWhiteListPlugin.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/plugin/UpdateWhitelistPlugin.java
similarity index 53%
rename from dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/plugin/UpdateWhiteListPlugin.java
rename to dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/plugin/UpdateWhitelistPlugin.java
index 4a5d317ec..46e2ecdce 100755
--- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/plugin/UpdateWhiteListPlugin.java
+++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/plugin/UpdateWhitelistPlugin.java
@@ -3,14 +3,14 @@
import org.camunda.bpm.engine.ProcessEngine;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
-public class UpdateWhiteListPlugin extends AbstractProcessEnginePlugin
+public class UpdateWhitelistPlugin extends AbstractProcessEnginePlugin
{
- private static final String UPDATE_WHITE_LISTE_FILE = "updateWhiteListe.bpmn";
+ private static final String UPDATE_WHITELIST_FILE = "updateWhitelist.bpmn";
@Override
public void postProcessEngineBuild(ProcessEngine processEngine)
{
- BpmnModelInstance updateWhiteListeProcess = readAndValidateModel("/" + UPDATE_WHITE_LISTE_FILE);
- deploy(processEngine, UPDATE_WHITE_LISTE_FILE, updateWhiteListeProcess);
+ BpmnModelInstance updateWhiteListeProcess = readAndValidateModel("/" + UPDATE_WHITELIST_FILE);
+ deploy(processEngine, UPDATE_WHITELIST_FILE, updateWhiteListeProcess);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhitelist.java
old mode 100755
new mode 100644
similarity index 84%
rename from dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java
rename to dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhitelist.java
index e366732f9..b5756b2c2
--- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java
+++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhitelist.java
@@ -15,8 +15,6 @@
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
-import org.highmed.dsf.fhir.variables.Outputs;
-import org.highmed.dsf.fhir.variables.OutputsValues;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
@@ -28,16 +26,24 @@
import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Reference;
+import org.hl7.fhir.r4.model.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
-public class UpdateWhiteList extends AbstractServiceDelegate implements InitializingBean
+import ca.uhn.fhir.context.FhirContext;
+
+public class UpdateWhitelist extends AbstractServiceDelegate implements InitializingBean
{
+ private static final Logger logger = LoggerFactory.getLogger(UpdateWhitelist.class);
+
private final OrganizationProvider organizationProvider;
- public UpdateWhiteList(OrganizationProvider organizationProvider, FhirWebserviceClientProvider clientProvider,
+ public UpdateWhitelist(OrganizationProvider organizationProvider, FhirWebserviceClientProvider clientProvider,
TaskHelper taskHelper)
{
super(clientProvider, taskHelper);
+
this.organizationProvider = organizationProvider;
}
@@ -45,6 +51,7 @@ public UpdateWhiteList(OrganizationProvider organizationProvider, FhirWebservice
public void afterPropertiesSet() throws Exception
{
super.afterPropertiesSet();
+
Objects.requireNonNull(organizationProvider, "organizationProvider");
}
@@ -53,7 +60,7 @@ public void doExecute(DelegateExecution execution) throws Exception
{
FhirWebserviceClient client = getFhirWebserviceClientProvider().getLocalWebserviceClient();
- Bundle searchSet = client.search(Organization.class,
+ Bundle searchSet = client.searchWithStrictHandling(Organization.class,
Map.of("active", Collections.singletonList("true"), "identifier",
Collections.singletonList(organizationProvider.getDefaultIdentifierSystem() + "|"), "_include",
Collections.singletonList("Organization:endpoint")));
@@ -68,11 +75,17 @@ public void doExecute(DelegateExecution execution) throws Exception
&& e.getResource() instanceof Organization)
.map(e -> (Organization) e.getResource()).forEach(addWhiteListEntry(transaction, searchSet));
- Bundle result = client.updateConditionaly(transaction,
+ logger.debug("Uploading new white-list transaction bundle: {}",
+ FhirContext.forR4().newJsonParser().encodeResourceToString(transaction));
+
+ IdType result = client.withMinimalReturn().updateConditionaly(transaction,
Map.of("identifier", Collections.singletonList(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST + "|"
+ Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST)));
- setTaskOutput(result, execution);
+ Task task = (Task) execution.getVariable(Constants.VARIABLE_LEADING_TASK);
+ task.addOutput().setValue(new Reference(new IdType("Bundle", result.getIdPart(), result.getVersionIdPart())))
+ .getType().addCoding().setSystem(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST)
+ .setCode(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST);
}
private Consumer super Organization> addWhiteListEntry(Bundle transaction, Bundle searchSet)
@@ -138,14 +151,4 @@ private Optional getEndpoint(Reference endpoint, Bundle searchSet)
&& e.getFullUrl().endsWith(endpoint.getReference()))
.map(e -> (Endpoint) e.getResource()).findFirst();
}
-
- private void setTaskOutput(Bundle result, DelegateExecution execution)
- {
- Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS);
-
- outputs.add(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST,
- Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST, new IdType(result.getId()).getIdPart());
-
- execution.setVariable(Constants.VARIABLE_PROCESS_OUTPUTS, OutputsValues.create(outputs));
- }
}
diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/spring/config/UpdateWhiteListConfig.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/spring/config/UpdateWhitelistConfig.java
similarity index 72%
rename from dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/spring/config/UpdateWhiteListConfig.java
rename to dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/spring/config/UpdateWhitelistConfig.java
index 5db3aa588..e0efe0d4b 100755
--- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/spring/config/UpdateWhiteListConfig.java
+++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/spring/config/UpdateWhitelistConfig.java
@@ -1,8 +1,8 @@
package org.highmed.dsf.bpe.spring.config;
import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
-import org.highmed.dsf.bpe.plugin.UpdateWhiteListPlugin;
-import org.highmed.dsf.bpe.service.UpdateWhiteList;
+import org.highmed.dsf.bpe.plugin.UpdateWhitelistPlugin;
+import org.highmed.dsf.bpe.service.UpdateWhitelist;
import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider;
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.task.TaskHelper;
@@ -11,7 +11,7 @@
import org.springframework.context.annotation.Configuration;
@Configuration
-public class UpdateWhiteListConfig
+public class UpdateWhitelistConfig
{
@Autowired
private FhirWebserviceClientProvider clientProvider;
@@ -25,12 +25,12 @@ public class UpdateWhiteListConfig
@Bean
public ProcessEnginePlugin updateWhiteListPlugin()
{
- return new UpdateWhiteListPlugin();
+ return new UpdateWhitelistPlugin();
}
@Bean
- public UpdateWhiteList updateWhiteList()
+ public UpdateWhitelist updateWhiteList()
{
- return new UpdateWhiteList(organizationProvider, clientProvider, taskHelper);
+ return new UpdateWhitelist(organizationProvider, clientProvider, taskHelper);
}
}
diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhitelist.bpmn
similarity index 81%
rename from dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn
rename to dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhitelist.bpmn
index 96ee697b9..13a84df30 100755
--- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn
+++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhitelist.bpmn
@@ -1,12 +1,12 @@
-
-
+
+
SequenceFlow_0oyvmcd
-
-
+
+
SequenceFlow_0bbhq2r
SequenceFlow_0oyvmcd
@@ -15,9 +15,9 @@
-
+
-
+
@@ -29,7 +29,7 @@
-
+
diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhitelist3MedicTtpExampleStarter.java
similarity index 87%
rename from dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java
rename to dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhitelist3MedicTtpExampleStarter.java
index def693de8..7d609a9f1 100644
--- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java
+++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhitelist3MedicTtpExampleStarter.java
@@ -8,7 +8,8 @@
import java.security.cert.CertificateException;
import java.util.Date;
-import org.highmed.dsf.fhir.service.ReferenceExtractor;
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
+import org.highmed.dsf.fhir.service.ReferenceCleanerImpl;
import org.highmed.dsf.fhir.service.ReferenceExtractorImpl;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.highmed.fhir.client.FhirWebserviceClientJersey;
@@ -21,7 +22,7 @@
import de.rwh.utils.crypto.CertificateHelper;
import de.rwh.utils.crypto.io.CertificateReader;
-public class UpdateWhiteList3MedicTtpExampleStarter
+public class UpdateWhitelist3MedicTtpExampleStarter
{
public static void main(String[] args)
throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException
@@ -33,13 +34,13 @@ public static void main(String[] args)
KeyStore trustStore = CertificateHelper.extractTrust(keyStore);
FhirContext context = FhirContext.forR4();
- ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl();
+ ReferenceCleaner referenceCleaner = new ReferenceCleanerImpl(new ReferenceExtractorImpl());
FhirWebserviceClient client = new FhirWebserviceClientJersey("https://ttp/fhir/", trustStore, keyStore,
- keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor);
+ keyStorePassword, null, null, null, 0, 0, null, context, referenceCleaner);
Task task = new Task();
task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist");
- task.setInstantiatesUri("http://highmed.org/bpe/Process/updateWhiteList/0.1.0");
+ task.setInstantiatesUri("http://highmed.org/bpe/Process/updateWhitelist/0.2.0");
task.setStatus(TaskStatus.REQUESTED);
task.setIntent(TaskIntent.ORDER);
task.setAuthoredOn(new Date());
@@ -51,6 +52,6 @@ public static void main(String[] args)
task.addInput().setValue(new StringType("updateWhitelistMessage")).getType().addCoding()
.setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name");
- client.create(task);
+ client.withMinimalReturn().create(task);
}
}
diff --git a/dsf-bpe/dsf-bpe-server-jetty/conf/config.properties b/dsf-bpe/dsf-bpe-server-jetty/conf/config.properties
index 654ff5654..05d2e3a34 100755
--- a/dsf-bpe/dsf-bpe-server-jetty/conf/config.properties
+++ b/dsf-bpe/dsf-bpe-server-jetty/conf/config.properties
@@ -1,42 +1,56 @@
-org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_Organization
-
-org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://localhost:8001/fhir
-org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=target/test-client_certificate.p12
-org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
-org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500
-org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
-
-org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500
-org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500
-#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
-#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
-#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort=
-
-org.highmed.dsf.bpe.fhir.local.websocket.url=wss://localhost:8001/fhir/ws
-org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=target/test-client_certificate.p12
-org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
-
-org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
-org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=target/last_event_time_file.txt
-
-org.highmed.dsf.bpe.db.driver=org.postgresql.Driver
-org.highmed.dsf.bpe.db.url=jdbc:postgresql://localhost/bpe
-org.highmed.dsf.bpe.db.liquibase_user=liquibase_user
-org.highmed.dsf.bpe.db.liquibase_user_password=fLp6ZSd5QrMAkGZMjxqXjmcWrTfa3Dn8fA57h92Y
-
-org.highmed.dsf.bpe.db.server_users_group=bpe_users
-org.highmed.dsf.bpe.db.server_user=bpe_server_user
-org.highmed.dsf.bpe.db.server_user_password=as2hm56BPcaJKtG25JEx
-
-org.highmed.dsf.bpe.db.camunda_users_group=camunda_users
-org.highmed.dsf.bpe.db.camunda_user=camunda_server_user
-org.highmed.dsf.bpe.db.camunda_user_password=arpJ2FgJuYvUJhbxeuh7
-
-org.highmed.dsf.bpe.openehr.webservice.baseUrl=http://localhost:8003/rest/openehr/v1
-org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
-org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
-org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
-org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
-
-org.highmed.dsf.bpe.cors.origins=
-
+org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_Organization
+
+org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://localhost:8001/fhir
+org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=target/test-client_certificate.p12
+org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
+org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500
+org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
+
+org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500
+org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500
+#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
+#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
+#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort=
+
+org.highmed.dsf.bpe.fhir.local.websocket.url=wss://localhost:8001/fhir/ws
+org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=target/test-client_certificate.p12
+org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
+
+org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
+org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=target/last_event_time_file.txt
+#org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis=5000
+#org.highmed.dsf.bpe.fhir.task.subscription.maxRetries=-1
+
+org.highmed.dsf.bpe.db.driver=org.postgresql.Driver
+org.highmed.dsf.bpe.db.url=jdbc:postgresql://localhost/bpe
+org.highmed.dsf.bpe.db.liquibase_user=liquibase_user
+org.highmed.dsf.bpe.db.liquibase_user_password=fLp6ZSd5QrMAkGZMjxqXjmcWrTfa3Dn8fA57h92Y
+
+org.highmed.dsf.bpe.db.server_users_group=bpe_users
+org.highmed.dsf.bpe.db.server_user=bpe_server_user
+org.highmed.dsf.bpe.db.server_user_password=as2hm56BPcaJKtG25JEx
+
+org.highmed.dsf.bpe.db.camunda_users_group=camunda_users
+org.highmed.dsf.bpe.db.camunda_user=camunda_server_user
+org.highmed.dsf.bpe.db.camunda_user_password=arpJ2FgJuYvUJhbxeuh7
+
+org.highmed.dsf.bpe.openehr.webservice.baseUrl=http://localhost:8003/rest/openehr/v1
+org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
+org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
+org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
+org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
+
+#org.highmed.dsf.bpe.mpi.webservice.factory.class=org.highmed.mpi.client.pdq.MasterPatientIndexClientPdqFactory
+#org.highmed.dsf.bpe.mpi.pdq.webservice.host=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.port=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.path=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.password=
+#org.highmed.dsf.bpe.mpi.pdq.sender.application=
+#org.highmed.dsf.bpe.mpi.pdq.sender.facility=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.application=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.facility=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.namespaceId=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.universalId=
+
+org.highmed.dsf.bpe.cors.origins=
+
diff --git a/dsf-bpe/dsf-bpe-server-jetty/docker/.dockerignore b/dsf-bpe/dsf-bpe-server-jetty/docker/.dockerignore
index 5c60d5a7e..847795777 100755
--- a/dsf-bpe/dsf-bpe-server-jetty/docker/.dockerignore
+++ b/dsf-bpe/dsf-bpe-server-jetty/docker/.dockerignore
@@ -1,6 +1,7 @@
-.dockerignore
-Dockerfile
-conf/README.md
-last_event/README.md
-lib/.gitignore
+.dockerignore
+.gitignore
+Dockerfile
+conf/README.md
+last_event/README.md
+lib/.gitignore
log/README.md
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-server-jetty/docker/.gitignore b/dsf-bpe/dsf-bpe-server-jetty/docker/.gitignore
index 088235a8a..c295afe8d 100755
--- a/dsf-bpe/dsf-bpe-server-jetty/docker/.gitignore
+++ b/dsf-bpe/dsf-bpe-server-jetty/docker/.gitignore
@@ -1 +1,2 @@
/dsf_bpe.jar
+/plugin/mpi_client_stub.jar
diff --git a/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile b/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile
index c578fdaba..6f9c238f7 100755
--- a/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile
+++ b/dsf-bpe/dsf-bpe-server-jetty/docker/Dockerfile
@@ -1,12 +1,21 @@
+FROM debian:buster-slim AS builder
+RUN adduser --system --no-create-home --group --uid 2202 java
+WORKDIR /opt/bpe
+COPY --chown=root:java ./ ./
+RUN chown root:java ./ && \
+ chmod 750 ./ ./lib ./plugin ./dsf_bpe_start.sh && \
+ chmod 640 ./dsf_bpe.jar ./lib/*.jar && \
+ chmod 1775 ./log ./last_event
+
+
FROM openjdk:11-slim
-MAINTAINER Hauke Hund
+LABEL maintainer="hauke.hund@hs-heilbronn.de"
EXPOSE 8080
RUN adduser --system --no-create-home --group --uid 2202 java
WORKDIR /opt/bpe
-COPY --chown=root:java ./ ./
-RUN chown root:java ./ && chmod 750 ./ ./lib ./plugin ./dsf_bpe_start.sh && chmod 640 ./dsf_bpe.jar ./lib/*.jar && chmod 1775 ./log ./last_event
+COPY --from=builder /opt/bpe ./
USER java
ENTRYPOINT ["./dsf_bpe_start.sh"]
diff --git a/dsf-bpe/dsf-bpe-server-jetty/pom.xml b/dsf-bpe/dsf-bpe-server-jetty/pom.xml
index 3b2f54624..ddb1217d4 100755
--- a/dsf-bpe/dsf-bpe-server-jetty/pom.xml
+++ b/dsf-bpe/dsf-bpe-server-jetty/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
@@ -34,7 +34,6 @@
javax.mail
mail
- 1.4.7
diff --git a/dsf-bpe/dsf-bpe-server/pom.xml b/dsf-bpe/dsf-bpe-server/pom.xml
index aa65fc907..c95b43274 100755
--- a/dsf-bpe/dsf-bpe-server/pom.xml
+++ b/dsf-bpe/dsf-bpe-server/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
@@ -49,6 +49,14 @@
org.highmed.dsf
dsf-openehr-model
+
+ org.highmed.dsf
+ dsf-mpi-client
+
+
+ org.highmed.dsf
+ dsf-mpi-client-stub
+
org.highmed.dsf
dsf-tools-build-info-reader
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/listener/EndListener.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/listener/EndListener.java
index 00687b4d2..76e4b3676 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/listener/EndListener.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/listener/EndListener.java
@@ -54,7 +54,7 @@ public void notify(DelegateExecution execution) throws Exception
}
task.setStatus(Task.TaskStatus.COMPLETED);
- webserviceClient.update(task);
+ webserviceClient.withMinimalReturn().update(task);
}
else
{
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java
index d2e8cdab8..688357e6b 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java
@@ -10,43 +10,29 @@
import java.security.cert.CertificateException;
import org.camunda.bpm.engine.ProcessEngine;
-import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
import org.highmed.dsf.fhir.client.FhirClientProviderImpl;
import org.highmed.dsf.fhir.client.FhirWebsocketClientProvider;
import org.highmed.dsf.fhir.group.GroupHelper;
import org.highmed.dsf.fhir.group.GroupHelperImpl;
import org.highmed.dsf.fhir.organization.OrganizationProvider;
import org.highmed.dsf.fhir.organization.OrganizationProviderImpl;
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
+import org.highmed.dsf.fhir.service.ReferenceCleanerImpl;
import org.highmed.dsf.fhir.service.ReferenceExtractor;
import org.highmed.dsf.fhir.service.ReferenceExtractorImpl;
import org.highmed.dsf.fhir.task.TaskHandler;
import org.highmed.dsf.fhir.task.TaskHelper;
import org.highmed.dsf.fhir.task.TaskHelperImpl;
-import org.highmed.dsf.fhir.variables.FeasibilityQueryResultSerializer;
-import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsSerializer;
-import org.highmed.dsf.fhir.variables.FhirPlugin;
-import org.highmed.dsf.fhir.variables.FhirResourceJacksonDeserializer;
-import org.highmed.dsf.fhir.variables.FhirResourceJacksonSerializer;
-import org.highmed.dsf.fhir.variables.FhirResourceSerializer;
-import org.highmed.dsf.fhir.variables.FhirResourcesListSerializer;
-import org.highmed.dsf.fhir.variables.MultiInstanceTargetSerializer;
-import org.highmed.dsf.fhir.variables.MultiInstanceTargetsSerializer;
-import org.highmed.dsf.fhir.variables.OutputSerializer;
-import org.highmed.dsf.fhir.variables.OutputsSerializer;
import org.highmed.dsf.fhir.websocket.FhirConnector;
+import org.highmed.dsf.fhir.websocket.FhirConnectorImpl;
import org.highmed.dsf.fhir.websocket.LastEventTimeIo;
-import org.hl7.fhir.r4.model.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
-
-import com.fasterxml.jackson.annotation.JsonInclude.Include;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.MapperFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.context.event.EventListener;
import ca.uhn.fhir.context.FhirContext;
import de.rwh.utils.crypto.CertificateHelper;
@@ -103,31 +89,16 @@ public class FhirConfig
@Value("${org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile}")
private String lastEventTimeFile;
+ @Value("${org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis:5000}")
+ private long websocketRetrySleepMillis;
+
+ @Value("${org.highmed.dsf.bpe.fhir.task.subscription.maxRetries:-1}")
+ private int websocketMaxRetries;
+
@Autowired
@Lazy
private ProcessEngine processEngine;
- @Bean
- public ObjectMapper fhirObjectMapper()
- {
- ObjectMapper mapper = new ObjectMapper();
-
- mapper.getFactory().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
- mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
- mapper.setSerializationInclusion(Include.NON_NULL);
- mapper.setSerializationInclusion(Include.NON_EMPTY);
-
- // mapper.enable(SerializationFeature.INDENT_OUTPUT);
-
- SimpleModule module = new SimpleModule();
- module.addSerializer(Resource.class, new FhirResourceJacksonSerializer(fhirContext()));
- module.addDeserializer(Resource.class, new FhirResourceJacksonDeserializer(fhirContext()));
-
- mapper.registerModule(module);
-
- return mapper;
- }
-
@Bean
public FhirContext fhirContext()
{
@@ -135,65 +106,15 @@ public FhirContext fhirContext()
}
@Bean
- public ReferenceExtractor referenceExtractor()
- {
- return new ReferenceExtractorImpl();
- }
-
- @Bean
- public ProcessEnginePlugin fhirPlugin()
- {
- return new FhirPlugin(fhirResourceSerializer(), fhirResourcesListSerializer(), multiInstanceTargetSerializer(),
- multiInstanceTargetsSerializer(), feasibilityQueryResultSerializer(),
- feasibilityQueryResultsSerializer(), outputSerializer(), outputsSerializer());
- }
-
- @Bean
- public FhirResourceSerializer fhirResourceSerializer()
- {
- return new FhirResourceSerializer(fhirContext());
- }
-
- @Bean
- public FhirResourcesListSerializer fhirResourcesListSerializer()
+ public ReferenceCleaner referenceCleaner()
{
- return new FhirResourcesListSerializer(fhirObjectMapper());
+ return new ReferenceCleanerImpl(referenceExtractor());
}
@Bean
- public MultiInstanceTargetSerializer multiInstanceTargetSerializer()
- {
- return new MultiInstanceTargetSerializer(fhirObjectMapper());
- }
-
- @Bean
- public MultiInstanceTargetsSerializer multiInstanceTargetsSerializer()
- {
- return new MultiInstanceTargetsSerializer(fhirObjectMapper());
- }
-
- @Bean
- public OutputSerializer outputSerializer()
- {
- return new OutputSerializer(fhirObjectMapper());
- }
-
- @Bean
- public OutputsSerializer outputsSerializer()
- {
- return new OutputsSerializer(fhirObjectMapper());
- }
-
- @Bean
- public FeasibilityQueryResultSerializer feasibilityQueryResultSerializer()
- {
- return new FeasibilityQueryResultSerializer(fhirObjectMapper());
- }
-
- @Bean
- public FeasibilityQueryResultsSerializer feasibilityQueryResultsSerializer()
+ public ReferenceExtractor referenceExtractor()
{
- return new FeasibilityQueryResultsSerializer(fhirObjectMapper());
+ return new ReferenceExtractorImpl();
}
@Bean
@@ -233,7 +154,7 @@ public FhirWebsocketClientProvider clientProvider()
localWebsocketKeyStorePassword);
KeyStore localWebsocketTrustStore = CertificateHelper.extractTrust(localWebsocketKeyStore);
- return new FhirClientProviderImpl(fhirContext(), referenceExtractor(), localWebserviceBaseUrl,
+ return new FhirClientProviderImpl(fhirContext(), referenceCleaner(), localWebserviceBaseUrl,
localReadTimeout, localConnectTimeout, localWebserviceTrustStore, localWebserviceKeyStore,
webserviceKeyStorePassword, remoteReadTimeout, remoteConnectTimeout, remoteProxyPassword,
remoteProxyUsername, remoteProxySchemeHostPort, localWebsocketUrl, localWebsocketTrustStore,
@@ -254,8 +175,14 @@ public OrganizationProvider organizationProvider()
@Bean
public FhirConnector fhirConnector()
{
- return new FhirConnector(clientProvider(), taskHandler(), lastEventTimeIo(), fhirContext(),
- subscriptionSearchParameter);
+ return new FhirConnectorImpl(clientProvider(), taskHandler(), lastEventTimeIo(), fhirContext(),
+ subscriptionSearchParameter, websocketRetrySleepMillis, websocketMaxRetries);
+ }
+
+ @EventListener({ ContextRefreshedEvent.class })
+ public void onContextRefreshedEvent(ContextRefreshedEvent event)
+ {
+ fhirConnector().connect();
}
@Bean
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/MasterPatientIndexConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/MasterPatientIndexConfig.java
new file mode 100644
index 000000000..bbe402089
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/MasterPatientIndexConfig.java
@@ -0,0 +1,43 @@
+package org.highmed.dsf.bpe.spring.config;
+
+import java.util.NoSuchElementException;
+
+import org.highmed.mpi.client.MasterPatientIndexClientFactory;
+import org.highmed.mpi.client.MasterPatientIndexClientServiceLoader;
+import org.highmed.mpi.client.stub.MasterPatientIndexClientStubFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MasterPatientIndexConfig
+{
+ private static final Logger logger = LoggerFactory.getLogger(MasterPatientIndexConfig.class);
+
+ @Value("${org.highmed.dsf.bpe.mpi.webservice.factory.class:org.highmed.mpi.client.stub.MasterPatientIndexClientStubFactory}")
+ private String masterPatientIndexClientFactoryClass;
+
+ @Bean
+ public MasterPatientIndexClientServiceLoader masterPatientIndexClientServiceLoader()
+ {
+ return new MasterPatientIndexClientServiceLoader();
+ }
+
+ @Bean
+ public MasterPatientIndexClientFactory masterPatientIndexClientFactory()
+ {
+ MasterPatientIndexClientFactory factory = masterPatientIndexClientServiceLoader()
+ .getMasterPatientIndexClientFactory(masterPatientIndexClientFactoryClass)
+ .orElseThrow(() -> new NoSuchElementException("Master patient index client factory with classname='"
+ + masterPatientIndexClientFactoryClass + "' not found"));
+
+ if(factory instanceof MasterPatientIndexClientStubFactory)
+ logger.warn("Using {} as MPI client factory", factory.getClass().getName());
+ else
+ logger.info("Using {} as MPI client factory", factory.getClass().getName());
+
+ return factory;
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/OpenEhrConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/OpenEhrConfig.java
index 63a734ff5..b2bb2e3c5 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/OpenEhrConfig.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/OpenEhrConfig.java
@@ -2,18 +2,12 @@
import org.highmed.dsf.openehr.client.OpenEhrClientProviderImpl;
import org.highmed.dsf.openehr.client.OpenEhrWebserviceClientProvider;
-
-import org.highmed.openehr.deserializer.RowElementDeserializer;
-import org.highmed.openehr.model.structure.RowElement;
+import org.highmed.openehr.json.OpenEhrObjectMapperFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.module.SimpleModule;
@Configuration
public class OpenEhrConfig
@@ -36,25 +30,7 @@ public class OpenEhrConfig
@Bean
public ObjectMapper openEhrObjectMapper()
{
- ObjectMapper mapper = new ObjectMapper();
-
- mapper.getFactory().disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
- mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
- mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
- mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
-
- SimpleModule module = new SimpleModule();
- module.addDeserializer(RowElement.class, rowElementDeserializer());
-
- mapper.registerModule(module);
-
- return mapper;
- }
-
- @Bean
- public RowElementDeserializer rowElementDeserializer()
- {
- return new RowElementDeserializer();
+ return OpenEhrObjectMapperFactory.createObjectMapper();
}
@Bean
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/SerializerConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/SerializerConfig.java
new file mode 100644
index 000000000..8c0fa5d1f
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/SerializerConfig.java
@@ -0,0 +1,129 @@
+package org.highmed.dsf.bpe.spring.config;
+
+import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin;
+import org.highmed.dsf.fhir.variables.BloomFilterConfigSerializer;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultSerializer;
+import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsSerializer;
+import org.highmed.dsf.fhir.variables.FhirResourceJacksonDeserializer;
+import org.highmed.dsf.fhir.variables.FhirResourceJacksonSerializer;
+import org.highmed.dsf.fhir.variables.FhirResourceSerializer;
+import org.highmed.dsf.fhir.variables.FhirResourcesListSerializer;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResultSerializer;
+import org.highmed.dsf.fhir.variables.FinalFeasibilityQueryResultsSerializer;
+import org.highmed.dsf.fhir.variables.MultiInstanceTargetSerializer;
+import org.highmed.dsf.fhir.variables.MultiInstanceTargetsSerializer;
+import org.highmed.dsf.fhir.variables.OutputSerializer;
+import org.highmed.dsf.fhir.variables.OutputsSerializer;
+import org.highmed.dsf.fhir.variables.SerializerPlugin;
+import org.highmed.openehr.json.OpenEhrObjectMapperFactory;
+import org.hl7.fhir.r4.model.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+
+import ca.uhn.fhir.context.FhirContext;
+
+@Configuration
+public class SerializerConfig
+{
+ @Autowired
+ private FhirContext fhirContext;
+
+ @Bean
+ public ObjectMapper objectMapper()
+ {
+ ObjectMapper mapper = new ObjectMapper();
+
+ mapper.setSerializationInclusion(Include.NON_NULL);
+ mapper.setSerializationInclusion(Include.NON_EMPTY);
+
+ SimpleModule module = new SimpleModule();
+ module.addSerializer(Resource.class, new FhirResourceJacksonSerializer(fhirContext));
+ module.addDeserializer(Resource.class, new FhirResourceJacksonDeserializer(fhirContext));
+
+ mapper.registerModule(module);
+ mapper.registerModule(OpenEhrObjectMapperFactory.openEhrModule());
+
+ return mapper;
+ }
+
+ @Bean
+ public FhirResourceSerializer fhirResourceSerializer()
+ {
+ return new FhirResourceSerializer(fhirContext);
+ }
+
+ @Bean
+ public FhirResourcesListSerializer fhirResourcesListSerializer()
+ {
+ return new FhirResourcesListSerializer(objectMapper());
+ }
+
+ @Bean
+ public MultiInstanceTargetSerializer multiInstanceTargetSerializer()
+ {
+ return new MultiInstanceTargetSerializer(objectMapper());
+ }
+
+ @Bean
+ public MultiInstanceTargetsSerializer multiInstanceTargetsSerializer()
+ {
+ return new MultiInstanceTargetsSerializer(objectMapper());
+ }
+
+ @Bean
+ public OutputSerializer outputSerializer()
+ {
+ return new OutputSerializer(objectMapper());
+ }
+
+ @Bean
+ public OutputsSerializer outputsSerializer()
+ {
+ return new OutputsSerializer(objectMapper());
+ }
+
+ @Bean
+ public FeasibilityQueryResultSerializer feasibilityQueryResultSerializer()
+ {
+ return new FeasibilityQueryResultSerializer(objectMapper());
+ }
+
+ @Bean
+ public FeasibilityQueryResultsSerializer feasibilityQueryResultsSerializer()
+ {
+ return new FeasibilityQueryResultsSerializer(objectMapper());
+ }
+
+ @Bean
+ public FinalFeasibilityQueryResultSerializer finalFeasibilityQueryResultSerializer()
+ {
+ return new FinalFeasibilityQueryResultSerializer(objectMapper());
+ }
+
+ @Bean
+ public FinalFeasibilityQueryResultsSerializer finalFeasibilityQueryResultsSerializer()
+ {
+ return new FinalFeasibilityQueryResultsSerializer(objectMapper());
+ }
+
+ @Bean
+ public BloomFilterConfigSerializer bloomFilterConfigSerializer()
+ {
+ return new BloomFilterConfigSerializer(objectMapper());
+ }
+
+ @Bean
+ public ProcessEnginePlugin serializerPlugin()
+ {
+ return new SerializerPlugin(fhirResourceSerializer(), fhirResourcesListSerializer(),
+ multiInstanceTargetSerializer(), multiInstanceTargetsSerializer(), feasibilityQueryResultSerializer(),
+ feasibilityQueryResultsSerializer(), finalFeasibilityQueryResultSerializer(),
+ finalFeasibilityQueryResultsSerializer(), bloomFilterConfigSerializer(), outputSerializer(),
+ outputsSerializer());
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java
index 8552722db..f201270de 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java
@@ -8,7 +8,7 @@
import java.util.Objects;
import java.util.stream.Collectors;
-import org.highmed.dsf.fhir.service.ReferenceExtractor;
+import org.highmed.dsf.fhir.service.ReferenceCleaner;
import org.highmed.fhir.client.FhirWebserviceClient;
import org.highmed.fhir.client.FhirWebserviceClientJersey;
import org.highmed.fhir.client.WebsocketClient;
@@ -32,7 +32,7 @@ public class FhirClientProviderImpl
private final Map websocketClientsBySubscriptionId = new HashMap<>();
private final FhirContext fhirContext;
- private final ReferenceExtractor referenceExtractor;
+ private final ReferenceCleaner referenceCleaner;
private final String localBaseUrl;
private final int localReadTimeout;
@@ -53,7 +53,7 @@ public class FhirClientProviderImpl
private final KeyStore localWebsocketKeyStore;
private final char[] localWebsocketKeyStorePassword;
- public FhirClientProviderImpl(FhirContext fhirContext, ReferenceExtractor referenceExtractor, String localBaseUrl,
+ public FhirClientProviderImpl(FhirContext fhirContext, ReferenceCleaner referenceCleaner, String localBaseUrl,
int localReadTimeout, int localConnectTimeout, KeyStore webserviceTrustStore, KeyStore webserviceKeyStore,
char[] webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout,
char[] remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort,
@@ -61,7 +61,7 @@ public FhirClientProviderImpl(FhirContext fhirContext, ReferenceExtractor refere
char[] localWebsocketKeyStorePassword)
{
this.fhirContext = fhirContext;
- this.referenceExtractor = referenceExtractor;
+ this.referenceCleaner = referenceCleaner;
this.localBaseUrl = localBaseUrl;
this.localReadTimeout = localReadTimeout;
this.localConnectTimeout = localConnectTimeout;
@@ -124,12 +124,12 @@ private FhirWebserviceClient getClient(String webserviceUrl)
if (localBaseUrl.equals(webserviceUrl))
client = new FhirWebserviceClientJersey(webserviceUrl, webserviceTrustStore, webserviceKeyStore,
webserviceKeyStorePassword, null, null, null, localConnectTimeout, localReadTimeout, null,
- fhirContext, referenceExtractor);
+ fhirContext, referenceCleaner);
else
client = new FhirWebserviceClientJersey(webserviceUrl, webserviceTrustStore, webserviceKeyStore,
webserviceKeyStorePassword, remoteProxySchemeHostPort, remoteProxyUsername,
remoteProxyPassword, remoteConnectTimeout, remoteReadTimeout, null, fhirContext,
- referenceExtractor);
+ referenceCleaner);
webserviceClientsByUrl.put(webserviceUrl, client);
return client;
@@ -172,7 +172,7 @@ public FhirWebserviceClient getRemoteWebserviceClient(IdType organizationReferen
private Endpoint searchForEndpoint(String searchParameter, String searchParameterValue)
{
- Bundle resultSet = getLocalWebserviceClient().search(Organization.class,
+ Bundle resultSet = getLocalWebserviceClient().searchWithStrictHandling(Organization.class,
Map.of(searchParameter, Collections.singletonList(searchParameterValue), "_include",
Collections.singletonList("Organization:endpoint")));
@@ -210,12 +210,11 @@ public FhirWebserviceClient getRemoteWebserviceClient(String organizationIdentif
}
@Override
- public WebsocketClient getLocalWebsocketClient(String subscriptionId)
+ public WebsocketClient getLocalWebsocketClient(Runnable reconnector, String subscriptionId)
{
if (!websocketClientsBySubscriptionId.containsKey(subscriptionId))
{
- WebsocketClientTyrus client = new WebsocketClientTyrus(URI.create(localWebsocketUrl),
- localWebsocketTrustStore, localWebsocketKeyStore, localWebsocketKeyStorePassword, subscriptionId);
+ WebsocketClientTyrus client = createWebsocketClient(reconnector, subscriptionId);
websocketClientsBySubscriptionId.put(subscriptionId, client);
return client;
@@ -224,6 +223,12 @@ public WebsocketClient getLocalWebsocketClient(String subscriptionId)
return websocketClientsBySubscriptionId.get(subscriptionId);
}
+ protected WebsocketClientTyrus createWebsocketClient(Runnable reconnector, String subscriptionId)
+ {
+ return new WebsocketClientTyrus(reconnector, URI.create(localWebsocketUrl), localWebsocketTrustStore,
+ localWebsocketKeyStore, localWebsocketKeyStorePassword, subscriptionId);
+ }
+
@Override
public void disconnectAll()
{
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirWebsocketClientProvider.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirWebsocketClientProvider.java
index 09793ee58..db733c528 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirWebsocketClientProvider.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirWebsocketClientProvider.java
@@ -4,7 +4,7 @@
public interface FhirWebsocketClientProvider extends FhirWebserviceClientProvider
{
- WebsocketClient getLocalWebsocketClient(String subscriptionId);
+ WebsocketClient getLocalWebsocketClient(Runnable reconnector, String subscriptionId);
void disconnectAll();
}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/organization/OrganizationProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/organization/OrganizationProviderImpl.java
index 2d2ad2582..fef4262f4 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/organization/OrganizationProviderImpl.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/organization/OrganizationProviderImpl.java
@@ -75,7 +75,7 @@ private Stream searchForOrganizations(String system, String identi
private Stream searchForOrganizations(String identifierValue)
{
- Bundle resultSet = clientProvider.getLocalWebserviceClient().search(Organization.class,
+ Bundle resultSet = clientProvider.getLocalWebserviceClient().searchWithStrictHandling(Organization.class,
Map.of("active", Collections.singletonList("true"), "identifier",
Collections.singletonList(identifierValue)));
@@ -112,7 +112,7 @@ public List getRemoteOrganizations()
@Override
public Stream getOrganizationsByType(String type)
{
- Bundle resultSet = clientProvider.getLocalWebserviceClient().search(Organization.class,
+ Bundle resultSet = clientProvider.getLocalWebserviceClient().searchWithStrictHandling(Organization.class,
Map.of("active", Collections.singletonList("true"), "type",
Collections.singletonList(getDefaultTypeSystem() + "|" + type)));
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHelperImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHelperImpl.java
index ec6079fa7..e9694d6aa 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHelperImpl.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHelperImpl.java
@@ -4,14 +4,19 @@
import java.util.stream.Stream;
import org.highmed.dsf.fhir.variables.Outputs;
+import org.hl7.fhir.r4.model.Base64BinaryType;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Extension;
+import org.hl7.fhir.r4.model.IntegerType;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.Task.ParameterComponent;
+import org.hl7.fhir.r4.model.Task.TaskOutputComponent;
import org.hl7.fhir.r4.model.Type;
+import org.hl7.fhir.r4.model.UnsignedIntType;
import org.hl7.fhir.r4.model.UrlType;
public class TaskHelperImpl implements TaskHelper
@@ -64,6 +69,22 @@ public Stream getInputParameterUrlValues(Task task, String system, Stri
return getInputParameterValues(task, system, code, UrlType.class);
}
+ @Override
+ public Optional getFirstInputParameterByteValue(Task task, String system, String code)
+ {
+ return getInputParameterValues(task, system, code, Base64BinaryType.class).map(Base64BinaryType::getValue)
+ .findFirst();
+ }
+
+ @Override
+ public Stream getInputParameterWithExtension(Task task, String system, String code, String url)
+ {
+ return task.getInput().stream()
+ .filter(input -> input.getType().getCoding().stream()
+ .anyMatch(coding -> coding.getSystem().equals(system) && coding.getCode().equals(code)))
+ .filter(input -> input.getExtension().stream().anyMatch(extension -> extension.getUrl().equals(url)));
+ }
+
private Stream getInputParameterValues(Task task, String system, String code, Class type)
{
return task.getInput().stream().filter(c -> type.isInstance(c.getValue()))
@@ -73,43 +94,59 @@ private Stream getInputParameterValues(Task task, String sys
}
@Override
- public Stream getInputParameterWithExtension(Task task, String system, String code,
- String url)
+ public ParameterComponent createInput(String system, String code, String value)
{
- return task.getInput().stream().filter(input -> input.getType().getCoding().stream()
- .anyMatch(coding -> coding.getSystem().equals(system) && coding.getCode().equals(code)))
- .filter(input -> input.getExtension().stream().anyMatch(extension -> extension.getUrl().equals(url)));
+ return new ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new StringType(value));
+ }
+
+ @Override
+ public ParameterComponent createInput(String system, String code, boolean value)
+ {
+ return new ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new BooleanType(value));
+ }
+
+ @Override
+ public ParameterComponent createInput(String system, String code, Reference reference)
+ {
+ return new ParameterComponent(new CodeableConcept(new Coding(system, code, null)), reference);
+ }
+
+ @Override
+ public ParameterComponent createInput(String system, String code, byte[] bytes)
+ {
+ return new ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new Base64BinaryType(bytes));
}
@Override
- public Task.ParameterComponent createInput(String system, String code, String value)
+ public ParameterComponent createInputUnsignedInt(String system, String code, int value)
{
- return new Task.ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new StringType(value));
+ return new ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new UnsignedIntType(value));
}
@Override
- public Task.ParameterComponent createInput(String system, String code, boolean value)
+ public ParameterComponent createInput(String system, String code, int value)
{
- return new Task.ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new BooleanType(value));
+ return new ParameterComponent(new CodeableConcept(new Coding(system, code, null)), new IntegerType(value));
}
@Override
- public Task.ParameterComponent createInput(String system, String code, Reference reference)
+ public TaskOutputComponent createOutput(String system, String code, String value)
{
- return new Task.ParameterComponent(new CodeableConcept(new Coding(system, code, null)), reference);
+ return new TaskOutputComponent(new CodeableConcept(new Coding(system, code, null)), new StringType(value));
}
@Override
- public Task.TaskOutputComponent createOutput(String system, String code, String value)
+ public TaskOutputComponent createOutputUnsignedInt(String system, String code, int value)
{
- return new Task.TaskOutputComponent(new CodeableConcept(new Coding(system, code, null)), new StringType(value));
+ return new TaskOutputComponent(new CodeableConcept(new Coding(system, code, null)), new UnsignedIntType(value));
}
@Override
public Task addOutputs(Task task, Outputs outputs)
{
- outputs.getOutputs().forEach(output -> {
- Task.TaskOutputComponent component = createOutput(output.getSystem(), output.getCode(), output.getValue());
+ outputs.getOutputs().forEach(output ->
+ {
+ TaskOutputComponent component = createOutput(output.getSystem(), output.getCode(), output.getValue());
if (output.hasExtension())
component.addExtension(
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ExistingTaskLoader.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ExistingTaskLoader.java
new file mode 100644
index 000000000..2a5b5eb70
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ExistingTaskLoader.java
@@ -0,0 +1,88 @@
+package org.highmed.dsf.fhir.websocket;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import javax.ws.rs.core.UriBuilder;
+
+import org.highmed.dsf.fhir.task.TaskHandler;
+import org.highmed.fhir.client.FhirWebserviceClient;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
+import org.hl7.fhir.r4.model.Task;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ExistingTaskLoader
+{
+ private static final Logger logger = LoggerFactory.getLogger(ExistingTaskLoader.class);
+
+ private static final String PARAM_LAST_UPDATED = "_lastUpdated";
+ private static final String PARAM_COUNT = "_count";
+ private static final String PARAM_PAGE = "_page";
+ private static final String PARAM_SORT = "_sort";
+ private static final int RESULT_PAGE_COUNT = 20;
+
+ private final LastEventTimeIo lastEventTimeIo;
+ private final FhirWebserviceClient webserviceClient;
+ private final TaskHandler taskHandler;
+
+ public ExistingTaskLoader(LastEventTimeIo lastEventTimeIo, TaskHandler taskHandler,
+ FhirWebserviceClient webserviceClient)
+ {
+ this.lastEventTimeIo = lastEventTimeIo;
+ this.taskHandler = taskHandler;
+ this.webserviceClient = webserviceClient;
+ }
+
+ public void readExistingTasks(Map> searchCriteriaQueryParameters)
+ {
+ // executing search until call results in no more found tasks
+ while (doReadExistingTasks(searchCriteriaQueryParameters))
+ ;
+ }
+
+ private boolean doReadExistingTasks(Map> searchCriteriaQueryParameters)
+ {
+ Map> queryParams = new HashMap<>(searchCriteriaQueryParameters);
+ Optional readLastEventTime = lastEventTimeIo.readLastEventTime();
+
+ readLastEventTime.ifPresent(lastEventTime -> queryParams.put(PARAM_LAST_UPDATED,
+ Collections.singletonList("gt" + lastEventTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME))));
+
+ queryParams.put(PARAM_COUNT, Collections.singletonList(String.valueOf(RESULT_PAGE_COUNT)));
+ queryParams.put(PARAM_PAGE, Collections.singletonList("1"));
+ queryParams.put(PARAM_SORT, Collections.singletonList(PARAM_LAST_UPDATED));
+
+ UriBuilder builder = UriBuilder.fromPath("Task");
+ queryParams.forEach((k, v) -> builder.replaceQueryParam(k, v.toArray()));
+
+ logger.debug("Executing search {}", builder.toString());
+ Bundle bundle = webserviceClient.searchWithStrictHandling(Task.class, queryParams);
+
+ if (bundle.getTotal() <= 0)
+ {
+ logger.debug("Result bundle.total <= 0");
+ return false;
+ }
+
+ for (BundleEntryComponent entry : bundle.getEntry())
+ {
+ if (entry.getResource() instanceof Task)
+ {
+ Task task = (Task) entry.getResource();
+ taskHandler.onTask(task);
+ lastEventTimeIo.writeLastEventTime(task.getAuthoredOn());
+ }
+ else
+ logger.warn("Ignoring resource of type {}");
+ }
+
+ return true;
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java
old mode 100755
new mode 100644
index 4c9e74bb4..0d2d6378e
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java
@@ -1,189 +1,6 @@
package org.highmed.dsf.fhir.websocket;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.function.Supplier;
-
-import org.highmed.dsf.fhir.client.FhirWebsocketClientProvider;
-import org.highmed.dsf.fhir.task.TaskHandler;
-import org.highmed.fhir.client.WebsocketClient;
-import org.hl7.fhir.r4.model.Bundle;
-import org.hl7.fhir.r4.model.Bundle.BundleType;
-import org.hl7.fhir.r4.model.Subscription;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.event.ContextClosedEvent;
-import org.springframework.context.event.ContextRefreshedEvent;
-import org.springframework.context.event.EventListener;
-import org.springframework.web.util.UriComponents;
-import org.springframework.web.util.UriComponentsBuilder;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.parser.IParser;
-import ca.uhn.fhir.rest.api.Constants;
-
-public class FhirConnector implements InitializingBean
+public interface FhirConnector
{
- private static final Logger logger = LoggerFactory.getLogger(FhirConnector.class);
-
- private final FhirWebsocketClientProvider clientProvider;
- private final TaskHandler taskHandler;
- private final LastEventTimeIo lastEventTimeIo;
- private final FhirContext fhirContext;
-
- private final Map> subscriptionSearchParameter;
-
- public FhirConnector(FhirWebsocketClientProvider clientProvider, TaskHandler taskHandler,
- LastEventTimeIo lastEventTimeIo, FhirContext fhirContext, String subscriptionSearchParameter)
- {
- this.clientProvider = clientProvider;
- this.taskHandler = taskHandler;
- this.lastEventTimeIo = lastEventTimeIo;
- this.fhirContext = fhirContext;
- this.subscriptionSearchParameter = parse(subscriptionSearchParameter, null);
- }
-
- private static Map> parse(String queryParameters, String expectedPath)
- {
- if (expectedPath != null && !expectedPath.isBlank())
- {
- UriComponents components = UriComponentsBuilder.fromUriString(queryParameters).build();
- if (!expectedPath.equals(components.getPath()))
- throw new RuntimeException("Unexpected query parameters format '" + queryParameters + "'");
- else
- return components.getQueryParams();
- }
- else
- {
- UriComponents componentes = UriComponentsBuilder
- .fromUriString(queryParameters.startsWith("?") ? queryParameters : "?" + queryParameters).build();
-
- return componentes.getQueryParams();
- }
- }
-
- @Override
- public void afterPropertiesSet() throws Exception
- {
- Objects.requireNonNull(clientProvider, "clientProvider");
- Objects.requireNonNull(taskHandler, "taskHandler");
- Objects.requireNonNull(lastEventTimeIo, "lastEventTimeIo");
- Objects.requireNonNull(fhirContext, "fhirContext");
- }
-
- @EventListener({ ContextRefreshedEvent.class })
- public void onContextRefreshedEvent(ContextRefreshedEvent event)
- {
- Subscription subscription = retrieveWebsocketSubscription();
-
- WebsocketClient client = clientProvider.getLocalWebsocketClient(subscription.getIdElement().getIdPart());
-
- EventType eventType = toEventType(subscription.getChannel().getPayload());
- if (EventType.PING.equals(eventType))
- {
- Map> subscriptionCriteria = parse(subscription.getCriteria(), "Task");
- setPingEventHandler(client, subscription.getIdElement().getIdPart(), subscriptionCriteria);
- }
- else
- setResourceEventHandler(client, eventType);
-
- try
- {
- logger.info("Connecting websocket to loal FHIR server with subscription id {} ...",
- subscription.getIdElement().getIdPart());
- client.connect();
- }
- catch (Exception e)
- {
- logger.warn("Error while connecting websocket to local FHIR server", e);
- throw e;
- }
- }
-
- private Subscription retrieveWebsocketSubscription()
- {
- try
- {
- Bundle bundle = clientProvider.getLocalWebserviceClient().search(Subscription.class,
- subscriptionSearchParameter);
-
- if (!BundleType.SEARCHSET.equals(bundle.getType()))
- throw new RuntimeException("Could not retrieve searchset for subscription search query "
- + subscriptionSearchParameter + ", but got " + bundle.getType());
- if (bundle.getTotal() != 1)
- throw new RuntimeException("Could not retrieve exactly one result for subscription search query "
- + subscriptionSearchParameter);
- if (!(bundle.getEntryFirstRep().getResource() instanceof Subscription))
- throw new RuntimeException("Could not retrieve exactly one Subscription for subscription search query "
- + subscriptionSearchParameter + ", but got "
- + bundle.getEntryFirstRep().getResource().getResourceType());
-
- return (Subscription) bundle.getEntryFirstRep().getResource();
- }
- catch (Exception e)
- {
- logger.warn("Error while retrieving websocket subscription from local FHIR server", e);
- throw e;
- }
- }
-
- private EventType toEventType(String payload)
- {
- if (payload == null)
- return EventType.PING;
-
- switch (payload)
- {
- case Constants.CT_FHIR_JSON:
- case Constants.CT_FHIR_JSON_NEW:
- return EventType.JSON;
- case Constants.CT_FHIR_XML:
- case Constants.CT_FHIR_XML_NEW:
- return EventType.XML;
- default:
- throw new RuntimeException("Unsupportet subscription.payload " + payload);
- }
- }
-
- @EventListener({ ContextClosedEvent.class })
- public void onContextClosedEvent(ContextClosedEvent event)
- {
- clientProvider.disconnectAll();
- }
-
- private void setPingEventHandler(WebsocketClient client, String subscriptionIdPart,
- Map> searchCriteriaQueryParameters)
- {
- PingEventHandler handler = new PingEventHandler(lastEventTimeIo, taskHandler,
- clientProvider.getLocalWebserviceClient());
- client.setPingHandler(ping -> handler.onPing(ping, subscriptionIdPart, searchCriteriaQueryParameters));
- }
-
- private void setResourceEventHandler(WebsocketClient client, EventType eventType)
- {
- ResourceEventHandler handler = new ResourceEventHandler(taskHandler);
- client.setDomainResourceHandler(handler::onResource, createParserFactory(eventType, fhirContext));
- }
-
- private Supplier createParserFactory(EventType eventType, FhirContext fhirContext)
- {
- switch (eventType)
- {
- case XML:
- return () -> configureParser(fhirContext.newXmlParser());
- case JSON:
- return () -> configureParser(fhirContext.newJsonParser());
- default:
- throw new RuntimeException("EventType " + eventType + " not supported");
- }
- }
-
- private IParser configureParser(IParser p)
- {
- p.setStripVersionsFromReferences(false);
- p.setOverrideResourceIdWithBundleEntryFullUrl(false);
- return p;
- }
-}
+ void connect();
+}
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnectorImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnectorImpl.java
new file mode 100755
index 000000000..f892ef168
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnectorImpl.java
@@ -0,0 +1,285 @@
+package org.highmed.dsf.fhir.websocket;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executors;
+import java.util.function.Supplier;
+
+import org.highmed.dsf.fhir.client.FhirWebsocketClientProvider;
+import org.highmed.dsf.fhir.task.TaskHandler;
+import org.highmed.fhir.client.FhirWebserviceClient;
+import org.highmed.fhir.client.WebsocketClient;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Bundle.BundleType;
+import org.hl7.fhir.r4.model.Subscription;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.web.util.UriComponents;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.parser.IParser;
+import ca.uhn.fhir.rest.api.Constants;
+
+public class FhirConnectorImpl implements InitializingBean, FhirConnector
+{
+ private static final Logger logger = LoggerFactory.getLogger(FhirConnectorImpl.class);
+
+ private final FhirWebsocketClientProvider clientProvider;
+ private final TaskHandler taskHandler;
+ private final LastEventTimeIo lastEventTimeIo;
+ private final FhirContext fhirContext;
+
+ private final long retrySleepMillis;
+ private final int maxRetries;
+ private final Map> subscriptionSearchParameter;
+
+ public FhirConnectorImpl(FhirWebsocketClientProvider clientProvider, TaskHandler taskHandler,
+ LastEventTimeIo lastEventTimeIo, FhirContext fhirContext, String subscriptionSearchParameter,
+ long retrySleepMillis, int maxRetries)
+ {
+ this.clientProvider = clientProvider;
+ this.taskHandler = taskHandler;
+ this.lastEventTimeIo = lastEventTimeIo;
+ this.fhirContext = fhirContext;
+ this.subscriptionSearchParameter = parse(subscriptionSearchParameter, null);
+ this.retrySleepMillis = retrySleepMillis;
+ this.maxRetries = maxRetries;
+ }
+
+ private static Map> parse(String queryParameters, String expectedPath)
+ {
+ if (expectedPath != null && !expectedPath.isBlank())
+ {
+ UriComponents components = UriComponentsBuilder.fromUriString(queryParameters).build();
+ if (!expectedPath.equals(components.getPath()))
+ throw new RuntimeException("Unexpected query parameters format '" + queryParameters + "'");
+ else
+ return components.getQueryParams();
+ }
+ else
+ {
+ UriComponents componentes = UriComponentsBuilder
+ .fromUriString(queryParameters.startsWith("?") ? queryParameters : "?" + queryParameters).build();
+
+ return componentes.getQueryParams();
+ }
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception
+ {
+ Objects.requireNonNull(clientProvider, "clientProvider");
+ Objects.requireNonNull(taskHandler, "taskHandler");
+ Objects.requireNonNull(lastEventTimeIo, "lastEventTimeIo");
+ Objects.requireNonNull(fhirContext, "fhirContext");
+ }
+
+ @Override
+ public void connect()
+ {
+ logger.debug("Retrieving Subscription and connecting to websocket");
+
+ CompletableFuture.supplyAsync(this::retrieveWebsocketSubscription, Executors.newSingleThreadExecutor())
+ .thenApply(this::loadExistingTasks).thenAccept(this::connectWebsocket).exceptionally(this::onError);
+ }
+
+ private Subscription retrieveWebsocketSubscription()
+ {
+ if (maxRetries >= 0)
+ return retry(() -> doRetrieveWebsocketSubscription());
+ else
+ return retryForever(() -> doRetrieveWebsocketSubscription());
+ }
+
+ private Subscription retry(Supplier supplier)
+ {
+ RuntimeException lastException = null;
+ for (int retryCounter = 0; retryCounter <= maxRetries; retryCounter++)
+ {
+ try
+ {
+ return supplier.get();
+ }
+ catch (RuntimeException e)
+ {
+ if (retryCounter < maxRetries)
+ {
+ logger.warn(
+ "Error while retrieving websocket subscription ({}), trying again in {} ms (retry {} of {})",
+ e.getMessage(), retrySleepMillis, retryCounter + 1, maxRetries);
+ try
+ {
+ Thread.sleep(retrySleepMillis);
+ }
+ catch (InterruptedException e1)
+ {
+ }
+ }
+
+ lastException = e;
+ }
+ }
+
+ logger.error("Error while retrieving websocket subscription ({}), giving up", lastException.getMessage());
+ throw lastException;
+ }
+
+ private Subscription retryForever(Supplier supplier)
+ {
+ for (int retryCounter = 1; true; retryCounter++)
+ {
+ try
+ {
+ return supplier.get();
+ }
+ catch (RuntimeException e)
+ {
+ logger.warn("Error while retrieving websocket subscription ({}), trying again in {} ms (retry {})",
+ e.getMessage(), retrySleepMillis, retryCounter);
+ try
+ {
+ Thread.sleep(retrySleepMillis);
+ }
+ catch (InterruptedException e1)
+ {
+ }
+ }
+ }
+ }
+
+ private Subscription doRetrieveWebsocketSubscription()
+ {
+ logger.debug("Retrieving websocket subscription");
+
+ Bundle bundle = clientProvider.getLocalWebserviceClient().searchWithStrictHandling(Subscription.class,
+ subscriptionSearchParameter);
+
+ if (!BundleType.SEARCHSET.equals(bundle.getType()))
+ throw new RuntimeException("Could not retrieve searchset for subscription search query "
+ + subscriptionSearchParameter + ", but got " + bundle.getType());
+ if (bundle.getTotal() != 1)
+ throw new RuntimeException("Could not retrieve exactly one result for subscription search query "
+ + subscriptionSearchParameter);
+ if (!(bundle.getEntryFirstRep().getResource() instanceof Subscription))
+ throw new RuntimeException("Could not retrieve exactly one Subscription for subscription search query "
+ + subscriptionSearchParameter + ", but got "
+ + bundle.getEntryFirstRep().getResource().getResourceType());
+
+ Subscription subscription = (Subscription) bundle.getEntryFirstRep().getResource();
+ logger.debug("Subscription with id {} found", subscription.getIdElement().getIdPart());
+
+ return subscription;
+ }
+
+ private Subscription loadExistingTasks(Subscription subscription)
+ {
+ logger.debug("Downloading existing Task resources");
+
+ FhirWebserviceClient webserviceClient = clientProvider.getLocalWebserviceClient();
+ ExistingTaskLoader existingTaskLoader = new ExistingTaskLoader(lastEventTimeIo, taskHandler, webserviceClient);
+ Map> subscriptionCriteria = parse(subscription.getCriteria(), "Task");
+ existingTaskLoader.readExistingTasks(subscriptionCriteria);
+
+ return subscription;
+ }
+
+ private void connectWebsocket(Subscription subscription)
+ {
+ logger.debug("Connecting to websocket");
+
+ WebsocketClient client = clientProvider.getLocalWebsocketClient(() -> connect(),
+ subscription.getIdElement().getIdPart());
+
+ EventType eventType = toEventType(subscription.getChannel().getPayload());
+ if (EventType.PING.equals(eventType))
+ {
+ Map> subscriptionCriteria = parse(subscription.getCriteria(), "Task");
+ setPingEventHandler(client, subscription.getIdElement().getIdPart(), subscriptionCriteria);
+ }
+ else
+ setResourceEventHandler(client, eventType);
+
+ try
+ {
+ logger.info("Connecting websocket to local FHIR server with subscription id {}",
+ subscription.getIdElement().getIdPart());
+ client.connect();
+ }
+ catch (Exception e)
+ {
+ logger.warn("Error while connecting websocket to local FHIR server", e);
+ throw e;
+ }
+ }
+
+ private Void onError(Throwable t)
+ {
+ logger.error("Error while connecting to websocket", t);
+ return null;
+ }
+
+ private EventType toEventType(String payload)
+ {
+ if (payload == null)
+ return EventType.PING;
+
+ switch (payload)
+ {
+ case Constants.CT_FHIR_JSON:
+ case Constants.CT_FHIR_JSON_NEW:
+ return EventType.JSON;
+ case Constants.CT_FHIR_XML:
+ case Constants.CT_FHIR_XML_NEW:
+ return EventType.XML;
+ default:
+ throw new RuntimeException("Unsupportet subscription.payload " + payload);
+ }
+ }
+
+ @EventListener({ ContextClosedEvent.class })
+ public void onContextClosedEvent(ContextClosedEvent event)
+ {
+ clientProvider.disconnectAll();
+ }
+
+ protected void setPingEventHandler(WebsocketClient client, String subscriptionIdPart,
+ Map> searchCriteriaQueryParameters)
+ {
+ FhirWebserviceClient webserviceClient = clientProvider.getLocalWebserviceClient();
+ PingEventHandler handler = new PingEventHandler(
+ new ExistingTaskLoader(lastEventTimeIo, taskHandler, webserviceClient));
+ client.setPingHandler(ping -> handler.onPing(ping, subscriptionIdPart, searchCriteriaQueryParameters));
+ }
+
+ protected void setResourceEventHandler(WebsocketClient client, EventType eventType)
+ {
+ ResourceEventHandler handler = new ResourceEventHandler(lastEventTimeIo, taskHandler);
+ client.setDomainResourceHandler(handler::onResource, createParserFactory(eventType, fhirContext));
+ }
+
+ private Supplier createParserFactory(EventType eventType, FhirContext fhirContext)
+ {
+ switch (eventType)
+ {
+ case XML:
+ return () -> configureParser(fhirContext.newXmlParser());
+ case JSON:
+ return () -> configureParser(fhirContext.newJsonParser());
+ default:
+ throw new RuntimeException("EventType " + eventType + " not supported");
+ }
+ }
+
+ private IParser configureParser(IParser p)
+ {
+ p.setStripVersionsFromReferences(false);
+ p.setOverrideResourceIdWithBundleEntryFullUrl(false);
+ return p;
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/LastEventTimeIo.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/LastEventTimeIo.java
index 6352f936a..b88a1da1f 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/LastEventTimeIo.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/LastEventTimeIo.java
@@ -5,7 +5,10 @@
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
+import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.Date;
import java.util.Objects;
import java.util.Optional;
@@ -16,6 +19,7 @@
public class LastEventTimeIo implements InitializingBean
{
private static final Logger logger = LoggerFactory.getLogger(LastEventTimeIo.class);
+ private static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
private final Path lastEventTimeFile;
@@ -32,37 +36,53 @@ public void afterPropertiesSet() throws Exception
if (Files.exists(lastEventTimeFile) && !Files.isWritable(lastEventTimeFile))
throw new IOException("Last event time file at " + lastEventTimeFile.toString() + " not writable");
else if (!Files.isWritable(lastEventTimeFile.getParent()))
- throw new IOException(
- "Last event time file at " + lastEventTimeFile.toString() + " not existing and parent not writable");
+ throw new IOException("Last event time file at " + lastEventTimeFile.toString()
+ + " not existing and parent not writable");
}
public Optional readLastEventTime()
{
try
{
- return Optional.of(
- LocalDateTime.parse(Files.readString(lastEventTimeFile), DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+ Optional value = Optional
+ .of(LocalDateTime.parse(Files.readString(lastEventTimeFile), DATE_TIME_FORMAT));
+
+ logger.debug("Read {} from {}", value.get(), lastEventTimeFile);
+ return value;
+ }
+ catch (DateTimeParseException e)
+ {
+ logger.warn("Error while reading last event time file: {} {}", e.getClass().getName(), e.getMessage());
+ return Optional.empty();
}
catch (IOException e)
{
- logger.warn("Error while reading last event time file: {}", e.getMessage());
+ logger.warn("Error while reading last event time file: {} {}", e.getClass().getName(), e.getMessage());
return Optional.empty();
}
}
- public LocalDateTime writeLastEventTime(LocalDateTime time)
+ public LocalDateTime writeLastEventTime(LocalDateTime localDateTime)
{
try
{
- Files.writeString(lastEventTimeFile, time.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME),
- StandardOpenOption.TRUNCATE_EXISTING);
+ String value = localDateTime.format(DATE_TIME_FORMAT);
+ logger.debug("Writing {} to {}", value, lastEventTimeFile);
+ Files.writeString(lastEventTimeFile, value, StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING);
}
catch (IOException e)
{
- logger.warn("Error while writing last event time file: {}", e.getMessage());
+ logger.warn("Error while writing last event time file: {} {}", e.getClass().getName(), e.getMessage());
}
- return time;
+ return localDateTime;
+ }
+
+ public void writeLastEventTime(Date authoredOn)
+ {
+ LocalDateTime localDateTime = LocalDateTime.ofInstant(authoredOn.toInstant(), ZoneId.systemDefault());
+ writeLastEventTime(localDateTime);
}
}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/PingEventHandler.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/PingEventHandler.java
index 27527c5f4..391254912 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/PingEventHandler.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/PingEventHandler.java
@@ -1,51 +1,20 @@
package org.highmed.dsf.fhir.websocket;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
-import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import org.highmed.dsf.fhir.task.TaskHandler;
-import org.highmed.fhir.client.FhirWebserviceClient;
-import org.hl7.fhir.r4.model.Bundle;
-import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
-import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.InitializingBean;
-public class PingEventHandler implements InitializingBean
+public class PingEventHandler
{
private static final Logger logger = LoggerFactory.getLogger(PingEventHandler.class);
- private static final String PARAM_LAST_UPDATE = "_lastUpdated";
- private static final String PARAM_COUNT = "_count";
- private static final String PARAM_PAGE = "_page";
- private static final String PARAM_SORT = "_sort";
- private static final int RESULT_PAGE_COUNT = 20;
+ private final ExistingTaskLoader taskLoader;
- private final LastEventTimeIo lastEventTimeIo;
- private final TaskHandler taskHandler;
- private final FhirWebserviceClient webserviceClient;
-
- public PingEventHandler(LastEventTimeIo lastEventTimeIo, TaskHandler taskHandler, FhirWebserviceClient webserviceClient)
- {
- this.lastEventTimeIo = lastEventTimeIo;
- this.taskHandler = taskHandler;
- this.webserviceClient = webserviceClient;
- }
-
- @Override
- public void afterPropertiesSet() throws Exception
+ public PingEventHandler(ExistingTaskLoader taskLoader)
{
- Objects.requireNonNull(lastEventTimeIo, "lastEventTimeIo");
- Objects.requireNonNull(taskHandler, "taskHandler");
- Objects.requireNonNull(webserviceClient, "webserviceClient");
+ this.taskLoader = taskLoader;
}
public void onPing(String ping, String subscriptionIdPart, Map> searchCriteriaQueryParameters)
@@ -58,48 +27,6 @@ public void onPing(String ping, String subscriptionIdPart, Map readLastEventTime = lastEventTimeIo.readLastEventTime();
-
- Map> queryParams = new HashMap<>(searchCriteriaQueryParameters);
- if (readLastEventTime.isPresent())
- {
- queryParams.put(PARAM_LAST_UPDATE,
- Arrays.asList("gt" + readLastEventTime.get().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)));
- queryParams.put(PARAM_COUNT, Arrays.asList(String.valueOf(RESULT_PAGE_COUNT)));
- }
- else
- {
- queryParams.put(PARAM_COUNT, Arrays.asList(String.valueOf(Integer.MAX_VALUE)));
- }
- queryParams.put(PARAM_PAGE, Arrays.asList("1"));
- queryParams.put(PARAM_SORT, Arrays.asList(PARAM_LAST_UPDATE));
-
- Bundle bundle = webserviceClient.search(Task.class, queryParams);
- lastEventTimeIo.writeLastEventTime(LocalDateTime.now());
-
- if (bundle.getTotal() <= 0)
- {
- logger.warn("Result bundle.total <= 0, ignoring ping");
- return;
- }
-
- for (BundleEntryComponent entry : bundle.getEntry())
- {
- if (entry.getResource() instanceof Task)
- {
- Task task = (Task) entry.getResource();
- taskHandler.onTask(task);
-
- lastEventTimeIo.writeLastEventTime(LocalDateTime.ofInstant(task.getMeta().getLastUpdated().toInstant(), ZoneId.systemDefault()));
- }
- else
- logger.warn("Ignoring resource of type {}");
- }
-
- if (bundle.getTotal() > RESULT_PAGE_COUNT)
- {
- logger.warn("Result bundle.total > {}, calling onPing again", RESULT_PAGE_COUNT);
- onPing(ping, subscriptionIdPart, searchCriteriaQueryParameters);
- }
+ taskLoader.readExistingTasks(searchCriteriaQueryParameters);
}
}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ResourceEventHandler.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ResourceEventHandler.java
index c38858504..cdc033f01 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ResourceEventHandler.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/ResourceEventHandler.java
@@ -1,39 +1,36 @@
package org.highmed.dsf.fhir.websocket;
-import java.util.Objects;
-
import org.highmed.dsf.fhir.task.TaskHandler;
import org.hl7.fhir.r4.model.DomainResource;
import org.hl7.fhir.r4.model.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.InitializingBean;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
-public class ResourceEventHandler implements InitializingBean
+public class ResourceEventHandler
{
private static final Logger logger = LoggerFactory.getLogger(ResourceEventHandler.class);
private final TaskHandler taskHandler;
+ private final LastEventTimeIo lastEventTimeIo;
- public ResourceEventHandler(TaskHandler taskHandler)
+ public ResourceEventHandler(LastEventTimeIo lastEventTimeIo, TaskHandler taskHandler)
{
+ this.lastEventTimeIo = lastEventTimeIo;
this.taskHandler = taskHandler;
}
- @Override
- public void afterPropertiesSet() throws Exception
- {
- Objects.requireNonNull(taskHandler, "taskHandler");
- }
-
public void onResource(DomainResource resource)
{
logger.trace("Resource of type {} received", resource.getClass().getAnnotation(ResourceDef.class).name());
if (resource instanceof Task)
- taskHandler.onTask((Task) resource);
+ {
+ Task task = (Task) resource;
+ taskHandler.onTask(task);
+ lastEventTimeIo.writeLastEventTime(task.getAuthoredOn());
+ }
else
logger.warn("Ignoring resource of type {}");
}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/openehr/client/OpenEhrClientProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/openehr/client/OpenEhrClientProviderImpl.java
index 99c302cbd..2549f533e 100755
--- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/openehr/client/OpenEhrClientProviderImpl.java
+++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/openehr/client/OpenEhrClientProviderImpl.java
@@ -2,8 +2,8 @@
import java.util.Objects;
-import org.highmed.openehr.client.OpenehrWebserviceClient;
-import org.highmed.openehr.client.OpenehrWebserviceClientJersey;
+import org.highmed.openehr.client.OpenEhrWebserviceClient;
+import org.highmed.openehr.client.OpenEhrWebserviceClientJersey;
import org.springframework.beans.factory.InitializingBean;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -46,9 +46,9 @@ public void afterPropertiesSet() throws Exception
}
@Override
- public OpenehrWebserviceClient getWebserviceClient()
+ public OpenEhrWebserviceClient getWebserviceClient()
{
- return new OpenehrWebserviceClientJersey(baseUrl, basicAuthUsername, basicAuthPassword, connectionTimeout,
+ return new OpenEhrWebserviceClientJersey(baseUrl, basicAuthUsername, basicAuthPassword, connectionTimeout,
readTimeout, objectMapper);
}
diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.12_to_7.13.sql b/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.12_to_7.13.sql
new file mode 100644
index 000000000..2625534b3
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.12_to_7.13.sql
@@ -0,0 +1,63 @@
+--
+-- Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
+-- under one or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information regarding copyright
+-- ownership. Camunda licenses this file to you under the Apache License,
+-- Version 2.0; you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+insert into ACT_GE_SCHEMA_LOG
+values ('200', CURRENT_TIMESTAMP, '7.13.0');
+
+-- https://jira.camunda.com/browse/CAM-10953
+create index ACT_IDX_HI_VAR_PI_NAME_TYPE on ACT_HI_VARINST(PROC_INST_ID_, NAME_, VAR_TYPE_);
+
+
+-- https://app.camunda.com/jira/browse/CAM-10784
+ALTER TABLE ACT_HI_JOB_LOG
+ ADD HOSTNAME_ varchar(255) default null;
+
+-- https://jira.camunda.com/browse/CAM-10378
+ALTER TABLE ACT_RU_JOB
+ ADD FAILED_ACT_ID_ varchar(255);
+
+ALTER TABLE ACT_HI_JOB_LOG
+ ADD FAILED_ACT_ID_ varchar(255);
+
+ALTER TABLE ACT_RU_INCIDENT
+ ADD FAILED_ACTIVITY_ID_ varchar(255);
+
+ALTER TABLE ACT_HI_INCIDENT
+ ADD FAILED_ACTIVITY_ID_ varchar(255);
+
+-- https://jira.camunda.com/browse/CAM-11616
+ALTER TABLE ACT_RU_AUTHORIZATION
+ ADD REMOVAL_TIME_ timestamp;
+create index ACT_IDX_AUTH_RM_TIME on ACT_RU_AUTHORIZATION(REMOVAL_TIME_);
+
+-- https://jira.camunda.com/browse/CAM-11616
+ALTER TABLE ACT_RU_AUTHORIZATION
+ ADD ROOT_PROC_INST_ID_ varchar(64);
+create index ACT_IDX_AUTH_ROOT_PI on ACT_RU_AUTHORIZATION(ROOT_PROC_INST_ID_);
+
+-- https://jira.camunda.com/browse/CAM-11188
+ALTER TABLE ACT_RU_JOBDEF
+ ADD DEPLOYMENT_ID_ varchar(64);
+
+
+-- https://jira.camunda.com/browse/CAM-10978
+
+ALTER TABLE ACT_RU_VARIABLE
+ ADD PROC_DEF_ID_ varchar(64);
+
+ALTER TABLE ACT_HI_DETAIL
+ ADD INITIAL_ boolean;
diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.2.0.xml b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.2.0.xml
new file mode 100644
index 000000000..ebbdd131f
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.2.0.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.changelog.xml b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.changelog.xml
index 6295cdbe4..2e32ed8f3 100644
--- a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.changelog.xml
+++ b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.changelog.xml
@@ -9,4 +9,6 @@
+
+
\ No newline at end of file
diff --git a/dsf-bpe/dsf-bpe-server/src/test/java/org/highmed/dsf/fhir/websocket/LastEventTimeIoTest.java b/dsf-bpe/dsf-bpe-server/src/test/java/org/highmed/dsf/fhir/websocket/LastEventTimeIoTest.java
new file mode 100644
index 000000000..0a1ecc6ec
--- /dev/null
+++ b/dsf-bpe/dsf-bpe-server/src/test/java/org/highmed/dsf/fhir/websocket/LastEventTimeIoTest.java
@@ -0,0 +1,57 @@
+package org.highmed.dsf.fhir.websocket;
+
+import static org.junit.Assert.*;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.util.Optional;
+import java.util.UUID;
+
+import org.junit.Test;
+
+public class LastEventTimeIoTest
+{
+ @Test
+ public void testWriteRead() throws Exception
+ {
+ Path lastEventTimeFile = Paths.get("target", UUID.randomUUID().toString());
+ try
+ {
+ LastEventTimeIo io = new LastEventTimeIo(lastEventTimeFile);
+
+ LocalDateTime written = io.writeLastEventTime(LocalDateTime.now());
+ assertNotNull(written);
+
+ Optional read = io.readLastEventTime();
+ assertTrue(read.isPresent());
+
+ assertEquals(written, read.get());
+ }
+ finally
+ {
+ Files.deleteIfExists(lastEventTimeFile);
+ }
+ }
+
+ @Test
+ public void testReadNotExistingFile() throws Exception
+ {
+ Path lastEventTimeFile = Paths.get("target", UUID.randomUUID().toString());
+ LastEventTimeIo io = new LastEventTimeIo(lastEventTimeFile);
+
+ assertFalse(io.readLastEventTime().isPresent());
+ }
+
+ @Test
+ public void testReadEmptyFile() throws Exception
+ {
+ Path lastEventTimeFile = Paths.get("target", UUID.randomUUID().toString());
+ Files.createFile(lastEventTimeFile);
+
+ LastEventTimeIo io = new LastEventTimeIo(lastEventTimeFile);
+
+ assertFalse(io.readLastEventTime().isPresent());
+ }
+}
diff --git a/dsf-bpe/dsf-bpe-webservice-client/pom.xml b/dsf-bpe/dsf-bpe-webservice-client/pom.xml
index 602a5f81d..c6be59b0b 100755
--- a/dsf-bpe/dsf-bpe-webservice-client/pom.xml
+++ b/dsf-bpe/dsf-bpe-webservice-client/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-bpe-pom
- 0.1.0
+ 0.2.0
diff --git a/dsf-bpe/pom.xml b/dsf-bpe/pom.xml
index 24082212d..3d3c97297 100755
--- a/dsf-bpe/pom.xml
+++ b/dsf-bpe/pom.xml
@@ -8,7 +8,7 @@
org.highmed.dsf
dsf-pom
- 0.1.0
+ 0.2.0
@@ -25,7 +25,7 @@
- 7.12.0
+ 7.13.0
@@ -120,6 +120,7 @@
dsf-fhir-webservice-client
${project.version}
+
org.highmed.dsf
dsf-openehr-model
@@ -142,6 +143,33 @@
${project.version}
+
+ org.highmed.dsf
+ dsf-pseudonymization-medic
+ ${project.version}
+
+
+ org.highmed.dsf
+ dsf-pseudonymization-ttp
+ ${project.version}
+
+
+
+ org.highmed.dsf
+ dsf-mpi-client
+ ${project.version}
+
+
+ org.highmed.dsf
+ dsf-mpi-client-pdq
+ ${project.version}
+
+
+ org.highmed.dsf
+ dsf-mpi-client-stub
+ ${project.version}
+
+
org.camunda.bpm
camunda-bom
@@ -149,11 +177,6 @@
import
pom
-
- org.mybatis
- mybatis
- 3.5.3
-
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.bat b/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.bat
index 5a0047cf3..a8b18d83d 100755
--- a/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.bat
+++ b/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.bat
@@ -4,21 +4,21 @@ REM For installing / starting local registry at registry:5000 see test_setup.txt
REM See https://docs.docker.com/registry/insecure/ for infos on pushing to / pulling from a local insecure registry
echo highmed/bpe ...
-docker build -t highmed/bpe ..\dsf-bpe\dsf-bpe-server-jetty\docker
+docker build --pull -t highmed/bpe ..\dsf-bpe\dsf-bpe-server-jetty\docker
docker tag highmed/bpe:latest registry:5000/highmed/bpe:latest
docker push registry:5000/highmed/bpe
echo highmed/bpe_proxy ...
-docker build -t highmed/bpe_proxy ..\dsf-docker\bpe_proxy
+docker build --pull -t highmed/bpe_proxy ..\dsf-docker\bpe_proxy
docker tag highmed/bpe_proxy:latest registry:5000/highmed/bpe_proxy:latest
docker push registry:5000/highmed/bpe_proxy
echo highmed/fhir ...
-docker build -t highmed/fhir ..\dsf-fhir\dsf-fhir-server-jetty\docker
+docker build --pull -t highmed/fhir ..\dsf-fhir\dsf-fhir-server-jetty\docker
docker tag highmed/fhir:latest registry:5000/highmed/fhir:latest
docker push registry:5000/highmed/fhir
echo highmed/fhir_proxy ...
-docker build -t highmed/fhir_proxy ..\dsf-docker\fhir_proxy
+docker build --pull -t highmed/fhir_proxy ..\dsf-docker\fhir_proxy
docker tag highmed/fhir_proxy:latest registry:5000/highmed/fhir_proxy:latest
docker push registry:5000/highmed/fhir_proxy
diff --git a/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.sh b/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.sh
index 23e8d0a33..c28d4b296 100755
--- a/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.sh
+++ b/dsf-docker-test-setup-3medic-ttp/docker-build-tag-push.sh
@@ -4,21 +4,21 @@
# See https://docs.docker.com/registry/insecure/ for infos on pushing to / pulling from a local insecure registry
echo highmed/bpe ...
-docker build -t highmed/bpe ../dsf-bpe/dsf-bpe-server-jetty/docker
+docker build --pull -t highmed/bpe ../dsf-bpe/dsf-bpe-server-jetty/docker
docker tag highmed/bpe:latest registry:5000/highmed/bpe:latest
docker push registry:5000/highmed/bpe
echo highmed/bpe_proxy ...
-docker build -t highmed/bpe_proxy ../dsf-docker/bpe_proxy
+docker build --pull -t highmed/bpe_proxy ../dsf-docker/bpe_proxy
docker tag highmed/bpe_proxy:latest registry:5000/highmed/bpe_proxy:latest
docker push registry:5000/highmed/bpe_proxy
echo highmed/fhir ...
-docker build -t highmed/fhir ../dsf-fhir/dsf-fhir-server-jetty/docker
+docker build --pull -t highmed/fhir ../dsf-fhir/dsf-fhir-server-jetty/docker
docker tag highmed/fhir:latest registry:5000/highmed/fhir:latest
docker push registry:5000/highmed/fhir
echo highmed/fhir_proxy ...
-docker build -t highmed/fhir_proxy ../dsf-docker/fhir_proxy
+docker build --pull -t highmed/fhir_proxy ../dsf-docker/fhir_proxy
docker tag highmed/fhir_proxy:latest registry:5000/highmed/fhir_proxy:latest
docker push registry:5000/highmed/fhir_proxy
diff --git a/dsf-docker-test-setup-3medic-ttp/highmed.yml b/dsf-docker-test-setup-3medic-ttp/highmed.yml
index 7e6a554bb..fd671aa04 100755
--- a/dsf-docker-test-setup-3medic-ttp/highmed.yml
+++ b/dsf-docker-test-setup-3medic-ttp/highmed.yml
@@ -67,9 +67,9 @@
append: true
- name: Download docker-compose
get_url:
- url: https://github.com/docker/compose/releases/download/1.25.4/docker-compose-Linux-x86_64
+ url: https://github.com/docker/compose/releases/download/1.26.0/docker-compose-Linux-x86_64
dest: /usr/local/bin/docker-compose
- checksum: sha256:542e93b1d5106d2769b325f60ba9a0ba087bb96e30dc2c1cb026f0cb642e9aed
+ checksum: sha256:ff6816932a57eab448798105926adbe4363b82f217802b105ade2edad95706cb
mode: '777'
- name: update /etc/hosts file
blockinfile:
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/.rsync-filter b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/.rsync-filter
index 716786e6e..a87a3a1cd 100644
--- a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/.rsync-filter
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/.rsync-filter
@@ -1,5 +1,6 @@
- .rsync-filter
- app/conf/.gitignore
+- app/last_event/README.md
- app/log/README.md
- app/plugin/.gitignore
- proxy/ssl/.gitignore
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties
index a7ae8f282..d0d88c5ab 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties
@@ -16,10 +16,10 @@ org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_1
org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic1/fhir
org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic1-client_certificate.p12
org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
-org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000
+org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
-org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000
+org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
@@ -31,6 +31,8 @@ org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file
+#org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis=5000
+#org.highmed.dsf.bpe.fhir.task.subscription.maxRetries=-1
org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1
org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
@@ -38,4 +40,16 @@ org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
+#org.highmed.dsf.bpe.mpi.webservice.factory.class=org.highmed.mpi.client.pdq.MasterPatientIndexClientPdqFactory
+#org.highmed.dsf.bpe.mpi.pdq.webservice.host=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.port=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.path=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.password=
+#org.highmed.dsf.bpe.mpi.pdq.sender.application=
+#org.highmed.dsf.bpe.mpi.pdq.sender.facility=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.application=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.facility=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.namespaceId=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.universalId=
+
org.highmed.dsf.bpe.cors.origins=
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/log4j2.xml
index 7006f1aaf..016d8e200 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/log4j2.xml
@@ -34,15 +34,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/last_event/README.md b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/last_event/README.md
new file mode 100644
index 000000000..12fefbfaa
--- /dev/null
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/last_event/README.md
@@ -0,0 +1 @@
+empty directory for last-event time.file
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/docker-compose.yml b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/docker-compose.yml
index 97bf3acd5..f11a6c301 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/docker-compose.yml
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/docker-compose.yml
@@ -35,6 +35,9 @@ services:
- type: bind
source: ./app/log
target: /opt/bpe/log
+ - type: bind
+ source: ./app/last_event
+ target: /opt/bpe/last_event
environment:
TZ: Europe/Berlin
networks:
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml
index 61f365c4c..33426c0b6 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml
@@ -49,15 +49,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/upload.yml b/dsf-docker-test-setup-3medic-ttp/medic1/upload.yml
index 42ed3bae3..35b6b9641 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic1/upload.yml
+++ b/dsf-docker-test-setup-3medic-ttp/medic1/upload.yml
@@ -30,6 +30,13 @@
group: '2202'
mode: '2775'
become: true
+ - name: Set bpe/app/last_event permissions
+ file:
+ path: /opt/highmed/bpe/app/last_event
+ owner: '{{ user }}'
+ group: '2202'
+ mode: '2775'
+ become: true
- name: Set fhir/app/log permissions
file:
path: /opt/highmed/fhir/app/log
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/.rsync-filter b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/.rsync-filter
index 716786e6e..a87a3a1cd 100644
--- a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/.rsync-filter
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/.rsync-filter
@@ -1,5 +1,6 @@
- .rsync-filter
- app/conf/.gitignore
+- app/last_event/README.md
- app/log/README.md
- app/plugin/.gitignore
- proxy/ssl/.gitignore
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties
index 5922d5d4b..4e16c97d7 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties
@@ -16,10 +16,10 @@ org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_2
org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic2/fhir
org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic2-client_certificate.p12
org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
-org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000
+org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
-org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000
+org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
@@ -31,6 +31,8 @@ org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file
+#org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis=5000
+#org.highmed.dsf.bpe.fhir.task.subscription.maxRetries=-1
org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1
org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
@@ -38,4 +40,16 @@ org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
+#org.highmed.dsf.bpe.mpi.webservice.factory.class=org.highmed.mpi.client.pdq.MasterPatientIndexClientPdqFactory
+#org.highmed.dsf.bpe.mpi.pdq.webservice.host=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.port=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.path=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.password=
+#org.highmed.dsf.bpe.mpi.pdq.sender.application=
+#org.highmed.dsf.bpe.mpi.pdq.sender.facility=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.application=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.facility=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.namespaceId=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.universalId=
+
org.highmed.dsf.bpe.cors.origins=
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/log4j2.xml
index 7006f1aaf..016d8e200 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/log4j2.xml
@@ -34,15 +34,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/last_event/README.md b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/last_event/README.md
new file mode 100644
index 000000000..12fefbfaa
--- /dev/null
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/last_event/README.md
@@ -0,0 +1 @@
+empty directory for last-event time.file
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/docker-compose.yml b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/docker-compose.yml
index 1fe67af8c..84ad9f325 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/docker-compose.yml
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/docker-compose.yml
@@ -35,6 +35,9 @@ services:
- type: bind
source: ./app/log
target: /opt/bpe/log
+ - type: bind
+ source: ./app/last_event
+ target: /opt/bpe/last_event
environment:
TZ: Europe/Berlin
networks:
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml
index 61f365c4c..33426c0b6 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml
@@ -49,15 +49,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/upload.yml b/dsf-docker-test-setup-3medic-ttp/medic2/upload.yml
index 9b7e283ba..ef642cf97 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic2/upload.yml
+++ b/dsf-docker-test-setup-3medic-ttp/medic2/upload.yml
@@ -30,6 +30,13 @@
group: '2202'
mode: '2775'
become: true
+ - name: Set bpe/app/last_event permissions
+ file:
+ path: /opt/highmed/bpe/app/last_event
+ owner: '{{ user }}'
+ group: '2202'
+ mode: '2775'
+ become: true
- name: Set fhir/app/log permissions
file:
path: /opt/highmed/fhir/app/log
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/.rsync-filter b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/.rsync-filter
index 716786e6e..a87a3a1cd 100644
--- a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/.rsync-filter
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/.rsync-filter
@@ -1,5 +1,6 @@
- .rsync-filter
- app/conf/.gitignore
+- app/last_event/README.md
- app/log/README.md
- app/plugin/.gitignore
- proxy/ssl/.gitignore
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties
index c8614100f..443abe2c6 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties
@@ -16,10 +16,10 @@ org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_3
org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic3/fhir
org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic3-client_certificate.p12
org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
-org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000
+org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
-org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000
+org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
@@ -31,6 +31,8 @@ org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file
+#org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis=5000
+#org.highmed.dsf.bpe.fhir.task.subscription.maxRetries=-1
org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1
org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
@@ -38,4 +40,16 @@ org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
+#org.highmed.dsf.bpe.mpi.webservice.factory.class=org.highmed.mpi.client.pdq.MasterPatientIndexClientPdqFactory
+#org.highmed.dsf.bpe.mpi.pdq.webservice.host=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.port=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.path=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.password=
+#org.highmed.dsf.bpe.mpi.pdq.sender.application=
+#org.highmed.dsf.bpe.mpi.pdq.sender.facility=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.application=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.facility=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.namespaceId=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.universalId=
+
org.highmed.dsf.bpe.cors.origins=
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/log4j2.xml
index 7006f1aaf..016d8e200 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/log4j2.xml
@@ -34,15 +34,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/last_event/README.md b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/last_event/README.md
new file mode 100644
index 000000000..12fefbfaa
--- /dev/null
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/last_event/README.md
@@ -0,0 +1 @@
+empty directory for last-event time.file
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/docker-compose.yml b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/docker-compose.yml
index 36c48de8a..477ff9f39 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/docker-compose.yml
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/docker-compose.yml
@@ -35,6 +35,9 @@ services:
- type: bind
source: ./app/log
target: /opt/bpe/log
+ - type: bind
+ source: ./app/last_event
+ target: /opt/bpe/last_event
environment:
TZ: Europe/Berlin
networks:
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml
index 61f365c4c..33426c0b6 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml
@@ -49,15 +49,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/upload.yml b/dsf-docker-test-setup-3medic-ttp/medic3/upload.yml
index a05d5077b..be50b483f 100755
--- a/dsf-docker-test-setup-3medic-ttp/medic3/upload.yml
+++ b/dsf-docker-test-setup-3medic-ttp/medic3/upload.yml
@@ -30,6 +30,13 @@
group: '2202'
mode: '2775'
become: true
+ - name: Set bpe/app/last_event permissions
+ file:
+ path: /opt/highmed/bpe/app/last_event
+ owner: '{{ user }}'
+ group: '2202'
+ mode: '2775'
+ become: true
- name: Set fhir/app/log permissions
file:
path: /opt/highmed/fhir/app/log
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/.rsync-filter b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/.rsync-filter
index 716786e6e..a87a3a1cd 100644
--- a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/.rsync-filter
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/.rsync-filter
@@ -1,5 +1,6 @@
- .rsync-filter
- app/conf/.gitignore
+- app/last_event/README.md
- app/log/README.md
- app/plugin/.gitignore
- proxy/ssl/.gitignore
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties
index e1c20401c..980d281b6 100755
--- a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties
@@ -16,10 +16,10 @@ org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_TTP
org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://ttp/fhir
org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/ttp-client_certificate.p12
org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
-org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000
+org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
-org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000
+org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=10000
org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
@@ -31,6 +31,8 @@ org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file
+#org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis=5000
+#org.highmed.dsf.bpe.fhir.task.subscription.maxRetries=-1
org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1
org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
@@ -38,4 +40,16 @@ org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
+#org.highmed.dsf.bpe.mpi.webservice.factory.class=org.highmed.mpi.client.pdq.MasterPatientIndexClientPdqFactory
+#org.highmed.dsf.bpe.mpi.pdq.webservice.host=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.port=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.path=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.password=
+#org.highmed.dsf.bpe.mpi.pdq.sender.application=
+#org.highmed.dsf.bpe.mpi.pdq.sender.facility=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.application=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.facility=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.namespaceId=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.universalId=
+
org.highmed.dsf.bpe.cors.origins=
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/log4j2.xml
index 7006f1aaf..016d8e200 100755
--- a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/log4j2.xml
@@ -34,15 +34,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/last_event/README.md b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/last_event/README.md
new file mode 100644
index 000000000..12fefbfaa
--- /dev/null
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/last_event/README.md
@@ -0,0 +1 @@
+empty directory for last-event time.file
\ No newline at end of file
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/docker-compose.yml b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/docker-compose.yml
index 818383aed..e9fa6db5b 100755
--- a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/docker-compose.yml
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/docker-compose.yml
@@ -35,6 +35,9 @@ services:
- type: bind
source: ./app/log
target: /opt/bpe/log
+ - type: bind
+ source: ./app/last_event
+ target: /opt/bpe/last_event
environment:
TZ: Europe/Berlin
networks:
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml
index 61f365c4c..33426c0b6 100755
--- a/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml
@@ -49,15 +49,8 @@
-
-
-
-
-
+
-
-
-
diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/upload.yml b/dsf-docker-test-setup-3medic-ttp/ttp/upload.yml
index cf93585eb..25a1e966a 100755
--- a/dsf-docker-test-setup-3medic-ttp/ttp/upload.yml
+++ b/dsf-docker-test-setup-3medic-ttp/ttp/upload.yml
@@ -30,6 +30,13 @@
group: '2202'
mode: '2775'
become: true
+ - name: Set bpe/app/last_event permissions
+ file:
+ path: /opt/highmed/bpe/app/last_event
+ owner: '{{ user }}'
+ group: '2202'
+ mode: '2775'
+ become: true
- name: Set fhir/app/log permissions
file:
path: /opt/highmed/fhir/app/log
diff --git a/dsf-docker-test-setup/bpe/app/conf/config.properties b/dsf-docker-test-setup/bpe/app/conf/config.properties
index 6da6fcf8e..e74fb3b7d 100755
--- a/dsf-docker-test-setup/bpe/app/conf/config.properties
+++ b/dsf-docker-test-setup/bpe/app/conf/config.properties
@@ -1,41 +1,55 @@
-org.highmed.dsf.bpe.db.driver=org.postgresql.Driver
-org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe
-org.highmed.dsf.bpe.db.liquibase_user=liquibase_user
-org.highmed.dsf.bpe.db.liquibase_user_password=PW99vXYyTbBTGzemQbCnVb4Bce7xuzcU77W5BUCVjYTjbwleVfpTXkQWtGFHYrT8
-
-org.highmed.dsf.bpe.db.server_users_group=bpe_users
-org.highmed.dsf.bpe.db.server_user=bpe_server_user
-org.highmed.dsf.bpe.db.server_user_password=8s4cGYqY41mrWqTmwhZ3beVQcz6wc3Yr
-
-org.highmed.dsf.bpe.db.camunda_users_group=camunda_users
-org.highmed.dsf.bpe.db.camunda_user=camunda_server_user
-org.highmed.dsf.bpe.db.camunda_user_password=dcPa7a9wTCaTxFk7BdjmCuQp8k29e2eL
-
-org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_Organization
-
-org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://fhir/fhir
-org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/test-client_certificate.p12
-org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
-org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500
-org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
-
-org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500
-org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500
-#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
-#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
-#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort=
-
-org.highmed.dsf.bpe.fhir.local.websocket.url=wss://fhir/fhir/ws
-org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/test-client_certificate.p12
-org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
-
-org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
-org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file
-
-org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1
-org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
-org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
-org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
-org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
-
-org.highmed.dsf.bpe.cors.origins=
+org.highmed.dsf.bpe.db.driver=org.postgresql.Driver
+org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe
+org.highmed.dsf.bpe.db.liquibase_user=liquibase_user
+org.highmed.dsf.bpe.db.liquibase_user_password=PW99vXYyTbBTGzemQbCnVb4Bce7xuzcU77W5BUCVjYTjbwleVfpTXkQWtGFHYrT8
+
+org.highmed.dsf.bpe.db.server_users_group=bpe_users
+org.highmed.dsf.bpe.db.server_user=bpe_server_user
+org.highmed.dsf.bpe.db.server_user_password=8s4cGYqY41mrWqTmwhZ3beVQcz6wc3Yr
+
+org.highmed.dsf.bpe.db.camunda_users_group=camunda_users
+org.highmed.dsf.bpe.db.camunda_user=camunda_server_user
+org.highmed.dsf.bpe.db.camunda_user_password=dcPa7a9wTCaTxFk7BdjmCuQp8k29e2eL
+
+org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_Organization
+
+org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://fhir/fhir
+org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/test-client_certificate.p12
+org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password
+org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500
+org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500
+
+org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500
+org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500
+#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password=
+#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username=
+#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort=
+
+org.highmed.dsf.bpe.fhir.local.websocket.url=wss://fhir/fhir/ws
+org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/test-client_certificate.p12
+org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password
+
+org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson
+org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file
+#org.highmed.dsf.bpe.fhir.task.subscription.retrySleepMillis=5000
+#org.highmed.dsf.bpe.fhir.task.subscription.maxRetries=-1
+
+org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1
+org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username
+org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password
+org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500
+org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500
+
+#org.highmed.dsf.bpe.mpi.webservice.factory.class=org.highmed.mpi.client.pdq.MasterPatientIndexClientPdqFactory
+#org.highmed.dsf.bpe.mpi.pdq.webservice.host=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.port=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.path=
+#org.highmed.dsf.bpe.mpi.pdq.webservice.keystore.password=
+#org.highmed.dsf.bpe.mpi.pdq.sender.application=
+#org.highmed.dsf.bpe.mpi.pdq.sender.facility=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.application=
+#org.highmed.dsf.bpe.mpi.pdq.receiver.facility=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.namespaceId=
+#org.highmed.dsf.bpe.mpi.pdq.assigningAuthority.universalId=
+
+org.highmed.dsf.bpe.cors.origins=
diff --git a/dsf-docker-test-setup/bpe/app/last_event/.gitignore b/dsf-docker-test-setup/bpe/app/last_event/.gitignore
new file mode 100644
index 000000000..9a81fe812
--- /dev/null
+++ b/dsf-docker-test-setup/bpe/app/last_event/.gitignore
@@ -0,0 +1 @@
+/time.file
\ No newline at end of file
diff --git a/dsf-docker-test-setup/bpe/docker-compose.yml b/dsf-docker-test-setup/bpe/docker-compose.yml
index e0f8b521b..4ef7969f5 100755
--- a/dsf-docker-test-setup/bpe/docker-compose.yml
+++ b/dsf-docker-test-setup/bpe/docker-compose.yml
@@ -25,12 +25,17 @@ services:
- type: bind
source: ./app/conf
target: /opt/bpe/conf
+ read_only: true
- type: bind
source: ./app/plugin
target: /opt/bpe/plugin
+ read_only: true
- type: bind
source: ./app/log
target: /opt/bpe/log
+ - type: bind
+ source: ./app/last_event
+ target: /opt/bpe/last_event
environment:
TZ: Europe/Berlin
networks:
diff --git a/dsf-docker-test-setup/docker-build.bat b/dsf-docker-test-setup/docker-build.bat
index ecfe317b5..0cc134768 100755
--- a/dsf-docker-test-setup/docker-build.bat
+++ b/dsf-docker-test-setup/docker-build.bat
@@ -1,13 +1,13 @@
@echo off
echo highmed/bpe ...
-docker build -t highmed/bpe ..\dsf-bpe\dsf-bpe-server-jetty\docker
+docker build --pull -t highmed/bpe ..\dsf-bpe\dsf-bpe-server-jetty\docker
echo highmed/bpe_proxy ...
-docker build -t highmed/bpe_proxy ..\dsf-docker\bpe_proxy
+docker build --pull -t highmed/bpe_proxy ..\dsf-docker\bpe_proxy
echo highmed/fhir ...
-docker build -t highmed/fhir ..\dsf-fhir\dsf-fhir-server-jetty\docker
+docker build --pull -t highmed/fhir ..\dsf-fhir\dsf-fhir-server-jetty\docker
echo highmed/fhir_proxy ...
-docker build -t highmed/fhir_proxy ..\dsf-docker\fhir_proxy
+docker build --pull -t highmed/fhir_proxy ..\dsf-docker\fhir_proxy
diff --git a/dsf-docker-test-setup/docker-build.sh b/dsf-docker-test-setup/docker-build.sh
index d26697a6c..7b9bb25c2 100755
--- a/dsf-docker-test-setup/docker-build.sh
+++ b/dsf-docker-test-setup/docker-build.sh
@@ -1,13 +1,13 @@
#!/bin/bash
echo highmed/bpe ...
-docker build -t highmed/bpe ../dsf-bpe/dsf-bpe-server-jetty/docker
+docker build --pull -t highmed/bpe ../dsf-bpe/dsf-bpe-server-jetty/docker
echo highmed/bpe_proxy ...
-docker build -t highmed/bpe_proxy ../dsf-docker/bpe_proxy
+docker build --pull -t highmed/bpe_proxy ../dsf-docker/bpe_proxy
echo highmed/fhir ...
-docker build -t highmed/fhir ../dsf-fhir/dsf-fhir-server-jetty/docker
+docker build --pull -t highmed/fhir ../dsf-fhir/dsf-fhir-server-jetty/docker
echo highmed/fhir_proxy ...
-docker build -t highmed/fhir_proxy ../dsf-docker/fhir_proxy
+docker build --pull -t highmed/fhir_proxy ../dsf-docker/fhir_proxy
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/pom.xml b/dsf-fhir/dsf-fhir-rest-adapter/pom.xml
index 43f059f2d..9c1e9143e 100755
--- a/dsf-fhir/dsf-fhir-rest-adapter/pom.xml
+++ b/dsf-fhir/dsf-fhir-rest-adapter/pom.xml
@@ -1,5 +1,5 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
dsf-fhir-rest-adapter
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-fhir-pom
- 0.1.0
+ 0.2.0
@@ -20,5 +20,11 @@
javax.ws.rs-api
provided
+
+
+ de.hs-heilbronn.mi
+ log4j2-utils
+ test
+
\ No newline at end of file
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java
index 32c1ac6f4..62864dbf4 100755
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java
@@ -81,6 +81,11 @@ public T readFrom(Class type, Type genericType, Annotation[] annotations, Med
MultivaluedMap httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException
{
- return getParser(null).parseResource(type, new InputStreamReader(entityStream));
+ return fixResource(getParser(null).parseResource(type, new InputStreamReader(entityStream)));
+ }
+
+ protected T fixResource(T resource)
+ {
+ return resource;
}
}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryJsonFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryJsonFhirAdapter.java
index 300705af1..37cd7ef87 100755
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryJsonFhirAdapter.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryJsonFhirAdapter.java
@@ -3,6 +3,7 @@
import javax.ws.rs.ext.Provider;
import org.hl7.fhir.r4.model.Binary;
+import org.hl7.fhir.r4.model.IdType;
import ca.uhn.fhir.context.FhirContext;
@@ -13,4 +14,20 @@ public BinaryJsonFhirAdapter(FhirContext fhirContext)
{
super(fhirContext, Binary.class);
}
+
+ @Override
+ protected Binary fixResource(Binary resource)
+ {
+ if (resource.hasIdElement() && resource.getIdElement().hasIdPart()
+ && !resource.getIdElement().hasVersionIdPart() && resource.hasMeta()
+ && resource.getMeta().hasVersionId())
+ {
+ // TODO Bugfix HAPI is removing version information from binary.id
+ IdType fixedId = new IdType(resource.getResourceType().name(), resource.getIdElement().getIdPart(),
+ resource.getMeta().getVersionId());
+ resource.setIdElement(fixedId);
+ }
+
+ return resource;
+ }
}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryXmlFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryXmlFhirAdapter.java
index bb31a9285..e4ae6e0b7 100755
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryXmlFhirAdapter.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BinaryXmlFhirAdapter.java
@@ -3,6 +3,7 @@
import javax.ws.rs.ext.Provider;
import org.hl7.fhir.r4.model.Binary;
+import org.hl7.fhir.r4.model.IdType;
import ca.uhn.fhir.context.FhirContext;
@@ -13,4 +14,20 @@ public BinaryXmlFhirAdapter(FhirContext fhirContext)
{
super(fhirContext, Binary.class);
}
+
+ @Override
+ protected Binary fixResource(Binary resource)
+ {
+ if (resource.hasIdElement() && resource.getIdElement().hasIdPart()
+ && !resource.getIdElement().hasVersionIdPart() && resource.hasMeta()
+ && resource.getMeta().hasVersionId())
+ {
+ // TODO Bugfix HAPI is removing version information from binary.id
+ IdType fixedId = new IdType(resource.getResourceType().name(), resource.getIdElement().getIdPart(),
+ resource.getMeta().getVersionId());
+ resource.setIdElement(fixedId);
+ }
+
+ return resource;
+ }
}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleJsonFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleJsonFhirAdapter.java
index 99da67c01..5e2e5c331 100755
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleJsonFhirAdapter.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleJsonFhirAdapter.java
@@ -3,6 +3,7 @@
import javax.ws.rs.ext.Provider;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
import ca.uhn.fhir.context.FhirContext;
@@ -13,4 +14,20 @@ public BundleJsonFhirAdapter(FhirContext fhirContext)
{
super(fhirContext, Bundle.class);
}
+
+ @Override
+ protected Bundle fixResource(Bundle resource)
+ {
+ if (resource.hasIdElement() && resource.getIdElement().hasIdPart()
+ && !resource.getIdElement().hasVersionIdPart() && resource.hasMeta()
+ && resource.getMeta().hasVersionId())
+ {
+ // TODO Bugfix HAPI is removing version information from bundle.id
+ IdType fixedId = new IdType(resource.getResourceType().name(), resource.getIdElement().getIdPart(),
+ resource.getMeta().getVersionId());
+ resource.setIdElement(fixedId);
+ }
+
+ return resource;
+ }
}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleXmlFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleXmlFhirAdapter.java
index 27b256b1c..cd848c816 100755
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleXmlFhirAdapter.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/BundleXmlFhirAdapter.java
@@ -3,6 +3,7 @@
import javax.ws.rs.ext.Provider;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
import ca.uhn.fhir.context.FhirContext;
@@ -13,4 +14,20 @@ public BundleXmlFhirAdapter(FhirContext fhirContext)
{
super(fhirContext, Bundle.class);
}
+
+ @Override
+ protected Bundle fixResource(Bundle resource)
+ {
+ if (resource.hasIdElement() && resource.getIdElement().hasIdPart()
+ && !resource.getIdElement().hasVersionIdPart() && resource.hasMeta()
+ && resource.getMeta().hasVersionId())
+ {
+ // TODO Bugfix HAPI is removing version information from bundle.id
+ IdType fixedId = new IdType(resource.getResourceType().name(), resource.getIdElement().getIdPart(),
+ resource.getMeta().getVersionId());
+ resource.setIdElement(fixedId);
+ }
+
+ return resource;
+ }
}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/HtmlFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/HtmlFhirAdapter.java
index ba7ed8d23..61687be45 100644
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/HtmlFhirAdapter.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/HtmlFhirAdapter.java
@@ -23,6 +23,7 @@
import org.hl7.fhir.r4.model.BaseResource;
import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Resource;
import ca.uhn.fhir.context.FhirContext;
@@ -177,8 +178,13 @@ private Optional getResourceUrl(T t) throws MalformedURLException
else if (t instanceof Resource && t.getIdElement().getResourceType() != null
&& t.getIdElement().getIdPart() != null)
{
- return Optional.of(String.format("%s/%s/%s", serverBaseProvider.getServerBase(),
- t.getIdElement().getResourceType(), t.getIdElement().getIdPart()));
+ if (!uriInfo.getPath().contains("_history"))
+ return Optional.of(String.format("%s/%s/%s", serverBaseProvider.getServerBase(),
+ t.getIdElement().getResourceType(), t.getIdElement().getIdPart()));
+ else
+ return Optional.of(String.format("%s/%s/%s/_history/%s", serverBaseProvider.getServerBase(),
+ t.getIdElement().getResourceType(), t.getIdElement().getIdPart(),
+ t.getIdElement().getVersionIdPart()));
}
else
return Optional.empty();
@@ -239,8 +245,19 @@ private void writeJson(T t, OutputStreamWriter out) throws IOException
private Optional getResourceName(T t, String uuid)
{
if (t instanceof Bundle)
- return ((Bundle) t).getEntry().stream().filter(c -> uuid.equals(c.getResource().getIdElement().getIdPart()))
- .map(c -> c.getResource().getClass().getAnnotation(ResourceDef.class).name()).findFirst();
+ return ((Bundle) t).getEntry().stream().filter(c ->
+ {
+ if (c.hasResource())
+ return uuid.equals(c.getResource().getIdElement().getIdPart());
+ else
+ return uuid.equals(new IdType(c.getResponse().getLocation()).getIdPart());
+ }).map(c ->
+ {
+ if (c.hasResource())
+ return c.getResource().getClass().getAnnotation(ResourceDef.class).name();
+ else
+ return new IdType(c.getResponse().getLocation()).getResourceType();
+ }).findFirst();
else if (t instanceof Resource)
return Optional.of(t.getClass().getAnnotation(ResourceDef.class).name());
else
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/prefer/PreferHandlingType.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/prefer/PreferHandlingType.java
new file mode 100644
index 000000000..c1da6e8df
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/prefer/PreferHandlingType.java
@@ -0,0 +1,33 @@
+package org.highmed.dsf.fhir.prefer;
+
+public enum PreferHandlingType
+{
+ STRICT("handling=strict"), LENIENT("handling=lenient");
+
+ private final String headerValue;
+
+ private PreferHandlingType(String headerValue)
+ {
+ this.headerValue = headerValue;
+ }
+
+ public static PreferHandlingType fromString(String prefer)
+ {
+ if (prefer == null)
+ return LENIENT;
+
+ switch (prefer)
+ {
+ case "handling=strict":
+ return STRICT;
+ case "handling=lenient":
+ default:
+ return LENIENT;
+ }
+ }
+
+ public String getHeaderValue()
+ {
+ return headerValue;
+ }
+}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/prefer/PreferReturnType.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/prefer/PreferReturnType.java
new file mode 100644
index 000000000..d6bafb0b8
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/prefer/PreferReturnType.java
@@ -0,0 +1,35 @@
+package org.highmed.dsf.fhir.prefer;
+
+public enum PreferReturnType
+{
+ MINIMAL("return=minimal"), REPRESENTATION("return=representation"), OPERATION_OUTCOME("return=OperationOutcome");
+
+ private final String headerValue;
+
+ private PreferReturnType(String headerValue)
+ {
+ this.headerValue = headerValue;
+ }
+
+ public static PreferReturnType fromString(String prefer)
+ {
+ if (prefer == null)
+ return REPRESENTATION;
+
+ switch (prefer)
+ {
+ case "return=minimal":
+ return MINIMAL;
+ case "return=OperationOutcome":
+ return OPERATION_OUTCOME;
+ case "return=representation":
+ default:
+ return REPRESENTATION;
+ }
+ }
+
+ public String getHeaderValue()
+ {
+ return headerValue;
+ }
+}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceCleaner.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceCleaner.java
new file mode 100644
index 000000000..dc1fe9d9f
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceCleaner.java
@@ -0,0 +1,24 @@
+package org.highmed.dsf.fhir.service;
+
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.Resource;
+
+public interface ReferenceCleaner
+{
+ /**
+ * Removes literal references, if a conditional reference is also set
+ *
+ * @param resource
+ * @return null if given resource is null, cleaned up resource (same instance)
+ */
+ R cleanLiteralReferences(R resource);
+
+ /**
+ * Removes embedded resources from references within {@link Bundle} entries
+ *
+ * @param
+ * @param resource
+ * @return null if given resource is null, cleaned up resource (same instance)
+ */
+ R cleanReferenceResourcesIfBundle(R resource);
+}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceCleanerImpl.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceCleanerImpl.java
new file mode 100644
index 000000000..901fcee70
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceCleanerImpl.java
@@ -0,0 +1,66 @@
+package org.highmed.dsf.fhir.service;
+
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.IdType;
+import org.hl7.fhir.r4.model.Reference;
+import org.hl7.fhir.r4.model.Resource;
+
+public class ReferenceCleanerImpl implements ReferenceCleaner
+{
+ private ReferenceExtractor referenceExtractor;
+
+ public ReferenceCleanerImpl(ReferenceExtractor referenceExtractor)
+ {
+ this.referenceExtractor = Objects.requireNonNull(referenceExtractor, "referenceExtractor");
+ }
+
+ @Override
+ public R cleanLiteralReferences(R resource)
+ {
+ if (resource == null)
+ return null;
+
+ Stream references = referenceExtractor.getReferences(resource);
+ references.forEach(this::cleanupReference);
+
+ return resource;
+ }
+
+ private void cleanupReference(ResourceReference resourceReference)
+ {
+ Reference ref = resourceReference.getReference();
+ if (ref.hasIdentifier() && ref.hasReference())
+ ref.setReferenceElement((IdType) null);
+ }
+
+ @Override
+ public R cleanReferenceResourcesIfBundle(R resource)
+ {
+ if (resource == null)
+ return null;
+
+ if (resource instanceof Bundle)
+ {
+ Bundle bundle = (Bundle) resource;
+ bundle.getEntry().stream().map(e -> e.getResource()).forEach(this::fixBundleEntry);
+ }
+
+ return resource;
+ }
+
+ private void fixBundleEntry(Resource resource)
+ {
+ if (resource instanceof Bundle)
+ {
+ cleanReferenceResourcesIfBundle(resource);
+ }
+ else
+ {
+ Stream references = referenceExtractor.getReferences(resource);
+ references.forEach(r -> r.getReference().setResource(null));
+ }
+ }
+}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java
index 88c69827b..67031ca5c 100644
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java
@@ -3,10 +3,13 @@
import java.util.stream.Stream;
import org.hl7.fhir.r4.model.ActivityDefinition;
+import org.hl7.fhir.r4.model.Binary;
+import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.Endpoint;
import org.hl7.fhir.r4.model.Group;
import org.hl7.fhir.r4.model.HealthcareService;
import org.hl7.fhir.r4.model.Location;
+import org.hl7.fhir.r4.model.NamingSystem;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Practitioner;
@@ -14,7 +17,10 @@
import org.hl7.fhir.r4.model.Provenance;
import org.hl7.fhir.r4.model.ResearchStudy;
import org.hl7.fhir.r4.model.Resource;
+import org.hl7.fhir.r4.model.StructureDefinition;
+import org.hl7.fhir.r4.model.Subscription;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.ValueSet;
public interface ReferenceExtractor
{
@@ -22,6 +28,13 @@ public interface ReferenceExtractor
Stream getReferences(ActivityDefinition resource);
+ Stream getReferences(Binary resource);
+
+ // Not implemented yet, special rules apply for tmp ids
+ // Stream getReferences(Bundle bundle);
+
+ Stream getReferences(CodeSystem resource);
+
Stream getReferences(Endpoint resource);
Stream getReferences(Group group);
@@ -30,6 +43,8 @@ public interface ReferenceExtractor
Stream getReferences(Location resource);
+ Stream getReferences(NamingSystem resource);
+
Stream getReferences(Organization resource);
Stream getReferences(Patient resource);
@@ -42,5 +57,11 @@ public interface ReferenceExtractor
Stream getReferences(ResearchStudy resource);
+ Stream getReferences(StructureDefinition resource);
+
+ Stream getReferences(Subscription resource);
+
Stream getReferences(Task resource);
+
+ Stream getReferences(ValueSet resource);
}
\ No newline at end of file
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java
index 2cb4fb2c2..dc0513fa8 100644
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java
@@ -8,17 +8,21 @@
import org.hl7.fhir.r4.model.ActivityDefinition;
import org.hl7.fhir.r4.model.BackboneElement;
+import org.hl7.fhir.r4.model.Binary;
import org.hl7.fhir.r4.model.CareTeam;
import org.hl7.fhir.r4.model.ClaimResponse;
+import org.hl7.fhir.r4.model.CodeSystem;
import org.hl7.fhir.r4.model.Coverage;
import org.hl7.fhir.r4.model.Device;
import org.hl7.fhir.r4.model.DomainResource;
import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.r4.model.Endpoint;
+import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.Group;
import org.hl7.fhir.r4.model.HealthcareService;
import org.hl7.fhir.r4.model.Location;
import org.hl7.fhir.r4.model.Medication;
+import org.hl7.fhir.r4.model.NamingSystem;
import org.hl7.fhir.r4.model.ObservationDefinition;
import org.hl7.fhir.r4.model.Organization;
import org.hl7.fhir.r4.model.Patient;
@@ -36,8 +40,11 @@
import org.hl7.fhir.r4.model.ResearchStudy;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.SpecimenDefinition;
+import org.hl7.fhir.r4.model.StructureDefinition;
+import org.hl7.fhir.r4.model.Subscription;
import org.hl7.fhir.r4.model.Substance;
import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.ValueSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -142,9 +149,38 @@ private Stream getReferences(E ba
private Stream getExtensionReferences(DomainResource resource)
{
- return resource.getExtension().stream().filter(e -> e.getValue() instanceof Reference)
- .map(e -> (Reference) e.getValue())
+ Stream extensions = resource.getExtension().stream()
+ .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
.map(toResourceReference(resource.getResourceType().name() + ".extension"));
+
+ Stream extensionExtensions = resource.getExtension().stream()
+ .flatMap(e -> getExtensionReferences(resource.getResourceType().name() + ".extension", e));
+
+ return Stream.concat(extensions, extensionExtensions);
+ }
+
+ private Stream getExtensionReferences(String baseElementName, BackboneElement resource)
+ {
+ Stream extensions = resource.getExtension().stream()
+ .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
+ .map(toResourceReference(baseElementName + ".extension"));
+
+ Stream extensionExtensions = resource.getExtension().stream()
+ .flatMap(e -> getExtensionReferences(baseElementName + ".extension", e));
+
+ return Stream.concat(extensions, extensionExtensions);
+ }
+
+ private Stream getExtensionReferences(String baseElementName, Extension resource)
+ {
+ Stream extensions = resource.getExtension().stream()
+ .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue())
+ .map(toResourceReference(baseElementName + ".extension"));
+
+ Stream extensionExtensions = resource.getExtension().stream()
+ .flatMap(e -> getExtensionReferences(baseElementName + ".extension", e));
+
+ return Stream.concat(extensions, extensionExtensions);
}
@SafeVarargs
@@ -166,7 +202,16 @@ public Stream getReferences(Resource resource)
if (resource == null)
return Stream.empty();
- if (resource instanceof Endpoint)
+ if (resource instanceof ActivityDefinition)
+ return getReferences((ActivityDefinition) resource);
+ // not implemented yet, special rules apply for tmp ids
+ // else if (resource instanceof Bundle)
+ // return getReferences((Bundle) resource);
+ else if (resource instanceof Binary)
+ return getReferences((Binary) resource);
+ else if (resource instanceof CodeSystem)
+ return getReferences((CodeSystem) resource);
+ else if (resource instanceof Endpoint)
return getReferences((Endpoint) resource);
else if (resource instanceof Group)
return getReferences((Group) resource);
@@ -174,6 +219,8 @@ else if (resource instanceof HealthcareService)
return getReferences((HealthcareService) resource);
else if (resource instanceof Location)
return getReferences((Location) resource);
+ else if (resource instanceof NamingSystem)
+ return getReferences((NamingSystem) resource);
else if (resource instanceof Organization)
return getReferences((Organization) resource);
else if (resource instanceof Patient)
@@ -186,8 +233,14 @@ else if (resource instanceof Provenance)
return getReferences((Provenance) resource);
else if (resource instanceof ResearchStudy)
return getReferences((ResearchStudy) resource);
+ else if (resource instanceof StructureDefinition)
+ return getReferences((StructureDefinition) resource);
+ else if (resource instanceof Subscription)
+ return getReferences((Subscription) resource);
else if (resource instanceof Task)
return getReferences((Task) resource);
+ else if (resource instanceof ValueSet)
+ return getReferences((ValueSet) resource);
else if (resource instanceof DomainResource)
{
logger.debug("DomainResource of type {} not supported, returning extension references only",
@@ -231,6 +284,29 @@ public Stream getReferences(ActivityDefinition resource)
observationResultRequirement, extensionReferences);
}
+ @Override
+ public Stream getReferences(Binary resource)
+ {
+ if (resource == null)
+ return Stream.empty();
+
+ var securityContext = getReference(resource, Binary::hasSecurityContext, Binary::getSecurityContext,
+ "Binary.securityContext");
+
+ return securityContext;
+ }
+
+ @Override
+ public Stream getReferences(CodeSystem resource)
+ {
+ if (resource == null)
+ return Stream.empty();
+
+ var extensionReferences = getExtensionReferences(resource);
+
+ return extensionReferences;
+ }
+
@Override
public Stream getReferences(Endpoint resource)
{
@@ -288,6 +364,9 @@ public Stream getReferences(HealthcareService resource)
@Override
public Stream getReferences(Location resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var managingOrganization = getReference(resource, Location::hasManagingOrganization,
Location::getManagingOrganization, "Location.managingOrganization", Organization.class);
var partOf = getReference(resource, Location::hasPartOf, Location::getPartOf, "Location.partOf",
@@ -300,9 +379,23 @@ public Stream getReferences(Location resource)
return concat(managingOrganization, partOf, endpoints, extensionReferences);
}
+ @Override
+ public Stream getReferences(NamingSystem resource)
+ {
+ if (resource == null)
+ return Stream.empty();
+
+ var extensionReferences = getExtensionReferences(resource);
+
+ return extensionReferences;
+ }
+
@Override
public Stream getReferences(Organization resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var partOf = getReference(resource, Organization::hasPartOf, Organization::getPartOf, "Organization.partOf",
Organization.class);
var endpoints = getReferences(resource, Organization::hasEndpoint, Organization::getEndpoint,
@@ -316,6 +409,9 @@ public Stream getReferences(Organization resource)
@Override
public Stream getReferences(Patient resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var contactsOrganization = getBackboneElementsReference(resource, Patient::hasContact, Patient::getContact,
ContactComponent::hasOrganization, ContactComponent::getOrganization, "Patient.contact.organization",
Organization.class);
@@ -337,6 +433,9 @@ public Stream getReferences(Patient resource)
@Override
public Stream getReferences(Practitioner resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var qualificationsIssuer = getBackboneElementsReference(resource, Practitioner::hasQualification,
Practitioner::getQualification, PractitionerQualificationComponent::hasIssuer,
PractitionerQualificationComponent::getIssuer, "Practitioner.qualification.issuer", Organization.class);
@@ -349,6 +448,9 @@ public Stream getReferences(Practitioner resource)
@Override
public Stream getReferences(PractitionerRole resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var practitioner = getReference(resource, PractitionerRole::hasPractitioner, PractitionerRole::getPractitioner,
"PractitionerRole.practitioner", Practitioner.class);
var organization = getReference(resource, PractitionerRole::hasOrganization, PractitionerRole::getOrganization,
@@ -368,6 +470,9 @@ public Stream getReferences(PractitionerRole resource)
@Override
public Stream getReferences(Provenance resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var targets = getReferences(resource, Provenance::hasTarget, Provenance::getTarget, "Provenance.target");
var location = getReference(resource, Provenance::hasLocation, Provenance::getLocation, "Provenance.location",
Location.class);
@@ -390,6 +495,9 @@ public Stream getReferences(Provenance resource)
@Override
public Stream getReferences(ResearchStudy resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var protocols = getReferences(resource, ResearchStudy::hasProtocol, ResearchStudy::getProtocol,
"ResearchStudy.protocol", PlanDefinition.class);
var partOfs = getReferences(resource, ResearchStudy::hasPartOf, ResearchStudy::getPartOf,
@@ -409,9 +517,34 @@ public Stream getReferences(ResearchStudy resource)
return concat(protocols, partOfs, enrollments, sponsor, principalInvestigator, sites, extensionReferences);
}
+ @Override
+ public Stream getReferences(StructureDefinition resource)
+ {
+ if (resource == null)
+ return Stream.empty();
+
+ var extensionReferences = getExtensionReferences(resource);
+
+ return extensionReferences;
+ }
+
+ @Override
+ public Stream getReferences(Subscription resource)
+ {
+ if (resource == null)
+ return Stream.empty();
+
+ var extensionReferences = getExtensionReferences(resource);
+
+ return extensionReferences;
+ }
+
@Override
public Stream getReferences(Task resource)
{
+ if (resource == null)
+ return Stream.empty();
+
var basedOns = getReferences(resource, Task::hasBasedOn, Task::getBasedOn, "Task.basedOn");
var partOfs = getReferences(resource, Task::hasPartOf, Task::getPartOf, "Task.partOf", Task.class);
var focus = getReference(resource, Task::hasFocus, Task::getFocus, "Task.focus");
@@ -439,21 +572,49 @@ public Stream getReferences(Task resource)
var outputReferences = getOutputReferences(resource);
var extensionReferences = getExtensionReferences(resource);
- return concat(basedOns, partOfs, focus, forRef, encounter, requester, owner, location, reasonReference, insurance,
- relevanteHistories, restrictionRecipiets, inputReferences, outputReferences, extensionReferences);
+ return concat(basedOns, partOfs, focus, forRef, encounter, requester, owner, location, reasonReference,
+ insurance, relevanteHistories, restrictionRecipiets, inputReferences, outputReferences,
+ extensionReferences);
}
private Stream getInputReferences(Task resource)
{
- return resource.getInput().stream().filter(in -> in.getValue() instanceof Reference)
- .map(in -> (Reference) in.getValue())
+ if (resource == null)
+ return Stream.empty();
+
+ Stream inputReferences = resource.getInput().stream()
+ .filter(in -> in.getValue() instanceof Reference).map(in -> (Reference) in.getValue())
.map(toResourceReference(resource.getResourceType().name() + ".input"));
+
+ Stream inputExtensionReferences = resource.getInput().stream()
+ .flatMap(in -> getExtensionReferences(resource.getResourceType().name() + ".input", in));
+
+ return Stream.concat(inputReferences, inputExtensionReferences);
}
private Stream getOutputReferences(Task resource)
{
- return resource.getOutput().stream().filter(out -> out.getValue() instanceof Reference)
- .map(out -> (Reference) out.getValue())
+ if (resource == null)
+ return Stream.empty();
+
+ Stream outputReferences = resource.getOutput().stream()
+ .filter(out -> out.getValue() instanceof Reference).map(in -> (Reference) in.getValue())
.map(toResourceReference(resource.getResourceType().name() + ".output"));
+
+ Stream outputExtensionReferences = resource.getOutput().stream()
+ .flatMap(out -> getExtensionReferences(resource.getResourceType().name() + ".output", out));
+
+ return Stream.concat(outputReferences, outputExtensionReferences);
+ }
+
+ @Override
+ public Stream getReferences(ValueSet resource)
+ {
+ if (resource == null)
+ return Stream.empty();
+
+ var extensionReferences = getExtensionReferences(resource);
+
+ return extensionReferences;
}
}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java
index 3a871fb86..da5913c63 100644
--- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java
@@ -135,9 +135,14 @@ public boolean supportsType(Class extends Resource> type)
}
/**
+ * Determines the {@link ReferenceType} based {@link Reference#getReference()} first and then looks at
+ * {@link Reference#getIdentifier()}
+ *
* @param localServerBase
* not null
- * @return
+ * @return one of this priority list: {@link ReferenceType#TEMPORARY}, {@link ReferenceType#LITERAL_INTERNAL},
+ * {@link ReferenceType#LITERAL_EXTERNAL}, {@link ReferenceType#CONDITIONAL}, {@link ReferenceType#LOGICAL},
+ * {@link ReferenceType#UNKNOWN}
*/
public ReferenceType getType(String localServerBase)
{
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/test/java/org/highmed/dsf/fhir/service/ReferenceExtractorTest.java b/dsf-fhir/dsf-fhir-rest-adapter/src/test/java/org/highmed/dsf/fhir/service/ReferenceExtractorTest.java
new file mode 100644
index 000000000..3ddd2cd56
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/test/java/org/highmed/dsf/fhir/service/ReferenceExtractorTest.java
@@ -0,0 +1,54 @@
+package org.highmed.dsf.fhir.service;
+
+import static org.junit.Assert.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.hl7.fhir.r4.model.Extension;
+import org.hl7.fhir.r4.model.Reference;
+import org.hl7.fhir.r4.model.StringType;
+import org.hl7.fhir.r4.model.Task;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReferenceExtractorTest
+{
+ private static final Logger logger = LoggerFactory.getLogger(ReferenceExtractorTest.class);
+
+ private ReferenceExtractor referenceExtractor;
+
+ @Before
+ public void before() throws Exception
+ {
+ referenceExtractor = new ReferenceExtractorImpl();
+ }
+
+ @Test
+ public void testExtractTaskReferences() throws Exception
+ {
+ Extension e0 = new Extension("url0", new Reference("task.ref"));
+ Extension e1 = new Extension("url1", new Reference("task.input.extension.ref"));
+ Extension e2 = new Extension("url2", new StringType("value"));
+ Extension e3 = new Extension("url3", new Reference("task.input.extension.extension.extension.ref"));
+ e1.addExtension(e2);
+ e2.addExtension(e3);
+
+ Task t = new Task();
+ t.addExtension(e0);
+ t.addInput().setValue(new Reference("task.input.ref")).addExtension(e1);
+
+ List refs = referenceExtractor.getReferences(t).collect(Collectors.toList());
+
+ logger.debug("refs: {}", refs.stream().map(r -> r.getReferenceLocation()).collect(Collectors.toList()));
+
+ assertNotNull(refs);
+ assertEquals(4, refs.size());
+ assertEquals("task.input.ref", refs.get(0).getReference().getReference());
+ assertEquals("task.input.extension.ref", refs.get(1).getReference().getReference());
+ assertEquals("task.input.extension.extension.extension.ref", refs.get(2).getReference().getReference());
+ assertEquals("task.ref", refs.get(3).getReference().getReference());
+ }
+}
diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/test/resources/log4j2.xml b/dsf-fhir/dsf-fhir-rest-adapter/src/test/resources/log4j2.xml
new file mode 100644
index 000000000..9999bb653
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-rest-adapter/src/test/resources/log4j2.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dsf-fhir/dsf-fhir-server-jetty/docker/.dockerignore b/dsf-fhir/dsf-fhir-server-jetty/docker/.dockerignore
index 91816beee..6024446f9 100755
--- a/dsf-fhir/dsf-fhir-server-jetty/docker/.dockerignore
+++ b/dsf-fhir/dsf-fhir-server-jetty/docker/.dockerignore
@@ -1,5 +1,6 @@
-.dockerignore
-Dockerfile
-conf/README.md
-lib/.gitignore
+.dockerignore
+.gitignore
+Dockerfile
+conf/README.md
+lib/.gitignore
log/README.md
\ No newline at end of file
diff --git a/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile b/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile
index 823d2cc14..0eedb083c 100755
--- a/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile
+++ b/dsf-fhir/dsf-fhir-server-jetty/docker/Dockerfile
@@ -1,12 +1,21 @@
+FROM debian:buster-slim AS builder
+RUN adduser --system --no-create-home --group --uid 2101 java
+WORKDIR /opt/fhir
+COPY --chown=root:java ./ ./
+RUN chown root:java ./ && \
+ chmod 750 ./ ./lib ./dsf_fhir_start.sh && \
+ chmod 640 ./dsf_fhir.jar ./lib/*.jar && \
+ chmod 1775 ./log
+
+
FROM openjdk:11-slim
-MAINTAINER Hauke Hund
+LABEL maintainer="hauke.hund@hs-heilbronn.de"
EXPOSE 8080
RUN adduser --system --no-create-home --group --uid 2101 java
WORKDIR /opt/fhir
-COPY --chown=root:java ./ ./
-RUN chown root:java ./ && chmod 750 ./ ./lib ./dsf_fhir_start.sh && chmod 640 ./dsf_fhir.jar ./lib/*.jar && chmod 1775 ./log
+COPY --from=builder /opt/fhir ./
USER java
ENTRYPOINT ["./dsf_fhir_start.sh"]
diff --git a/dsf-fhir/dsf-fhir-server-jetty/pom.xml b/dsf-fhir/dsf-fhir-server-jetty/pom.xml
index 89cb065e5..bc0708572 100755
--- a/dsf-fhir/dsf-fhir-server-jetty/pom.xml
+++ b/dsf-fhir/dsf-fhir-server-jetty/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-fhir-pom
- 0.1.0
+ 0.2.0
@@ -46,7 +46,6 @@
javax.mail
mail
- 1.4.7
diff --git a/dsf-fhir/dsf-fhir-server/pom.xml b/dsf-fhir/dsf-fhir-server/pom.xml
index fe3647577..a215c4927 100755
--- a/dsf-fhir/dsf-fhir-server/pom.xml
+++ b/dsf-fhir/dsf-fhir-server/pom.xml
@@ -7,7 +7,7 @@
org.highmed.dsf
dsf-fhir-pom
- 0.1.0
+ 0.2.0
@@ -79,6 +79,10 @@
ca.uhn.hapi.fhir
hapi-fhir-structures-r4
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-structures-r5
+
ca.uhn.hapi.fhir
hapi-fhir-validation
@@ -88,18 +92,8 @@
hapi-fhir-validation-resources-r4
- com.helger
- ph-schematron
-
-
- org.glassfish.jaxb
- jaxb-core
-
-
- com.helger
- ph-jaxb-pom
-
-
+ ca.uhn.hapi.fhir
+ hapi-fhir-validation-resources-r5
@@ -141,11 +135,12 @@
javax-websocket-server-impl
test
-
+
+
org.mockito
mockito-core
@@ -157,6 +152,19 @@
org.highmed.dsf
dsf-tools-bundle-generator
+ runtime
+
+
+ de.hs-heilbronn.mi
+ log4j2-utils
+ runtime
+
+
+
+
+ com.lmax
+ disruptor
+ test
@@ -209,6 +217,7 @@
${project.basedir}/src/main/resources/fhir
${project.basedir}
+ false
@@ -216,7 +225,7 @@
-
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java
index 69f0711db..b7bdfcc71 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java
@@ -118,20 +118,6 @@ public final Optional reasonDeleteAllowed(User user, R oldResource)
}
}
- @Override
- public final Optional reasonSearchAllowed(User user)
- {
- try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction())
- {
- return reasonSearchAllowed(connection, user);
- }
- catch (SQLException e)
- {
- logger.warn("Error while accessing database", e);
- throw new RuntimeException(e);
- }
- }
-
protected final boolean isLocalUser(User user)
{
return user != null && UserRole.LOCAL.equals(user.getRole());
@@ -201,11 +187,11 @@ protected final boolean isCurrentUserPartOfReferencedOrganization(Connection con
{
ResourceReference resReference = new ResourceReference(referenceLocation, reference, Organization.class);
- if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL)
- .contains(resReference.getType(serverBase)))
+ ReferenceType type = resReference.getType(serverBase);
+ if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(type))
{
logger.warn("Reference of type {} not supported while checking if user part of referenced organization",
- resReference.getType(serverBase));
+ type);
return false;
}
@@ -247,7 +233,8 @@ protected final Optional createIfLiteralInternalOrLogicalRefe
Reference reference, Class extends Resource>... referenceTypes)
{
ResourceReference r = new ResourceReference(referenceLocation, reference, referenceTypes);
- if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(r.getType(serverBase)))
+ ReferenceType type = r.getType(serverBase);
+ if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(type))
return Optional.of(r);
else
return Optional.empty();
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java
index cbe5a5d92..a2c9a3314 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java
@@ -224,10 +224,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Ac
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of ActivityDefinition authorized for {} user '{}', will be fitered by user role",
user.getRole(), user.getName());
return Optional.of("Allowed for all, filtered by user role");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of ActivityDefinition authorized for {} user '{}', will be fitered by user role",
+ user.getRole(), user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java
index 24064cb1c..8d8b54d42 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java
@@ -124,5 +124,5 @@ public interface AuthorizationRule
* not null
* @return Reason as String in {@link Optional#of(Object)} if delete allowed
*/
- Optional reasonSearchAllowed(Connection connection, User user);
+ Optional reasonHistoryAllowed(User user);
}
\ No newline at end of file
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java
index d966d7525..0af345947 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java
@@ -2,45 +2,65 @@
import java.util.Optional;
+import org.hl7.fhir.r4.model.ActivityDefinition;
+import org.hl7.fhir.r4.model.Binary;
+import org.hl7.fhir.r4.model.Bundle;
+import org.hl7.fhir.r4.model.CodeSystem;
+import org.hl7.fhir.r4.model.Endpoint;
+import org.hl7.fhir.r4.model.Group;
+import org.hl7.fhir.r4.model.HealthcareService;
+import org.hl7.fhir.r4.model.Location;
+import org.hl7.fhir.r4.model.NamingSystem;
+import org.hl7.fhir.r4.model.Organization;
+import org.hl7.fhir.r4.model.Patient;
+import org.hl7.fhir.r4.model.Practitioner;
+import org.hl7.fhir.r4.model.PractitionerRole;
+import org.hl7.fhir.r4.model.Provenance;
+import org.hl7.fhir.r4.model.ResearchStudy;
+import org.hl7.fhir.r4.model.StructureDefinition;
+import org.hl7.fhir.r4.model.Subscription;
+import org.hl7.fhir.r4.model.Task;
+import org.hl7.fhir.r4.model.ValueSet;
+
public interface AuthorizationRuleProvider
{
- ActivityDefinitionAuthorizationRule getActivityDefinitionAuthorizationRule();
+ AuthorizationRule getActivityDefinitionAuthorizationRule();
- BinaryAuthorizationRule getBinaryAuthorizationRule();
+ AuthorizationRule getBinaryAuthorizationRule();
- BundleAuthorizationRule getBundleAuthorizationRule();
+ AuthorizationRule getBundleAuthorizationRule();
- CodeSystemAuthorizationRule getCodeSystemAuthorizationRule();
+ AuthorizationRule getCodeSystemAuthorizationRule();
- EndpointAuthorizationRule getEndpointAuthorizationRule();
+ AuthorizationRule getEndpointAuthorizationRule();
- GroupAuthorizationRule getGroupAuthorizationRule();
+ AuthorizationRule getGroupAuthorizationRule();
- HealthcareServiceAuthorizationRule getHealthcareServiceAuthorizationRule();
+ AuthorizationRule getHealthcareServiceAuthorizationRule();
- LocationAuthorizationRule getLocationAuthorizationRule();
+ AuthorizationRule getLocationAuthorizationRule();
- NamingSystemAuthorizationRule getNamingSystemAuthorizationRule();
+ AuthorizationRule getNamingSystemAuthorizationRule();
- OrganizationAuthorizationRule getOrganizationAuthorizationRule();
+ AuthorizationRule getOrganizationAuthorizationRule();
- PatientAuthorizationRule getPatientAuthorizationRule();
+ AuthorizationRule getPatientAuthorizationRule();
- PractitionerAuthorizationRule getPractitionerAuthorizationRule();
+ AuthorizationRule getPractitionerAuthorizationRule();
- PractitionerRoleAuthorizationRule getPractitionerRoleAuthorizationRule();
+ AuthorizationRule getPractitionerRoleAuthorizationRule();
- ProvenanceAuthorizationRule getProvenanceAuthorizationRule();
+ AuthorizationRule getProvenanceAuthorizationRule();
- ResearchStudyAuthorizationRule getResearchStudyAuthorizationRule();
+ AuthorizationRule getResearchStudyAuthorizationRule();
- StructureDefinitionAuthorizationRule getStructureDefinitionAuthorizationRule();
+ AuthorizationRule getStructureDefinitionAuthorizationRule();
- SubscriptionAuthorizationRule getSubscriptionAuthorizationRule();
+ AuthorizationRule getSubscriptionAuthorizationRule();
- TaskAuthorizationRule getTaskAuthorizationRule();
+ AuthorizationRule getTaskAuthorizationRule();
- ValueSetAuthorizationRule getValueSetAuthorizationRule();
+ AuthorizationRule getValueSetAuthorizationRule();
Optional> getAuthorizationRule(Class> resourceClass);
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java
index 4af4770e5..6310cfee5 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java
@@ -29,45 +29,45 @@
public class AuthorizationRuleProviderImpl implements AuthorizationRuleProvider
{
- private final ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule;
- private final BinaryAuthorizationRule binaryAuthorizationRule;
- private final BundleAuthorizationRule bundleAuthorizationRule;
- private final CodeSystemAuthorizationRule codeSystemAuthorizationRule;
- private final EndpointAuthorizationRule endpointAuthorizationRule;
- private final GroupAuthorizationRule groupAuthorizationRule;
- private final HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule;
- private final LocationAuthorizationRule locationAuthorizationRule;
- private final NamingSystemAuthorizationRule namingSystemAuthorizationRule;
- private final OrganizationAuthorizationRule organizationAuthorizationRule;
- private final PatientAuthorizationRule patientAuthorizationRule;
- private final PractitionerAuthorizationRule practitionerAuthorizationRule;
- private final PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule;
- private final ProvenanceAuthorizationRule provenanceAuthorizationRule;
- private final ResearchStudyAuthorizationRule researchStudyAuthorizationRule;
- private final StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule;
- private final SubscriptionAuthorizationRule subscriptionAuthorizationRule;
- private final TaskAuthorizationRule taskAuthorizationRule;
- private final ValueSetAuthorizationRule valueSetAuthorizationRule;
+ private final AuthorizationRule activityDefinitionAuthorizationRule;
+ private final AuthorizationRule binaryAuthorizationRule;
+ private final AuthorizationRule bundleAuthorizationRule;
+ private final AuthorizationRule codeSystemAuthorizationRule;
+ private final AuthorizationRule endpointAuthorizationRule;
+ private final AuthorizationRule groupAuthorizationRule;
+ private final AuthorizationRule healthcareServiceAuthorizationRule;
+ private final AuthorizationRule locationAuthorizationRule;
+ private final AuthorizationRule namingSystemAuthorizationRule;
+ private final AuthorizationRule organizationAuthorizationRule;
+ private final AuthorizationRule patientAuthorizationRule;
+ private final AuthorizationRule practitionerAuthorizationRule;
+ private final AuthorizationRule practitionerRoleAuthorizationRule;
+ private final AuthorizationRule provenanceAuthorizationRule;
+ private final AuthorizationRule researchStudyAuthorizationRule;
+ private final AuthorizationRule structureDefinitionAuthorizationRule;
+ private final AuthorizationRule subscriptionAuthorizationRule;
+ private final AuthorizationRule taskAuthorizationRule;
+ private final AuthorizationRule valueSetAuthorizationRule;
private final Map, AuthorizationRule>> authorizationRulesByResourecClass = new HashMap<>();
private final Map> authorizationRulesByResourceTypeName = new HashMap<>();
- public AuthorizationRuleProviderImpl(ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule,
- BinaryAuthorizationRule binaryAuthorizationRule, BundleAuthorizationRule bundleAuthorizationRule,
- CodeSystemAuthorizationRule codeSystemAuthorizationRule,
- EndpointAuthorizationRule endpointAuthorizationRule, GroupAuthorizationRule groupAuthorizationRule,
- HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule,
- LocationAuthorizationRule locationAuthorizationRule,
- NamingSystemAuthorizationRule namingSystemAuthorizationRule,
- OrganizationAuthorizationRule organizationAuthorizationRule,
- PatientAuthorizationRule patientAuthorizationRule,
- PractitionerAuthorizationRule practitionerAuthorizationRule,
- PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule,
- ProvenanceAuthorizationRule provenanceAuthorizationRule,
- ResearchStudyAuthorizationRule researchStudyAuthorizationRule,
- StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule,
- SubscriptionAuthorizationRule subscriptionAuthorizationRule, TaskAuthorizationRule taskAuthorizationRule,
- ValueSetAuthorizationRule valueSetAuthorizationRule)
+ public AuthorizationRuleProviderImpl(AuthorizationRule activityDefinitionAuthorizationRule,
+ AuthorizationRule binaryAuthorizationRule, AuthorizationRule bundleAuthorizationRule,
+ AuthorizationRule codeSystemAuthorizationRule,
+ AuthorizationRule endpointAuthorizationRule, AuthorizationRule groupAuthorizationRule,
+ AuthorizationRule healthcareServiceAuthorizationRule,
+ AuthorizationRule locationAuthorizationRule,
+ AuthorizationRule namingSystemAuthorizationRule,
+ AuthorizationRule organizationAuthorizationRule,
+ AuthorizationRule patientAuthorizationRule,
+ AuthorizationRule practitionerAuthorizationRule,
+ AuthorizationRule practitionerRoleAuthorizationRule,
+ AuthorizationRule provenanceAuthorizationRule,
+ AuthorizationRule researchStudyAuthorizationRule,
+ AuthorizationRule structureDefinitionAuthorizationRule,
+ AuthorizationRule subscriptionAuthorizationRule,
+ AuthorizationRule taskAuthorizationRule, AuthorizationRule valueSetAuthorizationRule)
{
this.activityDefinitionAuthorizationRule = activityDefinitionAuthorizationRule;
this.binaryAuthorizationRule = binaryAuthorizationRule;
@@ -114,115 +114,115 @@ public AuthorizationRuleProviderImpl(ActivityDefinitionAuthorizationRule activit
}
@Override
- public ActivityDefinitionAuthorizationRule getActivityDefinitionAuthorizationRule()
+ public AuthorizationRule getActivityDefinitionAuthorizationRule()
{
return activityDefinitionAuthorizationRule;
}
@Override
- public BinaryAuthorizationRule getBinaryAuthorizationRule()
+ public AuthorizationRule getBinaryAuthorizationRule()
{
return binaryAuthorizationRule;
}
@Override
- public BundleAuthorizationRule getBundleAuthorizationRule()
+ public AuthorizationRule getBundleAuthorizationRule()
{
return bundleAuthorizationRule;
}
@Override
- public CodeSystemAuthorizationRule getCodeSystemAuthorizationRule()
+ public AuthorizationRule getCodeSystemAuthorizationRule()
{
return codeSystemAuthorizationRule;
}
@Override
- public EndpointAuthorizationRule getEndpointAuthorizationRule()
+ public AuthorizationRule getEndpointAuthorizationRule()
{
return endpointAuthorizationRule;
}
@Override
- public GroupAuthorizationRule getGroupAuthorizationRule()
+ public AuthorizationRule getGroupAuthorizationRule()
{
return groupAuthorizationRule;
}
@Override
- public HealthcareServiceAuthorizationRule getHealthcareServiceAuthorizationRule()
+ public AuthorizationRule getHealthcareServiceAuthorizationRule()
{
return healthcareServiceAuthorizationRule;
}
@Override
- public LocationAuthorizationRule getLocationAuthorizationRule()
+ public AuthorizationRule getLocationAuthorizationRule()
{
return locationAuthorizationRule;
}
@Override
- public NamingSystemAuthorizationRule getNamingSystemAuthorizationRule()
+ public AuthorizationRule getNamingSystemAuthorizationRule()
{
return namingSystemAuthorizationRule;
}
@Override
- public OrganizationAuthorizationRule getOrganizationAuthorizationRule()
+ public AuthorizationRule getOrganizationAuthorizationRule()
{
return organizationAuthorizationRule;
}
@Override
- public PatientAuthorizationRule getPatientAuthorizationRule()
+ public AuthorizationRule getPatientAuthorizationRule()
{
return patientAuthorizationRule;
}
@Override
- public PractitionerAuthorizationRule getPractitionerAuthorizationRule()
+ public AuthorizationRule getPractitionerAuthorizationRule()
{
return practitionerAuthorizationRule;
}
@Override
- public PractitionerRoleAuthorizationRule getPractitionerRoleAuthorizationRule()
+ public AuthorizationRule getPractitionerRoleAuthorizationRule()
{
return practitionerRoleAuthorizationRule;
}
@Override
- public ProvenanceAuthorizationRule getProvenanceAuthorizationRule()
+ public AuthorizationRule getProvenanceAuthorizationRule()
{
return provenanceAuthorizationRule;
}
@Override
- public ResearchStudyAuthorizationRule getResearchStudyAuthorizationRule()
+ public AuthorizationRule getResearchStudyAuthorizationRule()
{
return researchStudyAuthorizationRule;
}
@Override
- public StructureDefinitionAuthorizationRule getStructureDefinitionAuthorizationRule()
+ public AuthorizationRule getStructureDefinitionAuthorizationRule()
{
return structureDefinitionAuthorizationRule;
}
@Override
- public SubscriptionAuthorizationRule getSubscriptionAuthorizationRule()
+ public AuthorizationRule getSubscriptionAuthorizationRule()
{
return subscriptionAuthorizationRule;
}
@Override
- public TaskAuthorizationRule getTaskAuthorizationRule()
+ public AuthorizationRule getTaskAuthorizationRule()
{
return taskAuthorizationRule;
}
@Override
- public ValueSetAuthorizationRule getValueSetAuthorizationRule()
+ public AuthorizationRule getValueSetAuthorizationRule()
{
return valueSetAuthorizationRule;
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java
index f7012ba20..fa6380629 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java
@@ -119,10 +119,11 @@ public Optional reasonUpdateAllowed(Connection connection, User user, Bi
oldResource.getSecurityContext(), Organization.class);
ResourceReference newReference = new ResourceReference("Binary.SecurityContext",
newResource.getSecurityContext(), Organization.class);
- if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL)
- .contains(oldReference.getType(serverBase))
- && EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL)
- .contains(newReference.getType(serverBase)))
+ ReferenceType oldType = oldReference.getType(serverBase);
+ ReferenceType newType = newReference.getType(serverBase);
+
+ if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(oldType)
+ && EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(newType))
{
Optional oldSecurityContext = referenceResolver.resolveReference(user, oldReference,
connection);
@@ -188,10 +189,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Bi
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of Binary authorized for {} user '{}', will be fitered by users organization {}",
user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
return Optional.of("Allowed for all, filtered by users organization");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Binary authorized for {} user '{}', will be fitered by users organization {}",
+ user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
+ return Optional.of("Allowed for all, filtered by users organization");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java
index b6e9e599e..94b3ee0f2 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java
@@ -67,7 +67,7 @@ private Optional newResourceOk(Bundle newResource)
@Override
public Optional reasonReadAllowed(Connection connection, User user, Bundle existingResource)
{
- if (isLocalUser(user) && hasLocalAuthorizationRole(existingResource))
+ if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource))
{
logger.info("Read of Bundle authorized for local user '{}', Bundle has local or remote authorization role",
user.getName());
@@ -127,10 +127,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Bu
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of Bundle authorized for {} user '{}', will be fitered by user role", user.getRole(),
user.getName());
return Optional.of("Allowed for all, filtered by user role");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Bundle authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java
index a6c6f9cf5..73267f41d 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java
@@ -145,10 +145,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Co
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of CodeSystem authorized for {} user '{}', will be fitered by user role", user.getRole(),
user.getName());
return Optional.of("Allowed for all, filtered by user role");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of CodeSystem authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java
index 14967c401..4ecd8c04f 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java
@@ -132,7 +132,7 @@ private boolean endpointWithAddressExists(Connection connection, String address)
try
{
PartialResult result = dao.searchWithTransaction(connection, query);
- return result.getOverallCount() >= 1;
+ return result.getTotal() >= 1;
}
catch (SQLException e)
{
@@ -154,7 +154,7 @@ private boolean endpointWithIdentifierExists(Connection connection, String ident
try
{
PartialResult result = dao.searchWithTransaction(connection, query);
- return result.getOverallCount() >= 1;
+ return result.getTotal() >= 1;
}
catch (SQLException e)
{
@@ -257,10 +257,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, En
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of Endpoint authorized for {} user '{}', will be fitered by user role", user.getRole(),
user.getName());
return Optional.of("Allowed for all, filtered by user role");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Endpoint authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java
index 91f527cdb..c8db841a2 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java
@@ -118,10 +118,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Gr
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of Group authorized for {} user '{}', will be fitered by users organization {}",
user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
return Optional.of("Allowed for all, filtered by users organization");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Group authorized for {} user '{}', will be fitered by users organization {}",
+ user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
+ return Optional.of("Allowed for all, filtered by users organization");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java
index bd3fdb272..05e531c70 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java
@@ -96,10 +96,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, He
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
- logger.info("Search of HealthcareService authorized for {} user '{}', will be fitered by users organization {}",
- user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
- return Optional.of("Allowed for all, filtered by users organization");
+ logger.info("Search of HealthcareService authorized for {} user '{}', will be fitered by user role",
+ user.getRole(), user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of HealthcareService authorized for {} user '{}', will be fitered by user role",
+ user.getRole(), user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
}
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java
index 38a3aa8bc..c84936d35 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java
@@ -93,10 +93,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Lo
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
- logger.info("Search of Location authorized for {} user '{}', will be fitered by users organization {}",
- user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
- return Optional.of("Allowed for all, filtered by users organization");
+ logger.info("Search of Location authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Location authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
}
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java
index 1c59a5ffb..d363c5580 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java
@@ -143,10 +143,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Na
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of NamingSystem authorized for {} user '{}', will be fitered by user role", user.getRole(),
user.getName());
return Optional.of("Allowed for all, filtered by user role");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of NamingSystem authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java
index fbf4c241d..34b232381 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java
@@ -160,7 +160,7 @@ private boolean organizationWithIdentifierExists(Connection connection, String i
try
{
PartialResult result = dao.searchWithTransaction(connection, query);
- return result.getOverallCount() >= 1;
+ return result.getTotal() >= 1;
}
catch (SQLException e)
{
@@ -272,10 +272,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Or
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of Organization authorized for {} user '{}', will be fitered by user role", user.getRole(),
user.getName());
return Optional.of("Allowed for all, filtered by user role");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Organization authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java
index 235657d8a..5e57e11c5 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java
@@ -85,10 +85,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Pa
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
- logger.info("Search of Patient authorized for {} user '{}', will be fitered by users organization {}",
- user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
- return Optional.of("Allowed for all, filtered by users organization");
+ logger.info("Search of Patient authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Patient authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
}
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java
index 4349b2f55..b581ad926 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java
@@ -120,7 +120,7 @@ private boolean practitionerRoleWithPractitionerAndUsersOrganizationExists(Conne
try
{
PartialResult result = dao.searchWithTransaction(connection, query);
- return result.getOverallCount() > 0;
+ return result.getTotal() > 0;
}
catch (SQLException e)
{
@@ -162,10 +162,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Pr
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
- logger.info("Search of Practitioner authorized for {} user '{}', will be fitered by users organization {}",
- user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
- return Optional.of("Allowed for all, filtered by users organization");
+ logger.info("Search of Practitioner authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
+ }
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Practitioner authorized for {} user '{}', will be fitered by user role", user.getRole(),
+ user.getName());
+ return Optional.of("Allowed for all, filtered by user role");
}
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java
index e4cbec732..5f52d2b59 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java
@@ -223,10 +223,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Pr
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of PractitionerRole authorized for {} user '{}', will be fitered by users organization {}",
user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
return Optional.of("Allowed for all, filtered by users organization");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of PractitionerRole authorized for {} user '{}', will be fitered by users organization {}",
+ user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
+ return Optional.of("Allowed for all, filtered by users organization");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java
index cbf41e9d2..a061cd939 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java
@@ -85,10 +85,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Pr
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of Provenance authorized for {} user '{}', will be fitered by users organization {}",
user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
return Optional.of("Allowed for all, filtered by users organization");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of Provenance authorized for {} user '{}', will be fitered by users organization {}",
+ user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
+ return Optional.of("Allowed for all, filtered by users organization");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java
index 92fe9c4c7..d786f57a2 100644
--- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java
@@ -145,6 +145,8 @@ private Optional newResourceOk(Connection connection, User user, Researc
errors.add("ResearchStudy.enrollment one or more Group references missing");
}
+ // TODO: hasPrincipalInvestigator check is only optional for Feasability Requests. For full Data Sharing
+ // processes, the field is mandatory and should lead to a validation error if not supplied.
if (newResource.hasPrincipalInvestigator())
{
Optional practitioner = resolvePractitioner(connection, user,
@@ -164,10 +166,6 @@ private Optional newResourceOk(Connection connection, User user, Researc
"ResearchStudy.principalInvestigator not resolved or not instance of Practitioner or not active");
}
}
- else
- {
- errors.add("ResearchStudy.principalInvestigator missing");
- }
if (errors.isEmpty())
return Optional.empty();
@@ -221,7 +219,7 @@ private boolean practitionerRoleExists(Connection connection, User user, IdType
try
{
- return dao.searchWithTransaction(connection, query).getOverallCount() == 1;
+ return dao.searchWithTransaction(connection, query).getTotal() == 1;
}
catch (SQLException e)
{
@@ -253,7 +251,7 @@ private boolean researchStudyWithIdentifierExists(Connection connection, String
try
{
PartialResult result = dao.searchWithTransaction(connection, query);
- return result.getOverallCount() >= 1;
+ return result.getTotal() >= 1;
}
catch (SQLException e)
{
@@ -400,10 +398,18 @@ public Optional reasonDeleteAllowed(Connection connection, User user, Re
}
@Override
- public Optional reasonSearchAllowed(Connection connection, User user)
+ public Optional reasonSearchAllowed(User user)
{
logger.info("Search of ResearchStudy authorized for {} user '{}', will be fitered by users organization {}",
user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
return Optional.of("Allowed for all, filtered by users organization");
}
+
+ @Override
+ public Optional reasonHistoryAllowed(User user)
+ {
+ logger.info("History of ResearchStudy authorized for {} user '{}', will be fitered by users organization {}",
+ user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString());
+ return Optional.of("Allowed for all, filtered by users organization");
+ }
}
diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/RootAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/RootAuthorizationRule.java
new file mode 100644
index 000000000..ad75c176a
--- /dev/null
+++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/RootAuthorizationRule.java
@@ -0,0 +1,77 @@
+package org.highmed.dsf.fhir.authorization;
+
+import java.sql.Connection;
+import java.util.Optional;
+
+import org.highmed.dsf.fhir.authentication.User;
+import org.hl7.fhir.r4.model.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RootAuthorizationRule implements AuthorizationRule
+{
+ private static final Logger logger = LoggerFactory.getLogger(RootAuthorizationRule.class);
+
+ @Override
+ public Optional reasonCreateAllowed(User user, Resource newResource)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Optional