diff --git a/README.md b/README.md index 2084f47b..830a4023 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,11 @@ Prerequisite: Java 11, Maven >= 3.6 ``` mvn clean install (-P copy-to-highmed-dsf-process) - ``` + ``` + +## Executing the Processes +The HiGHmed DSF Wiki includes a section about [Manual Integration Testing](https://github.com/highmed/highmed-dsf/wiki/Build-and-Test-Project#manual-integration-testing-vms-for-docker-registry-3-medics-ttp), with detailed descriptions on how to run the processes in a simulated testing environment consisting of 3 MeDICs and 1 TTP. Example implementations to start a process can be found in the respective Maven sub-modules under `src/test/java` in the package `org.highmed.dsf.bpe.start`. + ## Implementing new Processes Instructions on how to implement a new process can be found in the HiGHmed DSF Wiki page with the name [Adding a new BPMN Process](https://github.com/highmed/highmed-dsf/wiki/Adding-BPMN-Processes). \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/README.md b/dsf-bpe-process-data-sharing/README.md new file mode 100644 index 00000000..ed2e4608 --- /dev/null +++ b/dsf-bpe-process-data-sharing/README.md @@ -0,0 +1,14 @@ +## Properties + +**MeDIC** +`keytool -genseckey -alias -keyalg aes -keysize 256 -keystore organization-keystore.p12 -storetype pkcs12` +where `` is the same as the property `org.highmed.dsf.bpe.fhir.organization.identifier.localValue` and the password for the key + +* org.highmed.dsf.bpe.psn.organization.keystore=conf/organization-keystore.p12 +* org.highmed.dsf.bpe.psn.organization.keystore.password=password + +**TTP** +Keystore will be created if none exists + +* org.highmed.dsf.bpe.psn.research.study.keystore=conf/research-study-keystore.p12 +* org.highmed.dsf.bpe.psn.research.study.keystore.password=password \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/pom.xml b/dsf-bpe-process-data-sharing/pom.xml new file mode 100644 index 00000000..133b7d56 --- /dev/null +++ b/dsf-bpe-process-data-sharing/pom.xml @@ -0,0 +1,298 @@ + + + 4.0.0 + + dsf-bpe-process-data-sharing + + + dsf-bpe-highmed-processes-pom + org.highmed.dsf + 0.6.0 + + + + ${project.basedir}/.. + ../../highmed-dsf + + + + + org.highmed.dsf + dsf-bpe-process-base + provided + + + + com.fasterxml.jackson.core + jackson-annotations + provided + + + + de.hs-heilbronn.mi + log4j2-utils + test + + + org.highmed.dsf + dsf-fhir-validation + test + + + org.highmed.dsf + dsf-bpe-process-base + test + test-jar + + + + + + copy-to-highmed-dsf-process + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-process-to-docker-test-setup + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup/bpe/process + + + + copy-process-to-docker-test-setup-3medic-ttp/medic1 + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic1/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp/medic2 + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic2/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp/medic3 + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic3/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp/ttp + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/ttp/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp-docker/medic1 + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic1/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp-docker/medic2 + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic2/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp-docker/medic3 + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic3/bpe/process + + + + + copy-process-to-docker-test-setup-3medic-ttp-docker/ttp + package + + copy + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/ttp/bpe/process + + + + + + + org.apache.maven.plugins + maven-clean-plugin + + + + ${dsf.location}/dsf-docker-test-setup/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic1/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic2/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic3/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp/ttp/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic1/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic2/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic3/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + ${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/ttp/bpe/process + + ${project.artifactId}-${project.version}.jar + + false + + + + + + + + + \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/ConstantsDataSharing.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/ConstantsDataSharing.java new file mode 100644 index 00000000..5afea9b1 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/ConstantsDataSharing.java @@ -0,0 +1,99 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsBase.PROCESS_HIGHMED_URI_BASE; +import static org.highmed.dsf.bpe.DataSharingProcessPluginDefinition.VERSION; + +public interface ConstantsDataSharing +{ + String PROCESS_NAME_COMPUTE_DATA_SHARING = "computeDataSharing"; + String PROCESS_NAME_EXECUTE_DATA_SHARING = "executeDataSharing"; + String PROCESS_NAME_REQUEST_DATA_SHARING = "requestDataSharing"; + + String PROCESS_NAME_FULL_COMPUTE_DATA_SHARING = "highmedorg_" + PROCESS_NAME_COMPUTE_DATA_SHARING; + String PROCESS_NAME_FULL_EXECUTE_DATA_SHARING = "highmedorg_" + PROCESS_NAME_EXECUTE_DATA_SHARING; + String PROCESS_NAME_FULL_REQUEST_DATA_SHARING = "highmedorg_" + PROCESS_NAME_REQUEST_DATA_SHARING; + + String BPMN_EXECUTION_ERROR_CODE_SINGLE_MEDIC_DATA_SHARING_RESULT = "errorSingleMedicDataSharingResult"; + String BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_RECEIVED_DATA_SHARING_RESULT = "errorMultiMedicReceivedDataSharingResult"; + String BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_PSEUDONYMIZED_DATA_SHARING_RESULT = "errorMultiMedicPseudonymizedDataSharingResult"; + + String BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY = "researchStudy"; + String BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER = "researchStudyIdentifier"; + String BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK = "needsConsentCheck"; + String BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE = "needsRecordLinkage"; + String BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG = "bloomFilterConfig"; + String BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY = "mdatAesKey"; + String BPMN_EXECUTION_VARIABLE_COHORTS = "cohorts"; + String BPMN_EXECUTION_VARIABLE_QUERIES = "queries"; + String BPMN_EXECUTION_VARIABLE_QUERY_RESULTS = "queryResults"; + String BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS = "finalQueryResults"; + + String CODESYSTEM_HIGHMED_DATA_SHARING = "http://highmed.org/fhir/CodeSystem/data-sharing"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE = "research-study-reference"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER = "research-study-identifier"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER = "consortium-identifier"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE = "needs-record-linkage"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK = "needs-consent-check"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG = "bloom-filter-configuration"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY = "mdat-aes-key"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY = "medic-correlation-key"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT = "single-medic-count-result"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE = "single-medic-result-set-reference"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE = "single-medic-result-share"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT = "multi-medic-count-result"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE = "multi-medic-result-set-reference"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE = "multi-medic-result-share"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS = "participating-medics"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_REQUEST_FORM_REFERENCE = "request-form-reference"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONTRACT_REFERENCE = "contract-reference"; + String CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_FEASIBILITY_QUERY_REFERENCE = "feasibility-query-reference"; + + String NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER = "http://highmed.org/sid/research-study-identifier"; + + String EXTENSION_HIGHMED_PARTICIPATING_MEDIC = "http://highmed.org/fhir/StructureDefinition/extension-participating-medic"; + String EXTENSION_HIGHMED_PARTICIPATING_TTP = "http://highmed.org/fhir/StructureDefinition/extension-participating-ttp"; + String EXTENSION_HIGHMED_GROUP_ID = "http://highmed.org/fhir/StructureDefinition/extension-group-id"; + String EXTENSION_HIGHMED_QUERY = "http://highmed.org/fhir/StructureDefinition/extension-query"; + + String PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING = "http://highmed.org/fhir/StructureDefinition/task-request-data-sharing"; + String PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_AND_VERSION = "http://highmed.org/fhir/StructureDefinition/task-request-data-sharing" + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_REQUEST_DATA_SHARING + "/"; + String PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_MESSAGE_NAME = "requestDataSharingMessage"; + + String PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING = "http://highmed.org/fhir/StructureDefinition/task-execute-data-sharing"; + String PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_AND_VERSION = "http://highmed.org/fhir/StructureDefinition/task-execute-data-sharing" + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_EXECUTE_DATA_SHARING + "/"; + String PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_MESSAGE_NAME = "executeDataSharingMessage"; + + String PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING = "http://highmed.org/fhir/StructureDefinition/task-compute-data-sharing"; + String PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_AND_VERSION = "http://highmed.org/fhir/StructureDefinition/task-compute-data-sharing" + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_COMPUTE_DATA_SHARING + "/"; + String PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_MESSAGE_NAME = "computeDataSharingMessage"; + + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING = "http://highmed.org/fhir/StructureDefinition/task-single-medic-result-data-sharing"; + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING_AND_VERSION = "http://highmed.org/fhir/StructureDefinition/task-single-medic-result-data-sharing" + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING_MESSAGE_NAME = "resultSingleMedicDataSharingMessage"; + + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-data-sharing"; + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING_AND_VERSION = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-data-sharing" + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING_MESSAGE_NAME = "resultMultiMedicDataSharingMessage"; + + String PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-data-sharing"; + String PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING_VERSION = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-data-sharing" + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING_MESSAGE_NAME = "errorMultiMedicDataSharingMessage"; +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/DataSharingProcessPluginDefinition.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/DataSharingProcessPluginDefinition.java new file mode 100644 index 00000000..39f4ec83 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/DataSharingProcessPluginDefinition.java @@ -0,0 +1,94 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROCESS_NAME_FULL_COMPUTE_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROCESS_NAME_FULL_EXECUTE_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROCESS_NAME_FULL_REQUEST_DATA_SHARING; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import org.highmed.dsf.bpe.spring.config.DataSharingConfig; +import org.highmed.dsf.bpe.spring.config.DataSharingSerializerConfig; +import org.highmed.dsf.fhir.resources.AbstractResource; +import org.highmed.dsf.fhir.resources.ActivityDefinitionResource; +import org.highmed.dsf.fhir.resources.CodeSystemResource; +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.highmed.dsf.fhir.resources.StructureDefinitionResource; +import org.highmed.dsf.fhir.resources.ValueSetResource; +import org.springframework.core.env.PropertyResolver; + +import ca.uhn.fhir.context.FhirContext; + +public class DataSharingProcessPluginDefinition implements ProcessPluginDefinition +{ + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); + + @Override + public String getName() + { + return "dsf-bpe-process-data-sharing"; + } + + @Override + public String getVersion() + { + return VERSION; + } + + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + + @Override + public Stream getBpmnFiles() + { + return Stream.of("bpe/requestDataSharing.bpmn", "bpe/executeDataSharing.bpmn", "bpe/computeDataSharing.bpmn"); + } + + @Override + public Stream> getSpringConfigClasses() + { + return Stream.of(DataSharingConfig.class, DataSharingSerializerConfig.class); + } + + @Override + public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader classLoader, + PropertyResolver resolver) + { + var c = CodeSystemResource.file("fhir/CodeSystem/highmed-data-sharing.xml"); + + var aCom = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-computeDataSharing.xml"); + var aExe = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-executeDataSharing.xml"); + var aReq = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-requestDataSharing.xml"); + + var sRSDS = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-research-study-data-sharing.xml"); + var sCom = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-compute-data-sharing.xml"); + var sExe = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-execute-data-sharing.xml"); + var sErrM = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-multi-medic-error-data-sharing.xml"); + var sResM = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-multi-medic-result-data-sharing.xml"); + var sReq = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-request-data-sharing.xml"); + var sResS = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-single-medic-result-data-sharing.xml"); + + var v = ValueSetResource.file("fhir/ValueSet/highmed-data-sharing.xml"); + + Map> resourcesByProcessKeyAndVersion = Map.of( + PROCESS_NAME_FULL_COMPUTE_DATA_SHARING + "/" + VERSION, Arrays.asList(c, aCom, sCom, sResS, v), + PROCESS_NAME_FULL_EXECUTE_DATA_SHARING + "/" + VERSION, Arrays.asList(c, aExe, sExe, sRSDS, v), + PROCESS_NAME_FULL_REQUEST_DATA_SHARING + "/" + VERSION, + Arrays.asList(c, aReq, sReq, sRSDS, sResM, sErrM, v)); + + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyConsumer.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyConsumer.java new file mode 100644 index 00000000..834a93d8 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyConsumer.java @@ -0,0 +1,8 @@ +package org.highmed.dsf.bpe.crypto; + +import java.security.Key; + +public interface KeyConsumer +{ + void store(String alias, Key key); +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyProvider.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyProvider.java new file mode 100644 index 00000000..2294f3f7 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyProvider.java @@ -0,0 +1,8 @@ +package org.highmed.dsf.bpe.crypto; + +import java.security.Key; + +public interface KeyProvider +{ + Key get(String alias); +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyStoreHelper.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyStoreHelper.java new file mode 100644 index 00000000..54c40427 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyStoreHelper.java @@ -0,0 +1,34 @@ +package org.highmed.dsf.bpe.crypto; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +public class KeyStoreHelper +{ + public static final String JCEKS = "JCEKS"; + public static final String PKCS12 = "PKCS12"; + + public static KeyStore createJceks(char[] password) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException + { + return create(password, JCEKS); + } + + public static KeyStore createPkcs12(char[] password) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException + { + return create(password, PKCS12); + } + + private static KeyStore create(char[] password, String type) + throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException + { + KeyStore keyStore = KeyStore.getInstance(type); + keyStore.load(null, password); + + return keyStore; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyStoreIo.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyStoreIo.java new file mode 100644 index 00000000..53debd02 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/KeyStoreIo.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.bpe.crypto; + +import static org.highmed.dsf.bpe.crypto.KeyStoreHelper.JCEKS; +import static org.highmed.dsf.bpe.crypto.KeyStoreHelper.PKCS12; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; + +public class KeyStoreIo +{ + public static KeyStore readJceks(Path file, char[] password) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException + { + return read(file, password, JCEKS); + } + + public static KeyStore readPkcs12(Path file, char[] password) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException + { + return read(file, password, PKCS12); + } + + private static KeyStore read(Path file, char[] password, String type) + throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException + { + try (InputStream stream = Files.newInputStream(file)) + { + KeyStore keystore = KeyStore.getInstance(type); + keystore.load(stream, password); + + return keystore; + } + } + + public static void write(KeyStore keystore, Path file, char[] password) + throws IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException + { + try (OutputStream stream = Files.newOutputStream(file)) + { + keystore.store(stream, password); + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/SecretKeyConsumerImpl.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/SecretKeyConsumerImpl.java new file mode 100644 index 00000000..146b9f0c --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/SecretKeyConsumerImpl.java @@ -0,0 +1,66 @@ +package org.highmed.dsf.bpe.crypto; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.security.Key; +import java.security.KeyStore; +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class SecretKeyConsumerImpl implements KeyConsumer, InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(SecretKeyConsumerImpl.class); + + private final Path keystoreFile; + private final char[] keystorePassword; + + private KeyStore keystore; + + public SecretKeyConsumerImpl(Path keystoreFile, char[] keystorePassword) + { + this.keystoreFile = keystoreFile; + this.keystorePassword = keystorePassword; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(keystoreFile, "keystoreFile"); + Objects.requireNonNull(keystorePassword, "keystorePassword"); + + try + { + keystore = KeyStoreIo.readPkcs12(keystoreFile, keystorePassword); + } + catch (FileNotFoundException | NoSuchFileException e) + { + logger.warn("Could not find keystore at {}, creating an empty keystore", keystoreFile); + + keystore = KeyStoreHelper.createPkcs12(keystorePassword); + KeyStoreIo.write(keystore, keystoreFile, keystorePassword); + } + + if (!Files.isWritable(keystoreFile)) + throw new IOException("ResearchStudy keystore at " + keystoreFile.toString() + " not writable"); + } + + @Override + public void store(String alias, Key key) + { + try + { + keystore.setKeyEntry(alias, key, keystorePassword, null); + KeyStoreIo.write(keystore, keystoreFile, keystorePassword); + } + catch (Exception e) + { + throw new RuntimeException("Could not store secret key", e); + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/SecretKeyProviderImpl.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/SecretKeyProviderImpl.java new file mode 100644 index 00000000..167629b3 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/crypto/SecretKeyProviderImpl.java @@ -0,0 +1,76 @@ +package org.highmed.dsf.bpe.crypto; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.security.Key; +import java.security.KeyStore; +import java.util.Objects; + +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.pseudonymization.crypto.AesGcmUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class SecretKeyProviderImpl implements KeyProvider, InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(SecretKeyProviderImpl.class); + + private final OrganizationProvider organizationProvider; + + private final Path keystoreFile; + private final char[] keystorePassword; + + private KeyStore keystore; + + public SecretKeyProviderImpl(OrganizationProvider organizationProvider, Path keystoreFile, char[] keystorePassword) + { + this.keystoreFile = keystoreFile; + this.keystorePassword = keystorePassword; + + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(keystoreFile, "keystoreFile"); + Objects.requireNonNull(keystorePassword, "keystorePassword"); + + Objects.requireNonNull(organizationProvider, "organizationProvider"); + + try + { + keystore = KeyStoreIo.readPkcs12(keystoreFile, keystorePassword); + } + catch (FileNotFoundException | NoSuchFileException e) + { + logger.warn("Could not find keystore at {}, creating a new keystore containing a new organization key", + keystoreFile); + + keystore = KeyStoreHelper.createPkcs12(keystorePassword); + keystore.setKeyEntry(organizationProvider.getLocalIdentifierValue(), AesGcmUtil.generateAES256Key(), + keystorePassword, null); + KeyStoreIo.write(keystore, keystoreFile, keystorePassword); + } + + if (!Files.isReadable(keystoreFile)) + throw new IOException("Organization keystore at " + keystoreFile.toString() + " not readable"); + } + + @Override + public Key get(String alias) + { + try + { + return keystore.getKey(alias, keystorePassword); + } + catch (Exception e) + { + throw new RuntimeException("Could not get SecretKey", e); + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/AbstractSendResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/AbstractSendResults.java new file mode 100755 index 00000000..7e275c27 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/AbstractSendResults.java @@ -0,0 +1,78 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; + +import java.util.Objects; +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +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 abstract class AbstractSendResults extends AbstractTaskMessageSend +{ + private static final Logger logger = LoggerFactory.getLogger(AbstractSendResults.class); + + private final String resultSetReferenceCodeSystemValue; + + public AbstractSendResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext, + String resultSetReferenceCodeSystemValue) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + + this.resultSetReferenceCodeSystemValue = resultSetReferenceCodeSystemValue; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(resultSetReferenceCodeSystemValue, "resultSetReferenceCodeSystemValue"); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + return results.getResults().stream().map(this::toInput); + } + + private Task.ParameterComponent toInput(QueryResult result) + { + if (result.isIdResultSetUrlResult()) + { + ParameterComponent input = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + resultSetReferenceCodeSystemValue, new Reference(result.getResultSetUrl())); + input.addExtension(createCohortIdExtension(result.getCohortId())); + return input; + } + else + { + logger.warn("Unexpected result (not a ResultSet URL result) for cohort with ID " + result.getCohortId()); + throw new RuntimeException( + "Unexpected result (not a ResultSet URL result) for cohort with ID " + result.getCohortId()); + } + } + + private Extension createCohortIdExtension(String cohortId) + { + return new Extension(EXTENSION_HIGHMED_GROUP_ID, new Reference(cohortId)); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendErrors.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendErrors.java new file mode 100755 index 00000000..d8cc7e35 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendErrors.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.IdType; +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; + +public abstract class SendErrors extends AbstractTaskMessageSend +{ + public SendErrors(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + Task task = getLeadingTaskFromExecutionVariables(); + String taskUrl = new Reference(new IdType(getFhirWebserviceClientProvider().getLocalBaseUrl() + "/Task", + task.getIdElement().getIdPart())).getReference(); + String errorMessage = createErrorMessage(taskUrl); + + ParameterComponent input = getTaskHelper().createInput(CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, errorMessage); + return Stream.of(input); + } + + protected abstract String createErrorMessage(String taskUrl); +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java new file mode 100755 index 00000000..b53925fc --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java @@ -0,0 +1,105 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.SecretKeyWrapper; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +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; + +public class SendMedicRequest extends AbstractTaskMessageSend +{ + public SendMedicRequest(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + ParameterComponent inputResearchStudyReference = createResearchStudyComponent(researchStudy); + + boolean needsConsentCheck = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); + ParameterComponent inputNeedsConsentCheck = createNeedsConsentCheckComponent(needsConsentCheck); + + boolean needsRecordLinkage = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); + ParameterComponent inputNeedsRecordLinkage = createNeedsRecordLinkageComponent(needsRecordLinkage); + + SecretKeyWrapper secretKeyWrapper = (SecretKeyWrapper) execution + .getVariable(BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY); + ParameterComponent inputMdatKey = createMdatKeyComponent(secretKeyWrapper); + + if (needsRecordLinkage) + { + BloomFilterConfig bloomFilterConfig = (BloomFilterConfig) execution + .getVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG); + ParameterComponent inputBloomFilterConfig = getBloomFilterConfigComponent(bloomFilterConfig); + + return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck, inputNeedsRecordLinkage, + inputBloomFilterConfig, inputMdatKey); + } + else + { + return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck, inputNeedsRecordLinkage, + inputMdatKey); + } + } + + private Task.ParameterComponent createResearchStudyComponent(ResearchStudy researchStudy) + { + IdType researchStudyId = new IdType( + getFhirWebserviceClientProvider().getLocalBaseUrl() + "/" + researchStudy.getId()); + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE, + new Reference().setReference(researchStudyId.toVersionless().getValueAsString())); + } + + private Task.ParameterComponent createNeedsConsentCheckComponent(boolean needsConsentCheck) + { + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck); + } + + private Task.ParameterComponent createNeedsRecordLinkageComponent(boolean needsRecordLinkage) + { + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + } + + private Task.ParameterComponent createMdatKeyComponent(SecretKeyWrapper secretKeyWrapper) + { + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY, secretKeyWrapper.getBytes()); + } + + private Task.ParameterComponent getBloomFilterConfigComponent(BloomFilterConfig bloomFilterConfig) + { + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG, bloomFilterConfig.toBytes()); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicErrors.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicErrors.java new file mode 100755 index 00000000..9c275362 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicErrors.java @@ -0,0 +1,24 @@ +package org.highmed.dsf.bpe.message; + +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +import ca.uhn.fhir.context.FhirContext; + +public class SendMultiMedicErrors extends SendErrors +{ + public SendMultiMedicErrors(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected String createErrorMessage(String taskUrl) + { + return "An error occurred while calculating the multi medic data sharing result for " + + "all defined cohorts, see task with url='" + taskUrl + "'"; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java new file mode 100755 index 00000000..98cfbb84 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java @@ -0,0 +1,20 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE; + +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +import ca.uhn.fhir.context.FhirContext; + +public class SendMultiMedicResults extends AbstractSendResults +{ + public SendMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java new file mode 100755 index 00000000..d117da35 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java @@ -0,0 +1,20 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; + +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +import ca.uhn.fhir.context.FhirContext; + +public class SendSingleMedicResults extends AbstractSendResults +{ + public SendSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java new file mode 100644 index 00000000..b4883089 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java @@ -0,0 +1,73 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +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.Targets; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; + +import ca.uhn.fhir.context.FhirContext; + +public class SendTtpRequest extends AbstractTaskMessageSend +{ + public SendTtpRequest(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream getAdditionalInputParameters(DelegateExecution execution) + { + Targets medicTargets = (Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS); + Stream inputMedicTargets = createTargetComponents(medicTargets); + + boolean needsRecordLinkage = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); + Task.ParameterComponent inputNeedsRecordLinkage = createRecordLinkageComponent(needsRecordLinkage); + + String researchStudyIdentifier = (String) execution + .getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER); + Task.ParameterComponent inputResearchStudyIdentifier = createInputResearchStudyIdentifierComponent( + researchStudyIdentifier); + + return Stream.concat(inputMedicTargets, Stream.of(inputNeedsRecordLinkage, inputResearchStudyIdentifier)); + } + + private Stream createTargetComponents(Targets targets) + { + return targets.getEntries().stream().map(target -> getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY, target.getCorrelationKey())); + } + + private Task.ParameterComponent createRecordLinkageComponent(boolean needsRecordLinkage) + { + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + } + + private Task.ParameterComponent createInputResearchStudyIdentifierComponent(String researchStudyIdentifierValue) + { + Reference reference = new Reference().setType(ResourceType.ResearchStudy.name()).setIdentifier(new Identifier() + .setValue(researchStudyIdentifierValue).setSystem(NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER)); + + return getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER, reference); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractCheckResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractCheckResults.java new file mode 100644 index 00000000..64071362 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractCheckResults.java @@ -0,0 +1,102 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractCheckResults extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(AbstractCheckResults.class); + + public AbstractCheckResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List filteredResults = filterErroneousResultsAndAddErrorsToCurrentTaskOutputs(results); + List postProcessedResults = postProcessAllPassingResults(filteredResults); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(postProcessedResults))); + } + + private List filterErroneousResultsAndAddErrorsToCurrentTaskOutputs(QueryResults results) + { + Task task = getLeadingTaskFromExecutionVariables(); + return results.getResults().stream().filter(r -> testResultAndAddPossibleError(r, task)) + .collect(Collectors.toList()); + } + + /** + * @param result + * not null + * @param task + * not null + * @return true if the supplied {@link QueryResult} passed all checks, false otherwise + */ + protected boolean testResultAndAddPossibleError(QueryResult result, Task task) + { + return checkColumns(result, task) && checkRows(result, task); + } + + /** + * @param passedResults + * all {@link QueryResult} objects that passed the checks executed by + * {@link #testResultAndAddPossibleError(QueryResult, Task)} + * @return a list of {@link QueryResult} objects after post processing + */ + protected List postProcessAllPassingResults(List passedResults) + { + return passedResults; + } + + protected void addError(Task task, String organizationIdentifier, String cohortId, String error) + { + String errorMessage = "QueryResult check failed for group with id='" + cohortId + + "' supplied from organization " + organizationIdentifier + ", reason: " + error; + logger.warn(errorMessage); + + task.getOutput().add(getTaskHelper().createOutput(CODESYSTEM_HIGHMED_BPMN, CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, + errorMessage)); + } + + protected boolean checkColumns(QueryResult result, Task task) + { + boolean passed = result.getResultSet().getColumns().size() > 0; + + if (!passed) + addError(task, result.getOrganizationIdentifier(), result.getCohortId(), "no columns present"); + + return passed; + } + + protected boolean checkRows(QueryResult result, Task task) + { + boolean passed = result.getResultSet().getRows().size() > 0; + + if (!passed) + addError(task, result.getOrganizationIdentifier(), result.getCohortId(), "no rows present"); + + return passed; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractDownloadResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractDownloadResults.java new file mode 100644 index 00000000..4535edc3 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractDownloadResults.java @@ -0,0 +1,109 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.OPENEHR_MIMETYPE_JSON; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +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.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +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 abstract class AbstractDownloadResults extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(AbstractDownloadResults.class); + + private final ObjectMapper openEhrObjectMapper; + + public AbstractDownloadResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper); + this.openEhrObjectMapper = openEhrObjectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(openEhrObjectMapper, "openEhrObjectMapper"); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + List results = getQueryResults(execution); + List resultsWithResultSets = download(results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(resultsWithResultSets))); + } + + /** + * @param execution + * the process execution environment + * @return the {@link QueryResult} objects containing the corresponding Binary result set url. + */ + protected abstract List getQueryResults(DelegateExecution execution); + + private List download(List results) + { + return results.stream().map(this::download).collect(Collectors.toList()); + } + + private QueryResult download(QueryResult result) + { + IdType id = new IdType(result.getResultSetUrl()); + FhirWebserviceClient client = getFhirWebserviceClientProvider().getWebserviceClient(id.getBaseUrl()); + + InputStream binary = readBinaryResource(client, id.getIdPart()); + ResultSet resultSet = deserializeResultSet(binary); + + return QueryResult.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(OPENEHR_MIMETYPE_JSON)); + } + catch (Exception exception) + { + logger.warn("Error while reading Binary resource: " + exception.getMessage()); + throw exception; + } + } + + private ResultSet deserializeResultSet(InputStream content) + { + try (content) + { + return openEhrObjectMapper.readValue(content, ResultSet.class); + } + catch (IOException exception) + { + logger.warn("Error while deserializing ResultSet: " + exception.getMessage()); + throw new RuntimeException(exception); + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractPseudonymizeResultsSecondOrder.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractPseudonymizeResultsSecondOrder.java new file mode 100644 index 00000000..f1bdc857 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/AbstractPseudonymizeResultsSecondOrder.java @@ -0,0 +1,184 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import javax.crypto.SecretKey; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.crypto.KeyConsumer; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.Column; +import org.highmed.openehr.model.structure.Meta; +import org.highmed.openehr.model.structure.ResultSet; +import org.highmed.pseudonymization.crypto.AesGcmUtil; +import org.highmed.pseudonymization.domain.PersonWithMdat; +import org.highmed.pseudonymization.domain.PseudonymizedPersonWithMdat; +import org.highmed.pseudonymization.domain.impl.PseudonymizedPersonImpl; +import org.highmed.pseudonymization.psn.PseudonymGenerator; +import org.highmed.pseudonymization.psn.PseudonymGeneratorImpl; +import org.highmed.pseudonymization.recordlinkage.FederatedMatcher; +import org.highmed.pseudonymization.recordlinkage.MatchedPerson; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedic; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToMedic; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToMedicImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public abstract class AbstractPseudonymizeResultsSecondOrder extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(AbstractPseudonymizeResultsSecondOrder.class); + + private final KeyConsumer keyConsumer; + + private final ResultSetTranslatorFromMedic resultSetTranslatorFromMedic; + private final FederatedMatcher federatedMatcher; + + private final ObjectMapper psnObjectMapper; + + public AbstractPseudonymizeResultsSecondOrder(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, KeyConsumer keyConsumer, + ResultSetTranslatorFromMedic resultSetTranslatorFromMedic, + FederatedMatcher federatedMatcher, ObjectMapper psnObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.keyConsumer = keyConsumer; + this.resultSetTranslatorFromMedic = resultSetTranslatorFromMedic; + this.federatedMatcher = federatedMatcher; + this.psnObjectMapper = psnObjectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(keyConsumer, "keyConsumer"); + Objects.requireNonNull(resultSetTranslatorFromMedic, "resultSetTranslatorFromMedic"); + Objects.requireNonNull(federatedMatcher, "federatedMatcher"); + Objects.requireNonNull(psnObjectMapper, "psnObjectMapper"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + String researchStudyIdentifier = (String) execution + .getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER); + + SecretKey researchStudyKey = createAndStoreResearchStudyKey(researchStudyIdentifier); + + Map> byCohortId = groupByCohortId(results); + QueryResults finalResults = createFinalResults(researchStudyIdentifier, researchStudyKey, byCohortId); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, QueryResultsValues.create(finalResults)); + } + + private SecretKey createAndStoreResearchStudyKey(String researchStudyIdentifier) throws Exception + { + SecretKey key = AesGcmUtil.generateAES256Key(); + keyConsumer.store(researchStudyIdentifier, key); + return key; + } + + private Map> groupByCohortId(QueryResults results) + { + return results.getResults().stream().collect(Collectors.groupingBy(QueryResult::getCohortId)); + } + + private QueryResults createFinalResults(String researchStudyIdentifier, SecretKey reserchStudyKey, + Map> groupedResults) + { + ResultSetTranslatorToMedic translatorToMedic = createResultSetTranslatorToMedic(); + PseudonymGenerator psnGenerator = createPseudonymGenerator( + researchStudyIdentifier, reserchStudyKey); + + List finalResults = groupedResults.entrySet().stream().filter(r -> !r.getValue().isEmpty()) + .map(e -> translateMatchAndPseudonymize(resultSetTranslatorFromMedic, federatedMatcher, psnGenerator, + translatorToMedic, e.getKey(), e.getValue())) + .collect(Collectors.toList()); + + return new QueryResults(finalResults); + } + + private QueryResult translateMatchAndPseudonymize(ResultSetTranslatorFromMedic translatorFromMedic, + FederatedMatcher matcher, + PseudonymGenerator psnGenerator, + ResultSetTranslatorToMedic translatorToMedic, String cohortId, List results) + { + logger.debug("Translating, matching and pseudonymizing results for cohort {}", cohortId); + + List> persons = translateFromMedicResultSets(translatorFromMedic, results); + Set> matchedPersons = matcher.matchPersons(persons); + List pseudonymizedPersons = psnGenerator + .createPseudonymsAndShuffle(matchedPersons); + ResultSet resultSet = translateToMedicResultSet(results.get(0).getResultSet(), translatorToMedic, + pseudonymizedPersons); + + return QueryResult.idResult("ttp", cohortId, resultSet); + } + + private List> translateFromMedicResultSets(ResultSetTranslatorFromMedic translator, + List results) + { + return results.stream().map(r -> translateFromMedicResultSet(translator, r)).collect(Collectors.toList()); + } + + private List translateFromMedicResultSet(ResultSetTranslatorFromMedic translator, + QueryResult toTranslate) + { + try + { + return translator.translate(toTranslate.getOrganizationIdentifier(), toTranslate.getResultSet()); + } + catch (Exception exception) + { + logger.warn("Error while translating ResultSet: " + exception.getMessage()); + throw exception; + } + } + + private ResultSet translateToMedicResultSet(ResultSet toTranslate, ResultSetTranslatorToMedic translator, + List pseudonymizedPersons) + { + try + { + Meta meta = toTranslate.getMeta() == null ? new Meta("", "", "", "", "", "") : toTranslate.getMeta(); + List columns = toTranslate.getColumns(); + return translator.translate(meta, columns, pseudonymizedPersons); + } + catch (Exception exception) + { + logger.warn("Error while translating ResultSet: " + exception.getMessage()); + throw exception; + } + } + + private ResultSetTranslatorToMedic createResultSetTranslatorToMedic() + { + return new ResultSetTranslatorToMedicImpl(); + } + + private PseudonymGenerator createPseudonymGenerator( + String researchStudyIdentifier, SecretKey researchStudyKey) + { + return new PseudonymGeneratorImpl<>(researchStudyIdentifier, researchStudyKey, psnObjectMapper, + PseudonymizedPersonImpl::new); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckDataSharingResources.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckDataSharingResources.java new file mode 100644 index 00000000..7f373a80 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckDataSharingResources.java @@ -0,0 +1,62 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesList; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckDataSharingResources extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(CheckDataSharingResources.class); + + public CheckDataSharingResources(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + checkConsentCheck(execution); + checkFullyQualifiedCohortIds(execution); + + // TODO: define and implement further checks + } + + private void checkConsentCheck(DelegateExecution execution) + { + Boolean needsConsentCheck = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); + + if (!needsConsentCheck) + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + logger.warn("Execution process executeDataSharing for ResearchStudy with id {} without consent check", + researchStudy.getId()); + } + + } + + private void checkFullyQualifiedCohortIds(DelegateExecution execution) + { + List cohorts = ((FhirResourcesList) execution.getVariable(BPMN_EXECUTION_VARIABLE_COHORTS)) + .getResourcesAndCast(); + + if (cohorts.stream().anyMatch(g -> !g.getIdElement().hasBaseUrl())) + { + throw new RuntimeException("Not all cohorts have fully qualified ids (containing server base url)"); + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckMedicMultiMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckMedicMultiMedicResults.java new file mode 100755 index 00000000..2ec01e3e --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckMedicMultiMedicResults.java @@ -0,0 +1,22 @@ +package org.highmed.dsf.bpe.service; + +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; + +public class CheckMedicMultiMedicResults extends AbstractCheckResults +{ + public CheckMedicMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected boolean testResultAndAddPossibleError(QueryResult result, Task task) + { + return super.testResultAndAddPossibleError(result, task); // TODO: define further checks + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckMedicSingleMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckMedicSingleMedicResults.java new file mode 100644 index 00000000..dbfb5997 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckMedicSingleMedicResults.java @@ -0,0 +1,69 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_ERROR_CODE_SINGLE_MEDIC_DATA_SHARING_RESULT; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.BpmnError; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckMedicSingleMedicResults extends AbstractCheckResults +{ + private static final Logger logger = LoggerFactory.getLogger(CheckMedicSingleMedicResults.class); + + public CheckMedicSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected boolean testResultAndAddPossibleError(QueryResult result, Task task) + { + return super.testResultAndAddPossibleError(result, task); // TODO: define further checks + } + + @Override + protected List postProcessAllPassingResults(List passedResults) + { + if (!atLeastOneResultExists(passedResults)) + throw new BpmnError(BPMN_EXECUTION_ERROR_CODE_SINGLE_MEDIC_DATA_SHARING_RESULT); + + return passedResults; + } + + private boolean atLeastOneResultExists(List results) + { + Task leadingTask = getLeadingTaskFromExecutionVariables(); + String taskId = leadingTask.getId(); + String businessKey = getTaskHelper().getFirstInputParameterStringValue(leadingTask, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY).orElse(null); + String correlationKey = getTaskHelper().getFirstInputParameterStringValue(leadingTask, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).orElse(null); + + if (results.size() < 1) + { + logger.warn( + "Could not calculate result for any cohort definition in the data sharing request " + + "with task-id='{}', business-key='{}' and correlation-key='{}'", + taskId, businessKey, correlationKey); + + leadingTask.getOutput().add(getTaskHelper().createOutput(CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, "Could not calculate results for any cohort definition")); + + return false; + } + + return true; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckTtpMultiMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckTtpMultiMedicResults.java new file mode 100644 index 00000000..28fca16b --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckTtpMultiMedicResults.java @@ -0,0 +1,69 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_PSEUDONYMIZED_DATA_SHARING_RESULT; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.BpmnError; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckTtpMultiMedicResults extends AbstractCheckResults +{ + private static final Logger logger = LoggerFactory.getLogger(CheckTtpMultiMedicResults.class); + + public CheckTtpMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected boolean testResultAndAddPossibleError(QueryResult result, Task task) + { + return super.testResultAndAddPossibleError(result, task); // TODO: define further checks + } + + @Override + protected List postProcessAllPassingResults(List passedResults) + { + if (!atLeastOneResultExists(passedResults)) + throw new BpmnError(BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_PSEUDONYMIZED_DATA_SHARING_RESULT); + + return passedResults; + } + + private boolean atLeastOneResultExists(List results) + { + Task leadingTask = getLeadingTaskFromExecutionVariables(); + String taskId = leadingTask.getId(); + String businessKey = getTaskHelper().getFirstInputParameterStringValue(leadingTask, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY).orElse(null); + String correlationKey = getTaskHelper().getFirstInputParameterStringValue(leadingTask, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).orElse(null); + + if (results.size() < 1) + { + logger.warn( + "Could not calculate result for any cohort definition in the data sharing request with " + + "task-id='{}', business-key='{}' and correlation-key='{}'", + taskId, businessKey, correlationKey); + + leadingTask.getOutput().add(getTaskHelper().createOutput(CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, "Could not calculate result for any cohort definition")); + + return false; + } + + return true; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckTtpSingleMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckTtpSingleMedicResults.java new file mode 100644 index 00000000..abee56d0 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/CheckTtpSingleMedicResults.java @@ -0,0 +1,70 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_PSEUDONYMIZED_DATA_SHARING_RESULT; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.BpmnError; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CheckTtpSingleMedicResults extends AbstractCheckResults +{ + private static final Logger logger = LoggerFactory.getLogger(CheckTtpSingleMedicResults.class); + + public CheckTtpSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected boolean testResultAndAddPossibleError(QueryResult result, Task task) + { + return super.testResultAndAddPossibleError(result, task); // TODO: define further checks + } + + @Override + protected List postProcessAllPassingResults(List passedResults) + { + if (!atLeastOneResultExists(passedResults)) + throw new BpmnError(BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_PSEUDONYMIZED_DATA_SHARING_RESULT); + + return passedResults; + } + + private boolean atLeastOneResultExists(List results) + { + Task leadingTask = getLeadingTaskFromExecutionVariables(); + String taskId = leadingTask.getId(); + String businessKey = getTaskHelper().getFirstInputParameterStringValue(leadingTask, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY).orElse(null); + String correlationKey = getTaskHelper().getFirstInputParameterStringValue(leadingTask, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).orElse(null); + + if (results.size() < 1) + { + logger.warn( + "Did not receive any valid results from any MeDIC for any cohort definition in the data sharing request with " + + "task-id='{}', business-key='{}' and correlation-key='{}', are there results present?", + taskId, businessKey, correlationKey); + + leadingTask.getOutput() + .add(getTaskHelper().createOutput(CODESYSTEM_HIGHMED_BPMN, CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, + "Did not receive any valid results from any MeDIC for any cohort definition")); + + return false; + } + + return true; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DecryptMultiMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DecryptMultiMedicResults.java new file mode 100644 index 00000000..93f394f7 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DecryptMultiMedicResults.java @@ -0,0 +1,101 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.crypto.SecretKey; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.bpe.variable.SecretKeyWrapper; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromTtp; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromTtpImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class DecryptMultiMedicResults extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(DecryptMultiMedicResults.class); + + private final ObjectMapper openEhrObjectMapper; + + public DecryptMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.openEhrObjectMapper = openEhrObjectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(openEhrObjectMapper, "openEhrObjectMapper"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + String researchStudyIdentifier = (String) execution + .getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER); + SecretKey mdatKey = getMdatKey(execution); + ResultSetTranslatorFromTtp translator = createResultSetTranslator(researchStudyIdentifier, mdatKey); + + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults decryptedResults = decryptResults(results, translator); + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, QueryResultsValues.create(decryptedResults)); + } + + private SecretKey getMdatKey(DelegateExecution execution) + { + SecretKeyWrapper secretKeyWrapper = (SecretKeyWrapper) execution + .getVariable(BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY); + return secretKeyWrapper.getSecretKey(); + } + + private ResultSetTranslatorFromTtp createResultSetTranslator(String researchStudyIdentifier, + SecretKey researchStudyKey) + { + return new ResultSetTranslatorFromTtpImpl(researchStudyIdentifier, researchStudyKey, openEhrObjectMapper); + } + + private QueryResults decryptResults(QueryResults results, ResultSetTranslatorFromTtp translator) + { + List translatedResults = results + .getResults().stream().map(result -> QueryResult.idResult(result.getOrganizationIdentifier(), + result.getCohortId(), translate(translator, result.getResultSet()))) + .collect(Collectors.toList()); + + return new QueryResults(translatedResults); + } + + private ResultSet translate(ResultSetTranslatorFromTtp translator, ResultSet toTranslate) + { + try + { + return translator.translate(toTranslate); + } + catch (Exception exception) + { + logger.warn("Error while translating ResultSet: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadDataSharingResources.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadDataSharingResources.java new file mode 100644 index 00000000..f5e7f8fc --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadDataSharingResources.java @@ -0,0 +1,228 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_PARTICIPATING_TTP; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfigValues; +import org.highmed.dsf.bpe.variable.SecretKeyWrapper; +import org.highmed.dsf.bpe.variable.SecretKeyWrapperValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +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.FhirResourceValues; +import org.highmed.dsf.fhir.variables.FhirResourcesListValues; +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; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DownloadDataSharingResources extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(DownloadDataSharingResources.class); + + private final OrganizationProvider organizationProvider; + + public DownloadDataSharingResources(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(organizationProvider, "organizationProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + Task task = getCurrentTaskFromExecutionVariables(); + + IdType researchStudyId = getResearchStudyId(task); + FhirWebserviceClient client = getWebserviceClient(researchStudyId); + Bundle bundle = getResearchStudyAndCohortDefinitions(researchStudyId, client); + + ResearchStudy researchStudy = getResearchStudy(bundle); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY, FhirResourceValues.create(researchStudy)); + + List cohortDefinitions = getCohortDefinitions(bundle, client.getBaseUrl()); + execution.setVariable(BPMN_EXECUTION_VARIABLE_COHORTS, FhirResourcesListValues.create(cohortDefinitions)); + + String ttpIdentifier = getTtpIdentifier(researchStudy); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER, ttpIdentifier); + + boolean needsConsentCheck = getNeedsConsentCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck); + + boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + + SecretKeyWrapper secretKey = getMdatKey(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY, SecretKeyWrapperValues.create(secretKey)); + + if (needsRecordLinkage) + { + BloomFilterConfig bloomFilterConfig = getBloomFilterConfig(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG, + BloomFilterConfigValues.create(bloomFilterConfig)); + } + } + + private IdType getResearchStudyId(Task task) + { + Reference researchStudyReference = getTaskHelper() + .getInputParameterReferenceValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("ResearchStudy reference is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); + + return new IdType(researchStudyReference.getReference()); + } + + private FhirWebserviceClient getWebserviceClient(IdType researchStudyId) + { + if (researchStudyId.getBaseUrl() == null + || researchStudyId.getBaseUrl().equals(getFhirWebserviceClientProvider().getLocalBaseUrl())) + { + return getFhirWebserviceClientProvider().getLocalWebserviceClient(); + } + else + { + return getFhirWebserviceClientProvider().getWebserviceClient(researchStudyId.getBaseUrl()); + } + } + + private Bundle getResearchStudyAndCohortDefinitions(IdType researchStudyId, FhirWebserviceClient client) + { + try + { + 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) + .anyMatch(b -> !b)) + { + throw new RuntimeException("Returned search-set contained unexpected resource at index >= 1"); + } + + return bundle; + } + catch (Exception e) + { + logger.warn("Error while reading ResearchStudy with id {} including Groups from {}: {}", + researchStudyId.getIdPart(), client.getBaseUrl(), e.getMessage()); + throw e; + } + } + + private ResearchStudy getResearchStudy(Bundle bundle) + { + Resource resource = bundle.getEntryFirstRep().getResource(); + if (resource instanceof ResearchStudy) + return (ResearchStudy) resource; + else + throw new RuntimeException("Expected first bundle entry to be of type research study"); + + } + + private List getCohortDefinitions(Bundle bundle, String baseUrl) + { + return bundle.getEntry().stream().skip(1).map(e -> + { + 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()); + } + + private String getTtpIdentifier(ResearchStudy researchStudy) + { + Extension ext = researchStudy.getExtensionByUrl(EXTENSION_HIGHMED_PARTICIPATING_TTP); + Reference ref = (Reference) ext.getValue(); + return ref.getIdentifier().getValue(); + } + + private boolean getNeedsConsentCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); + } + + private boolean getNeedsRecordLinkageCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) + .orElseThrow( + () -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); + } + + private SecretKeyWrapper getMdatKey(Task task) + { + byte[] bytes = getTaskHelper() + .getFirstInputParameterByteValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY) + .orElseThrow(() -> new IllegalArgumentException("mdat aes key is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); + + return SecretKeyWrapper.fromAes256Key(bytes); + } + + private BloomFilterConfig getBloomFilterConfig(Task task) + { + return BloomFilterConfig.fromBytes(getTaskHelper() + .getFirstInputParameterByteValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadMultiMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadMultiMedicResults.java new file mode 100644 index 00000000..5f456dab --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadMultiMedicResults.java @@ -0,0 +1,46 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_GROUP_ID; + +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class DownloadMultiMedicResults extends AbstractDownloadResults +{ + public DownloadMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, openEhrObjectMapper); + } + + @Override + protected List getQueryResults(DelegateExecution execution) + { + Task task = getCurrentTaskFromExecutionVariables(); + Reference requester = task.getRequester(); + + return getTaskHelper().getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE, EXTENSION_HIGHMED_GROUP_ID) + .map(input -> toQueryResult(input, requester)).collect(Collectors.toList()); + } + + private QueryResult toQueryResult(Task.ParameterComponent input, Reference requester) + { + String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference(); + String resultSetUrl = ((Reference) input.getValue()).getReference(); + + return QueryResult.idResult(requester.getIdentifier().getValue(), cohortId, resultSetUrl); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java new file mode 100644 index 00000000..baf1d318 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java @@ -0,0 +1,129 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; + +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +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.Identifier; +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; + +public class DownloadResearchStudyResource extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(DownloadResearchStudyResource.class); + + private final OrganizationProvider organizationProvider; + + public DownloadResearchStudyResource(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(organizationProvider, "organizationProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + Task task = getLeadingTaskFromExecutionVariables(); + FhirWebserviceClient client = getFhirWebserviceClientProvider().getLocalWebserviceClient(); + + IdType researchStudyId = getResearchStudyId(task); + ResearchStudy researchStudy = getResearchStudy(researchStudyId, client); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY, researchStudy); + + String researchStudyIdentifier = getResearchStudyIdentifier(researchStudy); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER, researchStudyIdentifier); + + boolean needsConsentCheck = getNeedsConsentCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck); + + boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER, + organizationProvider.getLocalIdentifierValue()); + } + + private IdType getResearchStudyId(Task task) + { + Reference researchStudyReference = getTaskHelper() + .getInputParameterReferenceValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("ResearchStudy reference is not set in task with id='" + + task.getId() + "', this error should have been caught by resource validation")); + + return new IdType(researchStudyReference.getReference()); + } + + private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceClient client) + { + try + { + return client.read(ResearchStudy.class, researchStudyid.getIdPart()); + } + catch (Exception e) + { + logger.warn("Error while reading ResearchStudy with id {} from {}", researchStudyid.getIdPart(), + client.getBaseUrl()); + throw e; + } + } + + private boolean getNeedsConsentCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); + } + + private boolean getNeedsRecordLinkageCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) + .orElseThrow( + () -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); + } + + private String getResearchStudyIdentifier(ResearchStudy researchStudy) + { + Identifier identifier = researchStudy.getIdentifier().stream() + .filter(i -> i.getSystem().equals(NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER)).findFirst() + .orElseThrow(() -> new IllegalArgumentException("Identifier is not set in research study with id='" + + researchStudy.getId() + "', this error should have been caught by resource validation")); + + return identifier.getValue(); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadSingleMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadSingleMedicResults.java new file mode 100644 index 00000000..155ff8c4 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/DownloadSingleMedicResults.java @@ -0,0 +1,29 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class DownloadSingleMedicResults extends AbstractDownloadResults +{ + public DownloadSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, openEhrObjectMapper); + } + + @Override + protected List getQueryResults(DelegateExecution execution) + { + return ((QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS)).getResults(); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/EncryptResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/EncryptResults.java new file mode 100644 index 00000000..c7148f0d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/EncryptResults.java @@ -0,0 +1,134 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.crypto.SecretKey; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.crypto.KeyProvider; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.bpe.variable.SecretKeyWrapper; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtp; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpEncrypt; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpEncryptImpl; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class EncryptResults extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(EncryptResults.class); + + private final OrganizationProvider organizationProvider; + private final KeyProvider keyProvider; + private final String ehrIdColumnPath; + + public EncryptResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, KeyProvider keyProvider, + String ehrIdColumnPath) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.organizationProvider = organizationProvider; + this.keyProvider = keyProvider; + this.ehrIdColumnPath = ehrIdColumnPath; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(organizationProvider, "organizationProvider"); + Objects.requireNonNull(keyProvider, "keyProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + String organizationIdentifier = organizationProvider.getLocalIdentifierValue(); + SecretKey idatKey = getIdatKey(organizationIdentifier); + String researchStudyIdentifier = getResearchStudyIdentifier(execution); + SecretKey mdatKey = getMdatKey(execution); + + ResultSetTranslatorToTtpEncrypt translator = createResultSetTranslator(organizationIdentifier, idatKey, + researchStudyIdentifier, mdatKey, ehrIdColumnPath); + + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List translatedResults = translateResults(translator, results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(translatedResults))); + } + + private SecretKey getIdatKey(String organizationIdentifier) + { + return (SecretKey) keyProvider.get(organizationIdentifier); + } + + private String getResearchStudyIdentifier(DelegateExecution execution) + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + return researchStudy.getIdentifier().stream() + .filter(s -> s.getSystem().equals(NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER)).findFirst() + .orElseThrow(() -> new IllegalArgumentException("Identifier is not set in research study with id='" + + researchStudy.getId() + "', this error should have been caught by resource validation")) + .getValue(); + } + + private SecretKey getMdatKey(DelegateExecution execution) + { + SecretKeyWrapper secretKeyWrapper = (SecretKeyWrapper) execution + .getVariable(BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY); + return secretKeyWrapper.getSecretKey(); + } + + private ResultSetTranslatorToTtpEncrypt createResultSetTranslator(String organizationIdentifier, + SecretKey organizationKey, String researchStudyIdentifier, SecretKey researchStudyKey, + String ehrIdColumnPath) + { + return new ResultSetTranslatorToTtpEncryptImpl(organizationIdentifier, organizationKey, researchStudyIdentifier, + researchStudyKey, ehrIdColumnPath); + } + + private List translateResults(ResultSetTranslatorToTtp translator, QueryResults results) + { + return results.getResults().stream().map(result -> translateResult(translator, result)) + .collect(Collectors.toList()); + } + + private QueryResult translateResult(ResultSetTranslatorToTtp translator, QueryResult result) + { + ResultSet translatedResultSet = translate(translator, result.getResultSet()); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), translatedResultSet); + } + + private ResultSet translate(ResultSetTranslatorToTtp resultSetTranslator, ResultSet resultSet) + { + try + { + return resultSetTranslator.translate(resultSet); + } + catch (Exception exception) + { + logger.warn("Error while encrypting ResultSet: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java new file mode 100644 index 00000000..dfabdee3 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java @@ -0,0 +1,66 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.client.OpenEhrClient; +import org.highmed.openehr.model.structure.ResultSet; + +public class ExecuteQueries extends AbstractServiceDelegate +{ + private final OpenEhrClient openehrClient; + private final OrganizationProvider organizationProvider; + + public ExecuteQueries(FhirWebserviceClientProvider clientProvider, OpenEhrClient openehrClient, + TaskHelper taskHelper, ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.openehrClient = openehrClient; + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(openehrClient, "openehrClient"); + Objects.requireNonNull(organizationProvider, "organizationProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + @SuppressWarnings("unchecked") + // + Map queries = (Map) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERIES); + + List results = queries.entrySet().stream() + .map(entry -> executeQuery(entry.getKey(), entry.getValue())).collect(Collectors.toList()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(results))); + } + + private QueryResult executeQuery(String cohortId, String cohortQuery) + { + // TODO: introduce a more complex result type to represent a count, errors and possible meta-data + ResultSet resultSet = openehrClient.query(cohortQuery, null); + return QueryResult.idResult(organizationProvider.getLocalIdentifierValue(), cohortId, resultSet); + } +} \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ExtractQueries.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ExtractQueries.java new file mode 100644 index 00000000..d9d7473d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ExtractQueries.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.group.GroupHelper; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesList; +import org.hl7.fhir.r4.model.Group; +import org.springframework.beans.factory.InitializingBean; + +public class ExtractQueries extends AbstractServiceDelegate implements InitializingBean +{ + private final GroupHelper groupHelper; + + public ExtractQueries(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, GroupHelper groupHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + this.groupHelper = groupHelper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(groupHelper, "groupHelper"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + List cohorts = ((FhirResourcesList) execution.getVariable(BPMN_EXECUTION_VARIABLE_COHORTS)) + .getResourcesAndCast(); + + // + Map queries = cohorts.stream() + .collect(Collectors.toMap(Group::getId, groupHelper::extractAqlQuery)); + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERIES, queries); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java new file mode 100644 index 00000000..13b776ed --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java @@ -0,0 +1,78 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.consent.client.ConsentClient; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class FilterResultsByConsent extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(FilterResultsByConsent.class); + + private final ConsentClient consentClient; + + public FilterResultsByConsent(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ConsentClient consentClient) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.consentClient = consentClient; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(consentClient, "consentClient"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List checkedResults = filterResultsByConsent(results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(checkedResults))); + } + + private List filterResultsByConsent(QueryResults results) + { + return results.getResults().stream().map(result -> filterResultByConsent(result)).collect(Collectors.toList()); + } + + private QueryResult filterResultByConsent(QueryResult result) + { + ResultSet checkedResultSet = removeRowsWithoutConsent(result.getResultSet()); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), checkedResultSet); + } + + private ResultSet removeRowsWithoutConsent(ResultSet resultSet) + { + try + { + return consentClient.removeRowsWithoutConsent(resultSet); + } + catch (Exception exception) + { + logger.warn("Error while filtering ResultSet: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java new file mode 100644 index 00000000..eec53075 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java @@ -0,0 +1,122 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +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.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +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.translation.ResultSetTranslatorToTtp; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpCreateRbf; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpCreateRbfImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class GenerateBloomFilters extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(GenerateBloomFilters.class); + + private static final int RBF_LENGTH = 3000; + private static final RecordBloomFilterGeneratorImpl.FieldWeights FBF_WEIGHTS = new RecordBloomFilterGeneratorImpl.FieldWeights( + 0.1, 0.1, 0.1, 0.2, 0.05, 0.1, 0.05, 0.2, 0.1); + private static final RecordBloomFilterGeneratorImpl.FieldBloomFilterLengths FBF_LENGTHS = new RecordBloomFilterGeneratorImpl.FieldBloomFilterLengths( + 500, 500, 250, 50, 500, 250, 500, 500, 500); + + private final MasterPatientIndexClient masterPatientIndexClient; + private final String ehrIdColumnPath; + private final BouncyCastleProvider bouncyCastleProvider; + + public GenerateBloomFilters(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, MasterPatientIndexClient masterPatientIndexClient, + String ehrIdColumnPath, BouncyCastleProvider bouncyCastleProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.masterPatientIndexClient = masterPatientIndexClient; + this.ehrIdColumnPath = ehrIdColumnPath; + this.bouncyCastleProvider = bouncyCastleProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(masterPatientIndexClient, "masterPatientIndexClient"); + Objects.requireNonNull(ehrIdColumnPath, "ehrIdColumnPath"); + Objects.requireNonNull(bouncyCastleProvider, "bouncyCastleProvided"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + RecordBloomFilterGenerator recordBloomFilterGenerator = createRecordBloomFilterGenerator(execution); + ResultSetTranslatorToTtpCreateRbf translator = createResultSetTranslator(ehrIdColumnPath, + recordBloomFilterGenerator, masterPatientIndexClient); + + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List translatedResults = translateResults(translator, results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(translatedResults))); + } + + private RecordBloomFilterGenerator createRecordBloomFilterGenerator(DelegateExecution execution) + { + BloomFilterConfig bloomFilterConfig = (BloomFilterConfig) execution + .getVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG); + return new RecordBloomFilterGeneratorImpl(RBF_LENGTH, bloomFilterConfig.getPermutationSeed(), FBF_WEIGHTS, + FBF_LENGTHS, + () -> new BloomFilterGenerator.HmacSha2HmacSha3BiGramHasher(bloomFilterConfig.getHmacSha2Key(), + bloomFilterConfig.getHmacSha3Key(), bouncyCastleProvider)); + } + + private ResultSetTranslatorToTtpCreateRbf createResultSetTranslator(String ehrIdColumnPath, + RecordBloomFilterGenerator recordBloomFilterGenerator, MasterPatientIndexClient masterPatientIndexClient) + { + return new ResultSetTranslatorToTtpCreateRbfImpl(ehrIdColumnPath, recordBloomFilterGenerator, + masterPatientIndexClient); + } + + private List translateResults(ResultSetTranslatorToTtp translator, QueryResults results) + { + return results.getResults().stream().map(result -> translateResult(translator, result)) + .collect(Collectors.toList()); + } + + private QueryResult translateResult(ResultSetTranslatorToTtp translator, QueryResult result) + { + ResultSet translatedResultSet = translate(translator, result.getResultSet()); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), translatedResultSet); + } + + private ResultSet translate(ResultSetTranslatorToTtp resultSetTranslator, ResultSet resultSet) + { + try + { + return resultSetTranslator.translate(resultSet); + } + catch (Exception exception) + { + logger.warn("Error while generating bloom filter: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/HandleErrorMultiMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/HandleErrorMultiMedicResults.java new file mode 100644 index 00000000..1f8489ea --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/HandleErrorMultiMedicResults.java @@ -0,0 +1,52 @@ +package org.highmed.dsf.bpe.service; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.ConstantsBase; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HandleErrorMultiMedicResults extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(HandleErrorMultiMedicResults.class); + + public HandleErrorMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + Task currentTask = getCurrentTaskFromExecutionVariables(); + Task leadingTask = getLeadingTaskFromExecutionVariables(); + + currentTask.getInput().stream().filter(this::isErrorInput) + .forEach(input -> transformToOutput(currentTask.getId(), input, leadingTask)); + + // The current task finishes here but is not automatically set to completed + // because it is an additional task during the execution of the main process + currentTask.setStatus(Task.TaskStatus.COMPLETED); + getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().update(currentTask); + } + + private boolean isErrorInput(Task.ParameterComponent input) + { + return input.getType().getCoding().stream() + .anyMatch(code -> code.getSystem().equals(ConstantsBase.CODESYSTEM_HIGHMED_BPMN) + && code.getCode().equals(ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR)); + } + + private void transformToOutput(String taskId, Task.ParameterComponent input, Task leadingTask) + { + String errorMessage = input.getValue().primitiveValue(); + logger.warn("Received multi medic data sharing error in task with id='{}', reason: {}", taskId, errorMessage); + leadingTask.getOutput().add(getTaskHelper().createOutput(ConstantsBase.CODESYSTEM_HIGHMED_BPMN, + ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, errorMessage)); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java new file mode 100644 index 00000000..cb681400 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java @@ -0,0 +1,74 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; + +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class ModifyQueries extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(ModifyQueries.class); + + private final String ehrIdColumnPath; + + public ModifyQueries(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, String ehrIdColumnPath) + { + super(clientProvider, taskHelper, readAccessHelper); + this.ehrIdColumnPath = ehrIdColumnPath; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(ehrIdColumnPath, "ehrIdColumnPath"); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + Boolean needsConsentCheck = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); + Boolean needsRecordLinkage = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); + + if (Boolean.TRUE.equals(needsConsentCheck) || Boolean.TRUE.equals(needsRecordLinkage)) + { + @SuppressWarnings("unchecked") + // + Map queries = (Map) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERIES); + Map modifiedQueries = modifyQueries(queries); + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERIES, modifiedQueries); + } + } + + private Map modifyQueries(Map queries) + { + return queries.entrySet().stream() + .collect(Collectors.toMap(Map.Entry::getKey, entry -> modify(entry.getValue()))); + } + + private String modify(String query) + { + // TODO: implement correct check for id query + if (!query.startsWith("SELECT e" + ehrIdColumnPath + " as EHRID")) + { + query = query.replace("SELECT", "SELECT e" + ehrIdColumnPath + " as EHRID,"); + logger.warn("Query does not start with '{}', adapting SELECT statement", + "SELECT e" + ehrIdColumnPath + " as EHRID"); + } + + return query; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsFirstOrder.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsFirstOrder.java new file mode 100644 index 00000000..89a3321a --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsFirstOrder.java @@ -0,0 +1,78 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +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.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.highmed.pseudonymization.client.PseudonymizationClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class PseudonymizeResultsFirstOrder extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(PseudonymizeResultsFirstOrder.class); + + private final PseudonymizationClient pseudonymizationClient; + + public PseudonymizeResultsFirstOrder(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, PseudonymizationClient pseudonymizationClient) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.pseudonymizationClient = pseudonymizationClient; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(pseudonymizationClient, "pseudonymizationClient"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List pseudonymizedResults = pseudonymizeResults(results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(pseudonymizedResults))); + } + + private List pseudonymizeResults(QueryResults results) + { + return results.getResults().stream().map(result -> pseudonymizeResult(result)).collect(Collectors.toList()); + } + + private QueryResult pseudonymizeResult(QueryResult result) + { + ResultSet pseudonymizedResultSet = pseudonymize(result.getResultSet()); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), pseudonymizedResultSet); + } + + private ResultSet pseudonymize(ResultSet resultSet) + { + try + { + return pseudonymizationClient.pseudonymize(resultSet); + } + catch (Exception exception) + { + logger.warn("Error while encrypting ResultSet: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsSecondOrderWithRecordLinkage.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsSecondOrderWithRecordLinkage.java new file mode 100644 index 00000000..795e28b3 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsSecondOrderWithRecordLinkage.java @@ -0,0 +1,25 @@ +package org.highmed.dsf.bpe.service; + +import org.highmed.dsf.bpe.crypto.KeyConsumer; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.pseudonymization.domain.PersonWithMdat; +import org.highmed.pseudonymization.recordlinkage.FederatedMatcher; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicWithRbf; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class PseudonymizeResultsSecondOrderWithRecordLinkage extends AbstractPseudonymizeResultsSecondOrder + implements InitializingBean +{ + public PseudonymizeResultsSecondOrderWithRecordLinkage(FhirWebserviceClientProvider clientProvider, + TaskHelper taskHelper, ReadAccessHelper readAccessHelper, KeyConsumer keyConsumer, + ResultSetTranslatorFromMedicWithRbf resultSetTranslatorFromMedicWithRbf, + FederatedMatcher federatedMatcher, ObjectMapper psnObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, keyConsumer, resultSetTranslatorFromMedicWithRbf, + federatedMatcher, psnObjectMapper); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsSecondOrderWithoutRecordLinkage.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsSecondOrderWithoutRecordLinkage.java new file mode 100644 index 00000000..7498d765 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/PseudonymizeResultsSecondOrderWithoutRecordLinkage.java @@ -0,0 +1,25 @@ +package org.highmed.dsf.bpe.service; + +import org.highmed.dsf.bpe.crypto.KeyConsumer; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.pseudonymization.domain.PersonWithMdat; +import org.highmed.pseudonymization.recordlinkage.FederatedMatcher; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicNoRbf; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class PseudonymizeResultsSecondOrderWithoutRecordLinkage extends AbstractPseudonymizeResultsSecondOrder + implements InitializingBean +{ + public PseudonymizeResultsSecondOrderWithoutRecordLinkage(FhirWebserviceClientProvider clientProvider, + TaskHelper taskHelper, ReadAccessHelper readAccessHelper, KeyConsumer keyConsumer, + ResultSetTranslatorFromMedicNoRbf resultSetTranslatorFromMedicNoRbf, + FederatedMatcher federatedMatcher, ObjectMapper psnObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, keyConsumer, resultSetTranslatorFromMedicNoRbf, + federatedMatcher, psnObjectMapper); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java new file mode 100644 index 00000000..85cfa16a --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java @@ -0,0 +1,155 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +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.ConstantsBase; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfigValues; +import org.highmed.dsf.bpe.variable.SecretKeyWrapper; +import org.highmed.dsf.bpe.variable.SecretKeyWrapperValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.highmed.dsf.fhir.variables.Targets; +import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.springframework.beans.factory.InitializingBean; + +public class SelectRequestTargets extends AbstractServiceDelegate implements InitializingBean +{ + private final Random random = new SecureRandom(); + + private final EndpointProvider endpointProvider; + private final KeyGenerator hmacSha2Generator; + private final KeyGenerator hmacSha3Generator; + + public SelectRequestTargets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider, + BouncyCastleProvider bouncyCastleProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + + try + { + Objects.requireNonNull(bouncyCastleProvider, "bouncyCastleProvider"); + + hmacSha2Generator = KeyGenerator.getInstance("HmacSHA256", bouncyCastleProvider); + hmacSha3Generator = KeyGenerator.getInstance("HmacSHA3-256", bouncyCastleProvider); + } + catch (NoSuchAlgorithmException exception) + { + throw new RuntimeException(exception); + } + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(endpointProvider, "endpointProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + + Targets medicTargets = getMedicTargets(researchStudy); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(medicTargets)); + + Target ttpTarget = getTtpTarget(researchStudy); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, TargetValues.create(ttpTarget)); + + SecretKeyWrapper secretKey = SecretKeyWrapper.newAes256Key(); + execution.setVariable(BPMN_EXECUTION_VARIABLE_MDAT_AES_KEY, SecretKeyWrapperValues.create(secretKey)); + + Boolean needsRecordLinkage = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); + if (Boolean.TRUE.equals(needsRecordLinkage)) + { + BloomFilterConfig bloomFilterConfig = createBloomFilterConfig(); + execution.setVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG, + BloomFilterConfigValues.create(bloomFilterConfig)); + } + } + + private Targets getMedicTargets(ResearchStudy researchStudy) + { + List targets = researchStudy.getExtensionsByUrl(ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC) + .stream().filter(Extension::hasValue).map(Extension::getValue).filter(v -> v instanceof Reference) + .map(v -> (Reference) v).filter(Reference::hasIdentifier).map(Reference::getIdentifier) + .filter(Identifier::hasValue).map(Identifier::getValue).map(medicIdentifier -> + { + Endpoint endpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIdentifier); + return Target.createBiDirectionalTarget(medicIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), UUID.randomUUID().toString()); + }).collect(Collectors.toList()); + + return new Targets(targets); + } + + private Target getTtpTarget(ResearchStudy researchStudy) + { + return researchStudy.getExtensionsByUrl(ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_TTP).stream() + .filter(Extension::hasValue).map(Extension::getValue).filter(v -> v instanceof Reference) + .map(v -> (Reference) v).filter(Reference::hasIdentifier).map(Reference::getIdentifier) + .filter(Identifier::hasValue).map(Identifier::getValue).map(ttpIdentifier -> + { + Endpoint endpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP, ttpIdentifier); + return Target.createUniDirectionalTarget(ttpIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress()); + }).findFirst().get(); + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } + + private BloomFilterConfig createBloomFilterConfig() + { + return new BloomFilterConfig(random.nextLong(), hmacSha2Generator.generateKey(), + hmacSha3Generator.generateKey()); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java new file mode 100644 index 00000000..71139dee --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java @@ -0,0 +1,64 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; + +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Identifier; +import org.springframework.beans.factory.InitializingBean; + +public class SelectResponseTargetMedic extends AbstractServiceDelegate implements InitializingBean +{ + private final EndpointProvider endpointProvider; + + public SelectResponseTargetMedic(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + String medicIndentifier = getLeadingTaskFromExecutionVariables().getRequester().getIdentifier().getValue(); + + Endpoint endpoint = endpointProvider.getFirstConsortiumEndpoint( + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIndentifier).get(); + + Target medicTarget = Target.createUniDirectionalTarget(medicIndentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, TargetValues.create(medicTarget)); + } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java new file mode 100644 index 00000000..4b4a6eb2 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java @@ -0,0 +1,78 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; + +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Task; + +public class SelectResponseTargetTtp extends AbstractServiceDelegate +{ + private final EndpointProvider endpointProvider; + + public SelectResponseTargetTtp(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + String ttpIdentifier = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER); + String correlationKey = getCorrelationKey(); + + Endpoint endpoint = endpointProvider.getFirstConsortiumEndpoint( + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP, ttpIdentifier).get(); + + Target ttpTarget = Target.createBiDirectionalTarget(ttpIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), correlationKey); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, TargetValues.create(ttpTarget)); + } + + private String getCorrelationKey() + { + Task task = getCurrentTaskFromExecutionVariables(); + return getTaskHelper() + .getFirstInputParameterStringValue(task, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY) + .orElseThrow(() -> new IllegalStateException( + "No correlation key found, this error should have been caught by resource validation")); + } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java new file mode 100644 index 00000000..ba50f5bd --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java @@ -0,0 +1,91 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER; + +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Task; + +public class StoreCorrelationKeys extends AbstractServiceDelegate +{ + public StoreCorrelationKeys(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + Task task = getCurrentTaskFromExecutionVariables(); + + String leadingMedicIdentifier = getLeadingMedicIdentifier(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER, leadingMedicIdentifier); + + Targets targets = getTargets(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(targets)); + + boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + + String researchStudyIdentifier = getResearchStudyIdentifier(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY_IDENTIFIER, researchStudyIdentifier); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, QueryResultsValues.create(new QueryResults(null))); + } + + private String getLeadingMedicIdentifier(Task task) + { + return task.getRequester().getIdentifier().getValue(); + } + + private String getResearchStudyIdentifier(Task task) + { + return getTaskHelper() + .getFirstInputParameterReferenceValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER) + .orElseThrow(() -> new IllegalArgumentException("Research study identifier is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")) + .getIdentifier().getValue(); + } + + private Targets getTargets(Task task) + { + List targets = getTaskHelper() + .getInputParameterStringValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY) + .map(correlationKey -> Target.createBiDirectionalTarget("", "", "", correlationKey)) + .collect(Collectors.toList()); + + return new Targets(targets); + } + + private boolean getNeedsRecordLinkageCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) + .orElseThrow( + () -> new IllegalArgumentException("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-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreMultiMedicResultsForLeadingMedic.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreMultiMedicResultsForLeadingMedic.java new file mode 100644 index 00000000..bbf3edf6 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreMultiMedicResultsForLeadingMedic.java @@ -0,0 +1,25 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class StoreMultiMedicResultsForLeadingMedic extends StoreResults +{ + public StoreMultiMedicResultsForLeadingMedic(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, openEhrObjectMapper); + } + + @Override + protected String getSecurityIdentifier(DelegateExecution execution) + { + return (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreMultiMedicResultsForResearcher.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreMultiMedicResultsForResearcher.java new file mode 100644 index 00000000..dc36d60b --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreMultiMedicResultsForResearcher.java @@ -0,0 +1,64 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class StoreMultiMedicResultsForResearcher extends StoreResults +{ + public StoreMultiMedicResultsForResearcher(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, openEhrObjectMapper); + } + + @Override + protected String getSecurityIdentifier(DelegateExecution execution) + { + return (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_LEADING_MEDIC_IDENTIFIER); + } + + @Override + protected List postProcessStoredResults(List storedResults, DelegateExecution execution) + { + Task currentTask = getCurrentTaskFromExecutionVariables(); + Task leadingTask = getLeadingTaskFromExecutionVariables(); + + storedResults.forEach(result -> addOutput(leadingTask, result)); + + // The current task finishes here but is not automatically set to completed + // because it is an additional task during the execution of the main process + currentTask.setStatus(Task.TaskStatus.COMPLETED); + getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().update(currentTask); + + return storedResults; + } + + private void addOutput(Task task, QueryResult result) + { + Task.TaskOutputComponent output = getTaskHelper().createOutput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE, + new Reference(result.getResultSetUrl())); + output.addExtension(createCohortIdExtension(result.getCohortId())); + task.addOutput(output); + } + + private Extension createCohortIdExtension(String cohortId) + { + return new Extension(EXTENSION_HIGHMED_GROUP_ID, new Reference(cohortId)); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java new file mode 100644 index 00000000..f9b38214 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java @@ -0,0 +1,138 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.OPENEHR_MIMETYPE_JSON; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +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.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResourceType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +public abstract class StoreResults extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(StoreResults.class); + + private final ObjectMapper openEhrObjectMapper; + + public StoreResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper); + this.openEhrObjectMapper = openEhrObjectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + Objects.requireNonNull(openEhrObjectMapper, "openEhrObjectMapper"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + String securityIdentifier = getSecurityIdentifier(execution); + + List savedResults = saveQueryResults(results, securityIdentifier); + List postProcessedResults = postProcessStoredResults(savedResults, execution); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(postProcessedResults))); + } + + /** + * @param execution + * the bpmn process execution environment + * @return the identifier of the organization that should have read access to the stored Binary resource from the + * local FHIR server + */ + protected abstract String getSecurityIdentifier(DelegateExecution execution); + + /** + * @param storedResults + * the {@link QueryResult} objects after storing them to the local FHIR server + * @param execution + * the bpmn process execution environment + * @return the {@link QueryResult} objects after post processing + */ + protected List postProcessStoredResults(List storedResults, DelegateExecution execution) + { + return storedResults; + } + + private List saveQueryResults(QueryResults results, String securityIdentifier) + { + return results.getResults().stream().map(result -> saveResultSetAsBinary(result, securityIdentifier)) + .collect(Collectors.toList()); + } + + private QueryResult saveResultSetAsBinary(QueryResult result, String securityIdentifier) + { + String binaryId = save(result.getResultSet(), securityIdentifier); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), binaryId); + } + + private String save(ResultSet resultSet, String securityIdentifier) + { + byte[] content = serializeResultSet(resultSet); + Reference securityContext = new Reference(); + securityContext.setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(securityIdentifier); + Binary binary = new Binary().setContentType(OPENEHR_MIMETYPE_JSON).setSecurityContext(securityContext) + .setData(content); + + IdType created = createBinaryResource(binary); + return new IdType(getFhirWebserviceClientProvider().getLocalBaseUrl(), ResourceType.Binary.name(), + created.getIdPart(), created.getVersionIdPart()).getValue(); + } + + private byte[] serializeResultSet(ResultSet resultSet) + { + try + { + return openEhrObjectMapper.writeValueAsBytes(resultSet); + } + catch (JsonProcessingException exception) + { + logger.warn("Error while serializing ResultSet: " + exception.getMessage()); + throw new RuntimeException(exception); + } + } + + private IdType createBinaryResource(Binary binary) + { + try + { + return getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().create(binary); + } + catch (Exception exception) + { + logger.debug("Binary to create {}", FhirContext.forR4().newJsonParser().encodeResourceToString(binary)); + logger.warn("Error while creating Binary resoruce: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResultLinks.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResultLinks.java new file mode 100644 index 00000000..ba8e7d09 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResultLinks.java @@ -0,0 +1,61 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_GROUP_ID; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task; + +public class StoreSingleMedicResultLinks extends AbstractServiceDelegate +{ + public StoreSingleMedicResultLinks(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + QueryResults currentResults = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List newResults = getNewResults(); + + List extendedResults = Stream.of(currentResults.getResults(), newResults) + .flatMap(Collection::stream).collect(Collectors.toList()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(extendedResults))); + } + + private List getNewResults() + { + Task task = getCurrentTaskFromExecutionVariables(); + Reference requester = task.getRequester(); + + return getTaskHelper().getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE, EXTENSION_HIGHMED_GROUP_ID) + .map(input -> getQueryResult(input, requester)).collect(Collectors.toList()); + } + + private QueryResult getQueryResult(Task.ParameterComponent input, Reference requester) + { + String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference(); + String resultSetUrl = ((Reference) input.getValue()).getReference(); + return QueryResult.idResult(requester.getIdentifier().getValue(), cohortId, resultSetUrl); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResults.java new file mode 100644 index 00000000..c0123cb3 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResults.java @@ -0,0 +1,25 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class StoreSingleMedicResults extends StoreResults +{ + public StoreSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) + { + super(clientProvider, taskHelper, readAccessHelper, openEhrObjectMapper); + } + + @Override + protected String getSecurityIdentifier(DelegateExecution execution) + { + return (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/spring/config/DataSharingConfig.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/spring/config/DataSharingConfig.java new file mode 100755 index 00000000..11343a4d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/spring/config/DataSharingConfig.java @@ -0,0 +1,424 @@ +package org.highmed.dsf.bpe.spring.config; + +import java.nio.file.Paths; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.highmed.consent.client.ConsentClient; +import org.highmed.consent.client.ConsentClientFactory; +import org.highmed.dsf.bpe.crypto.KeyConsumer; +import org.highmed.dsf.bpe.crypto.KeyProvider; +import org.highmed.dsf.bpe.crypto.SecretKeyConsumerImpl; +import org.highmed.dsf.bpe.crypto.SecretKeyProviderImpl; +import org.highmed.dsf.bpe.message.SendMedicRequest; +import org.highmed.dsf.bpe.message.SendMultiMedicErrors; +import org.highmed.dsf.bpe.message.SendMultiMedicResults; +import org.highmed.dsf.bpe.message.SendSingleMedicResults; +import org.highmed.dsf.bpe.message.SendTtpRequest; +import org.highmed.dsf.bpe.service.CheckDataSharingResources; +import org.highmed.dsf.bpe.service.CheckMedicMultiMedicResults; +import org.highmed.dsf.bpe.service.CheckMedicSingleMedicResults; +import org.highmed.dsf.bpe.service.CheckTtpMultiMedicResults; +import org.highmed.dsf.bpe.service.CheckTtpSingleMedicResults; +import org.highmed.dsf.bpe.service.DecryptMultiMedicResults; +import org.highmed.dsf.bpe.service.DownloadDataSharingResources; +import org.highmed.dsf.bpe.service.DownloadMultiMedicResults; +import org.highmed.dsf.bpe.service.DownloadResearchStudyResource; +import org.highmed.dsf.bpe.service.DownloadSingleMedicResults; +import org.highmed.dsf.bpe.service.EncryptResults; +import org.highmed.dsf.bpe.service.ExecuteQueries; +import org.highmed.dsf.bpe.service.ExtractQueries; +import org.highmed.dsf.bpe.service.FilterResultsByConsent; +import org.highmed.dsf.bpe.service.GenerateBloomFilters; +import org.highmed.dsf.bpe.service.HandleErrorMultiMedicResults; +import org.highmed.dsf.bpe.service.ModifyQueries; +import org.highmed.dsf.bpe.service.PseudonymizeResultsFirstOrder; +import org.highmed.dsf.bpe.service.PseudonymizeResultsSecondOrderWithRecordLinkage; +import org.highmed.dsf.bpe.service.PseudonymizeResultsSecondOrderWithoutRecordLinkage; +import org.highmed.dsf.bpe.service.SelectRequestTargets; +import org.highmed.dsf.bpe.service.SelectResponseTargetMedic; +import org.highmed.dsf.bpe.service.SelectResponseTargetTtp; +import org.highmed.dsf.bpe.service.StoreCorrelationKeys; +import org.highmed.dsf.bpe.service.StoreMultiMedicResultsForLeadingMedic; +import org.highmed.dsf.bpe.service.StoreMultiMedicResultsForResearcher; +import org.highmed.dsf.bpe.service.StoreSingleMedicResultLinks; +import org.highmed.dsf.bpe.service.StoreSingleMedicResults; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.group.GroupHelper; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.mpi.client.MasterPatientIndexClient; +import org.highmed.mpi.client.MasterPatientIndexClientFactory; +import org.highmed.openehr.client.OpenEhrClient; +import org.highmed.openehr.client.OpenEhrClientFactory; +import org.highmed.pseudonymization.client.PseudonymizationClient; +import org.highmed.pseudonymization.client.PseudonymizationClientFactory; +import org.highmed.pseudonymization.domain.PersonWithMdat; +import org.highmed.pseudonymization.domain.impl.MatchedPersonImpl; +import org.highmed.pseudonymization.recordlinkage.AbstractMatcher; +import org.highmed.pseudonymization.recordlinkage.FederatedMatcher; +import org.highmed.pseudonymization.recordlinkage.FederatedMatcherImpl; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicNoRbf; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicNoRbfImpl; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicWithRbf; +import org.highmed.pseudonymization.translation.ResultSetTranslatorFromMedicWithRbfImpl; +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.core.env.Environment; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +@Configuration +public class DataSharingConfig +{ + @Autowired + private FhirWebserviceClientProvider fhirClientProvider; + + @Autowired + private ConsentClientFactory consentClientFactory; + + @Autowired + private PseudonymizationClientFactory pseudonymizationClientFactory; + + @Autowired + private MasterPatientIndexClientFactory masterPatientIndexClientFactory; + + @Autowired + private OpenEhrClientFactory openEhrClientFactory; + + @Autowired + private OrganizationProvider organizationProvider; + + @Autowired + private EndpointProvider endpointProvider; + + @Autowired + private TaskHelper taskHelper; + + @Autowired + private ReadAccessHelper readAccessHelper; + + @Autowired + private GroupHelper groupHelper; + + @Autowired + private FhirContext fhirContext; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private Environment environment; + + @Value("${org.highmed.dsf.bpe.psn.organization.keystore:psn/organization-keystore.p12}") + private String organizationKeystoreFile; + + @Value("${org.highmed.dsf.bpe.psn.organization.keystore.password:password}") + private String organizationKeystorePassword; + + @Value("${org.highmed.dsf.bpe.psn.research.study.keystore:psn/research-study-keystore.p12}") + private String researchStudyKeystoreFile; + + @Value("${org.highmed.dsf.bpe.psn.research.study.keystore.password:password}") + private String getResearchStudyKeystorePassword; + + @Value("${org.highmed.dsf.bpe.openehr.subject_external_id.path:/ehr_status/subject/external_ref/id/value}") + private String ehrIdColumnPath; + + // + // process requestDataSharing implementations + // + + @Bean + public DownloadResearchStudyResource downloadResearchStudyResource() + { + return new DownloadResearchStudyResource(fhirClientProvider, taskHelper, readAccessHelper, + organizationProvider); + } + + @Bean + public SelectRequestTargets selectRequestTargets() + { + return new SelectRequestTargets(fhirClientProvider, taskHelper, readAccessHelper, endpointProvider, + bouncyCastleProvider()); + } + + @Bean + public SendTtpRequest sendTtpRequest() + { + return new SendTtpRequest(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Bean + public SendMedicRequest sendMedicRequest() + { + return new SendMedicRequest(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } + + @Bean + public DownloadMultiMedicResults downloadMultiMedicResults() + { + return new DownloadMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); + } + + @Bean + public DecryptMultiMedicResults decryptMultiMedicResults() + { + return new DecryptMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); + } + + @Bean + public CheckMedicMultiMedicResults checkMedicMultiMedicResults() + { + return new CheckMedicMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public StoreMultiMedicResultsForLeadingMedic storeMultiMedicResultsForLeadingMedic() + { + return new StoreMultiMedicResultsForLeadingMedic(fhirClientProvider, taskHelper, readAccessHelper, + objectMapper); + } + + @Bean + public StoreMultiMedicResultsForResearcher storeMultiMedicResultsForResearcher() + { + return new StoreMultiMedicResultsForResearcher(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); + } + + @Bean + public HandleErrorMultiMedicResults handleErrorMultiMedicResults() + { + return new HandleErrorMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper); + } + + // + // process computeDataSharing implementations + // + + @Bean + public StoreCorrelationKeys storeCorrelationKeys() + { + return new StoreCorrelationKeys(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public StoreSingleMedicResultLinks storeSingleMedicResultLinks() + { + return new StoreSingleMedicResultLinks(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public DownloadSingleMedicResults downloadSingleMedicResults() + { + return new DownloadSingleMedicResults(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); + } + + @Bean + public CheckTtpSingleMedicResults checkTtpSingleMedicResults() + { + return new CheckTtpSingleMedicResults(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public KeyConsumer keyConsumer() + { + return new SecretKeyConsumerImpl(Paths.get(researchStudyKeystoreFile), + getResearchStudyKeystorePassword.toCharArray()); + } + + @Bean + public ResultSetTranslatorFromMedicWithRbf resultSetTranslatorFromMedicWithRbf() + { + return new ResultSetTranslatorFromMedicWithRbfImpl(); + } + + @Bean + public FederatedMatcher createFederatedMatcherStrategyMin() + { + return new FederatedMatcherImpl<>(MatchedPersonImpl::new, AbstractMatcher.MatchCalculatorStrategy.MIN); + } + + @Bean + public PseudonymizeResultsSecondOrderWithRecordLinkage pseudonymizeResultsSecondOrderWithRecordLinkage() + { + return new PseudonymizeResultsSecondOrderWithRecordLinkage(fhirClientProvider, taskHelper, readAccessHelper, + keyConsumer(), resultSetTranslatorFromMedicWithRbf(), createFederatedMatcherStrategyMin(), + objectMapper); + } + + @Bean + public ResultSetTranslatorFromMedicNoRbf resultSetTranslatorFromMedicNoRbf() + { + return new ResultSetTranslatorFromMedicNoRbfImpl(); + } + + @Bean + public FederatedMatcher createFederatedMatcherStrategyNone() + { + return new FederatedMatcherImpl<>(MatchedPersonImpl::new, AbstractMatcher.MatchCalculatorStrategy.NONE); + } + + @Bean + public PseudonymizeResultsSecondOrderWithoutRecordLinkage pseudonymizeResultsSecondOrderWithoutRecordLinkage() + { + return new PseudonymizeResultsSecondOrderWithoutRecordLinkage(fhirClientProvider, taskHelper, readAccessHelper, + keyConsumer(), resultSetTranslatorFromMedicNoRbf(), createFederatedMatcherStrategyNone(), objectMapper); + } + + @Bean + public SelectResponseTargetMedic selectResponseTargetMedic() + { + return new SelectResponseTargetMedic(fhirClientProvider, taskHelper, readAccessHelper, endpointProvider); + } + + @Bean + public CheckTtpMultiMedicResults checkTtpMultiMedicResults() + { + return new CheckTtpMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public SendMultiMedicResults sendMultiMedicResults() + { + return new SendMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } + + @Bean + public SendMultiMedicErrors sendMultiMedicErrors() + { + return new SendMultiMedicErrors(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } + + // + // process executeDataSharing implementations + // + + @Bean + public DownloadDataSharingResources downloadDataSharingResources() + { + return new DownloadDataSharingResources(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider); + } + + @Bean + public CheckDataSharingResources checkDataSharingResources() + { + return new CheckDataSharingResources(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public ExtractQueries extractQueries() + { + return new ExtractQueries(fhirClientProvider, taskHelper, readAccessHelper, groupHelper); + } + + @Bean + public ModifyQueries modifyQueries() + { + return new ModifyQueries(fhirClientProvider, taskHelper, readAccessHelper, ehrIdColumnPath); + } + + @Bean + public ExecuteQueries executeQueries() + { + return new ExecuteQueries(fhirClientProvider, openEhrClient(), taskHelper, readAccessHelper, + organizationProvider); + } + + @Bean + public OpenEhrClient openEhrClient() + { + return openEhrClientFactory.createClient(environment::getProperty); + } + + @Bean + public ConsentClient consentClient() + { + return consentClientFactory.createClient(environment::getProperty); + } + + @Bean + public FilterResultsByConsent filterResultsByConsent() + { + return new FilterResultsByConsent(fhirClientProvider, taskHelper, readAccessHelper, consentClient()); + } + + @Bean + public MasterPatientIndexClient masterPatientIndexClient() + { + return masterPatientIndexClientFactory.createClient(environment::getProperty); + } + + @Bean + public BouncyCastleProvider bouncyCastleProvider() + { + return new BouncyCastleProvider(); + } + + @Bean + public GenerateBloomFilters generateBloomFilters() + { + return new GenerateBloomFilters(fhirClientProvider, taskHelper, readAccessHelper, masterPatientIndexClient(), + ehrIdColumnPath, bouncyCastleProvider()); + } + + @Bean + public PseudonymizationClient pseudonymizationClient() + { + return pseudonymizationClientFactory.createClient(environment::getProperty); + } + + @Bean + public PseudonymizeResultsFirstOrder pseudonymizeResultsFirstOrder() + { + return new PseudonymizeResultsFirstOrder(fhirClientProvider, taskHelper, readAccessHelper, + pseudonymizationClient()); + } + + @Bean + public KeyProvider keyProvider() + { + return new SecretKeyProviderImpl(organizationProvider, Paths.get(organizationKeystoreFile), + organizationKeystorePassword.toCharArray()); + } + + @Bean + public EncryptResults encryptResults() + { + return new EncryptResults(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, keyProvider(), + ehrIdColumnPath); + } + + @Bean + public SelectResponseTargetTtp selectResponseTargetTtp() + { + return new SelectResponseTargetTtp(fhirClientProvider, taskHelper, readAccessHelper, endpointProvider); + } + + @Bean + public CheckMedicSingleMedicResults checkMedicSingleMedicResults() + { + return new CheckMedicSingleMedicResults(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public StoreSingleMedicResults storeSingleMedicResults() + { + return new StoreSingleMedicResults(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); + } + + @Bean + public SendSingleMedicResults sendSingleMedicResults() + { + return new SendSingleMedicResults(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/spring/config/DataSharingSerializerConfig.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/spring/config/DataSharingSerializerConfig.java new file mode 100644 index 00000000..c4da4e58 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/spring/config/DataSharingSerializerConfig.java @@ -0,0 +1,42 @@ +package org.highmed.dsf.bpe.spring.config; + +import org.highmed.dsf.bpe.variable.BloomFilterConfigSerializer; +import org.highmed.dsf.bpe.variable.QueryResultSerializer; +import org.highmed.dsf.bpe.variable.QueryResultsSerializer; +import org.highmed.dsf.bpe.variable.SecretKeyWrapperSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@Configuration +public class DataSharingSerializerConfig +{ + @Autowired + private ObjectMapper objectMapper; + + @Bean + public BloomFilterConfigSerializer bloomFilterConfigSerializer() + { + return new BloomFilterConfigSerializer(objectMapper); + } + + @Bean + public QueryResultSerializer queryResultSerializer() + { + return new QueryResultSerializer(objectMapper); + } + + @Bean + public QueryResultsSerializer queryResultsSerializer() + { + return new QueryResultsSerializer(objectMapper); + } + + @Bean + public SecretKeyWrapperSerializer secretKeyWrapperSerializer() + { + return new SecretKeyWrapperSerializer(objectMapper); + } +} diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfig.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfig.java similarity index 96% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfig.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfig.java index bbf4ac18..b1d35d1f 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfig.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfig.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.security.Key; @@ -8,7 +8,6 @@ import org.highmed.dsf.fhir.variables.KeySerializer; 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; @@ -60,22 +59,24 @@ public BloomFilterConfig(@JsonProperty("permutationSeed") long permutationSeed, this.hmacSha3Key = hmacSha3Key; } + @JsonProperty("permutationSeed") public long getPermutationSeed() { return permutationSeed; } + @JsonProperty("hmacSha2Key") public Key getHmacSha2Key() { return hmacSha2Key; } + @JsonProperty("hmacSha3Key") public Key getHmacSha3Key() { return hmacSha3Key; } - @JsonIgnore public byte[] toBytes() { byte[] bytes = new byte[SEED_LENGTH + HMAC_SHA2_KEY_LENGTH + HMAC_SHA3_KEY_LENGTH]; diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfigSerializer.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfigSerializer.java similarity index 93% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfigSerializer.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfigSerializer.java index b6d6c8cb..111a0c07 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfigSerializer.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfigSerializer.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.io.IOException; import java.util.Objects; @@ -6,7 +6,7 @@ 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.bpe.variables.BloomFilterConfigValues.BloomFilterConfigValue; +import org.highmed.dsf.bpe.variable.BloomFilterConfigValues.BloomFilterConfigValue; import org.springframework.beans.factory.InitializingBean; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfigValues.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfigValues.java similarity index 97% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfigValues.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfigValues.java index 4640b0b0..0f6b2570 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/BloomFilterConfigValues.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/BloomFilterConfigValues.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.util.Map; diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResult.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResult.java similarity index 59% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResult.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResult.java index d168aff7..87ddfd54 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResult.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResult.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import org.highmed.openehr.model.structure.ResultSet; @@ -6,7 +6,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -public class FeasibilityQueryResult +public class QueryResult { private final String organizationIdentifier; private final String cohortId; @@ -14,26 +14,31 @@ public class FeasibilityQueryResult private final ResultSet resultSet; private final String resultSetUrl; - public static FeasibilityQueryResult countResult(String organizationIdentifier, String cohortId, int cohortSize) + public static QueryResult countResult(String organizationIdentifier, String cohortId, int cohortSize) { if (cohortSize < 0) throw new IllegalArgumentException("cohortSize >= 0 expected"); - return new FeasibilityQueryResult(organizationIdentifier, cohortId, cohortSize, null, null); + return new QueryResult(organizationIdentifier, cohortId, cohortSize, null, null); } - public static FeasibilityQueryResult idResult(String organizationIdentifier, String cohortId, ResultSet resultSet) + public static QueryResult mpcCountResult(String organizationIdentifier, String cohortId, int cohortSize) { - return new FeasibilityQueryResult(organizationIdentifier, cohortId, -1, resultSet, null); + return new QueryResult(organizationIdentifier, cohortId, cohortSize, null, null); } - public static FeasibilityQueryResult idResult(String organizationIdentifier, String cohortId, String resultSetUrl) + public static QueryResult idResult(String organizationIdentifier, String cohortId, ResultSet resultSet) { - return new FeasibilityQueryResult(organizationIdentifier, cohortId, -1, null, resultSetUrl); + return new QueryResult(organizationIdentifier, cohortId, -1, resultSet, null); + } + + public static QueryResult idResult(String organizationIdentifier, String cohortId, String resultSetUrl) + { + return new QueryResult(organizationIdentifier, cohortId, -1, null, resultSetUrl); } @JsonCreator - public FeasibilityQueryResult(@JsonProperty("organizationIdentifier") String organizationIdentifier, + public QueryResult(@JsonProperty("organizationIdentifier") String organizationIdentifier, @JsonProperty("cohortId") String cohortId, @JsonProperty("cohortSize") int cohortSize, @JsonProperty("resultSet") ResultSet resultSet, @JsonProperty("resultSetUrl") String resultSetUrl) { @@ -44,26 +49,31 @@ public FeasibilityQueryResult(@JsonProperty("organizationIdentifier") String org this.resultSetUrl = resultSetUrl; } + @JsonProperty("organizationIdentifier") public String getOrganizationIdentifier() { return organizationIdentifier; } + @JsonProperty("cohortId") public String getCohortId() { return cohortId; } + @JsonProperty("cohortSize") public int getCohortSize() { return cohortSize; } + @JsonProperty("resultSet") public ResultSet getResultSet() { return resultSet; } + @JsonProperty("resultSetUrl") public String getResultSetUrl() { return resultSetUrl; @@ -86,4 +96,4 @@ public boolean isIdResultSetUrlResult() { return resultSet == null && resultSetUrl != null; } -} +} \ No newline at end of file diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultSerializer.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultSerializer.java similarity index 65% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultSerializer.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultSerializer.java index a6623fac..a0a43873 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultSerializer.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultSerializer.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.io.IOException; import java.util.Objects; @@ -6,20 +6,20 @@ 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.bpe.variables.FeasibilityQueryResultValues.FeasibilityQueryResultValue; +import org.highmed.dsf.bpe.variable.QueryResultValues.FeasibilityQueryResultValue; import org.springframework.beans.factory.InitializingBean; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -public class FeasibilityQueryResultSerializer extends PrimitiveValueSerializer +public class QueryResultSerializer extends PrimitiveValueSerializer implements InitializingBean { private final ObjectMapper objectMapper; - public FeasibilityQueryResultSerializer(ObjectMapper objectMapper) + public QueryResultSerializer(ObjectMapper objectMapper) { - super(FeasibilityQueryResultValues.VALUE_TYPE); + super(QueryResultValues.VALUE_TYPE); this.objectMapper = objectMapper; } @@ -33,7 +33,7 @@ public void afterPropertiesSet() throws Exception @Override public void writeValue(FeasibilityQueryResultValue value, ValueFields valueFields) { - FeasibilityQueryResult result = value.getValue(); + QueryResult result = value.getValue(); try { if (result != null) @@ -48,7 +48,7 @@ public void writeValue(FeasibilityQueryResultValue value, ValueFields valueField @Override public FeasibilityQueryResultValue convertToTypedValue(UntypedValueImpl untypedValue) { - return FeasibilityQueryResultValues.create((FeasibilityQueryResult) untypedValue.getValue()); + return QueryResultValues.create((QueryResult) untypedValue.getValue()); } @Override @@ -58,9 +58,9 @@ public FeasibilityQueryResultValue readValue(ValueFields valueFields, boolean as try { - FeasibilityQueryResult result = (bytes == null || bytes.length <= 0) ? null - : objectMapper.readValue(bytes, FeasibilityQueryResult.class); - return FeasibilityQueryResultValues.create(result); + QueryResult result = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, QueryResult.class); + return QueryResultValues.create(result); } catch (IOException e) { diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultValues.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultValues.java similarity index 51% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultValues.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultValues.java index d2eea04a..bebc28ea 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultValues.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultValues.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.util.Map; @@ -8,18 +8,18 @@ import org.camunda.bpm.engine.variable.value.PrimitiveValue; import org.camunda.bpm.engine.variable.value.TypedValue; -public class FeasibilityQueryResultValues +public class QueryResultValues { - public static interface FeasibilityQueryResultValue extends PrimitiveValue + public static interface FeasibilityQueryResultValue extends PrimitiveValue { } - private static class FeasibilityQueryResultValueImpl extends PrimitiveTypeValueImpl - implements FeasibilityQueryResultValues.FeasibilityQueryResultValue + private static class FeasibilityQueryResultValueImpl extends PrimitiveTypeValueImpl + implements QueryResultValues.FeasibilityQueryResultValue { private static final long serialVersionUID = 1L; - public FeasibilityQueryResultValueImpl(FeasibilityQueryResult value, PrimitiveValueType type) + public FeasibilityQueryResultValueImpl(QueryResult value, PrimitiveValueType type) { super(value, type); } @@ -31,25 +31,24 @@ public static class FeasibilityQueryResultValueTypeImpl extends PrimitiveValueTy private FeasibilityQueryResultValueTypeImpl() { - super(FeasibilityQueryResult.class); + super(QueryResult.class); } @Override public TypedValue createValue(Object value, Map valueInfo) { - return new FeasibilityQueryResultValues.FeasibilityQueryResultValueImpl((FeasibilityQueryResult) value, - VALUE_TYPE); + return new QueryResultValues.FeasibilityQueryResultValueImpl((QueryResult) value, VALUE_TYPE); } } - public static final PrimitiveValueType VALUE_TYPE = new FeasibilityQueryResultValues.FeasibilityQueryResultValueTypeImpl(); + public static final PrimitiveValueType VALUE_TYPE = new QueryResultValues.FeasibilityQueryResultValueTypeImpl(); - private FeasibilityQueryResultValues() + private QueryResultValues() { } - public static FeasibilityQueryResultValues.FeasibilityQueryResultValue create(FeasibilityQueryResult value) + public static QueryResultValues.FeasibilityQueryResultValue create(QueryResult value) { - return new FeasibilityQueryResultValues.FeasibilityQueryResultValueImpl(value, VALUE_TYPE); + return new QueryResultValues.FeasibilityQueryResultValueImpl(value, VALUE_TYPE); } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResults.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResults.java similarity index 52% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResults.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResults.java index e999bd24..89c11818 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResults.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResults.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.util.ArrayList; import java.util.Collection; @@ -8,30 +8,31 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -public class FeasibilityQueryResults +public class QueryResults { - private final List results = new ArrayList<>(); + private final List results = new ArrayList<>(); @JsonCreator - public FeasibilityQueryResults(@JsonProperty("results") Collection results) + public QueryResults(@JsonProperty("results") Collection results) { if (results != null) this.results.addAll(results); } - public void add(FeasibilityQueryResult newResult) + public void add(QueryResult newResult) { if (newResult != null) results.add(newResult); } - public void addAll(Collection results) + public void addAll(Collection results) { if (results != null) this.results.addAll(results); } - public List getResults() + @JsonProperty("results") + public List getResults() { return Collections.unmodifiableList(results); } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultsSerializer.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultsSerializer.java similarity index 64% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultsSerializer.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultsSerializer.java index 26022a95..b4a5e4c2 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultsSerializer.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultsSerializer.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.io.IOException; import java.util.Objects; @@ -6,20 +6,20 @@ 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.bpe.variables.FeasibilityQueryResultsValues.FeasibilityQueryResultsValue; +import org.highmed.dsf.bpe.variable.QueryResultsValues.FeasibilityQueryResultsValue; import org.springframework.beans.factory.InitializingBean; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -public class FeasibilityQueryResultsSerializer extends PrimitiveValueSerializer +public class QueryResultsSerializer extends PrimitiveValueSerializer implements InitializingBean { private final ObjectMapper objectMapper; - public FeasibilityQueryResultsSerializer(ObjectMapper objectMapper) + public QueryResultsSerializer(ObjectMapper objectMapper) { - super(FeasibilityQueryResultsValues.VALUE_TYPE); + super(QueryResultsValues.VALUE_TYPE); this.objectMapper = objectMapper; } @@ -33,7 +33,7 @@ public void afterPropertiesSet() throws Exception @Override public void writeValue(FeasibilityQueryResultsValue value, ValueFields valueFields) { - FeasibilityQueryResults results = value.getValue(); + QueryResults results = value.getValue(); try { if (results != null) @@ -48,7 +48,7 @@ public void writeValue(FeasibilityQueryResultsValue value, ValueFields valueFiel @Override public FeasibilityQueryResultsValue convertToTypedValue(UntypedValueImpl untypedValue) { - return FeasibilityQueryResultsValues.create((FeasibilityQueryResults) untypedValue.getValue()); + return QueryResultsValues.create((QueryResults) untypedValue.getValue()); } @Override @@ -58,9 +58,9 @@ public FeasibilityQueryResultsValue readValue(ValueFields valueFields, boolean a try { - FeasibilityQueryResults results = (bytes == null || bytes.length <= 0) ? null - : objectMapper.readValue(bytes, FeasibilityQueryResults.class); - return FeasibilityQueryResultsValues.create(results); + QueryResults results = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, QueryResults.class); + return QueryResultsValues.create(results); } catch (IOException e) { diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultsValues.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultsValues.java similarity index 50% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultsValues.java rename to dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultsValues.java index 7151c4cc..0171b353 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FeasibilityQueryResultsValues.java +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/QueryResultsValues.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.bpe.variables; +package org.highmed.dsf.bpe.variable; import java.util.Map; @@ -8,18 +8,18 @@ import org.camunda.bpm.engine.variable.value.PrimitiveValue; import org.camunda.bpm.engine.variable.value.TypedValue; -public class FeasibilityQueryResultsValues +public class QueryResultsValues { - public static interface FeasibilityQueryResultsValue extends PrimitiveValue + public static interface FeasibilityQueryResultsValue extends PrimitiveValue { } - private static class FeasibilityQueryResultsValueImpl extends PrimitiveTypeValueImpl - implements FeasibilityQueryResultsValues.FeasibilityQueryResultsValue + private static class FeasibilityQueryResultsValueImpl extends PrimitiveTypeValueImpl + implements QueryResultsValues.FeasibilityQueryResultsValue { private static final long serialVersionUID = 1L; - public FeasibilityQueryResultsValueImpl(FeasibilityQueryResults value, PrimitiveValueType type) + public FeasibilityQueryResultsValueImpl(QueryResults value, PrimitiveValueType type) { super(value, type); } @@ -31,25 +31,24 @@ public static class FeasibilityQueryResultsValueTypeImpl extends PrimitiveValueT private FeasibilityQueryResultsValueTypeImpl() { - super(FeasibilityQueryResults.class); + super(QueryResults.class); } @Override public TypedValue createValue(Object value, Map valueInfo) { - return new FeasibilityQueryResultsValues.FeasibilityQueryResultsValueImpl((FeasibilityQueryResults) value, - VALUE_TYPE); + return new QueryResultsValues.FeasibilityQueryResultsValueImpl((QueryResults) value, VALUE_TYPE); } } - public static final PrimitiveValueType VALUE_TYPE = new FeasibilityQueryResultsValues.FeasibilityQueryResultsValueTypeImpl(); + public static final PrimitiveValueType VALUE_TYPE = new QueryResultsValues.FeasibilityQueryResultsValueTypeImpl(); - private FeasibilityQueryResultsValues() + private QueryResultsValues() { } - public static FeasibilityQueryResultsValues.FeasibilityQueryResultsValue create(FeasibilityQueryResults value) + public static QueryResultsValues.FeasibilityQueryResultsValue create(QueryResults value) { - return new FeasibilityQueryResultsValues.FeasibilityQueryResultsValueImpl(value, VALUE_TYPE); + return new QueryResultsValues.FeasibilityQueryResultsValueImpl(value, VALUE_TYPE); } } diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapper.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapper.java new file mode 100644 index 00000000..46d68a17 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapper.java @@ -0,0 +1,72 @@ +package org.highmed.dsf.bpe.variable; + +import java.security.NoSuchAlgorithmException; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.highmed.pseudonymization.crypto.AesGcmUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SecretKeyWrapper +{ + private static final Logger logger = LoggerFactory.getLogger(SecretKeyWrapper.class); + private static final String AES_ALGORITHM = "AES"; + + public static SecretKeyWrapper newAes256Key() + { + try + { + return new SecretKeyWrapper(AesGcmUtil.generateAES256Key().getEncoded(), AES_ALGORITHM); + } + catch (NoSuchAlgorithmException exception) + { + logger.warn("Could not create new AES256 key: {}", exception.getMessage()); + throw new RuntimeException(exception); + } + } + + public static SecretKeyWrapper fromAes256Key(byte[] key) + { + byte[] bytes = new byte[key.length]; + System.arraycopy(key, 0, bytes, 0, bytes.length); + + return new SecretKeyWrapper(bytes, AES_ALGORITHM); + } + + private final byte[] bytes; + private final String algorithm; + + @JsonCreator + private SecretKeyWrapper(@JsonProperty("bytes") byte[] bytes, @JsonProperty("algorithm") String algorithm) + { + this.bytes = bytes; + this.algorithm = algorithm; + } + + @JsonIgnore + public SecretKey getSecretKey() + { + return new SecretKeySpec(bytes, algorithm); + } + + @JsonProperty("algorithm") + public String getAlgorithm() + { + return algorithm; + } + + @JsonProperty("bytes") + public byte[] getBytes() + { + byte[] key = new byte[bytes.length]; + System.arraycopy(bytes, 0, key, 0, key.length); + + return key; + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapperSerializer.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapperSerializer.java new file mode 100644 index 00000000..ab24e5ec --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapperSerializer.java @@ -0,0 +1,70 @@ +package org.highmed.dsf.bpe.variable; + +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.bpe.variable.SecretKeyWrapperValues.SecretKeyWrapperValue; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class SecretKeyWrapperSerializer extends PrimitiveValueSerializer + implements InitializingBean +{ + private final ObjectMapper objectMapper; + + public SecretKeyWrapperSerializer(ObjectMapper objectMapper) + { + super(SecretKeyWrapperValues.VALUE_TYPE); + + this.objectMapper = objectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(objectMapper, "objectMapper"); + } + + @Override + public void writeValue(SecretKeyWrapperValue value, ValueFields valueFields) + { + SecretKeyWrapper target = value.getValue(); + try + { + if (target != null) + valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(target)); + } + catch (JsonProcessingException e) + { + throw new RuntimeException(e); + } + } + + @Override + public SecretKeyWrapperValue convertToTypedValue(UntypedValueImpl untypedValue) + { + return SecretKeyWrapperValues.create((SecretKeyWrapper) untypedValue.getValue()); + } + + @Override + public SecretKeyWrapperValue readValue(ValueFields valueFields, boolean asTransientValue) + { + byte[] bytes = valueFields.getByteArrayValue(); + + try + { + SecretKeyWrapper target = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, SecretKeyWrapper.class); + return SecretKeyWrapperValues.create(target); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapperValues.java b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapperValues.java new file mode 100644 index 00000000..579bd9fe --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/java/org/highmed/dsf/bpe/variable/SecretKeyWrapperValues.java @@ -0,0 +1,54 @@ +package org.highmed.dsf.bpe.variable; + +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 SecretKeyWrapperValues +{ + public static interface SecretKeyWrapperValue extends PrimitiveValue + { + } + + private static class SecretKeyWrapperValueImpl extends PrimitiveTypeValueImpl + implements SecretKeyWrapperValues.SecretKeyWrapperValue + { + private static final long serialVersionUID = 1L; + + public SecretKeyWrapperValueImpl(SecretKeyWrapper value, PrimitiveValueType type) + { + super(value, type); + } + } + + public static class SecretKeyWrapperValueTypeImpl extends PrimitiveValueTypeImpl + { + private static final long serialVersionUID = 1L; + + private SecretKeyWrapperValueTypeImpl() + { + super(SecretKeyWrapper.class); + } + + @Override + public TypedValue createValue(Object value, Map valueInfo) + { + return new SecretKeyWrapperValues.SecretKeyWrapperValueImpl((SecretKeyWrapper) value, VALUE_TYPE); + } + } + + public static final PrimitiveValueType VALUE_TYPE = new SecretKeyWrapperValues.SecretKeyWrapperValueTypeImpl(); + + private SecretKeyWrapperValues() + { + } + + public static SecretKeyWrapperValues.SecretKeyWrapperValue create(SecretKeyWrapper value) + { + return new SecretKeyWrapperValues.SecretKeyWrapperValueImpl(value, VALUE_TYPE); + } +} diff --git a/dsf-bpe-process-data-sharing/src/main/resources/META-INF/services/org.highmed.dsf.bpe.ProcessPluginDefinition b/dsf-bpe-process-data-sharing/src/main/resources/META-INF/services/org.highmed.dsf.bpe.ProcessPluginDefinition new file mode 100644 index 00000000..5f28df5d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/META-INF/services/org.highmed.dsf.bpe.ProcessPluginDefinition @@ -0,0 +1 @@ +org.highmed.dsf.bpe.DataSharingProcessPluginDefinition \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/bpe/computeDataSharing.bpmn b/dsf-bpe-process-data-sharing/src/main/resources/bpe/computeDataSharing.bpmn new file mode 100644 index 00000000..b7b4d2a2 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/bpe/computeDataSharing.bpmn @@ -0,0 +1,320 @@ + + + + + SequenceFlow_1lfe4wr + SequenceFlow_0xxpamp + + + SequenceFlow_0mj024w + + + SequenceFlow_0by0at7 + SequenceFlow_0mj024w + + + + + ${target.correlationKey} + + + SequenceFlow_0qjt33w + SequenceFlow_0by0at7 + + + SequenceFlow_0qjt33w + + + + + + + SequenceFlow_0h3to47 + + PT5M + + + + SequenceFlow_01pjftq + + + + + + http://highmed.org/bpe/Process/requestDataSharing/#{version} + resultMultiMedicDataSharingMessage + http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-data-sharing|#{version} + + + Flow_0uaqn1r + + + + + + Flow_0g86uan + SequenceFlow_0t4lx4v + SequenceFlow_0calilw + + + + + ${!needsRecordLinkage} + + + SequenceFlow_0calilw + SequenceFlow_02zmrer + + + + SequenceFlow_02zmrer + Flow_115yfgb + Flow_1qqffoq + + + SequenceFlow_01pjftq + SequenceFlow_1lfe4wr + + + Flow_1qqffoq + Flow_1wig1wj + + + + + http://highmed.org/bpe/Process/requestDataSharing/#{version} + errorMultiMedicDataSharingMessage + http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-data-sharing|#{version} + + + Flow_1tmnvhl + Flow_0rwc0yo + + + + Flow_1wig1wj + Flow_0mogdyo + + + Flow_1tmnvhl + + + + + ${needsRecordLinkage} + + + SequenceFlow_0xxpamp + SequenceFlow_0h3to47 + Flow_0b5n9vc + + + + + Flow_0b5n9vc + Flow_0gx8n5k + + + Flow_0mogdyo + Flow_0uaqn1r + + + + + + + + SequenceFlow_0t4lx4v + Flow_115yfgb + + + + Flow_0gx8n5k + Flow_0g86uan + + + Flow_0rwc0yo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dsf-bpe-process-data-sharing/src/main/resources/bpe/executeDataSharing.bpmn b/dsf-bpe-process-data-sharing/src/main/resources/bpe/executeDataSharing.bpmn new file mode 100755 index 00000000..577d10ca --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/bpe/executeDataSharing.bpmn @@ -0,0 +1,309 @@ + + + + + Flow_1pzik8k + Flow_08925ay + + + SequenceFlow_1etju4m + Flow_1kp6eaq + + + SequenceFlow_14cn0vs + + + + + + + SequenceFlow_14cn0vs + SequenceFlow_1etju4m + + + + + http://highmed.org/bpe/Process/computeDataSharing/#{version} + resultSingleMedicDataSharingMessage + http://highmed.org/fhir/StructureDefinition/task-single-medic-result-data-sharing|#{version} + + + Flow_1611vr6 + + + + SequenceFlow_1rmqv20 + SequenceFlow_05r9whd + SequenceFlow_0isxkuy + + + ${!needsConsentCheck} + + + ${needsConsentCheck} + + + SequenceFlow_0isxkuy + SequenceFlow_0kzp6tl + + + SequenceFlow_05r9whd + SequenceFlow_0kzp6tl + Flow_14nlfvk + + + + Flow_0xt2bfn + Flow_1df64h2 + + + Flow_0m3ah40 + Flow_1pzik8k + + + Flow_0qsitvp + SequenceFlow_1rmqv20 + + + + + Flow_1ecoehc + Flow_0qsitvp + + + + Flow_1kp6eaq + Flow_1ecoehc + + + Flow_14nlfvk + Flow_0xt2bfn + Flow_09dzkmp + + + + Flow_09dzkmp + Flow_1df64h2 + Flow_1pgebfo + + + ${!needsRecordLinkage} + + + ${needsRecordLinkage} + + + Flow_08925ay + Flow_1611vr6 + + + + + + + Flow_0wymq8g + Flow_0m3ah40 + + + Flow_1o1ugb3 + + + + + Flow_1o1ugb3 + + + + + Flow_1pgebfo + Flow_0wymq8g + + + + uac check, study definiton validity, type of cohort, ethics commitee vote, included medics, user authentication, rate limit, etc. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dsf-bpe-process-data-sharing/src/main/resources/bpe/requestDataSharing.bpmn b/dsf-bpe-process-data-sharing/src/main/resources/bpe/requestDataSharing.bpmn new file mode 100644 index 00000000..6d6d1018 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/bpe/requestDataSharing.bpmn @@ -0,0 +1,231 @@ + + + + + + + Flow_0dd6nmz + + + + Flow_0dd6nmz + Flow_06otxko + + + + + + http://highmed.org/bpe/Process/executeDataSharing/#{version} + executeDataSharingMessage + http://highmed.org/fhir/StructureDefinition/task-execute-data-sharing|#{version} + + + Flow_18ie7l6 + Flow_1lw96cm + + + + Flow_1q5jnli + Flow_1gf3n6o + + + + Flow_1harl90 + Flow_1id9r0h + + + + Flow_1lw96cm + Flow_1q5jnli + Flow_1harl90 + + + Flow_1m59ov0 + Flow_0rwo9pn + + + Flow_1id9r0h + Flow_1s74o06 + + + Flow_1s74o06 + Flow_1rnnd6d + Flow_0amk6ah + + + Flow_0amk6ah + + + + + + + + + + + + + http://highmed.org/bpe/Process/computeDataSharing/#{version} + computeDataSharingMessage + http://highmed.org/fhir/StructureDefinition/task-compute-data-sharing|#{version} + + + Flow_0cx3xe1 + Flow_18ie7l6 + + + + + Flow_06otxko + Flow_0cx3xe1 + + + Flow_1gf3n6o + Flow_025quhl + + + + + Flow_0rwo9pn + Flow_1rnnd6d + + + + Flow_025quhl + Flow_1m59ov0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-computeDataSharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-computeDataSharing.xml new file mode 100644 index 00000000..19c6cc5d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-computeDataSharing.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <subtitle value="Process to compute a data sharing result" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to compute a data sharing result and to send the result back to the requesting organization" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-executeDataSharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-executeDataSharing.xml new file mode 100644 index 00000000..0667ba3a --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-executeDataSharing.xml @@ -0,0 +1,97 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="executeDataSharingMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-execute-data-sharing|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/executeDataSharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="ExecuteDataSharing" /> + <title value="Execute Data Sharing" /> + <subtitle value="Process to execute a data sharing query" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to execute a data sharing query received from a MeDIC and to send result to a TTP" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-requestDataSharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-requestDataSharing.xml new file mode 100644 index 00000000..998f885b --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ActivityDefinition/highmed-requestDataSharing.xml @@ -0,0 +1,173 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="requestDataSharingMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-request-data-sharing|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="resultMultiMedicDataSharingMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-data-sharing|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="errorMultiMedicDataSharingMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-data-sharing|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/requestDataSharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="RequestDataSharing" /> + <title value="Request Data Sharing" /> + <subtitle value="Process to request data sharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to start a data sharing project, process sends messages to all MeDICs and a TTP, receives result from TTP" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/CodeSystem/highmed-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/CodeSystem/highmed-data-sharing.xml new file mode 100644 index 00000000..e1be662d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/CodeSystem/highmed-data-sharing.xml @@ -0,0 +1,116 @@ +<CodeSystem xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/CodeSystem/data-sharing"/> + <!-- version managed by bpe --> + <version value="#{version}"/> + <name value="HiGHmed_Data_Sharing"/> + <title value="HiGHmed Data Sharing"/> + <!-- status managed by bpe --> + <status value="unknown"/> + <experimental value="false"/> + <!-- date managed by bpe --> + <date value="#{date}"/> + <publisher value="HiGHmed"/> + <description value="CodeSystem with standard values for HiGhmed data sharing processes"/> + <caseSensitive value="true"/> + <hierarchyMeaning value="grouped-by"/> + <versionNeeded value="false"/> + <content value="complete"/> + <concept> + <code value="research-study-reference"/> + <display value="Research Study Reference"/> + <definition value="Research study resource reference"/> + </concept> + <concept> + <code value="research-study-identifier"/> + <display value="Research Study Identifier"/> + <definition value="Research study resource unique identifier"/> + </concept> + <concept> + <code value="needs-record-linkage"/> + <display value="Needs Record Linkage"/> + <definition value="Boolean indicating if a data analysis needs record linkage"/> + </concept> + <concept> + <code value="needs-consent-check"/> + <display value="Needs Consent Check"/> + <definition value="Boolean indicating if a data analysis needs consent check"/> + </concept> + <concept> + <code value="consortium-identifier"/> + <display value="Consortium Identifier"/> + <definition value="Consortium organization resource identifier"/> + </concept> + <concept> + <code value="bloom-filter-configuration"/> + <display value="Bloom Filter Configuration"/> + <definition value="Base64 binary encoded bloom filter configuration"/> + </concept> + <concept> + <code value="mdat-aes-key"/> + <display value="MDAT AES Secret Key"/> + <definition value="Base64 binary encoded MDAT AES secret key"/> + </concept> + <concept> + <code value="medic-correlation-key"/> + <display value="MeDIC Correlation Key"/> + <definition value="MeDIC Correlation Key transferred to TTP for correlating incoming medic results"/> + </concept> + <concept> + <code value="single-medic-count-result"/> + <display value="Single MeDIC Count Result"/> + <definition value="Result of a single count query execution"/> + </concept> + <concept> + <code value="single-medic-result-share"/> + <display value="Single MeDIC MPC Result Share"/> + <definition value="MPC result share of a single count query execution"/> + </concept> + <concept> + <code value="single-medic-result-set-reference"/> + <display value="Single MeDIC Result Set Reference"/> + <definition value="Reference to an openEHR ResultSet containing the result of a single query + execution and/or the record-bloom-filters of a single query execution"/> + </concept> + <concept> + <code value="multi-medic-count-result"/> + <display value="Multi MeDIC Result"/> + <definition value="Aggregated result of all single count query execution results"/> + </concept> + <concept> + <code value="multi-medic-result-share"/> + <display value="Multi MeDIC MPC Result Share"/> + <definition value="Aggregated result of all received single count query execution result shares"/> + </concept> + <concept> + <code value="multi-medic-result-set-reference"/> + <display value="Multi MeDIC Result Set Reference"/> + <definition value="Reference to an openEHR ResultSet containing the aggregated result of a all single query + execution ResultSets"/> + </concept> + <concept> + <code value="participating-medics"/> + <display value="Participating MeDICs"/> + <definition value="Count of all MeDICs who participated in a data sharing request"/> + </concept> + <concept> + <code value="request-form-reference"/> + <display value="Request Form Reference"/> + <definition value="Url to a Binary resource containing the request form"/> + </concept> + <concept> + <code value="contract-reference"/> + <display value="Contract Reference"/> + <definition value="Url to a Binary resource containing the data usage contract"/> + </concept> + <concept> + <code value="feasibility-query-reference"/> + <display value="Feasibility Query Reference"/> + <definition value="Url to a completed Task resource containing the feasibility query result"/> + </concept> +</CodeSystem> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-research-study-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-research-study-data-sharing.xml new file mode 100644 index 00000000..1f8b8470 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-research-study-data-sharing.xml @@ -0,0 +1,104 @@ +<?xml version="1.0" encoding="utf-8"?> +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/research-study-data-sharing" /> + <version value="#{version}" /> + <name value="ResearchStudyDataSharing" /> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="ResearchStudy" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/research-study" /> + <derivation value="constraint" /> + <differential> + <element id="ResearchStudy.relatedArtifact"> + <path value="ResearchStudy.relatedArtifact" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="label" /> + </discriminator> + <rules value="open" /> + </slicing> + <min value="3" /> + </element> + <element id="ResearchStudy.relatedArtifact:request-form-reference"> + <path value="ResearchStudy.relatedArtifact" /> + <sliceName value="request-form-reference" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="ResearchStudy.relatedArtifact:request-form-reference.type"> + <path value="ResearchStudy.relatedArtifact.type" /> + <fixedCode value="documentation" /> + </element> + <element id="ResearchStudy.relatedArtifact:request-form-reference.label"> + <path value="ResearchStudy.relatedArtifact.label" /> + <min value="1" /> + <fixedString value="request-form-reference" /> + <binding> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="ResearchStudy.relatedArtifact:request-form-reference.url"> + <path value="ResearchStudy.relatedArtifact.url" /> + <min value="1" /> + </element> + <element id="ResearchStudy.relatedArtifact:contract-reference"> + <path value="ResearchStudy.relatedArtifact" /> + <sliceName value="contract-reference" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="ResearchStudy.relatedArtifact:contract-reference.type"> + <path value="ResearchStudy.relatedArtifact.type" /> + <fixedCode value="justification" /> + </element> + <element id="ResearchStudy.relatedArtifact:contract-reference.label"> + <path value="ResearchStudy.relatedArtifact.label" /> + <min value="1" /> + <fixedString value="contract-reference" /> + <binding> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="ResearchStudy.relatedArtifact:contract-reference.url"> + <path value="ResearchStudy.relatedArtifact.url" /> + <min value="1" /> + </element> + <element id="ResearchStudy.relatedArtifact:feasibility-query-reference"> + <path value="ResearchStudy.relatedArtifact" /> + <sliceName value="feasibility-query-reference" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="ResearchStudy.relatedArtifact:feasibility-query-reference.type"> + <path value="ResearchStudy.relatedArtifact.type" /> + <fixedCode value="justification" /> + </element> + <element id="ResearchStudy.relatedArtifact:feasibility-query-reference.label"> + <path value="ResearchStudy.relatedArtifact.label" /> + <min value="1" /> + <fixedString value="feasibility-query-reference" /> + <binding> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="ResearchStudy.relatedArtifact:feasibility-query-reference.url"> + <path value="ResearchStudy.relatedArtifact.url" /> + <min value="1" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-compute-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-compute-data-sharing.xml new file mode 100644 index 00000000..82c9f854 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-compute-data-sharing.xml @@ -0,0 +1,194 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-compute-data-sharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskComputeDataSharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/computeDataSharing/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="5" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="computeDataSharingMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="0" /> + <max value="0" /> + </element> + <element id="Task.input:medic-correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="medic-correlation-key" /> + <min value="1" /> + </element> + <element id="Task.input:medic-correlation-key.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:medic-correlation-key.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:medic-correlation-key.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:medic-correlation-key.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="medic-correlation-key" /> + </element> + <element id="Task.input:medic-correlation-key.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="string" /> + </type> + </element> + <element id="Task.input:needs-record-linkage"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-record-linkage" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-record-linkage.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-record-linkage.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-record-linkage.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-record-linkage.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-record-linkage" /> + </element> + <element id="Task.input:needs-record-linkage.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + <element id="Task.input:research-study-identifier"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="research-study-identifier" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study-identifier.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:research-study-identifier.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study-identifier.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:research-study-identifier.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="research-study-identifier" /> + </element> + <element id="Task.input:research-study-identifier.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/research-study" /> + </type> + </element> + <element id="Task.input:research-study-identifier.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="0" /> + <max value="0" /> + </element> + <element id="Task.input:research-study-identifier.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <min value="1" /> + <max value="1" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-execute-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-execute-data-sharing.xml new file mode 100644 index 00000000..10addc27 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-execute-data-sharing.xml @@ -0,0 +1,265 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-execute-data-sharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskExecuteDataSharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/executeDataSharing/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="7" /> + <max value="8" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="executeDataSharingMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="1" /> + </element> + <element id="Task.input:research-study"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="research-study" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:research-study.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:research-study.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="research-study-reference" /> + </element> + <element id="Task.input:research-study.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/research-study-data-sharing" /> + </type> + </element> + <element id="Task.input:needs-record-linkage"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-record-linkage" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-record-linkage.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-record-linkage.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-record-linkage.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-record-linkage.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-record-linkage" /> + </element> + <element id="Task.input:needs-record-linkage.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + <element id="Task.input:needs-consent-check"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-consent-check" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-consent-check.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-consent-check" /> + </element> + <element id="Task.input:needs-consent-check.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + <element id="Task.input:bloom-filter-configuration"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="bloom-filter-configuration" /> + <min value="0" /> + <max value="1" /> + </element> + <element id="Task.input:bloom-filter-configuration.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:bloom-filter-configuration.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:bloom-filter-configuration.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:bloom-filter-configuration.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="bloom-filter-configuration" /> + </element> + <element id="Task.input:bloom-filter-configuration.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="base64Binary" /> + </type> + </element> + <element id="Task.input:mdat-aes-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="mdat-aes-key" /> + <min value="0" /> + <max value="1" /> + </element> + <element id="Task.input:mdat-aes-key.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:mdat-aes-key.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:mdat-aes-key.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:mdat-aes-key.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="mdat-aes-key" /> + </element> + <element id="Task.input:mdat-aes-key.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="base64Binary" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-error-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-error-data-sharing.xml new file mode 100644 index 00000000..697acc73 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-error-data-sharing.xml @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="utf-8"?> +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-data-sharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskMultiMedicErrorDataSharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/requestDataSharing/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="3" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="errorMultiMedicDataSharingMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="0" /> + <max value="0" /> + </element> + <element id="Task.input:error"> + <path value="Task.input" /> + <sliceName value="error" /> + <min value="1" /> + </element> + <element id="Task.input:error.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/bpmn-message" /> + </binding> + </element> + <element id="Task.input:error.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:error.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/bpmn-message" /> + </element> + <element id="Task.input:error.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="error" /> + </element> + <element id="Task.input:error.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="string" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-data-sharing.xml new file mode 100644 index 00000000..bed845b8 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-data-sharing.xml @@ -0,0 +1,131 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-data-sharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskMultiMedicResultDataSharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/requestDataSharing/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="3" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="resultMultiMedicDataSharingMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="0" /> + <max value="0" /> + </element> + <element id="Task.input:multi-medic-result-set-reference"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="multi-medic-result-set-reference" /> + <min value="1" /> + </element> + <element id="Task.input:multi-medic-result-set-reference.extension"> + <path value="Task.input.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.input:multi-medic-result-set-reference.extension:group-id"> + <path value="Task.input.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.input:multi-medic-result-set-reference.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:multi-medic-result-set-reference.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:multi-medic-result-set-reference.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:multi-medic-result-set-reference.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="multi-medic-result-set-reference" /> + </element> + <element id="Task.input:multi-medic-result-set-reference.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://hl7.org/fhir/StructureDefinition/Binary" /> + </type> + </element> + <element id="Task.input:multi-medic-result-set-reference.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.input:multi-medic-result-set-reference.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <max value="0" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-request-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-request-data-sharing.xml new file mode 100644 index 00000000..fb5387f4 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-request-data-sharing.xml @@ -0,0 +1,260 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-request-data-sharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskRequestDataSharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/requestDataSharing/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="4" /> + <max value="4" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="requestDataSharingMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <max value="0" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:research-study-reference"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="research-study-reference" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study-reference.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:research-study-reference.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study-reference.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:research-study-reference.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="research-study-reference" /> + </element> + <element id="Task.input:research-study-reference.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/research-study-data-sharing" /> + </type> + </element> + <element id="Task.input:research-study-reference.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.input:research-study-reference.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <max value="0" /> + </element> + <element id="Task.input:needs-record-linkage"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-record-linkage" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-record-linkage.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-record-linkage.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-record-linkage.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-record-linkage.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-record-linkage" /> + </element> + <element id="Task.input:needs-record-linkage.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + <element id="Task.input:needs-consent-check"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-consent-check" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-consent-check.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-consent-check" /> + </element> + <element id="Task.input:needs-consent-check.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + <element id="Task.output:multi-medic-result-set-reference"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.output" /> + <sliceName value="multi-medic-result-set-reference" /> + <min value="0" /> + </element> + <element id="Task.output:multi-medic-result-set-reference.extension"> + <path value="Task.output.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.output:multi-medic-result-set-reference.extension:group-id"> + <path value="Task.output.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.output:multi-medic-result-set-reference.type"> + <path value="Task.output.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskOutputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.output:multi-medic-result-set-reference.type.coding"> + <path value="Task.output.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.output:multi-medic-result-set-reference.type.coding.system"> + <path value="Task.output.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.output:multi-medic-result-set-reference.type.coding.code"> + <path value="Task.output.type.coding.code" /> + <min value="1" /> + <fixedCode value="multi-medic-result-set-reference" /> + </element> + <element id="Task.output:multi-medic-result-set-reference.value[x]"> + <path value="Task.output.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://hl7.org/fhir/StructureDefinition/Binary" /> + </type> + </element> + <element id="Task.output:multi-medic-result-set-reference.value[x].reference"> + <path value="Task.output.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.output:multi-medic-result-set-reference.value[x].identifier"> + <path value="Task.output.value[x].identifier" /> + <max value="0" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-data-sharing.xml new file mode 100644 index 00000000..e089d280 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-data-sharing.xml @@ -0,0 +1,130 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-single-medic-result-data-sharing" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskSingleMedicResultDataSharing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/computeDataSharing/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="4" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="resultSingleMedicDataSharingMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="1" /> + </element> + <element id="Task.input:single-medic-result-set-reference"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="single-medic-result-set-reference" /> + <min value="1" /> + </element> + <element id="Task.input:single-medic-result-set-reference.extension"> + <path value="Task.input.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.input:single-medic-result-set-reference.extension:group-id"> + <path value="Task.input.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.input:single-medic-result-set-reference.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:single-medic-result-set-reference.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:single-medic-result-set-reference.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:single-medic-result-set-reference.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="single-medic-result-set-reference" /> + </element> + <element id="Task.input:single-medic-result-set-reference.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://hl7.org/fhir/StructureDefinition/Binary" /> + </type> + </element> + <element id="Task.input:single-medic-result-set-reference.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.input:single-medic-result-set-reference.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <max value="0" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/main/resources/fhir/ValueSet/highmed-data-sharing.xml b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ValueSet/highmed-data-sharing.xml new file mode 100644 index 00000000..c02879f1 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/main/resources/fhir/ValueSet/highmed-data-sharing.xml @@ -0,0 +1,26 @@ +<ValueSet xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/ValueSet/data-sharing"/> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="HiGHmed_Data_Sharing"/> + <title value="HiGHmed Data Sharing"/> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false"/> + <!-- date managed by bpe --> + <date value="#{date}"/> + <publisher value="HiGHmed"/> + <description value="ValueSet with standard values for HiGhmed data sharing processes"/> + <immutable value="true"/> + <compose> + <include> + <system value="http://highmed.org/fhir/CodeSystem/data-sharing"/> + </include> + </compose> +</ValueSet> \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/DataSharingProcessPluginDefinitionTest.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/DataSharingProcessPluginDefinitionTest.java new file mode 100644 index 00000000..48a7e26f --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/DataSharingProcessPluginDefinitionTest.java @@ -0,0 +1,41 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROCESS_NAME_FULL_COMPUTE_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROCESS_NAME_FULL_EXECUTE_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROCESS_NAME_FULL_REQUEST_DATA_SHARING; +import static org.highmed.dsf.bpe.DataSharingProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class DataSharingProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition definition = new DataSharingProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var computeDataSharing = provider.getResources(PROCESS_NAME_FULL_COMPUTE_DATA_SHARING + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(computeDataSharing); + assertEquals(5, computeDataSharing.count()); + + var executeDataSharing = provider.getResources(PROCESS_NAME_FULL_EXECUTE_DATA_SHARING + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(executeDataSharing); + assertEquals(5, executeDataSharing.count()); + + var requestDataSharing = provider.getResources(PROCESS_NAME_FULL_REQUEST_DATA_SHARING + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(requestDataSharing); + assertEquals(7, requestDataSharing.count()); + } +} diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestDataSharingFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestDataSharingFromMedicsViaMedic1ExampleStarter.java new file mode 100644 index 00000000..ac7ecc6b --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestDataSharingFromMedicsViaMedic1ExampleStarter.java @@ -0,0 +1,189 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.CODE_TYPE_AQL_QUERY; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.PROFILE_HIGHEMD_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsBase.PROFILE_HIGHMED_GROUP; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONTRACT_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_FEASIBILITY_QUERY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_REQUEST_FORM_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_QUERY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_AND_VERSION; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_2; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_3; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; + +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +import org.highmed.dsf.bpe.ConstantsBase; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelperImpl; +import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Expression; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Narrative; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.RelatedArtifact; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.ResourceType; +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; + +public abstract class AbstractRequestDataSharingFromMedicsViaMedic1ExampleStarter +{ + private final boolean needsConsentCheck = true; + private final boolean needsRecordLinkage = true; + + private final String requestFormReference = "https://foo/fhir/Binary/9f747003-5d80-4313-b77f-d6dbe2ef4c55"; + private final String contractReference = "https://foo/fhir/Binary/9f747003-5d80-4313-b77f-d6dbe2ef4c55"; + private final String feasibilityReference = "https://foo/fhir/Task/9f747003-5d80-4313-b77f-d6dbe2ef4c55"; + + private final String query = "SELECT e/ehr_status/subject/external_ref/id/value as EHRID, " + + "v/items[at0024,'Bezeichnung']/value, v/items [at0001,'Messwert'], " + + "v/items[at0006,'Dokumentationsdatum Untersuchung']/value FROM EHR e CONTAINS COMPOSITION c " + + "CONTAINS CLUSTER v[openEHR-EHR-CLUSTER.laboratory_test_analyte.v1] " + + "WHERE v/items[at0024,'Bezeichnung']/value/value = 'Natrium' OFFSET 0 LIMIT 15;"; + + private final String[] medicIdentifier = new String[] { NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1, + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_2, + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_3 }; + private final String ttpIdentifier = NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; + + private final ReadAccessHelper readAccessHelper = new ReadAccessHelperImpl(); + + protected void main(String[] args, String baseUrl) throws Exception + { + Bundle bundle = createStartResource(); + ExampleStarter.forServer(args, baseUrl).startWith(bundle); + } + + private Bundle createStartResource() + { + Group group1 = createGroup("Group 1"); + Group group2 = createGroup("Group 2"); + ResearchStudy researchStudy = createResearchStudy(group1, group2); + Task task = createTask(researchStudy); + + Bundle bundle = new Bundle(); + bundle.setType(Bundle.BundleType.TRANSACTION); + bundle.addEntry().setResource(group1).setFullUrl(group1.getIdElement().getIdPart()).getRequest() + .setMethod(Bundle.HTTPVerb.POST).setUrl(ResourceType.Group.name()); + bundle.addEntry().setResource(group2).setFullUrl(group2.getIdElement().getIdPart()).getRequest() + .setMethod(Bundle.HTTPVerb.POST).setUrl(ResourceType.Group.name()); + bundle.addEntry().setResource(researchStudy).setFullUrl(researchStudy.getIdElement().getIdPart()).getRequest() + .setMethod(Bundle.HTTPVerb.POST).setUrl(ResourceType.ResearchStudy.name()); + bundle.addEntry().setResource(task).setFullUrl(task.getIdElement().getIdPart()).getRequest() + .setMethod(Bundle.HTTPVerb.POST).setUrl(ResourceType.Task.name()); + + return bundle; + } + + private Group createGroup(String name) + { + Group group = new Group(); + group.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + + group.getMeta().addProfile(PROFILE_HIGHMED_GROUP); + group.getText().getDiv().addText("This is the description"); + group.getText().setStatus(Narrative.NarrativeStatus.ADDITIONAL); + group.setType(Group.GroupType.PERSON); + group.setActual(false); + group.setActive(true); + group.addExtension().setUrl(EXTENSION_HIGHMED_QUERY) + .setValue(new Expression().setLanguageElement(CODE_TYPE_AQL_QUERY).setExpression(query)); + group.setName(name); + + Arrays.stream(medicIdentifier).forEach(i -> readAccessHelper.addOrganization(group, i)); + readAccessHelper.addOrganization(group, ttpIdentifier); + + return group; + } + + private ResearchStudy createResearchStudy(Group group1, Group group2) + { + ResearchStudy researchStudy = new ResearchStudy(); + researchStudy.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + + researchStudy.getMeta().addProfile(PROFILE_HIGHEMD_RESEARCH_STUDY); + researchStudy.addIdentifier().setSystem(NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER) + .setValue(UUID.randomUUID().toString()); + researchStudy.setStatus(ResearchStudy.ResearchStudyStatus.ACTIVE); + + researchStudy.addEnrollment().setReference(group1.getIdElement().getIdPart()); + researchStudy.addEnrollment().setReference(group2.getIdElement().getIdPart()); + + researchStudy.addRelatedArtifact().setType(RelatedArtifact.RelatedArtifactType.DOCUMENTATION) + .setLabel(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_REQUEST_FORM_REFERENCE).setUrl(requestFormReference); + researchStudy.addRelatedArtifact().setType(RelatedArtifact.RelatedArtifactType.JUSTIFICATION) + .setLabel(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONTRACT_REFERENCE).setUrl(contractReference); + researchStudy.addRelatedArtifact().setType(RelatedArtifact.RelatedArtifactType.JUSTIFICATION) + .setLabel(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_FEASIBILITY_QUERY_REFERENCE) + .setUrl(feasibilityReference); + + Arrays.stream(medicIdentifier) + .forEach(i -> researchStudy.addExtension().setUrl(ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC) + .setValue(new Reference().setType(ResourceType.Organization.name()).setIdentifier( + new Identifier().setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(i)))); + + researchStudy.addExtension().setUrl(ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_TTP) + .setValue(new Reference().setType(ResourceType.Organization.name()).setIdentifier(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(ttpIdentifier))); + + Arrays.stream(medicIdentifier).forEach(i -> readAccessHelper.addOrganization(researchStudy, i)); + readAccessHelper.addOrganization(researchStudy, ttpIdentifier); + + return researchStudy; + } + + private Task createTask(ResearchStudy researchStudy) + { + Task task = new Task(); + task.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_AND_VERSION); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput() + .setValue(new Reference().setReference(researchStudy.getIdElement().getIdPart()) + .setType(ResourceType.ResearchStudy.name())) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput().setValue(new BooleanType(needsRecordLinkage)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(needsConsentCheck)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + + return task; + } +} diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/RequestDataSharingFromMedicsViaMedic1DockerExampleStarter.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/RequestDataSharingFromMedicsViaMedic1DockerExampleStarter.java new file mode 100644 index 00000000..f587d2a1 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/RequestDataSharingFromMedicsViaMedic1DockerExampleStarter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.MEDIC_1_DOCKER_FHIR_BASE_URL; + +public class RequestDataSharingFromMedicsViaMedic1DockerExampleStarter + extends AbstractRequestDataSharingFromMedicsViaMedic1ExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new RequestDataSharingFromMedicsViaMedic1DockerExampleStarter().main(args, MEDIC_1_DOCKER_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/RequestDataSharingFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/RequestDataSharingFromMedicsViaMedic1ExampleStarter.java new file mode 100644 index 00000000..6fe55619 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/start/RequestDataSharingFromMedicsViaMedic1ExampleStarter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.MEDIC_1_FHIR_BASE_URL; + +public class RequestDataSharingFromMedicsViaMedic1ExampleStarter + extends AbstractRequestDataSharingFromMedicsViaMedic1ExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new RequestDataSharingFromMedicsViaMedic1ExampleStarter().main(args, MEDIC_1_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/variables/BloomFilterConfigTest.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/BloomFilterConfigSerializationTest.java similarity index 79% rename from dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/variables/BloomFilterConfigTest.java rename to dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/BloomFilterConfigSerializationTest.java index db543402..4526ca8d 100644 --- a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/variables/BloomFilterConfigTest.java +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/BloomFilterConfigSerializationTest.java @@ -7,15 +7,19 @@ import javax.crypto.spec.SecretKeySpec; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.fhir.json.ObjectMapperFactory; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; -public class BloomFilterConfigTest +import ca.uhn.fhir.context.FhirContext; + +public class BloomFilterConfigSerializationTest { - private static final Logger logger = LoggerFactory.getLogger(BloomFilterConfigTest.class); + private static final Logger logger = LoggerFactory.getLogger(BloomFilterConfigSerializationTest.class); private static final byte[] b1 = Base64.getDecoder().decode("KLhuuy3lDSmo8A/mcYBBZJ+Xu+ok30qDGM4L0magwyY="); private static final byte[] b2 = Base64.getDecoder().decode("VALdwRisuEsUBIXaqJ01L9lk0jJUSGm5ZBE+Ha5bm8c="); @@ -24,16 +28,16 @@ public class BloomFilterConfigTest @Test public void testReadWriteJson() throws Exception { - ObjectMapper objectMapper = new ObjectMapper(); + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); BloomFilterConfig bfc = new BloomFilterConfig(l, new SecretKeySpec(b1, "HmacSHA256"), new SecretKeySpec(b2, "HmacSHA3-256")); - String value = objectMapper.writeValueAsString(bfc); + String value = mapper.writeValueAsString(bfc); logger.debug("BloomFilterConfig: {}", value); - BloomFilterConfig readBfc = objectMapper.readValue(value, BloomFilterConfig.class); + BloomFilterConfig readBfc = mapper.readValue(value, BloomFilterConfig.class); assertNotNull(readBfc); assertEquals(bfc.getPermutationSeed(), readBfc.getPermutationSeed()); diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/QueryResultsSerializationTest.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/QueryResultsSerializationTest.java new file mode 100644 index 00000000..d26d39f2 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/QueryResultsSerializationTest.java @@ -0,0 +1,91 @@ +package org.highmed.dsf.bpe.variables; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.fhir.json.ObjectMapperFactory; +import org.highmed.openehr.model.datatypes.IntegerRowElement; +import org.highmed.openehr.model.datatypes.StringRowElement; +import org.highmed.openehr.model.structure.Column; +import org.highmed.openehr.model.structure.Meta; +import org.highmed.openehr.model.structure.ResultSet; +import org.highmed.openehr.model.structure.RowElement; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +public class QueryResultsSerializationTest +{ + private static final Logger logger = LoggerFactory.getLogger(QueryResultsSerializationTest.class); + + @Test + public void testEmptyQueryResultsSerialization() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + QueryResults results = new QueryResults(Collections.emptyList()); + + String resultsAsString = mapper.writeValueAsString(results); + assertNotNull(resultsAsString); + + logger.debug("QueryResults (empty): '{}'", resultsAsString); + + QueryResults readResults = mapper.readValue(resultsAsString, QueryResults.class); + assertNotNull(readResults); + assertNotNull(readResults.getResults()); + assertTrue(readResults.getResults().isEmpty()); + } + + @Test + public void testNonEmptyQueryResultsSerialization() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + QueryResult result = new QueryResult("test.org", UUID.randomUUID().toString(), 1, createResultSet(), + "http://test.com/fhir/Binary/" + UUID.randomUUID().toString()); + QueryResults results = new QueryResults(Collections.singleton(result)); + + String resultsAsString = mapper.writeValueAsString(results); + assertNotNull(resultsAsString); + + logger.debug("QueryResults (non empty): '{}'", resultsAsString); + + QueryResults readResults = mapper.readValue(resultsAsString, QueryResults.class); + assertNotNull(readResults); + assertNotNull(readResults.getResults()); + assertFalse(readResults.getResults().isEmpty()); + assertEquals(1, readResults.getResults().size()); + assertNotNull(readResults.getResults().get(0)); + assertEquals(result.getCohortId(), readResults.getResults().get(0).getCohortId()); + assertEquals(result.getCohortSize(), readResults.getResults().get(0).getCohortSize()); + assertEquals(result.getOrganizationIdentifier(), readResults.getResults().get(0).getOrganizationIdentifier()); + assertEquals(result.getResultSetUrl(), readResults.getResults().get(0).getResultSetUrl()); + assertNotNull(readResults.getResults().get(0).getResultSet()); + assertEquals(result.getResultSet().getName(), readResults.getResults().get(0).getResultSet().getName()); + assertEquals(result.getResultSet().getQuery(), readResults.getResults().get(0).getResultSet().getQuery()); + // Not testing every ResultSet property, see ResultSet serialization tests + } + + private ResultSet createResultSet() + { + Meta meta = new Meta("href", "type", "schemaVersion", "created", "generator", "executedAql"); + List<Column> columns = Arrays.asList(new Column("name1", "path1"), new Column("name2", "path2")); + List<List<RowElement>> rows = Arrays.asList(Arrays.asList(new IntegerRowElement(123)), + Arrays.asList(new StringRowElement("456"))); + ResultSet resultSet = new ResultSet(meta, "name", "query", columns, rows); + return resultSet; + } +} diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/SecretKeyWrapperSerializationTest.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/SecretKeyWrapperSerializationTest.java new file mode 100644 index 00000000..b14d3603 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/bpe/variables/SecretKeyWrapperSerializationTest.java @@ -0,0 +1,61 @@ +package org.highmed.dsf.bpe.variables; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.bpe.variable.SecretKeyWrapper; +import org.highmed.dsf.fhir.json.ObjectMapperFactory; +import org.highmed.pseudonymization.crypto.AesGcmUtil; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +public class SecretKeyWrapperSerializationTest +{ + private static final Logger logger = LoggerFactory.getLogger(SecretKeyWrapperSerializationTest.class); + + @Test + public void testReadWriteJson() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + SecretKeyWrapper key = SecretKeyWrapper.newAes256Key(); + + String value = mapper.writeValueAsString(key); + + logger.debug("SecretKeyWrapper: {}", value); + + SecretKeyWrapper readkey = mapper.readValue(value, SecretKeyWrapper.class); + + assertNotNull(readkey); + assertEquals(key.getAlgorithm(), readkey.getAlgorithm()); + assertArrayEquals(key.getBytes(), readkey.getBytes()); + assertEquals(key.getSecretKey(), readkey.getSecretKey()); + } + + @Test + public void testReadWriteJsonFromBytes() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + byte[] bytes = AesGcmUtil.generateAES256Key().getEncoded(); + SecretKeyWrapper key = SecretKeyWrapper.fromAes256Key(bytes); + assertArrayEquals(bytes, key.getBytes()); + + String value = mapper.writeValueAsString(key); + + logger.debug("SecretKeyWrapper: {}", value); + + SecretKeyWrapper readkey = mapper.readValue(value, SecretKeyWrapper.class); + + assertNotNull(readkey); + assertEquals(key.getAlgorithm(), readkey.getAlgorithm()); + assertArrayEquals(key.getBytes(), readkey.getBytes()); + assertEquals(key.getSecretKey(), readkey.getSecretKey()); + } +} diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java new file mode 100644 index 00000000..629fdeac --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java @@ -0,0 +1,101 @@ +package org.highmed.dsf.fhir.profile; + +import static org.highmed.dsf.bpe.DataSharingProcessPluginDefinition.RELEASE_DATE; +import static org.highmed.dsf.bpe.DataSharingProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.nio.file.Paths; +import java.util.Arrays; + +import org.highmed.dsf.fhir.authorization.process.ProcessAuthorizationHelper; +import org.highmed.dsf.fhir.authorization.process.ProcessAuthorizationHelperImpl; +import org.highmed.dsf.fhir.validation.ResourceValidator; +import org.highmed.dsf.fhir.validation.ResourceValidatorImpl; +import org.highmed.dsf.fhir.validation.ValidationSupportRule; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.validation.ResultSeverityEnum; +import ca.uhn.fhir.validation.ValidationResult; + +public class ActivityDefinitionProfileTest +{ + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); + + @ClassRule + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, + Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", + "highmed-extension-process-authorization-consortium-role-0.5.0.xml", + "highmed-extension-process-authorization-organization-0.5.0.xml", + "highmed-coding-process-authorization-local-all-0.5.0.xml", + "highmed-coding-process-authorization-local-consortium-role-0.5.0.xml", + "highmed-coding-process-authorization-local-organization-0.5.0.xml", + "highmed-coding-process-authorization-remote-all-0.5.0.xml", + "highmed-coding-process-authorization-remote-consortium-role-0.5.0.xml", + "highmed-coding-process-authorization-remote-organization-0.5.0.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-process-authorization-0.5.0.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-process-authorization-recipient-0.5.0.xml", + "highmed-process-authorization-requester-0.5.0.xml")); + + private final ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), + validationRule.getValidationSupport()); + + private final ProcessAuthorizationHelper processAuthorizationHelper = new ProcessAuthorizationHelperImpl(); + + @Test + public void testComputeFeasibilityValid() throws Exception + { + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-computeDataSharing.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> + { + System.err.println("Org: " + orgIdentifier); + return true; + }, role -> + { + System.err.println("Role:" + role); + return true; + })); + } + + @Test + public void testExecuteFeasibilityValid() throws Exception + { + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeDataSharing.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); + } + + @Test + public void testRequestFeasibilityValid() throws Exception + { + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-requestDataSharing.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); + } +} \ No newline at end of file diff --git a/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java new file mode 100644 index 00000000..6be6c921 --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java @@ -0,0 +1,412 @@ +package org.highmed.dsf.fhir.profile; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.DataSharingProcessPluginDefinition.RELEASE_DATE; +import static org.highmed.dsf.bpe.DataSharingProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; + +import java.nio.charset.StandardCharsets; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +import org.highmed.dsf.fhir.validation.ResourceValidator; +import org.highmed.dsf.fhir.validation.ResourceValidatorImpl; +import org.highmed.dsf.fhir.validation.ValidationSupportRule; +import org.highmed.pseudonymization.crypto.AesGcmUtil; +import org.hl7.fhir.r4.model.Base64BinaryType; +import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResourceType; +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.TaskIntent; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.validation.ResultSeverityEnum; +import ca.uhn.fhir.validation.ValidationResult; + +public class TaskProfileTest +{ + private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); + + @ClassRule + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, + Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-group-0.5.0.xml", + "highmed-extension-group-id-0.5.0.xml", "highmed-research-study-0.5.0.xml", + "highmed-research-study-data-sharing.xml", "highmed-task-request-data-sharing.xml", + "highmed-task-execute-data-sharing.xml", "highmed-task-single-medic-result-data-sharing.xml", + "highmed-task-compute-data-sharing.xml", "highmed-task-multi-medic-result-data-sharing.xml", + "highmed-task-multi-medic-error-data-sharing.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", + "highmed-data-sharing.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", + "highmed-data-sharing.xml")); + + private ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), + validationRule.getValidationSupport()); + + @Test + public void testTaskRequestDataSharingValid() throws Exception + { + Task task = createValidTaskRequestDataSharing(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskRequestDataSharingValidWithOutput() throws Exception + { + String groupId1 = "Group/" + UUID.randomUUID().toString(); + String groupId2 = "Group/" + UUID.randomUUID().toString(); + + Task task = createValidTaskRequestDataSharing(); + + TaskOutputComponent outMultiMedicResult1 = task.addOutput(); + outMultiMedicResult1.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE); + outMultiMedicResult1.addExtension("http://highmed.org/fhir/StructureDefinition/extension-group-id", + new Reference(groupId1)); + + TaskOutputComponent outMultiMedicResult2 = task.addOutput(); + outMultiMedicResult2.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); + outMultiMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskRequestDataSharing() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new Reference("ResearchStudy/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + + return task; + } + + @Test + public void testTaskExecuteDataSharingValid() throws Exception + { + Task task = createValidTaskExecuteDataSharing(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskExecuteDataSharingValidWithBloomFilterConfig() throws Exception + { + Task task = createValidTaskExecuteDataSharing(); + task.addInput().setValue(new Base64BinaryType("TEST".getBytes(StandardCharsets.UTF_8))).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskExecuteDataSharing() throws NoSuchAlgorithmException + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 2"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_EXECUTE_DATA_SHARING_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + + task.addInput().setValue(new Reference("ResearchStudy/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + task.addInput().setValue(new Base64BinaryType(AesGcmUtil.generateAES256Key().getEncoded())).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MDAT_AES_KEY); + + return task; + } + + @Test + public void testTaskSingleMedicResultDataSharingReferenceResultValid() throws Exception + { + Task task = createValidTaskSingleMedicResultDataSharingReferenceResult(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskSingleMedicResultDataSharing() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 2"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_DATA_SHARING_MESSAGE_NAME)) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + + return task; + } + + private Task createValidTaskSingleMedicResultDataSharingReferenceResult() + { + Task task = createValidTaskSingleMedicResultDataSharing(); + + String groupId1 = "Group/" + UUID.randomUUID().toString(); + String groupId2 = "Group/" + UUID.randomUUID().toString(); + + ParameterComponent inSingleMedicResult1 = task.addInput(); + inSingleMedicResult1.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE); + inSingleMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); + ParameterComponent inSingleMedicResult2 = task.addInput(); + inSingleMedicResult2.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE); + inSingleMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + + return task; + } + + @Test + public void testTaskComputeDataSharingValid() throws Exception + { + Task task = createValidTaskComputeDataSharing(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskComputeDataSharing() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_COMPUTE_DATA_SHARING_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + Reference rsRef = new Reference().setIdentifier(new Identifier().setValue(UUID.randomUUID().toString()) + .setSystem(NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER)); + task.addInput().setValue(rsRef).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_IDENTIFIER); + + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); + + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + + return task; + } + + @Test + public void testTaskMultiMedicResultDataSharingValid() throws Exception + { + Task task = createValidTaskMultiMedicResultDataSharing(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskMultiMedicResultDataSharing() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_DATA_SHARING_MESSAGE_NAME)) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + String groupId1 = "Group/" + UUID.randomUUID().toString(); + String groupId2 = "Group/" + UUID.randomUUID().toString(); + + ParameterComponent inMultiMedicResult1 = task.addInput(); + inMultiMedicResult1.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE); + inMultiMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); + + ParameterComponent inMultiMedicResult2 = task.addInput(); + inMultiMedicResult2.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SET_REFERENCE); + inMultiMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + + return task; + } + + @Test + public void testTaskErrorDataSharingValid() throws Exception + { + Task task = createValidTaskErrorDataSharing(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskErrorDataSharing() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_DATA_SHARING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_ERROR_DATA_SHARING_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + ParameterComponent error = task.addInput(); + error.setValue(new StringType("Could not calculate multi medic results sets for all defined cohorts")).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR); + + return task; + } +} diff --git a/dsf-bpe-process-data-sharing/src/test/resources/log4j2.xml b/dsf-bpe-process-data-sharing/src/test/resources/log4j2.xml new file mode 100644 index 00000000..f1afe81d --- /dev/null +++ b/dsf-bpe-process-data-sharing/src/test/resources/log4j2.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="INFO" monitorInterval="30" + verbose="false"> + + <Appenders> + <Console name="CONSOLE" target="SYSTEM_OUT"> + <PatternLayout pattern="%p\t%t - %C{1}.%M(%L) | %m%n"/> + </Console> + <!-- <RollingFile name="FILE" fileName="log/adt_db.log" + filePattern="log/adt_db_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy /> + <TimeBasedTriggeringPolicy /> + </Policies> + </RollingFile> --> + + <!-- <SMTP name="MAIL" subject="Production RWH LAB Gateway Error" + to="hauke.hund@med.uni-heidelberg.de, thomas.hilbel@med.uni-heidelberg.de" + from="med3-kvm15@med.uni-heidelberg.de" + replyTo="hauke.hund@med.uni-heidelberg.de" smtpHost="localhost" + smtpPort="25" bufferSize="50"> + </SMTP> + <SMTP name="MAIL_CERTIFICATE" subject="Production RWH LAB Gateway Certificate Warning" + to="hauke.hund@med.uni-heidelberg.de, thomas.hilbel@med.uni-heidelberg.de" + from="med3-kvm15@med.uni-heidelberg.de" + replyTo="hauke.hund@med.uni-heidelberg.de" smtpHost="localhost" + smtpPort="25" bufferSize="1"> + <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/> + </SMTP> + <SMTP name="MAIL_HL7" subject="Production RWH ADT Gateway HL7 Warning" + to="hauke.hund@med.uni-heidelberg.de, thomas.hilbel@med.uni-heidelberg.de" + from="med3-kvm15@med.uni-heidelberg.de" + replyTo="hauke.hund@med.uni-heidelberg.de" smtpHost="localhost" + smtpPort="25" bufferSize="1"> + <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/> + </SMTP> --> + </Appenders> + + <Loggers> + <Logger name="de.rwh" level="TRACE"/> + <Logger name="org.highmed" level="TRACE"/> + <Logger name="org.apache" level="WARN"/> + <Logger name="org.springframework" level="WARN"/> + <Logger name="jndi" level="WARN"/> + <Logger name="org.eclipse.jetty" level="INFO"/> + <Logger name="com.sun.jersey" level="WARN"/> + <Logger name="liquibase" level="WARN"/> + <Logger name="ca.uhn.hl7v2" level="WARN"/> + + <!-- <Logger name="certificate-warning-logger" level="INFO"> + <AppenderRef ref="MAIL_CERTIFICATE" /> + </Logger> + <Logger name="async-message-handler-warning-logger" level="INFO"> + <AppenderRef ref="MAIL_HL7" /> + </Logger> --> + + <Root level="WARN"> + <AppenderRef ref="CONSOLE"/> + <!-- <AppenderRef ref="FILE" /> --> + <!-- <AppenderRef ref="MAIL" /> --> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/pom.xml b/dsf-bpe-process-feasibility-mpc/pom.xml new file mode 100644 index 00000000..1c0a943b --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/pom.xml @@ -0,0 +1,299 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <artifactId>dsf-bpe-process-feasibility-mpc</artifactId> + + <parent> + <artifactId>dsf-bpe-highmed-processes-pom</artifactId> + <groupId>org.highmed.dsf</groupId> + <version>0.6.0</version> + </parent> + + <properties> + <main.basedir>${project.basedir}/..</main.basedir> + <dsf.location>../../highmed-dsf</dsf.location> + </properties> + + <dependencies> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-base</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-data-sharing</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-annotations</artifactId> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>de.hs-heilbronn.mi</groupId> + <artifactId>log4j2-utils</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-fhir-validation</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-base</artifactId> + <scope>test</scope> + <type>test-jar</type> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>copy-to-highmed-dsf-process</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-process-plugin-to-docker-test-setup</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup/bpe/process</outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-plugin-to-docker-test-setup-3medic-ttp/medic1</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic1/bpe/process</outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-plugin-to-docker-test-setup-3medic-ttp/medic2</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic2/bpe/process</outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-plugin-to-docker-test-setup-3medic-ttp/medic3</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic3/bpe/process</outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-plugin-to-docker-test-setup-3medic-ttp/ttp</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/ttp/bpe/process</outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-to-docker-test-setup-3medic-ttp-docker/medic1</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic1/bpe/process + </outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-to-docker-test-setup-3medic-ttp-docker/medic2</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic2/bpe/process + </outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-to-docker-test-setup-3medic-ttp-docker/medic3</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic3/bpe/process + </outputDirectory> + </configuration> + </execution> + <execution> + <id>copy-process-to-docker-test-setup-3medic-ttp-docker/ttp</id> + <phase>package</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </artifactItem> + </artifactItems> + <outputDirectory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/ttp/bpe/process + </outputDirectory> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-clean-plugin</artifactId> + <configuration> + <filesets> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic1/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic2/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/medic3/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp/ttp/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic1/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic2/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/medic3/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + <fileset> + <directory>${dsf.location}/dsf-docker-test-setup-3medic-ttp-docker/ttp/bpe/process</directory> + <includes> + <include>${project.artifactId}-${project.version}.jar</include> + </includes> + <followSymlinks>false</followSymlinks> + </fileset> + </filesets> + </configuration> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project> diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibilityMpc.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibilityMpc.java new file mode 100644 index 00000000..d0b3260f --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibilityMpc.java @@ -0,0 +1,67 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsBase.PROCESS_HIGHMED_URI_BASE; +import static org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition.VERSION; + +public interface ConstantsFeasibilityMpc +{ + String PROCESS_NAME_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE = "executeFeasibilityMpcMultiShare"; + String PROCESS_NAME_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE = "executeFeasibilityMpcSingleShare"; + String PROCESS_NAME_REQUEST_FEASIBILITY_MPC = "requestFeasibilityMpc"; + + String PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE = "highmedorg_" + + PROCESS_NAME_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE; + String PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE = "highmedorg_" + + PROCESS_NAME_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE; + String PROCESS_NAME_FULL_REQUEST_FEASIBILITY_MPC = "highmedorg_" + PROCESS_NAME_REQUEST_FEASIBILITY_MPC; + + String BPMN_EXECUTION_VARIABLE_CORRELATION_KEY = "correlationKey"; + // String BPMN_EXECUTION_VARIABLE_CORRELATION_KEYS_SINGLE_MEDIC_SHARE = "correlationKeysSingleMedicShare"; + + String BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES = "queryResultsSingleMedicShare"; + String BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES = "queryResultsMultiMedicShare"; + + // Must be 3 or larger, as otherwise it is possible to draw conclusions about the individual MeDICs + // (if I already know the cohort size in my MeDIC) + int MIN_PARTICIPATING_MEDICS = 3; + int MIN_COHORT_DEFINITIONS = 1; + + String FEASIBILITY_MPC_QUERY_PREFIX = "SELECT COUNT"; + + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC = "http://highmed.org/fhir/StructureDefinition/task-request-feasibility-mpc"; + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_REQUEST_FEASIBILITY_MPC + "/"; + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_MESSAGE_NAME = "requestFeasibilityMpcMessage"; + + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE = "http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-multi-share"; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE + "/"; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_MESSAGE_NAME = "executeFeasibilityMpcMultiShareMessage"; + + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE = "http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-single-share"; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE + "/"; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_MESSAGE_NAME = "executeFeasibilityMpcSingleShareMessage"; + + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC = "http://highmed.org/fhir/StructureDefinition/task-single-medic-result-share-feasibility-mpc"; + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_MESSAGE_NAME = "resultShareSingleMedicFeasibilityMpcMessage"; + + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-share-feasibility-mpc"; + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_MESSAGE_NAME = "resultShareMultiMedicFeasibilityMpcMessage"; +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/FeasibilityMpcProcessPluginDefinition.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/FeasibilityMpcProcessPluginDefinition.java new file mode 100644 index 00000000..18dce86a --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/FeasibilityMpcProcessPluginDefinition.java @@ -0,0 +1,110 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROCESS_NAME_FULL_REQUEST_FEASIBILITY_MPC; + +import java.time.LocalDate; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import org.highmed.dsf.bpe.spring.config.DataSharingSerializerConfig; +import org.highmed.dsf.bpe.spring.config.FeasibilityMpcConfig; +import org.highmed.dsf.bpe.spring.config.FeasibilityMpcSerializerConfig; +import org.highmed.dsf.fhir.resources.AbstractResource; +import org.highmed.dsf.fhir.resources.ActivityDefinitionResource; +import org.highmed.dsf.fhir.resources.CodeSystemResource; +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.highmed.dsf.fhir.resources.StructureDefinitionResource; +import org.highmed.dsf.fhir.resources.ValueSetResource; +import org.springframework.core.env.PropertyResolver; + +import ca.uhn.fhir.context.FhirContext; + +public class FeasibilityMpcProcessPluginDefinition implements ProcessPluginDefinition +{ + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); + + private static final String DEPENDENCY_DATA_SHARING_VERSION = "0.6.0"; + private static final String DEPENDENCY_DATA_SHARING_NAME_AND_VERSION = "dsf-bpe-process-data-sharing-0.6.0"; + + @Override + public String getName() + { + return "dsf-bpe-process-feasibility-mpc"; + } + + @Override + public String getVersion() + { + return VERSION; + } + + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + + @Override + public Stream<String> getBpmnFiles() + { + return Stream.of("bpe/requestFeasibilityMpc.bpmn", "bpe/executeFeasibilityMpcSingleShare.bpmn", + "bpe/executeFeasibilityMpcMultiShare.bpmn"); + } + + @Override + public Stream<Class<?>> getSpringConfigClasses() + { + return Stream.of(FeasibilityMpcConfig.class, FeasibilityMpcSerializerConfig.class, + DataSharingSerializerConfig.class); + } + + @Override + public List<String> getDependencyNamesAndVersions() + { + return Arrays.asList(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION); + } + + @Override + public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader classLoader, + PropertyResolver resolver) + { + var c = CodeSystemResource.dependency(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION, + "http://highmed.org/fhir/CodeSystem/data-sharing", DEPENDENCY_DATA_SHARING_VERSION); + + var aExeM = ActivityDefinitionResource + .file("fhir/ActivityDefinition/highmed-executeFeasibilityMpcMultiShare.xml"); + var aExeS = ActivityDefinitionResource + .file("fhir/ActivityDefinition/highmed-executeFeasibilityMpcSingleShare.xml"); + var aReq = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-requestFeasibilityMpc.xml"); + + var sExeM = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-multi-share.xml"); + var sExeS = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-single-share.xml"); + var sReq = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-request-feasibility-mpc.xml"); + var sResM = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-multi-medic-result-share-feasibility-mpc.xml"); + var sResS = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-single-medic-result-share-feasibility-mpc.xml"); + + var v = ValueSetResource.dependency(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION, + "http://highmed.org/fhir/ValueSet/data-sharing", DEPENDENCY_DATA_SHARING_VERSION); + + Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map.of( + PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE + "/" + VERSION, + Arrays.asList(c, aExeM, sExeM, sResS, v), + PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE + "/" + VERSION, + Arrays.asList(c, aExeS, sExeS, v), PROCESS_NAME_FULL_REQUEST_FEASIBILITY_MPC + "/" + VERSION, + Arrays.asList(c, aReq, sReq, sResM, v)); + + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequestMultiShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequestMultiShare.java new file mode 100644 index 00000000..ee038f76 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequestMultiShare.java @@ -0,0 +1,40 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +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.Targets; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.ParameterComponent; + +import ca.uhn.fhir.context.FhirContext; + +public class SendMedicRequestMultiShare extends AbstractTaskMessageSend +{ + public SendMedicRequestMultiShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream<ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) + { + Targets targets = (Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS); + Stream<Task.ParameterComponent> inputTargets = targets.getEntries().stream() + .map(target -> getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY, + target.getCorrelationKey())); + + return inputTargets; + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequestSingleShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequestSingleShare.java new file mode 100644 index 00000000..b9141711 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequestSingleShare.java @@ -0,0 +1,49 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +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.ParameterComponent; + +import ca.uhn.fhir.context.FhirContext; + +public class SendMedicRequestSingleShare extends AbstractTaskMessageSend +{ + public SendMedicRequestSingleShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream<ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + IdType researchStudyId = new IdType( + getFhirWebserviceClientProvider().getLocalBaseUrl() + "/" + researchStudy.getId()); + + ParameterComponent inputResearchStudyReference = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE, + new Reference().setReference(researchStudyId.toVersionless().getValueAsString())); + + boolean needsConsentCheck = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); + ParameterComponent inputNeedsConsentCheck = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck); + + return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResultShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResultShare.java new file mode 100644 index 00000000..152aaaaf --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResultShare.java @@ -0,0 +1,55 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +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; + +public class SendMultiMedicResultShare extends AbstractTaskMessageSend +{ + public SendMultiMedicResultShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream<Task.ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) + { + QueryResults results = (QueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES); + + return results.getResults().stream().map(this::toInput); + } + + private Task.ParameterComponent toInput(QueryResult result) + { + ParameterComponent input = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE, result.getCohortSize()); + input.addExtension(createCohortIdExtension(result.getCohortId())); + + return input; + } + + private Extension createCohortIdExtension(String cohortId) + { + return new Extension(EXTENSION_HIGHMED_GROUP_ID, new Reference(cohortId)); + } +} \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResultShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResultShare.java new file mode 100644 index 00000000..46bfcd2b --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResultShare.java @@ -0,0 +1,57 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +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; + +public class SendSingleMedicResultShare extends AbstractTaskMessageSend +{ + public SendSingleMedicResultShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream<Task.ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) + { + String targetIdentifier = getTarget().getOrganizationIdentifierValue(); + QueryResults shares = (QueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES); + + return shares.getResults().stream().filter(s -> s.getOrganizationIdentifier().equals(targetIdentifier)) + .map(this::toInput); + } + + private Task.ParameterComponent toInput(QueryResult share) + { + ParameterComponent input = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE, share.getCohortSize()); + input.addExtension(createCohortIdExtension(share.getCohortId())); + + return input; + } + + private Extension createCohortIdExtension(String cohortId) + { + return new Extension(EXTENSION_HIGHMED_GROUP_ID, new Reference(cohortId)); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/mpc/ArithmeticShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/mpc/ArithmeticShare.java new file mode 100644 index 00000000..38e8fca4 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/mpc/ArithmeticShare.java @@ -0,0 +1,46 @@ +package org.highmed.dsf.bpe.mpc; + +import static org.highmed.dsf.bpe.mpc.ArithmeticSharing.DEFAULT_RING_SIZE; + +import java.math.BigInteger; + +/** + * @author Tobias Kussel + */ +public class ArithmeticShare +{ + private final BigInteger value; + private final BigInteger ringSize; + + public ArithmeticShare(long value) + { + this(BigInteger.valueOf(value), DEFAULT_RING_SIZE); + } + + public ArithmeticShare(BigInteger value) + { + this(value, DEFAULT_RING_SIZE); + } + + public ArithmeticShare(BigInteger value, BigInteger ringSize) + { + this.value = value; + this.ringSize = ringSize; + } + + public BigInteger getValue() + { + return value; + } + + public BigInteger getRingSize() + { + return ringSize; + } + + @Override + public String toString() + { + return value + " mod " + ringSize; + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/mpc/ArithmeticSharing.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/mpc/ArithmeticSharing.java new file mode 100644 index 00000000..b878f505 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/mpc/ArithmeticSharing.java @@ -0,0 +1,109 @@ +package org.highmed.dsf.bpe.mpc; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.Objects; + +/** + * @author Tobias Kussel + */ +public class ArithmeticSharing +{ + private static final int MAX_POWER_FOR_INT = 31; + public static final BigInteger DEFAULT_RING_SIZE = BigInteger.valueOf(2).pow(MAX_POWER_FOR_INT) + .subtract(BigInteger.ONE); + + private static final SecureRandom RANDOM_GENERATOR = new SecureRandom(); + + private final BigInteger ringSize; + private final int numParties; + + public ArithmeticSharing(int numParties) + { + this(numParties, DEFAULT_RING_SIZE); + } + + public ArithmeticSharing(int numParties, BigInteger ringSize) + { + Objects.requireNonNull(ringSize, "ringSize"); + + if (BigInteger.ZERO.compareTo(ringSize) >= 0) + throw new IllegalArgumentException("ringSize < 1"); + + if (numParties < 1) + throw new IllegalArgumentException("numParties < 1"); + + this.numParties = numParties; + this.ringSize = ringSize; + } + + public int getNumParties() + { + return numParties; + } + + public BigInteger getRingSize() + { + return ringSize; + } + + public ArithmeticShare[] createShares(int secret) + { + return createShares(BigInteger.valueOf(secret)); + } + + public ArithmeticShare[] createShares(BigInteger secret) + { + BigInteger[] shares = new BigInteger[numParties]; + shares[numParties - 1] = secret; + + for (int i = 0; i < numParties - 1; i++) + { + shares[i] = getBlind(MAX_POWER_FOR_INT); + shares[numParties - 1] = shares[numParties - 1].subtract(shares[i]); + } + + shares[numParties - 1] = shares[numParties - 1].mod(ringSize); + + ArithmeticShare[] result = new ArithmeticShare[numParties]; + for (int i = 0; i < numParties; i++) + { + result[i] = new ArithmeticShare(shares[i], ringSize); + } + + return result; + } + + public int reconstructSecretToInt(ArithmeticShare[] shares) + { + return reconstructSecret(shares).intValueExact(); + } + + public BigInteger reconstructSecret(ArithmeticShare[] shares) + { + if (shares.length != numParties) + throw new IllegalArgumentException("Number of provided ArithmeticShares does not match numParties, shares=" + + shares.length + " ,numParties=" + numParties); + + BigInteger reconstruction = BigInteger.ZERO; + BigInteger firstRingSize = shares[0].getRingSize(); + for (int i = 0; i < shares.length; i++) + { + if (!(shares[i].getRingSize().equals(firstRingSize))) + { + throw new IllegalArgumentException("Incompatible ringSizes found!"); + } + reconstruction = reconstruction.add(shares[i].getValue()).remainder(shares[i].getRingSize()); + } + + return reconstruction; + } + + private BigInteger getBlind(int bitlength) throws IllegalArgumentException + { + if (bitlength < 2) + throw new IllegalArgumentException("Bitlength must be larger than 2"); + + return new BigInteger(bitlength, RANDOM_GENERATOR); + } +} \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResult.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResult.java new file mode 100644 index 00000000..ac8150dd --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResult.java @@ -0,0 +1,64 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.mpc.ArithmeticShare; +import org.highmed.dsf.bpe.mpc.ArithmeticSharing; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResult; +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResults; +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Targets; + +public class CalculateMultiMedicResult extends AbstractServiceDelegate +{ + public CalculateMultiMedicResult(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults shares = (QueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES); + + Targets targets = ((Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS)); + + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(targets.getEntries().size()); + + Map<String, List<QueryResult>> byCohortId = shares.getResults().stream() + .collect(Collectors.groupingBy(QueryResult::getCohortId)); + + List<FinalFeasibilityMpcQueryResult> reconstructedResults = byCohortId.entrySet().stream() + .map(group -> toReconstructedResult(arithmeticSharing, group)).collect(Collectors.toList()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS, FinalFeasibilityMpcQueryResultsValues + .create(new FinalFeasibilityMpcQueryResults(reconstructedResults))); + } + + private FinalFeasibilityMpcQueryResult toReconstructedResult(ArithmeticSharing arithmeticSharing, + Map.Entry<String, List<QueryResult>> group) + { + String cohortId = group.getKey(); + ArithmeticShare[] toReconstruct = group.getValue().stream().map(QueryResult::getCohortSize) + .map(ArithmeticShare::new).toArray(ArithmeticShare[]::new); + + int reconstructedResult = arithmeticSharing.reconstructSecretToInt(toReconstruct); + + return new FinalFeasibilityMpcQueryResult(cohortId, arithmeticSharing.getNumParties(), reconstructedResult); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResultShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResultShare.java new file mode 100644 index 00000000..d8f79091 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResultShare.java @@ -0,0 +1,80 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.mpc.ArithmeticShare; +import org.highmed.dsf.bpe.mpc.ArithmeticSharing; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +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.Targets; +import org.springframework.beans.factory.InitializingBean; + +public class CalculateMultiMedicResultShare extends AbstractServiceDelegate implements InitializingBean +{ + private final OrganizationProvider organizationProvider; + + public CalculateMultiMedicResultShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(organizationProvider, "organizationProvided"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults shares = (QueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES); + + Targets targets = ((Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS)); + + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(targets.getEntries().size()); + String organizationIdentifier = organizationProvider.getLocalIdentifierValue(); + + Map<String, List<QueryResult>> byCohortId = shares.getResults().stream() + .collect(Collectors.groupingBy(QueryResult::getCohortId)); + + List<QueryResult> reconstructedResults = byCohortId.entrySet().stream() + .map(group -> toReconstructedResult(arithmeticSharing, organizationIdentifier, group)) + .collect(Collectors.toList()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES, + QueryResultsValues.create(new QueryResults(reconstructedResults))); + } + + private QueryResult toReconstructedResult(ArithmeticSharing arithmeticSharing, String organizationIdentifier, + Map.Entry<String, List<QueryResult>> group) + { + String cohortId = group.getKey(); + + ArithmeticShare[] toReconstruct = group.getValue().stream().map(QueryResult::getCohortSize) + .map(ArithmeticShare::new).toArray(ArithmeticShare[]::new); + + int reconstructedResult = arithmeticSharing.reconstructSecretToInt(toReconstruct); + + return QueryResult.mpcCountResult(organizationIdentifier, cohortId, reconstructedResult); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateSingleMedicResultShares.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateSingleMedicResultShares.java new file mode 100644 index 00000000..f256ce32 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CalculateSingleMedicResultShares.java @@ -0,0 +1,71 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES; + +import java.math.BigInteger; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.mpc.ArithmeticShare; +import org.highmed.dsf.bpe.mpc.ArithmeticSharing; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; + +public class CalculateSingleMedicResultShares extends AbstractServiceDelegate +{ + public CalculateSingleMedicResultShares(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults queryResults = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + Targets targets = (Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS); + + List<QueryResult> shares = queryResults.getResults().stream() + .flatMap(queryResult -> toArithmeticSharesForCohortAndOrganization(queryResult, targets)) + .collect(Collectors.toList()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES, + QueryResultsValues.create(new QueryResults(shares))); + } + + private Stream<QueryResult> toArithmeticSharesForCohortAndOrganization(QueryResult queryResult, Targets targets) + { + List<Target> organizations = targets.getEntries(); + + int numParties = organizations.size(); + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(numParties); + + int secret = queryResult.getCohortSize(); + int maxSecret = arithmeticSharing.getRingSize().divide(BigInteger.valueOf(numParties)).intValueExact(); + + if (secret > maxSecret) + throw new IllegalStateException( + "Secret > maxSecret (" + maxSecret + ") for " + numParties + " participating organizations"); + + ArithmeticShare[] shares = arithmeticSharing.createShares(secret); + + if (shares.length != numParties) + throw new IllegalStateException("Number of shares does not match number of targets"); + + return IntStream.range(0, numParties) + .mapToObj(i -> QueryResult.mpcCountResult(organizations.get(i).getOrganizationIdentifierValue(), + queryResult.getCohortId(), shares[i].getValue().intValueExact())); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityMpcResources.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityMpcResources.java new file mode 100644 index 00000000..9cf98a3f --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityMpcResources.java @@ -0,0 +1,74 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.MIN_COHORT_DEFINITIONS; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.MIN_PARTICIPATING_MEDICS; + +import java.util.List; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesList; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; + +public class CheckFeasibilityMpcResources extends AbstractServiceDelegate +{ + public CheckFeasibilityMpcResources(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + + List<Group> cohorts = ((FhirResourcesList) execution.getVariable(BPMN_EXECUTION_VARIABLE_COHORTS)) + .getResourcesAndCast(); + + checkNumberOfParticipatingMedics(researchStudy); + checkFullyQualifiedCohortIds(cohorts); + checkNumberOfCohortDefinitions(cohorts); + } + + private void checkNumberOfParticipatingMedics(ResearchStudy researchStudy) + { + long medics = researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).stream() + .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue()) + .map(r -> r.getIdentifier()) + .filter(i -> NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER.equals(i.getSystem())).map(i -> i.getValue()) + .distinct().count(); + + if (medics < MIN_PARTICIPATING_MEDICS) + { + throw new RuntimeException( + "Number of distinct participanting MeDICs is < " + MIN_PARTICIPATING_MEDICS + ", got " + medics); + } + } + + private void checkFullyQualifiedCohortIds(List<Group> 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<Group> cohorts) + { + int size = cohorts.size(); + if (size < MIN_COHORT_DEFINITIONS) + { + throw new RuntimeException("Number of defined cohorts is < " + MIN_COHORT_DEFINITIONS + ", got " + size); + } + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java new file mode 100644 index 00000000..5d2e70cb --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java @@ -0,0 +1,70 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResult; +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResults; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task; + +public class CheckMultiMedicResults extends AbstractServiceDelegate +{ + public CheckMultiMedicResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + Task leadingTask = getLeadingTaskFromExecutionVariables(); + + FinalFeasibilityMpcQueryResults results = (FinalFeasibilityMpcQueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS); + + FinalFeasibilityMpcQueryResults checkedResults = checkResults(results); + + addFinalFeasibilityQueryResultsToLeadingTask(checkedResults, leadingTask); + } + + protected FinalFeasibilityMpcQueryResults checkResults(FinalFeasibilityMpcQueryResults results) + { + // TODO implement check for results + // - criterias tbd + return results; + } + + private void addFinalFeasibilityQueryResultsToLeadingTask(FinalFeasibilityMpcQueryResults results, Task toWrite) + { + results.getResults().forEach(result -> addResultOutput(result, toWrite)); + } + + private void addResultOutput(FinalFeasibilityMpcQueryResult result, Task toWrite) + { + Task.TaskOutputComponent output1 = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT, result.getCohortSize()); + output1.addExtension(createCohortIdExtension(result.getCohortId())); + toWrite.addOutput(output1); + + Task.TaskOutputComponent output2 = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS, result.getParticipatingMedics()); + output2.addExtension(createCohortIdExtension(result.getCohortId())); + toWrite.addOutput(output2); + } + + private Extension createCohortIdExtension(String cohortId) + { + return new Extension(EXTENSION_HIGHMED_GROUP_ID, new Reference(cohortId)); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java new file mode 100644 index 00000000..9be90051 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java @@ -0,0 +1,81 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.FEASIBILITY_MPC_QUERY_PREFIX; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.group.GroupHelper; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesList; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class CheckQueries extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(CheckQueries.class); + + private final GroupHelper groupHelper; + + public CheckQueries(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, GroupHelper groupHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.groupHelper = groupHelper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(groupHelper, "groupHelper"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + List<Group> cohorts = ((FhirResourcesList) execution.getVariable(BPMN_EXECUTION_VARIABLE_COHORTS)) + .getResourcesAndCast(); + + Map<String, String> queries = new HashMap<>(); + + Task leadingTask = getLeadingTaskFromExecutionVariables(); + cohorts.forEach(group -> + { + String aqlQuery = groupHelper.extractAqlQuery(group); + + String groupId = group.getId(); + if (!aqlQuery.startsWith(FEASIBILITY_MPC_QUERY_PREFIX)) + { + String errorMessage = "Initial single medic FeasibilityMpc query check failed, wrong format for query of group with id '" + + groupId + "', expected query to start with '" + FEASIBILITY_MPC_QUERY_PREFIX + "' but got '" + + aqlQuery + "'"; + + logger.info(errorMessage); + leadingTask.getOutput().add(getTaskHelper().createOutput(CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR, errorMessage)); + } + else + { + queries.put(groupId, aqlQuery); + } + }); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERIES, queries); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityMpcResources.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityMpcResources.java new file mode 100644 index 00000000..8bf50499 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityMpcResources.java @@ -0,0 +1,166 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_CORRELATION_KEY; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +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.FhirResourceValues; +import org.highmed.dsf.fhir.variables.FhirResourcesListValues; +import org.highmed.fhir.client.FhirWebserviceClient; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Group; +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; + +public class DownloadFeasibilityMpcResources extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(DownloadFeasibilityMpcResources.class); + + private final OrganizationProvider organizationProvider; + + public DownloadFeasibilityMpcResources(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(organizationProvider, "organizationProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + Task task = getCurrentTaskFromExecutionVariables(); + + IdType researchStudyId = getResearchStudyId(task); + FhirWebserviceClient client = getWebserviceClient(researchStudyId); + Bundle bundle = getResearchStudyAndCohortDefinitions(researchStudyId, client); + + ResearchStudy researchStudy = (ResearchStudy) bundle.getEntryFirstRep().getResource(); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY, FhirResourceValues.create(researchStudy)); + + List<Group> cohortDefinitions = getCohortDefinitions(bundle, client.getBaseUrl()); + execution.setVariable(BPMN_EXECUTION_VARIABLE_COHORTS, FhirResourcesListValues.create(cohortDefinitions)); + + boolean needsConsentCheck = getNeedsConsentCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck); + + String correlationKey = getCorrelationKey(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_CORRELATION_KEY, correlationKey); + } + + private IdType getResearchStudyId(Task task) + { + Reference researchStudyReference = getTaskHelper().getInputParameterReferenceValues(task, + CODESYSTEM_HIGHMED_DATA_SHARING, CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE) + .findFirst().get(); + + return new IdType(researchStudyReference.getReference()); + } + + private FhirWebserviceClient getWebserviceClient(IdType researchStudyId) + { + if (researchStudyId.getBaseUrl() == null + || researchStudyId.getBaseUrl().equals(getFhirWebserviceClientProvider().getLocalBaseUrl())) + { + return getFhirWebserviceClientProvider().getLocalWebserviceClient(); + } + else + { + return getFhirWebserviceClientProvider().getWebserviceClient(researchStudyId.getBaseUrl()); + } + } + + private Bundle getResearchStudyAndCohortDefinitions(IdType researchStudyId, FhirWebserviceClient client) + { + try + { + 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 (Exception e) + { + logger.warn("Error while reading ResearchStudy with id {} including Groups from {}: {}", + researchStudyId.getIdPart(), client.getBaseUrl(), e.getMessage()); + throw e; + } + } + + private List<Group> getCohortDefinitions(Bundle bundle, String baseUrl) + { + return bundle.getEntry().stream().skip(1).map(e -> + { + 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()); + } + + private boolean getNeedsConsentCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); + } + + private String getCorrelationKey(Task task) + { + return getTaskHelper() + .getFirstInputParameterStringValue(task, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY) + .orElseThrow(() -> new IllegalArgumentException("CorrelationKey is not set in task with id='" + + task.getId() + "', this error should have been caught by resource validation")); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java new file mode 100644 index 00000000..057dafdc --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java @@ -0,0 +1,210 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES; + +import java.util.ArrayList; +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.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +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.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class DownloadResearchStudyResource extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(DownloadResearchStudyResource.class); + + private final OrganizationProvider organizationProvider; + + public DownloadResearchStudyResource(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(organizationProvider, "organizationProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + Task task = getCurrentTaskFromExecutionVariables(); + + IdType researchStudyId = getResearchStudyId(task); + FhirWebserviceClient client = getFhirWebserviceClientProvider().getLocalWebserviceClient(); + ResearchStudy researchStudy = getResearchStudy(researchStudyId, client); + String consortiumIdentifier = getConsortiumIdentifier(task); + + researchStudy = checkConsortiumAffiliationAndAddMissingOrganizations(researchStudy, consortiumIdentifier, + client); + execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY, researchStudy); + + boolean needsConsentCheck = getNeedsConsentCheck(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES, + QueryResultsValues.create(new QueryResults(null))); + } + + private IdType getResearchStudyId(Task task) + { + Reference researchStudyReference = getTaskHelper() + .getInputParameterReferenceValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("ResearchStudy reference is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); + + return new IdType(researchStudyReference.getReference()); + } + + private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceClient client) + { + try + { + return client.read(ResearchStudy.class, researchStudyid.getIdPart()); + } + catch (Exception e) + { + logger.warn("Error while reading ResearchStudy with id {} from {}", researchStudyid.getIdPart(), + client.getBaseUrl()); + throw e; + } + } + + private ResearchStudy checkConsortiumAffiliationAndAddMissingOrganizations(ResearchStudy researchStudy, + String consortiumIdentifier, FhirWebserviceClient client) + { + List<String> identifiersConsortium = getOrganizationIdentifiersOfConsortium(consortiumIdentifier); + List<String> identifiersResearchStudy = getOrganizationIdentifiersOfResearchStudy(researchStudy); + + checkConsortiumAffiliation(identifiersConsortium, identifiersResearchStudy, researchStudy.getId(), + consortiumIdentifier); + + return addMissingOrganizations(identifiersConsortium, identifiersResearchStudy, researchStudy, client); + } + + private List<String> getOrganizationIdentifiersOfConsortium(String consortiumIdentifier) + { + return organizationProvider + .getOrganizationsByConsortiumAndRole(consortiumIdentifier, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC) + .flatMap(o -> o.getIdentifier().stream()) + .filter(i -> NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER.equals(i.getSystem())).map(i -> i.getValue()) + .collect(Collectors.toList()); + } + + private List<String> getOrganizationIdentifiersOfResearchStudy(ResearchStudy researchStudy) + { + return researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).stream() + .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue()) + .map(r -> r.getIdentifier().getValue()).collect(Collectors.toList()); + } + + private void checkConsortiumAffiliation(List<String> identifiersConsortium, List<String> identifiersResearchStudy, + String researchStudyId, String consortiumIdentifier) + { + List<String> identifiersWrongConsortium = new ArrayList<>(identifiersResearchStudy); + identifiersWrongConsortium.removeAll(identifiersConsortium); + if (!identifiersWrongConsortium.isEmpty()) + { + logger.warn( + "Organizations with identifiers='{}' are part of FeasibilityMpc research study with id='{}' but do " + + "not belong to the consortium with identifier='{}'", + identifiersWrongConsortium, researchStudyId, consortiumIdentifier); + + throw new RuntimeException("Organizations with identifiers='" + identifiersWrongConsortium + + "' are part of FeasibilityMpc research study with id='" + researchStudyId + + "' but do not belong to the consortium with identifier='" + consortiumIdentifier + "'"); + } + } + + private ResearchStudy addMissingOrganizations(List<String> identifiersConsortium, + List<String> identifiersResearchStudy, ResearchStudy researchStudy, FhirWebserviceClient client) + { + identifiersConsortium.removeAll(identifiersResearchStudy); + + if (!identifiersConsortium.isEmpty()) + { + identifiersConsortium.forEach(identifier -> + { + logger.warn( + "Adding missing organization with identifier='{}' to FeasibilityMpc research study with id='{}'", + identifier, researchStudy.getId()); + + researchStudy.addExtension().setUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).setValue( + new Reference().setType(ResourceType.Organization.name()).setIdentifier(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_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) + { + logger.warn("Error while updating ResearchStudy resource: " + e.getMessage()); + throw e; + } + } + + private String getConsortiumIdentifier(Task task) + { + return getTaskHelper() + .getFirstInputParameterReferenceValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER) + .orElseThrow(() -> new IllegalArgumentException("ConsortiumIdentifier is not set in task with id='" + + task.getId() + "', this error should have been caught by resource validation")) + .getIdentifier().getValue(); + } + + private boolean getNeedsConsentCheck(Task task) + { + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java new file mode 100644 index 00000000..5898f17a --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java @@ -0,0 +1,82 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.client.OpenEhrClient; +import org.highmed.openehr.model.structure.ResultSet; +import org.springframework.beans.factory.InitializingBean; + +public class ExecuteQueries extends AbstractServiceDelegate implements InitializingBean +{ + private final OpenEhrClient openehrClient; + private final OrganizationProvider organizationProvider; + + public ExecuteQueries(FhirWebserviceClientProvider clientProvider, OpenEhrClient openehrClient, + TaskHelper taskHelper, ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.openehrClient = openehrClient; + this.organizationProvider = organizationProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(openehrClient, "openehrClient"); + Objects.requireNonNull(organizationProvider, "organizationProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + // <groupId, query> + @SuppressWarnings("unchecked") + Map<String, String> queries = (Map<String, String>) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERIES); + + Boolean needsConsentCheck = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); + + List<QueryResult> results = queries.entrySet().stream() + .map(entry -> executeQuery(entry.getKey(), entry.getValue(), needsConsentCheck)) + .collect(Collectors.toList()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(results))); + } + + private QueryResult 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. + + ResultSet resultSet = openehrClient.query(cohortQuery, null); + + if (idQuery) + { + return QueryResult.idResult(organizationProvider.getLocalIdentifierValue(), cohortId, resultSet); + } + else + { + int count = Integer.parseInt(resultSet.getRow(0).get(0).getValueAsString()); + return QueryResult.mpcCountResult(organizationProvider.getLocalIdentifierValue(), cohortId, count); + } + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java new file mode 100644 index 00000000..13b776ed --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java @@ -0,0 +1,78 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.consent.client.ConsentClient; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class FilterResultsByConsent extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(FilterResultsByConsent.class); + + private final ConsentClient consentClient; + + public FilterResultsByConsent(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ConsentClient consentClient) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.consentClient = consentClient; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(consentClient, "consentClient"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List<QueryResult> checkedResults = filterResultsByConsent(results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(checkedResults))); + } + + private List<QueryResult> filterResultsByConsent(QueryResults results) + { + return results.getResults().stream().map(result -> filterResultByConsent(result)).collect(Collectors.toList()); + } + + private QueryResult filterResultByConsent(QueryResult result) + { + ResultSet checkedResultSet = removeRowsWithoutConsent(result.getResultSet()); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), checkedResultSet); + } + + private ResultSet removeRowsWithoutConsent(ResultSet resultSet) + { + try + { + return consentClient.removeRowsWithoutConsent(resultSet); + } + catch (Exception exception) + { + logger.warn("Error while filtering ResultSet: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java new file mode 100644 index 00000000..80f71f97 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java @@ -0,0 +1,46 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; + +public class GenerateCountFromIds extends AbstractServiceDelegate +{ + public GenerateCountFromIds(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + + List<QueryResult> filteredResults = count(results.getResults()); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(filteredResults))); + } + + private List<QueryResult> count(List<QueryResult> results) + { + return results.stream().map(this::count).collect(Collectors.toList()); + } + + protected QueryResult count(QueryResult result) + { + return QueryResult.countResult(result.getOrganizationIdentifier(), result.getCohortId(), + result.getResultSet().getRows().size()); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java new file mode 100644 index 00000000..7f7d7c9b --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java @@ -0,0 +1,74 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.pseudonymization.openehr.Constants.EHRID_COLUMN_NAME; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.springframework.beans.factory.InitializingBean; + +public class ModifyQueries extends AbstractServiceDelegate implements InitializingBean +{ + private final String ehrIdColumnPath; + + public ModifyQueries(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, String ehrIdColumnPath) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.ehrIdColumnPath = ehrIdColumnPath; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(ehrIdColumnPath, "ehrIdColumnPath"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + Boolean needsConsentCheck = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); + Boolean needsRecordLinkage = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); + boolean idQuery = Boolean.TRUE.equals(needsConsentCheck) || Boolean.TRUE.equals(needsRecordLinkage); + + if (idQuery) + { + // <groupId, query> + @SuppressWarnings("unchecked") + Map<String, String> queries = (Map<String, String>) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERIES); + + Map<String, String> modifiedQueries = modifyQueries(queries); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERIES, modifiedQueries); + } + } + + private Map<String, String> modifyQueries(Map<String, String> queries) + { + Map<String, String> modifiedQueries = new HashMap<>(); + + for (Entry<String, String> 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" + ehrIdColumnPath + " as " + EHRID_COLUMN_NAME); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectMultiMedicResultShareTarget.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectMultiMedicResultShareTarget.java new file mode 100644 index 00000000..539665fd --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectMultiMedicResultShareTarget.java @@ -0,0 +1,66 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_CORRELATION_KEY; + +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Identifier; +import org.springframework.beans.factory.InitializingBean; + +public class SelectMultiMedicResultShareTarget extends AbstractServiceDelegate implements InitializingBean +{ + private final EndpointProvider endpointProvider; + + public SelectMultiMedicResultShareTarget(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + String identifier = getLeadingTaskFromExecutionVariables().getRequester().getIdentifier().getValue(); + String correlationKey = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_CORRELATION_KEY); + + Endpoint endpoint = endpointProvider.getFirstConsortiumEndpoint( + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, identifier).get(); + + Target medicTarget = Target.createBiDirectionalTarget(identifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), correlationKey); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, TargetValues.create(medicTarget)); + } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectMultiMedicTargets.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectMultiMedicTargets.java new file mode 100644 index 00000000..6a6d02f0 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectMultiMedicTargets.java @@ -0,0 +1,89 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; + +public class SelectMultiMedicTargets extends AbstractServiceDelegate +{ + private final EndpointProvider endpointProvider; + + public SelectMultiMedicTargets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + + Targets targets = getTargets(researchStudy); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(targets)); + } + + private Targets getTargets(ResearchStudy researchStudy) + { + List<Target> targets = researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).stream() + .filter(Extension::hasValue).map(Extension::getValue).filter(v -> v instanceof Reference) + .map(v -> (Reference) v).filter(Reference::hasIdentifier).map(Reference::getIdentifier) + .filter(Identifier::hasValue).map(Identifier::getValue).map(medicIdentifier -> + { + Endpoint endpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIdentifier); + return Target.createBiDirectionalTarget(medicIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), UUID.randomUUID().toString()); + }).collect(Collectors.toList()); + + return new Targets(targets); + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectSingleMedicResultShareTargets.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectSingleMedicResultShareTargets.java new file mode 100644 index 00000000..f460290f --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/SelectSingleMedicResultShareTargets.java @@ -0,0 +1,90 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_CORRELATION_KEY; + +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.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; + +public class SelectSingleMedicResultShareTargets extends AbstractServiceDelegate +{ + private final EndpointProvider endpointProvider; + + public SelectSingleMedicResultShareTargets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.endpointProvider = endpointProvider; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + } + + @Override + protected void doExecute(DelegateExecution execution) + { + ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY); + String correlationKey = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_CORRELATION_KEY); + + Targets targets = getTargets(researchStudy, correlationKey); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(targets)); + } + + private Targets getTargets(ResearchStudy researchStudy, String correlationKey) + { + List<Target> targets = researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).stream() + .filter(Extension::hasValue).map(Extension::getValue).filter(v -> v instanceof Reference) + .map(v -> (Reference) v).filter(Reference::hasIdentifier).map(Reference::getIdentifier) + .filter(Identifier::hasValue).map(Identifier::getValue).map(medicIdentifier -> + { + Endpoint endpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIdentifier); + return Target.createBiDirectionalTarget(medicIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), correlationKey); + }).collect(Collectors.toList()); + + return new Targets(targets); + } + + private Endpoint getEndpoint(String role, String identifier) + { + return endpointProvider + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) + .get(); + } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreResultsMultiMedicShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreResultsMultiMedicShare.java new file mode 100644 index 00000000..0eec7209 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreResultsMultiMedicShare.java @@ -0,0 +1,65 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +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 StoreResultsMultiMedicShare extends AbstractServiceDelegate implements InitializingBean +{ + public StoreResultsMultiMedicShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES); + + Task task = getCurrentTaskFromExecutionVariables(); + + List<QueryResult> extendedResults = new ArrayList<>(); + extendedResults.addAll(results.getResults()); + extendedResults.addAll(getResults(task)); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_MULTI_MEDIC_SHARES, + QueryResultsValues.create(new QueryResults(extendedResults))); + } + + private List<QueryResult> getResults(Task task) + { + TaskHelper taskHelper = getTaskHelper(); + Reference requester = task.getRequester(); + + return taskHelper + .getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE, EXTENSION_HIGHMED_GROUP_ID) + .map(input -> + { + String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference(); + int cohortSize = ((UnsignedIntType) input.getValue()).getValue(); + + return QueryResult.mpcCountResult(requester.getIdentifier().getValue(), cohortId, cohortSize); + }).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreResultsSingleMedicShare.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreResultsSingleMedicShare.java new file mode 100644 index 00000000..cf28a7e2 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreResultsSingleMedicShare.java @@ -0,0 +1,68 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +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 StoreResultsSingleMedicShare extends AbstractServiceDelegate implements InitializingBean +{ + public StoreResultsSingleMedicShare(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults shares = (QueryResults) execution + .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES); + + Task task = getCurrentTaskFromExecutionVariables(); + + List<QueryResult> extendedShares = new ArrayList<>(); + extendedShares.addAll(shares.getResults()); + extendedShares.addAll(getShares(task)); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES, + QueryResultsValues.create(new QueryResults(extendedShares))); + } + + private List<QueryResult> getShares(Task task) + { + TaskHelper taskHelper = getTaskHelper(); + Reference requester = task.getRequester(); + + return taskHelper + .getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE, EXTENSION_HIGHMED_GROUP_ID) + .map(input -> toQueryResultShare(requester, input)).collect(Collectors.toList()); + } + + private QueryResult toQueryResultShare(Reference requester, Task.ParameterComponent input) + { + String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference(); + String organizationIdentifier = requester.getIdentifier().getValue(); + int shareSize = ((UnsignedIntType) input.getValue()).getValue(); + + return QueryResult.mpcCountResult(organizationIdentifier, cohortId, shareSize); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResultShareCorrelationKeys.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResultShareCorrelationKeys.java new file mode 100644 index 00000000..daae0bcf --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/service/StoreSingleMedicResultShareCorrelationKeys.java @@ -0,0 +1,68 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES; + +import java.util.List; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Task; + +public class StoreSingleMedicResultShareCorrelationKeys extends AbstractServiceDelegate +{ + public StoreSingleMedicResultShareCorrelationKeys(FhirWebserviceClientProvider clientProvider, + TaskHelper taskHelper, ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + Task task = getCurrentTaskFromExecutionVariables(); + + Targets targets = getTargets(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(targets)); + + String correlationKey = getCorrelationKey(task); + execution.setVariable(BPMN_EXECUTION_VARIABLE_CORRELATION_KEY, correlationKey); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS_SINGLE_MEDIC_SHARES, + QueryResultsValues.create(new QueryResults(null))); + } + + private Targets getTargets(Task task) + { + List<Target> targets = getTaskHelper() + .getInputParameterStringValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY) + .map(correlationKey -> Target.createBiDirectionalTarget("", "", "", correlationKey)) + .collect(Collectors.toList()); + + return new Targets(targets); + } + + private String getCorrelationKey(Task task) + { + return getTaskHelper() + .getFirstInputParameterStringValue(task, CODESYSTEM_HIGHMED_BPMN, + CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY) + .orElseThrow(() -> new IllegalArgumentException("CorrelationKey is not set in task with id='" + + task.getId() + "', this error should have been caught by resource validation")); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityMpcConfig.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityMpcConfig.java new file mode 100644 index 00000000..0df213dd --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityMpcConfig.java @@ -0,0 +1,244 @@ +package org.highmed.dsf.bpe.spring.config; + +import org.highmed.consent.client.ConsentClient; +import org.highmed.consent.client.ConsentClientFactory; +import org.highmed.dsf.bpe.message.SendMedicRequestMultiShare; +import org.highmed.dsf.bpe.message.SendMedicRequestSingleShare; +import org.highmed.dsf.bpe.message.SendMultiMedicResultShare; +import org.highmed.dsf.bpe.message.SendSingleMedicResultShare; +import org.highmed.dsf.bpe.service.CalculateMultiMedicResult; +import org.highmed.dsf.bpe.service.CalculateMultiMedicResultShare; +import org.highmed.dsf.bpe.service.CalculateSingleMedicResultShares; +import org.highmed.dsf.bpe.service.CheckFeasibilityMpcResources; +import org.highmed.dsf.bpe.service.CheckMultiMedicResults; +import org.highmed.dsf.bpe.service.CheckQueries; +import org.highmed.dsf.bpe.service.DownloadFeasibilityMpcResources; +import org.highmed.dsf.bpe.service.DownloadResearchStudyResource; +import org.highmed.dsf.bpe.service.ExecuteQueries; +import org.highmed.dsf.bpe.service.FilterResultsByConsent; +import org.highmed.dsf.bpe.service.GenerateCountFromIds; +import org.highmed.dsf.bpe.service.ModifyQueries; +import org.highmed.dsf.bpe.service.SelectMultiMedicResultShareTarget; +import org.highmed.dsf.bpe.service.SelectMultiMedicTargets; +import org.highmed.dsf.bpe.service.SelectSingleMedicResultShareTargets; +import org.highmed.dsf.bpe.service.StoreResultsMultiMedicShare; +import org.highmed.dsf.bpe.service.StoreResultsSingleMedicShare; +import org.highmed.dsf.bpe.service.StoreSingleMedicResultShareCorrelationKeys; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.group.GroupHelper; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.client.OpenEhrClient; +import org.highmed.openehr.client.OpenEhrClientFactory; +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.core.env.Environment; + +import ca.uhn.fhir.context.FhirContext; + +@Configuration +public class FeasibilityMpcConfig +{ + @Autowired + private FhirWebserviceClientProvider fhirClientProvider; + + @Autowired + private ConsentClientFactory consentClientFactory; + + @Autowired + private OpenEhrClientFactory openEhrClientFactory; + + @Autowired + private OrganizationProvider organizationProvider; + + @Autowired + private EndpointProvider endpointProvider; + + @Autowired + private TaskHelper taskHelper; + + @Autowired + private ReadAccessHelper readAccessHelper; + + @Autowired + private GroupHelper groupHelper; + + @Autowired + private FhirContext fhirContext; + + @Autowired + private Environment environment; + + @Value("${org.highmed.dsf.bpe.openehr.subject.external.id.path:/ehr_status/subject/external_ref/id/value}") + private String ehrIdColumnPath; + + // + // process requestFeasibilityMpc implementations + // + + @Bean + public DownloadResearchStudyResource downloadResearchStudyResource() + { + return new DownloadResearchStudyResource(fhirClientProvider, taskHelper, readAccessHelper, + organizationProvider); + } + + @Bean + public SelectMultiMedicTargets selectMultiMedicTargets() + { + return new SelectMultiMedicTargets(fhirClientProvider, taskHelper, readAccessHelper, endpointProvider); + } + + @Bean + public SendMedicRequestMultiShare sendMedicRequestMultiShare() + { + return new SendMedicRequestMultiShare(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } + + @Bean + public SendMedicRequestSingleShare sendMedicRequestSingleShare() + { + return new SendMedicRequestSingleShare(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } + + @Bean + public StoreResultsMultiMedicShare storeResultsMultiMedicShare() + { + return new StoreResultsMultiMedicShare(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public CalculateMultiMedicResultShare calculateMulitMedicResultShare() + { + return new CalculateMultiMedicResultShare(fhirClientProvider, taskHelper, readAccessHelper, + organizationProvider); + } + + @Bean + public CheckMultiMedicResults checkMultiMedicResults() + { + return new CheckMultiMedicResults(fhirClientProvider, taskHelper, readAccessHelper); + } + + // + // process executeFeasibilityMpcSingleShare implementations + // + + // + // process executeFeasibilityMpcMultiShare implementations + // + + @Bean + public DownloadFeasibilityMpcResources downloadFeasibilityMpcResources() + { + return new DownloadFeasibilityMpcResources(fhirClientProvider, taskHelper, readAccessHelper, + organizationProvider); + } + + @Bean + public CheckFeasibilityMpcResources checkFeasibilityMpcResources() + { + return new CheckFeasibilityMpcResources(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public StoreSingleMedicResultShareCorrelationKeys storeSingleMedicResultShareCorrelationKeys() + { + return new StoreSingleMedicResultShareCorrelationKeys(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public CheckQueries checkQueries() + { + return new CheckQueries(fhirClientProvider, taskHelper, readAccessHelper, groupHelper); + } + + @Bean + public ModifyQueries modifyQueries() + { + return new ModifyQueries(fhirClientProvider, taskHelper, readAccessHelper, ehrIdColumnPath); + } + + @Bean + public OpenEhrClient openEhrClient() + { + return openEhrClientFactory.createClient(environment::getProperty); + } + + @Bean + public ExecuteQueries executeQueries() + { + return new ExecuteQueries(fhirClientProvider, openEhrClient(), taskHelper, readAccessHelper, + organizationProvider); + } + + @Bean + public ConsentClient consentClient() + { + return consentClientFactory.createClient(environment::getProperty); + } + + @Bean + public FilterResultsByConsent filterResultsByConsent() + { + return new FilterResultsByConsent(fhirClientProvider, taskHelper, readAccessHelper, consentClient()); + } + + @Bean + public GenerateCountFromIds generateCountFromIds() + { + return new GenerateCountFromIds(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public CalculateSingleMedicResultShares calculateSingleMedicResultShares() + { + return new CalculateSingleMedicResultShares(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public SelectSingleMedicResultShareTargets selectSingleMedicResultShareTargets() + { + return new SelectSingleMedicResultShareTargets(fhirClientProvider, taskHelper, readAccessHelper, + endpointProvider); + } + + @Bean + public SendSingleMedicResultShare sendSingleMedicResultShare() + { + return new SendSingleMedicResultShare(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } + + @Bean + public StoreResultsSingleMedicShare storeResultsSingleMedicShare() + { + return new StoreResultsSingleMedicShare(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public CalculateMultiMedicResult calculateMultiMedicResult() + { + return new CalculateMultiMedicResult(fhirClientProvider, taskHelper, readAccessHelper); + } + + @Bean + public SelectMultiMedicResultShareTarget selectMultiMedicResultShareTarget() + { + return new SelectMultiMedicResultShareTarget(fhirClientProvider, taskHelper, readAccessHelper, + endpointProvider); + } + + @Bean + public SendMultiMedicResultShare sendMultiMedicResultShare() + { + return new SendMultiMedicResultShare(fhirClientProvider, taskHelper, readAccessHelper, organizationProvider, + fhirContext); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityMpcSerializerConfig.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityMpcSerializerConfig.java new file mode 100644 index 00000000..0b479601 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityMpcSerializerConfig.java @@ -0,0 +1,28 @@ +package org.highmed.dsf.bpe.spring.config; + +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResultSerializer; +import org.highmed.dsf.bpe.variables.FinalFeasibilityMpcQueryResultsSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.fasterxml.jackson.databind.ObjectMapper; + +@Configuration +public class FeasibilityMpcSerializerConfig +{ + @Autowired + private ObjectMapper objectMapper; + + @Bean + public FinalFeasibilityMpcQueryResultSerializer finalFeasibilityMpcQueryResultSerializer() + { + return new FinalFeasibilityMpcQueryResultSerializer(objectMapper); + } + + @Bean + public FinalFeasibilityMpcQueryResultsSerializer finalFeasibilityMpcQueryResultsSerializer() + { + return new FinalFeasibilityMpcQueryResultsSerializer(objectMapper); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResult.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResult.java new file mode 100644 index 00000000..542436b1 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResult.java @@ -0,0 +1,38 @@ +package org.highmed.dsf.bpe.variables; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class FinalFeasibilityMpcQueryResult +{ + private final String cohortId; + private final int participatingMedics; + private final int cohortSize; + + @JsonCreator + public FinalFeasibilityMpcQueryResult(@JsonProperty("cohortId") String cohortId, + @JsonProperty("participatingMedics") int participatingMedics, @JsonProperty("cohortSize") int cohortSize) + { + this.cohortId = cohortId; + this.participatingMedics = participatingMedics; + this.cohortSize = cohortSize; + } + + @JsonProperty("cohortId") + public String getCohortId() + { + return cohortId; + } + + @JsonProperty("participatingMedics") + public int getParticipatingMedics() + { + return participatingMedics; + } + + @JsonProperty("cohortSize") + public int getCohortSize() + { + return cohortSize; + } +} \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultSerializer.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultSerializer.java new file mode 100644 index 00000000..f4f37e3c --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultSerializer.java @@ -0,0 +1,70 @@ +package org.highmed.dsf.bpe.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.bpe.variables.FinalFeasibilityMpcQueryResultValues.FinalFeasibilityMpcQueryResultValue; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class FinalFeasibilityMpcQueryResultSerializer + extends PrimitiveValueSerializer<FinalFeasibilityMpcQueryResultValue> implements InitializingBean +{ + private final ObjectMapper objectMapper; + + public FinalFeasibilityMpcQueryResultSerializer(ObjectMapper objectMapper) + { + super(FinalFeasibilityMpcQueryResultValues.VALUE_TYPE); + + this.objectMapper = objectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(objectMapper, "objectMapper"); + } + + @Override + public void writeValue(FinalFeasibilityMpcQueryResultValue value, ValueFields valueFields) + { + FinalFeasibilityMpcQueryResult result = value.getValue(); + try + { + if (result != null) + valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(result)); + } + catch (JsonProcessingException e) + { + throw new RuntimeException(e); + } + } + + @Override + public FinalFeasibilityMpcQueryResultValue convertToTypedValue(UntypedValueImpl untypedValue) + { + return FinalFeasibilityMpcQueryResultValues.create((FinalFeasibilityMpcQueryResult) untypedValue.getValue()); + } + + @Override + public FinalFeasibilityMpcQueryResultValue readValue(ValueFields valueFields, boolean asTransientValue) + { + byte[] bytes = valueFields.getByteArrayValue(); + + try + { + FinalFeasibilityMpcQueryResult result = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, FinalFeasibilityMpcQueryResult.class); + return FinalFeasibilityMpcQueryResultValues.create(result); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultValues.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultValues.java new file mode 100644 index 00000000..304076dd --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultValues.java @@ -0,0 +1,57 @@ +package org.highmed.dsf.bpe.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 FinalFeasibilityMpcQueryResultValues +{ + public static interface FinalFeasibilityMpcQueryResultValue extends PrimitiveValue<FinalFeasibilityMpcQueryResult> + { + } + + private static class FinalFeasibilityMpcQueryResultValueImpl + extends PrimitiveTypeValueImpl<FinalFeasibilityMpcQueryResult> + implements FinalFeasibilityMpcQueryResultValues.FinalFeasibilityMpcQueryResultValue + { + private static final long serialVersionUID = 1L; + + public FinalFeasibilityMpcQueryResultValueImpl(FinalFeasibilityMpcQueryResult value, PrimitiveValueType type) + { + super(value, type); + } + } + + public static class FinalFeasibilityMpcQueryResultValueTypeImpl extends PrimitiveValueTypeImpl + { + private static final long serialVersionUID = 1L; + + private FinalFeasibilityMpcQueryResultValueTypeImpl() + { + super(FinalFeasibilityMpcQueryResult.class); + } + + @Override + public TypedValue createValue(Object value, Map<String, Object> valueInfo) + { + return new FinalFeasibilityMpcQueryResultValues.FinalFeasibilityMpcQueryResultValueImpl( + (FinalFeasibilityMpcQueryResult) value, VALUE_TYPE); + } + } + + public static final PrimitiveValueType VALUE_TYPE = new FinalFeasibilityMpcQueryResultValues.FinalFeasibilityMpcQueryResultValueTypeImpl(); + + private FinalFeasibilityMpcQueryResultValues() + { + } + + public static FinalFeasibilityMpcQueryResultValues.FinalFeasibilityMpcQueryResultValue create( + FinalFeasibilityMpcQueryResult value) + { + return new FinalFeasibilityMpcQueryResultValues.FinalFeasibilityMpcQueryResultValueImpl(value, VALUE_TYPE); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResults.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResults.java new file mode 100644 index 00000000..f086e50b --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResults.java @@ -0,0 +1,40 @@ +package org.highmed.dsf.bpe.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 FinalFeasibilityMpcQueryResults +{ + private final List<FinalFeasibilityMpcQueryResult> results = new ArrayList<>(); + + @JsonCreator + public FinalFeasibilityMpcQueryResults( + @JsonProperty("results") Collection<? extends FinalFeasibilityMpcQueryResult> results) + { + if (results != null) + this.results.addAll(results); + } + + public void add(FinalFeasibilityMpcQueryResult newResult) + { + if (newResult != null) + results.add(newResult); + } + + public void addAll(Collection<FinalFeasibilityMpcQueryResult> results) + { + if (results != null) + this.results.addAll(results); + } + + @JsonProperty("results") + public List<FinalFeasibilityMpcQueryResult> getResults() + { + return Collections.unmodifiableList(results); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsSerializer.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsSerializer.java new file mode 100644 index 00000000..b0ddb60d --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsSerializer.java @@ -0,0 +1,70 @@ +package org.highmed.dsf.bpe.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.bpe.variables.FinalFeasibilityMpcQueryResultsValues.FinalFeasibilityMpcQueryResultsValue; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class FinalFeasibilityMpcQueryResultsSerializer + extends PrimitiveValueSerializer<FinalFeasibilityMpcQueryResultsValue> implements InitializingBean +{ + private final ObjectMapper objectMapper; + + public FinalFeasibilityMpcQueryResultsSerializer(ObjectMapper objectMapper) + { + super(FinalFeasibilityMpcQueryResultsValues.VALUE_TYPE); + + this.objectMapper = objectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(objectMapper, "objectMapper"); + } + + @Override + public void writeValue(FinalFeasibilityMpcQueryResultsValue value, ValueFields valueFields) + { + FinalFeasibilityMpcQueryResults results = value.getValue(); + try + { + if (results != null) + valueFields.setByteArrayValue(objectMapper.writeValueAsBytes(results)); + } + catch (JsonProcessingException e) + { + throw new RuntimeException(e); + } + } + + @Override + public FinalFeasibilityMpcQueryResultsValue convertToTypedValue(UntypedValueImpl untypedValue) + { + return FinalFeasibilityMpcQueryResultsValues.create((FinalFeasibilityMpcQueryResults) untypedValue.getValue()); + } + + @Override + public FinalFeasibilityMpcQueryResultsValue readValue(ValueFields valueFields, boolean asTransientValue) + { + byte[] bytes = valueFields.getByteArrayValue(); + + try + { + FinalFeasibilityMpcQueryResults results = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, FinalFeasibilityMpcQueryResults.class); + return FinalFeasibilityMpcQueryResultsValues.create(results); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsValues.java b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsValues.java new file mode 100644 index 00000000..a7076e52 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsValues.java @@ -0,0 +1,57 @@ +package org.highmed.dsf.bpe.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 FinalFeasibilityMpcQueryResultsValues +{ + public static interface FinalFeasibilityMpcQueryResultsValue extends PrimitiveValue<FinalFeasibilityMpcQueryResults> + { + } + + private static class FinalFeasibilityMpcQueryResultsValueImpl + extends PrimitiveTypeValueImpl<FinalFeasibilityMpcQueryResults> + implements FinalFeasibilityMpcQueryResultsValues.FinalFeasibilityMpcQueryResultsValue + { + private static final long serialVersionUID = 1L; + + public FinalFeasibilityMpcQueryResultsValueImpl(FinalFeasibilityMpcQueryResults value, PrimitiveValueType type) + { + super(value, type); + } + } + + public static class FinalFeasibilityMpcQueryResultsValueTypeImpl extends PrimitiveValueTypeImpl + { + private static final long serialVersionUID = 1L; + + private FinalFeasibilityMpcQueryResultsValueTypeImpl() + { + super(FinalFeasibilityMpcQueryResults.class); + } + + @Override + public TypedValue createValue(Object value, Map<String, Object> valueInfo) + { + return new FinalFeasibilityMpcQueryResultsValues.FinalFeasibilityMpcQueryResultsValueImpl( + (FinalFeasibilityMpcQueryResults) value, VALUE_TYPE); + } + } + + public static final PrimitiveValueType VALUE_TYPE = new FinalFeasibilityMpcQueryResultsValues.FinalFeasibilityMpcQueryResultsValueTypeImpl(); + + private FinalFeasibilityMpcQueryResultsValues() + { + } + + public static FinalFeasibilityMpcQueryResultsValues.FinalFeasibilityMpcQueryResultsValue create( + FinalFeasibilityMpcQueryResults value) + { + return new FinalFeasibilityMpcQueryResultsValues.FinalFeasibilityMpcQueryResultsValueImpl(value, VALUE_TYPE); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/META-INF/services/org.highmed.dsf.bpe.ProcessPluginDefinition b/dsf-bpe-process-feasibility-mpc/src/main/resources/META-INF/services/org.highmed.dsf.bpe.ProcessPluginDefinition new file mode 100644 index 00000000..38c28e0e --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/META-INF/services/org.highmed.dsf.bpe.ProcessPluginDefinition @@ -0,0 +1 @@ +org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/executeFeasibilityMpcMultiShare.bpmn b/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/executeFeasibilityMpcMultiShare.bpmn new file mode 100644 index 00000000..1c1b52cb --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/executeFeasibilityMpcMultiShare.bpmn @@ -0,0 +1,168 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0drkcb5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.12.0"> + <bpmn:process id="highmedorg_executeFeasibilityMpcMultiShare" isExecutable="true" camunda:versionTag="#{version}"> + <bpmn:startEvent id="StartEvent" name="start"> + <bpmn:outgoing>Flow_0zwnqdn</bpmn:outgoing> + <bpmn:messageEventDefinition id="MessageEventDefinition_0sjtzj6" messageRef="Message_1yz2a31" /> + </bpmn:startEvent> + <bpmn:endEvent id="EndEvent" name="send multi medic result share"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/requestFeasibilityMpc/#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">resultShareMultiMedicFeasibilityMpcMessage</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-share-feasibility-mpc|#{version}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_1p3ixg0</bpmn:incoming> + <bpmn:messageEventDefinition id="MessageEventDefinition_13swtie" messageRef="Message_0qpomdh" camunda:class="org.highmed.dsf.bpe.message.SendMultiMedicResultShare" /> + </bpmn:endEvent> + <bpmn:subProcess id="Activity_11idi2o"> + <bpmn:incoming>Flow_15s0sha</bpmn:incoming> + <bpmn:outgoing>Flow_18n85hs</bpmn:outgoing> + <bpmn:multiInstanceLoopCharacteristics camunda:collection="${targets.entries}" camunda:elementVariable="target" /> + <bpmn:endEvent id="Event_1q7uhca"> + <bpmn:incoming>Flow_1p7mmcy</bpmn:incoming> + </bpmn:endEvent> + <bpmn:serviceTask id="temporarillyStoreSingleMedicResultShare" name="temporarilly store single medic result share" camunda:class="org.highmed.dsf.bpe.service.StoreResultsSingleMedicShare"> + <bpmn:incoming>Flow_1dzs2th</bpmn:incoming> + <bpmn:outgoing>Flow_1p7mmcy</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:receiveTask id="receiveSingleMedicResultShare" name="receive single medic result share" messageRef="Message_1ycrgfa"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="correlationKey">${target.correlationKey}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_17saewg</bpmn:incoming> + <bpmn:outgoing>Flow_1dzs2th</bpmn:outgoing> + </bpmn:receiveTask> + <bpmn:startEvent id="Event_0sfgw8l"> + <bpmn:outgoing>Flow_17saewg</bpmn:outgoing> + </bpmn:startEvent> + <bpmn:sequenceFlow id="Flow_1p7mmcy" sourceRef="temporarillyStoreSingleMedicResultShare" targetRef="Event_1q7uhca" /> + <bpmn:sequenceFlow id="Flow_1dzs2th" sourceRef="receiveSingleMedicResultShare" targetRef="temporarillyStoreSingleMedicResultShare" /> + <bpmn:sequenceFlow id="Flow_17saewg" sourceRef="Event_0sfgw8l" targetRef="receiveSingleMedicResultShare" /> + </bpmn:subProcess> + <bpmn:exclusiveGateway id="Gateway_0atmr78"> + <bpmn:incoming>Flow_18n85hs</bpmn:incoming> + <bpmn:incoming>Flow_1688meb</bpmn:incoming> + <bpmn:outgoing>Flow_18sujdf</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:boundaryEvent id="Event_1qabwc2" attachedToRef="Activity_11idi2o"> + <bpmn:outgoing>Flow_1688meb</bpmn:outgoing> + <bpmn:timerEventDefinition id="TimerEventDefinition_0jn3631"> + <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT2M</bpmn:timeDuration> + </bpmn:timerEventDefinition> + </bpmn:boundaryEvent> + <bpmn:sequenceFlow id="Flow_18n85hs" sourceRef="Activity_11idi2o" targetRef="Gateway_0atmr78" /> + <bpmn:sequenceFlow id="Flow_1688meb" sourceRef="Event_1qabwc2" targetRef="Gateway_0atmr78" /> + <bpmn:serviceTask id="calculateMultiMedicResultShare" name="calculate multi medic result share" camunda:class="org.highmed.dsf.bpe.service.CalculateMultiMedicResultShare"> + <bpmn:incoming>Flow_18sujdf</bpmn:incoming> + <bpmn:outgoing>Flow_0bm0z7u</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_0bm0z7u" sourceRef="calculateMultiMedicResultShare" targetRef="selectMultiMedicResultShareTarget" /> + <bpmn:serviceTask id="storeSingleMedicResultShareCorrelationKeys" name="store single medic result share correlation keys" camunda:class="org.highmed.dsf.bpe.service.StoreSingleMedicResultShareCorrelationKeys"> + <bpmn:incoming>Flow_0zwnqdn</bpmn:incoming> + <bpmn:outgoing>Flow_15s0sha</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_1p3ixg0" sourceRef="selectMultiMedicResultShareTarget" targetRef="EndEvent" /> + <bpmn:serviceTask id="selectMultiMedicResultShareTarget" name="select multi medic result share target" camunda:class="org.highmed.dsf.bpe.service.SelectMultiMedicResultShareTarget"> + <bpmn:incoming>Flow_0bm0z7u</bpmn:incoming> + <bpmn:outgoing>Flow_1p3ixg0</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_15s0sha" sourceRef="storeSingleMedicResultShareCorrelationKeys" targetRef="Activity_11idi2o" /> + <bpmn:sequenceFlow id="Flow_0zwnqdn" sourceRef="StartEvent" targetRef="storeSingleMedicResultShareCorrelationKeys" /> + <bpmn:sequenceFlow id="Flow_18sujdf" sourceRef="Gateway_0atmr78" targetRef="calculateMultiMedicResultShare" /> + </bpmn:process> + <bpmn:message id="Message_1yz2a31" name="executeFeasibilityMpcMultiShareMessage" /> + <bpmn:message id="Message_1dr71re" name="resultMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_1ycrgfa" name="resultShareSingleMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_0qpomdh" name="resultShareMultiMedicFeasibilityMpcMessage" /> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="highmedorg_executeFeasibilityMpcMultiShare"> + <bpmndi:BPMNEdge id="Flow_18sujdf_di" bpmnElement="Flow_18sujdf"> + <di:waypoint x="1055" y="147" /> + <di:waypoint x="1110" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0zwnqdn_di" bpmnElement="Flow_0zwnqdn"> + <di:waypoint x="188" y="147" /> + <di:waypoint x="260" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_15s0sha_di" bpmnElement="Flow_15s0sha"> + <di:waypoint x="360" y="147" /> + <di:waypoint x="420" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1p3ixg0_di" bpmnElement="Flow_1p3ixg0"> + <di:waypoint x="1380" y="147" /> + <di:waypoint x="1452" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0bm0z7u_di" bpmnElement="Flow_0bm0z7u"> + <di:waypoint x="1210" y="147" /> + <di:waypoint x="1280" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1688meb_di" bpmnElement="Flow_1688meb"> + <di:waypoint x="936" y="214" /> + <di:waypoint x="1030" y="214" /> + <di:waypoint x="1030" y="172" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_18n85hs_di" bpmnElement="Flow_18n85hs"> + <di:waypoint x="918" y="147" /> + <di:waypoint x="1005" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="StartEvent_1fzso6r_di" bpmnElement="StartEvent"> + <dc:Bounds x="152" y="129" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="160" y="172" width="22" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="EndEvent_10xdh63_di" bpmnElement="EndEvent"> + <dc:Bounds x="1452" y="129" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="1428" y="172" width="83" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_11idi2o_di" bpmnElement="Activity_11idi2o" isExpanded="true"> + <dc:Bounds x="420" y="80" width="498" height="134" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Flow_17saewg_di" bpmnElement="Flow_17saewg"> + <di:waypoint x="480" y="149" /> + <di:waypoint x="534" y="149" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1dzs2th_di" bpmnElement="Flow_1dzs2th"> + <di:waypoint x="634" y="149" /> + <di:waypoint x="697" y="149" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1p7mmcy_di" bpmnElement="Flow_1p7mmcy"> + <di:waypoint x="797" y="149" /> + <di:waypoint x="845" y="149" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Event_1q7uhca_di" bpmnElement="Event_1q7uhca"> + <dc:Bounds x="845" y="131" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1dodsnn_di" bpmnElement="temporarillyStoreSingleMedicResultShare"> + <dc:Bounds x="697" y="109" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_01ldf9a_di" bpmnElement="receiveSingleMedicResultShare"> + <dc:Bounds x="534" y="109" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0sfgw8l_di" bpmnElement="Event_0sfgw8l"> + <dc:Bounds x="444" y="131" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_0atmr78_di" bpmnElement="Gateway_0atmr78" isMarkerVisible="true"> + <dc:Bounds x="1005" y="122" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_07k3fpm_di" bpmnElement="calculateMultiMedicResultShare"> + <dc:Bounds x="1110" y="107" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1r2389r_di" bpmnElement="storeSingleMedicResultShareCorrelationKeys"> + <dc:Bounds x="260" y="107" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_19ocdmp_di" bpmnElement="selectMultiMedicResultShareTarget"> + <dc:Bounds x="1280" y="107" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_1qabwc2_di" bpmnElement="Event_1qabwc2"> + <dc:Bounds x="900" y="196" width="36" height="36" /> + </bpmndi:BPMNShape> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions> diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/executeFeasibilityMpcSingleShare.bpmn b/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/executeFeasibilityMpcSingleShare.bpmn new file mode 100644 index 00000000..04d7a415 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/executeFeasibilityMpcSingleShare.bpmn @@ -0,0 +1,258 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0drkcb5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.12.0"> + <bpmn:process id="highmedorg_executeFeasibilityMpcSingleShare" isExecutable="true" camunda:versionTag="#{version}"> + <bpmn:serviceTask id="checkFeasibilityMpcResources" name="check feasibility resources" camunda:class="org.highmed.dsf.bpe.service.CheckFeasibilityMpcResources"> + <bpmn:incoming>Flow_1czhll7</bpmn:incoming> + <bpmn:outgoing>Flow_1dnygeo</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:startEvent id="StartEvent" name="start"> + <bpmn:outgoing>SequenceFlow_14cn0vs</bpmn:outgoing> + <bpmn:messageEventDefinition id="MessageEventDefinition_0sjtzj6" messageRef="Message_1yz2a31" /> + </bpmn:startEvent> + <bpmn:sequenceFlow id="SequenceFlow_1rmqv20" sourceRef="executeQueries" targetRef="ExclusiveGateway_0bq7zdz" /> + <bpmn:sequenceFlow id="SequenceFlow_14cn0vs" sourceRef="StartEvent" targetRef="downloadFeasibilityMpcResources" /> + <bpmn:serviceTask id="downloadFeasibilityMpcResources" name="download feasibility resources" camunda:class="org.highmed.dsf.bpe.service.DownloadFeasibilityMpcResources"> + <bpmn:incoming>SequenceFlow_14cn0vs</bpmn:incoming> + <bpmn:outgoing>Flow_1czhll7</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="SequenceFlow_07wtgee" sourceRef="checkQueries" targetRef="ExclusiveGateway_1dln3in" /> + <bpmn:serviceTask id="checkQueries" name="check query" camunda:class="org.highmed.dsf.bpe.service.CheckQueries"> + <bpmn:incoming>Flow_1dnygeo</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_07wtgee</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:exclusiveGateway id="ExclusiveGateway_1dln3in"> + <bpmn:incoming>SequenceFlow_07wtgee</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0zlq6j4</bpmn:outgoing> + <bpmn:outgoing>SequenceFlow_0yqpkri</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="SequenceFlow_0zlq6j4" name="else" sourceRef="ExclusiveGateway_1dln3in" targetRef="ExclusiveGateway_1r4c9fx"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!needsConsentCheck}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:sequenceFlow id="SequenceFlow_0yqpkri" name="needs consent check" sourceRef="ExclusiveGateway_1dln3in" targetRef="replaceCountpartWithIdSelection"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsConsentCheck}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:serviceTask id="replaceCountpartWithIdSelection" name="replace countpart with id selection" camunda:class="org.highmed.dsf.bpe.service.ModifyQueries"> + <bpmn:incoming>SequenceFlow_0yqpkri</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_1u1p9j2</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:exclusiveGateway id="ExclusiveGateway_1r4c9fx"> + <bpmn:incoming>SequenceFlow_0zlq6j4</bpmn:incoming> + <bpmn:incoming>SequenceFlow_1u1p9j2</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0bwn08k</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="SequenceFlow_0bwn08k" sourceRef="ExclusiveGateway_1r4c9fx" targetRef="executeQueries" /> + <bpmn:sequenceFlow id="SequenceFlow_1u1p9j2" sourceRef="replaceCountpartWithIdSelection" targetRef="ExclusiveGateway_1r4c9fx" /> + <bpmn:exclusiveGateway id="ExclusiveGateway_0bq7zdz"> + <bpmn:incoming>SequenceFlow_1rmqv20</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0isxkuy</bpmn:outgoing> + <bpmn:outgoing>SequenceFlow_17otl7p</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="SequenceFlow_0isxkuy" name="needs consent check" sourceRef="ExclusiveGateway_0bq7zdz" targetRef="filterByConsent"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsConsentCheck}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:serviceTask id="filterByConsent" name="filter result by consent" camunda:class="org.highmed.dsf.bpe.service.FilterResultsByConsent"> + <bpmn:incoming>SequenceFlow_0isxkuy</bpmn:incoming> + <bpmn:outgoing>Flow_19itw20</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="SequenceFlow_17otl7p" name="else" sourceRef="ExclusiveGateway_0bq7zdz" targetRef="ExclusiveGateway_002t87f"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!needsConsentCheck}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:exclusiveGateway id="ExclusiveGateway_002t87f"> + <bpmn:incoming>SequenceFlow_17otl7p</bpmn:incoming> + <bpmn:incoming>SequenceFlow_1kpvsx9</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0q803rh</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="SequenceFlow_0q803rh" sourceRef="ExclusiveGateway_002t87f" targetRef="selectResponseTargetTtp" /> + <bpmn:sequenceFlow id="SequenceFlow_1kpvsx9" sourceRef="countIds" targetRef="ExclusiveGateway_002t87f" /> + <bpmn:serviceTask id="countIds" name="count id's" camunda:class="org.highmed.dsf.bpe.service.GenerateCountFromIds"> + <bpmn:incoming>Flow_19itw20</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_1kpvsx9</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="SequenceFlow_0ascyjc" sourceRef="selectResponseTargetTtp" targetRef="calculateSingleMedicResultShares" /> + <bpmn:serviceTask id="selectResponseTargetTtp" name="select single medic result  share targets" camunda:class="org.highmed.dsf.bpe.service.SelectSingleMedicResultShareTargets"> + <bpmn:incoming>SequenceFlow_0q803rh</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0ascyjc</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:serviceTask id="executeQueries" name="execute query" camunda:class="org.highmed.dsf.bpe.service.ExecuteQueries"> + <bpmn:incoming>SequenceFlow_0bwn08k</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_1rmqv20</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:serviceTask id="calculateSingleMedicResultShares" name="calculate single medic result shares" camunda:class="org.highmed.dsf.bpe.service.CalculateSingleMedicResultShares"> + <bpmn:incoming>SequenceFlow_0ascyjc</bpmn:incoming> + <bpmn:outgoing>Flow_08uzidj</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sendTask id="sendSingleMedicResultShares" name="send single medic result shares" camunda:class="org.highmed.dsf.bpe.message.SendSingleMedicResultShare"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-single-medic-result-share-feasibility-mpc|#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">resultShareSingleMedicFeasibilityMpcMessage</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeFeasibilityMpcMultiShare/#{version}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_08uzidj</bpmn:incoming> + <bpmn:outgoing>Flow_1tfx2ak</bpmn:outgoing> + <bpmn:multiInstanceLoopCharacteristics camunda:collection="${targets.entries}" camunda:elementVariable="target" /> + </bpmn:sendTask> + <bpmn:sequenceFlow id="Flow_19itw20" sourceRef="filterByConsent" targetRef="countIds" /> + <bpmn:sequenceFlow id="Flow_1czhll7" sourceRef="downloadFeasibilityMpcResources" targetRef="checkFeasibilityMpcResources" /> + <bpmn:endEvent id="Event_1smcidr"> + <bpmn:incoming>Flow_1tfx2ak</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="Flow_1tfx2ak" sourceRef="sendSingleMedicResultShares" targetRef="Event_1smcidr" /> + <bpmn:sequenceFlow id="Flow_1dnygeo" sourceRef="checkFeasibilityMpcResources" targetRef="checkQueries" /> + <bpmn:sequenceFlow id="Flow_08uzidj" sourceRef="calculateSingleMedicResultShares" targetRef="sendSingleMedicResultShares" /> + <bpmn:textAnnotation id="TextAnnotation_0euut3n"> + <bpmn:text>uac check, study definiton validity, type of cohort, ethics commitee vote, included medics, user authentication, rate limit, etc.</bpmn:text> + </bpmn:textAnnotation> + <bpmn:association id="Association_1ncewqu" sourceRef="checkFeasibilityMpcResources" targetRef="TextAnnotation_0euut3n" /> + </bpmn:process> + <bpmn:message id="Message_1yz2a31" name="executeFeasibilityMpcSingleShareMessage" /> + <bpmn:message id="Message_1dr71re" name="resultMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_1ycrgfa" name="resultSingleMedicResultShareFeasibilityMpcMessage" /> + <bpmn:message id="Message_0qpomdh" name="resultShareMultiMedicFeasibilityMpcMessage" /> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="highmedorg_executeFeasibilityMpcSingleShare"> + <bpmndi:BPMNEdge id="Flow_08uzidj_di" bpmnElement="Flow_08uzidj"> + <di:waypoint x="1940" y="272" /> + <di:waypoint x="2010" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1dnygeo_di" bpmnElement="Flow_1dnygeo"> + <di:waypoint x="540" y="272" /> + <di:waypoint x="600" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1tfx2ak_di" bpmnElement="Flow_1tfx2ak"> + <di:waypoint x="2110" y="272" /> + <di:waypoint x="2182" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1czhll7_di" bpmnElement="Flow_1czhll7"> + <di:waypoint x="360" y="272" /> + <di:waypoint x="440" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_19itw20_di" bpmnElement="Flow_19itw20"> + <di:waypoint x="1440" y="141" /> + <di:waypoint x="1520" y="141" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0ascyjc_di" bpmnElement="SequenceFlow_0ascyjc"> + <di:waypoint x="1770" y="272" /> + <di:waypoint x="1840" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_1kpvsx9_di" bpmnElement="SequenceFlow_1kpvsx9"> + <di:waypoint x="1570" y="181" /> + <di:waypoint x="1570" y="247" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0q803rh_di" bpmnElement="SequenceFlow_0q803rh"> + <di:waypoint x="1595" y="272" /> + <di:waypoint x="1670" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_17otl7p_di" bpmnElement="SequenceFlow_17otl7p"> + <di:waypoint x="1245" y="272" /> + <di:waypoint x="1545" y="272" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="1254" y="254" width="21" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0isxkuy_di" bpmnElement="SequenceFlow_0isxkuy"> + <di:waypoint x="1220" y="247" /> + <di:waypoint x="1220" y="141" /> + <di:waypoint x="1340" y="141" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="1227" y="146" width="72" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_1u1p9j2_di" bpmnElement="SequenceFlow_1u1p9j2"> + <di:waypoint x="940" y="181" /> + <di:waypoint x="940" y="247" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0bwn08k_di" bpmnElement="SequenceFlow_0bwn08k"> + <di:waypoint x="965" y="272" /> + <di:waypoint x="1030" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0yqpkri_di" bpmnElement="SequenceFlow_0yqpkri"> + <di:waypoint x="788" y="247" /> + <di:waypoint x="788" y="141" /> + <di:waypoint x="890" y="141" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="793" y="146" width="72" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0zlq6j4_di" bpmnElement="SequenceFlow_0zlq6j4"> + <di:waypoint x="813" y="272" /> + <di:waypoint x="915" y="272" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="817" y="254" width="21" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_07wtgee_di" bpmnElement="SequenceFlow_07wtgee"> + <di:waypoint x="700" y="272" /> + <di:waypoint x="763" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_14cn0vs_di" bpmnElement="SequenceFlow_14cn0vs"> + <di:waypoint x="188" y="272" /> + <di:waypoint x="260" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_1rmqv20_di" bpmnElement="SequenceFlow_1rmqv20"> + <di:waypoint x="1130" y="272" /> + <di:waypoint x="1195" y="272" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="ServiceTask_0jna5l2_di" bpmnElement="checkFeasibilityMpcResources"> + <dc:Bounds x="440" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="StartEvent_1fzso6r_di" bpmnElement="StartEvent"> + <dc:Bounds x="152" y="254" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="160" y="297" width="22" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_0b8j3ka_di" bpmnElement="downloadFeasibilityMpcResources"> + <dc:Bounds x="260" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_1pt9xhp_di" bpmnElement="checkQueries"> + <dc:Bounds x="600" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ExclusiveGateway_1dln3in_di" bpmnElement="ExclusiveGateway_1dln3in" isMarkerVisible="true"> + <dc:Bounds x="763" y="247" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_02nwn9u_di" bpmnElement="replaceCountpartWithIdSelection"> + <dc:Bounds x="890" y="101" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ExclusiveGateway_1r4c9fx_di" bpmnElement="ExclusiveGateway_1r4c9fx" isMarkerVisible="true"> + <dc:Bounds x="915" y="247" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ExclusiveGateway_0bq7zdz_di" bpmnElement="ExclusiveGateway_0bq7zdz" isMarkerVisible="true"> + <dc:Bounds x="1195" y="247" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_0l3b9as_di" bpmnElement="filterByConsent"> + <dc:Bounds x="1340" y="101" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ExclusiveGateway_002t87f_di" bpmnElement="ExclusiveGateway_002t87f" isMarkerVisible="true"> + <dc:Bounds x="1545" y="247" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_17kpyle_di" bpmnElement="countIds"> + <dc:Bounds x="1520" y="101" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_15aifhd_di" bpmnElement="selectResponseTargetTtp"> + <dc:Bounds x="1670" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_0u5pb4i_di" bpmnElement="executeQueries"> + <dc:Bounds x="1030" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0z7c65s_di" bpmnElement="calculateSingleMedicResultShares"> + <dc:Bounds x="1840" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="TextAnnotation_0euut3n_di" bpmnElement="TextAnnotation_0euut3n"> + <dc:Bounds x="490" y="113" width="267" height="56" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0j0x0r2_di" bpmnElement="sendSingleMedicResultShares"> + <dc:Bounds x="2010" y="232" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_1smcidr_di" bpmnElement="Event_1smcidr"> + <dc:Bounds x="2182" y="254" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Association_1ncewqu_di" bpmnElement="Association_1ncewqu"> + <di:waypoint x="460" y="230" /> + <di:waypoint x="460" y="140" /> + <di:waypoint x="490" y="140" /> + </bpmndi:BPMNEdge> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions> diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/requestFeasibilityMpc.bpmn b/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/requestFeasibilityMpc.bpmn new file mode 100644 index 00000000..30255987 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/bpe/requestFeasibilityMpc.bpmn @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0inb4ax" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.12.0"> + <bpmn:process id="highmedorg_requestFeasibilityMpc" isExecutable="true" camunda:versionTag="#{version}"> + <bpmn:startEvent id="StartEvent" name="start"> + <bpmn:outgoing>SequenceFlow_11k77gx</bpmn:outgoing> + <bpmn:messageEventDefinition id="MessageEventDefinition_10c2suu" messageRef="Message_1pq9qxp" /> + </bpmn:startEvent> + <bpmn:serviceTask id="selectMultiMedicResultSharetTargets" name="select multi medic result share targets" camunda:class="org.highmed.dsf.bpe.service.SelectMultiMedicTargets"> + <bpmn:incoming>SequenceFlow_18ajfnh</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_0b5s4ef</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sendTask id="sendRequestMultiShareToMedics" name="send request multi share to medics" camunda:class="org.highmed.dsf.bpe.message.SendMedicRequestMultiShare"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeFeasibilityMpcMultiShare/#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">executeFeasibilityMpcMultiShareMessage</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-multi-share|#{version}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>SequenceFlow_0b5s4ef</bpmn:incoming> + <bpmn:outgoing>Flow_1k1a943</bpmn:outgoing> + <bpmn:multiInstanceLoopCharacteristics camunda:collection="${targets.entries}" camunda:elementVariable="target" /> + </bpmn:sendTask> + <bpmn:sequenceFlow id="SequenceFlow_11k77gx" sourceRef="StartEvent" targetRef="downloadResearchStudyResource" /> + <bpmn:sequenceFlow id="SequenceFlow_0b5s4ef" sourceRef="selectMultiMedicResultSharetTargets" targetRef="sendRequestMultiShareToMedics" /> + <bpmn:serviceTask id="downloadResearchStudyResource" name="download research study resource" camunda:class="org.highmed.dsf.bpe.service.DownloadResearchStudyResource"> + <bpmn:incoming>SequenceFlow_11k77gx</bpmn:incoming> + <bpmn:outgoing>SequenceFlow_18ajfnh</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="SequenceFlow_18ajfnh" sourceRef="downloadResearchStudyResource" targetRef="selectMultiMedicResultSharetTargets" /> + <bpmn:subProcess id="Activity_0lcbiwk"> + <bpmn:incoming>Flow_1b19aj3</bpmn:incoming> + <bpmn:outgoing>Flow_0w3k4vv</bpmn:outgoing> + <bpmn:multiInstanceLoopCharacteristics camunda:collection="${targets.entries}" camunda:elementVariable="target" /> + <bpmn:endEvent id="Event_1j6g4x8"> + <bpmn:incoming>Flow_13lm9he</bpmn:incoming> + </bpmn:endEvent> + <bpmn:serviceTask id="temporarillyStoreMultiMedicResultShare" name="temporarilly store multi medic result share" camunda:class="org.highmed.dsf.bpe.service.StoreResultsMultiMedicShare"> + <bpmn:incoming>Flow_0j3mv3q</bpmn:incoming> + <bpmn:outgoing>Flow_13lm9he</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:receiveTask id="receiveMultiMedicResultShare" name="receive multi medic result share" messageRef="Message_1k57zqd"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="correlationKey">${target.correlationKey}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_0t3ex93</bpmn:incoming> + <bpmn:outgoing>Flow_0j3mv3q</bpmn:outgoing> + </bpmn:receiveTask> + <bpmn:startEvent id="Event_1xy6pw3"> + <bpmn:outgoing>Flow_0t3ex93</bpmn:outgoing> + </bpmn:startEvent> + <bpmn:sequenceFlow id="Flow_13lm9he" sourceRef="temporarillyStoreMultiMedicResultShare" targetRef="Event_1j6g4x8" /> + <bpmn:sequenceFlow id="Flow_0j3mv3q" sourceRef="receiveMultiMedicResultShare" targetRef="temporarillyStoreMultiMedicResultShare" /> + <bpmn:sequenceFlow id="Flow_0t3ex93" sourceRef="Event_1xy6pw3" targetRef="receiveMultiMedicResultShare" /> + </bpmn:subProcess> + <bpmn:boundaryEvent id="Event_1ih81k1" attachedToRef="Activity_0lcbiwk"> + <bpmn:outgoing>Flow_0nau6pf</bpmn:outgoing> + <bpmn:timerEventDefinition id="TimerEventDefinition_0tvpxsv"> + <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT5M</bpmn:timeDuration> + </bpmn:timerEventDefinition> + </bpmn:boundaryEvent> + <bpmn:sequenceFlow id="Flow_1k1a943" sourceRef="sendRequestMultiShareToMedics" targetRef="sendRequestSingleShareToMedics" /> + <bpmn:serviceTask id="calculateMultiMedicCohortSize" name="calculate multi medic cohort size" camunda:class="org.highmed.dsf.bpe.service.CalculateMultiMedicResult"> + <bpmn:incoming>Flow_161cxwt</bpmn:incoming> + <bpmn:outgoing>Flow_08i18td</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:exclusiveGateway id="Gateway_1cv27w0"> + <bpmn:incoming>Flow_0w3k4vv</bpmn:incoming> + <bpmn:incoming>Flow_0nau6pf</bpmn:incoming> + <bpmn:outgoing>Flow_161cxwt</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="Flow_0w3k4vv" sourceRef="Activity_0lcbiwk" targetRef="Gateway_1cv27w0" /> + <bpmn:sequenceFlow id="Flow_0nau6pf" sourceRef="Event_1ih81k1" targetRef="Gateway_1cv27w0" /> + <bpmn:sequenceFlow id="Flow_161cxwt" sourceRef="Gateway_1cv27w0" targetRef="calculateMultiMedicCohortSize" /> + <bpmn:serviceTask id="checkMultimedicCohortSize" name="check multimedic cohort size" camunda:class="org.highmed.dsf.bpe.service.CheckMultiMedicResults"> + <bpmn:incoming>Flow_08i18td</bpmn:incoming> + <bpmn:outgoing>Flow_1atjmt6</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:sequenceFlow id="Flow_1atjmt6" sourceRef="checkMultimedicCohortSize" targetRef="Event_123lecz" /> + <bpmn:sequenceFlow id="Flow_08i18td" sourceRef="calculateMultiMedicCohortSize" targetRef="checkMultimedicCohortSize" /> + <bpmn:endEvent id="Event_123lecz" name="success"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/requestFeasibilityMpc/#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">resultMultiMedicFeasibilityMpcMessage</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-FeasibilityMpc|#{version}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_1atjmt6</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sendTask id="sendRequestSingleShareToMedics" name="send request single share to medics" camunda:class="org.highmed.dsf.bpe.message.SendMedicRequestSingleShare"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeFeasibilityMpcSingleShare/#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">executeFeasibilityMpcSingleShareMessage</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-single-share|#{version}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_1k1a943</bpmn:incoming> + <bpmn:outgoing>Flow_1b19aj3</bpmn:outgoing> + <bpmn:multiInstanceLoopCharacteristics camunda:collection="${targets.entries}" camunda:elementVariable="target" /> + </bpmn:sendTask> + <bpmn:sequenceFlow id="Flow_1b19aj3" sourceRef="sendRequestSingleShareToMedics" targetRef="Activity_0lcbiwk" /> + </bpmn:process> + <bpmn:message id="Message_1pq9qxp" name="requestFeasibilityMpcMessage" /> + <bpmn:message id="Message_07ayhv1" name="resultFeasibilityMpcMessage" /> + <bpmn:message id="Message_0gifb86" name="computeFeasibilityMpcMessage" /> + <bpmn:error id="Error_0dl03kn" /> + <bpmn:error id="Error_07exqe7" /> + <bpmn:error id="Error_1jhmarr" /> + <bpmn:message id="Message_0qfng3q" name="receiveMultiMedicCohortSizeResultMessage" /> + <bpmn:message id="Message_0srg3vv" name="resultMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_0nmxozg" name="errorFeasibilityMpcMessage" /> + <bpmn:message id="Message_1y0yxv0" name="resultMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_0v1bo0o" name="errorFeasibilityMpcMessage" /> + <bpmn:message id="Message_10vqhu0" name="errorMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_1vrxfsk" name="resultMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_1k57zqd" name="resultShareMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_15g8gns" name="resultMultiMedicFeasibilityMpcMessage" /> + <bpmn:message id="Message_1hrloi3" name="errorMultiMedicFeasibilityMpcMessage" /> + <bpmn:error id="Error_0ttn640" name="errorMultiMedicFeasibilityMpcResult" errorCode="errorMultiMedicFeasibilityMpcResult" camunda:errorMessage="errorMultiMedicFeasibilityMpcResult" /> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="highmedorg_requestFeasibilityMpc"> + <bpmndi:BPMNEdge id="Flow_1b19aj3_di" bpmnElement="Flow_1b19aj3"> + <di:waypoint x="850" y="145" /> + <di:waypoint x="910" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_08i18td_di" bpmnElement="Flow_08i18td"> + <di:waypoint x="1720" y="145" /> + <di:waypoint x="1790" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1atjmt6_di" bpmnElement="Flow_1atjmt6"> + <di:waypoint x="1890" y="145" /> + <di:waypoint x="1962" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_161cxwt_di" bpmnElement="Flow_161cxwt"> + <di:waypoint x="1555" y="145" /> + <di:waypoint x="1620" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0nau6pf_di" bpmnElement="Flow_0nau6pf"> + <di:waypoint x="1426" y="212" /> + <di:waypoint x="1530" y="212" /> + <di:waypoint x="1530" y="170" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0w3k4vv_di" bpmnElement="Flow_0w3k4vv"> + <di:waypoint x="1408" y="145" /> + <di:waypoint x="1505" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1k1a943_di" bpmnElement="Flow_1k1a943"> + <di:waypoint x="690" y="145" /> + <di:waypoint x="750" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_18ajfnh_di" bpmnElement="SequenceFlow_18ajfnh"> + <di:waypoint x="340" y="145" /> + <di:waypoint x="410" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_0b5s4ef_di" bpmnElement="SequenceFlow_0b5s4ef"> + <di:waypoint x="510" y="145" /> + <di:waypoint x="590" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_11k77gx_di" bpmnElement="SequenceFlow_11k77gx"> + <di:waypoint x="188" y="145" /> + <di:waypoint x="240" y="145" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="StartEvent_1ozsjmr_di" bpmnElement="StartEvent"> + <dc:Bounds x="152" y="127" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="160" y="170" width="22" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_0vfud44_di" bpmnElement="selectMultiMedicResultSharetTargets"> + <dc:Bounds x="410" y="105" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="SendTask_1pu8i9n_di" bpmnElement="sendRequestMultiShareToMedics"> + <dc:Bounds x="590" y="105" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="ServiceTask_052xqjx_di" bpmnElement="downloadResearchStudyResource"> + <dc:Bounds x="240" y="105" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0lcbiwk_di" bpmnElement="Activity_0lcbiwk" isExpanded="true"> + <dc:Bounds x="910" y="78" width="498" height="134" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Flow_0t3ex93_di" bpmnElement="Flow_0t3ex93"> + <di:waypoint x="970" y="147" /> + <di:waypoint x="1024" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0j3mv3q_di" bpmnElement="Flow_0j3mv3q"> + <di:waypoint x="1124" y="147" /> + <di:waypoint x="1187" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_13lm9he_di" bpmnElement="Flow_13lm9he"> + <di:waypoint x="1287" y="147" /> + <di:waypoint x="1335" y="147" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Event_1j6g4x8_di" bpmnElement="Event_1j6g4x8"> + <dc:Bounds x="1335" y="129" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0289vyo_di" bpmnElement="temporarillyStoreMultiMedicResultShare"> + <dc:Bounds x="1187" y="107" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1jnfv03_di" bpmnElement="receiveMultiMedicResultShare"> + <dc:Bounds x="1024" y="107" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_1xy6pw3_di" bpmnElement="Event_1xy6pw3"> + <dc:Bounds x="934" y="129" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_044pdxe_di" bpmnElement="calculateMultiMedicCohortSize"> + <dc:Bounds x="1620" y="105" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_1cv27w0_di" bpmnElement="Gateway_1cv27w0" isMarkerVisible="true"> + <dc:Bounds x="1505" y="120" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0o1pue0_di" bpmnElement="checkMultimedicCohortSize"> + <dc:Bounds x="1790" y="105" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0r58kgi_di" bpmnElement="Event_123lecz"> + <dc:Bounds x="1962" y="127" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="1961" y="170" width="40" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1uwfouh_di" bpmnElement="sendRequestSingleShareToMedics"> + <dc:Bounds x="750" y="105" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_1ih81k1_di" bpmnElement="Event_1ih81k1"> + <dc:Bounds x="1390" y="194" width="36" height="36" /> + </bpmndi:BPMNShape> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions> diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcMultiShare.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcMultiShare.xml new file mode 100644 index 00000000..fd15f520 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcMultiShare.xml @@ -0,0 +1,169 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag"/> + <code value="ALL"/> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="executeFeasibilityMpcMultiShareMessage"/> + </extension> + <extension url="task-profile"> + <valueCanonical + value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-multi-share|#{version}"/> + </extension> + <extension url="requester"> + <valueCoding> + <extension + url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier"/> + <value value="highmed.org"/> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization"/> + <code value="LOCAL_ROLE"/> + </valueCoding> + </extension> + <extension url="requester"> + <valueCoding> + <extension + url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier"/> + <value value="highmed.org"/> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization"/> + <code value="REMOTE_ROLE"/> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension + url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier"/> + <value value="highmed.org"/> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization"/> + <code value="LOCAL_ROLE"/> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="resultShareSingleMedicFeasibilityMpcMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-single-medic-result-share-feasibility-mpc|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/executeFeasibilityMpcMultiShare"/> + <!-- version managed by bpe --> + <version value="#{version}"/> + <name value="ExecuteFeasibilityMpcMultiShare"/> + <title value="Execute Feasibility Mpc Multi Share"/> + <subtitle value="Feasibility Mpc Multi Share Execution Process"/> + <!-- status managed by bpe --> + <status value="unknown"/> + <experimental value="false"/> + <!-- date managed by bpe --> + <date value="#{date}"/> + <publisher value="HiGHmed"/> + <contact> + <name value="HiGHmed"/> + <telecom> + <system value="email"/> + <value value="pmo@highmed.org"/> + </telecom> + </contact> + <description value="Process receives single medic result shares from each MeDIC, process calculates multi medic result share and sends it to coordinating MeDIC"/> + <kind value="Task"/> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcSingleShare.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcSingleShare.xml new file mode 100644 index 00000000..11f11dd4 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcSingleShare.xml @@ -0,0 +1,101 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag"/> + <code value="ALL"/> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="executeFeasibilityMpcSingleShareMessage"/> + </extension> + <extension url="task-profile"> + <valueCanonical + value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-single-share|#{version}"/> + </extension> + <extension url="requester"> + <valueCoding> + <extension + url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier"/> + <value value="highmed.org"/> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization"/> + <code value="LOCAL_ROLE"/> + </valueCoding> + </extension> + <extension url="requester"> + <valueCoding> + <extension + url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier"/> + <value value="highmed.org"/> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization"/> + <code value="REMOTE_ROLE"/> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension + url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier"/> + <value value="highmed.org"/> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization"/> + <code value="LOCAL_ROLE"/> + </valueCoding> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/executeFeasibilityMpcSingleShare"/> + <!-- version managed by bpe --> + <version value="#{version}"/> + <name value="ExecuteFeasibilityMpcSingleShare"/> + <title value="Execute Feasibility Mpc Single Share"/> + <subtitle value="Feasibility Mpc Single Share Execution Process"/> + <!-- status managed by bpe --> + <status value="unknown"/> + <experimental value="false"/> + <!-- date managed by bpe --> + <date value="#{date}"/> + <publisher value="HiGHmed"/> + <contact> + <name value="HiGHmed"/> + <telecom> + <system value="email"/> + <value value="pmo@highmed.org"/> + </telecom> + </contact> + <description value="Process executes feasibility query and sends single medic result shares to each MeDIC"/> + <kind value="Task"/> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibilityMpc.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibilityMpc.xml new file mode 100644 index 00000000..c7902926 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibilityMpc.xml @@ -0,0 +1,145 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="requestFeasibilityMpcMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-request-feasibility-mpc|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="resultShareMultiMedicFeasibilityMpcMessage" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-share-feasibility-mpc|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + <extension url="requester"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="REMOTE_ROLE" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization-consortium-role"> + <extension url="consortium"> + <valueIdentifier> + <system value="http://highmed.org/sid/organization-identifier" /> + <value value="highmed.org" /> + </valueIdentifier> + </extension> + <extension url="role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ROLE" /> + </valueCoding> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/requestFeasibilityMpc" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="RequestFeasibilityMpc" /> + <title value="Request Feasibility Mpc" /> + <subtitle value="Feasibility Mpc Request Process" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process starts feasibility execution using MPC at each MeDIC, process receives multi medic result shares from each MeDIC" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-multi-share.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-multi-share.xml new file mode 100644 index 00000000..8854d559 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-multi-share.xml @@ -0,0 +1,104 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-multi-share" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskExecuteFeasibilityMpcMultiShare" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/executeFeasibilityMpcMultiShare/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="3" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="executeFeasibilityMpcMultiShareMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:medic-correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="medic-correlation-key" /> + <min value="1" /> + </element> + <element id="Task.input:medic-correlation-key.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:medic-correlation-key.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:medic-correlation-key.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:medic-correlation-key.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="medic-correlation-key" /> + </element> + <element id="Task.input:medic-correlation-key.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="string" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-single-share.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-single-share.xml new file mode 100644 index 00000000..8a844a20 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility-mpc-single-share.xml @@ -0,0 +1,146 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility-mpc-single-share" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskExecuteFeasibilityMpcSingleShare" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/executeFeasibilityMpcSingleShare/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="5" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="executeFeasibilityMpcSingleShareMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="research-study" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:research-study.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:research-study.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="research-study-reference" /> + </element> + <element id="Task.input:research-study.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/research-study" /> + </type> + </element> + <element id="Task.input:needs-consent-check"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-consent-check" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-consent-check.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-consent-check" /> + </element> + <element id="Task.input:needs-consent-check.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-share-feasibility-mpc.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-share-feasibility-mpc.xml new file mode 100644 index 00000000..cfdd63db --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-share-feasibility-mpc.xml @@ -0,0 +1,124 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-share-feasibility-mpc" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskMultiMedicResultFeasibilityMpc" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/requestFeasibilityMpc/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="4" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="resultShareMultiMedicFeasibilityMpcMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:multi-medic-result-share"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="multi-medic-result-share" /> + <min value="1" /> + <max value="*" /> + </element> + <element id="Task.input:multi-medic-result-share.extension"> + <path value="Task.input.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.input:multi-medic-result-share.extension:group-id"> + <path value="Task.input.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.input:multi-medic-result-share.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:multi-medic-result-share.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:multi-medic-result-share.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:multi-medic-result-share.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="multi-medic-result-share" /> + </element> + <element id="Task.input:multi-medic-result-share.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="unsignedInt" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility-mpc.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility-mpc.xml new file mode 100644 index 00000000..141433a2 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility-mpc.xml @@ -0,0 +1,310 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-request-feasibility-mpc" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskRequestFeasibilityMpc" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/requestFeasibilityMpc/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="4" /> + <max value="4" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="requestFeasibilityMpcMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <max value="0" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:research-study-reference"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="research-study-reference" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study-reference.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:research-study-reference.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:research-study-reference.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:research-study-reference.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="research-study-reference" /> + </element> + <element id="Task.input:research-study-reference.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/research-study" /> + </type> + </element> + <element id="Task.input:research-study-reference.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="1" /> + </element> + <element id="Task.input:research-study-reference.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <max value="0" /> + </element> + <element id="Task.input:consortium-identifier"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="consortium-identifier" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:consortium-identifier.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:consortium-identifier.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:consortium-identifier.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:consortium-identifier.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="consortium-identifier" /> + </element> + <element id="Task.input:consortium-identifier.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/organization" /> + </type> + </element> + <element id="Task.input:consortium-identifier.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <max value="0" /> + </element> + <element id="Task.input:consortium-identifier.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <min value="1" /> + </element> + <element id="Task.input:needs-consent-check"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="needs-consent-check" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:needs-consent-check.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:needs-consent-check.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="needs-consent-check" /> + </element> + <element id="Task.input:needs-consent-check.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="boolean" /> + </type> + </element> + <element id="Task.output:participating-medics"> + <path value="Task.output" /> + <sliceName value="participating-medics" /> + </element> + <element id="Task.output:participating-medics.extension"> + <path value="Task.output.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.output:participating-medics.extension:group-id"> + <path value="Task.output.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.output:participating-medics.type"> + <path value="Task.output.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskOutputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.output:participating-medics.type.coding"> + <path value="Task.output.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.output:participating-medics.type.coding.system"> + <path value="Task.output.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.output:participating-medics.type.coding.code"> + <path value="Task.output.type.coding.code" /> + <min value="1" /> + <fixedCode value="participating-medics" /> + </element> + <element id="Task.output:participating-medics.value[x]"> + <path value="Task.output.value[x]" /> + <type> + <code value="unsignedInt" /> + </type> + </element> + <element id="Task.output:multi-medic-count-result"> + <path value="Task.output" /> + <sliceName value="multi-medic-count-result" /> + </element> + <element id="Task.output:multi-medic-count-result.extension"> + <path value="Task.output.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.output:multi-medic-count-result.extension:group-id"> + <path value="Task.output.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.output:multi-medic-count-result.type"> + <path value="Task.output.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskOutputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.output:multi-medic-count-result.type.coding"> + <path value="Task.output.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.output:multi-medic-count-result.type.coding.system"> + <path value="Task.output.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.output:multi-medic-count-result.type.coding.code"> + <path value="Task.output.type.coding.code" /> + <min value="1" /> + <fixedCode value="multi-medic-count-result" /> + </element> + <element id="Task.output:multi-medic-count-result.value[x]"> + <path value="Task.output.value[x]" /> + <type> + <code value="unsignedInt" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-share-feasibility-mpc.xml b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-share-feasibility-mpc.xml new file mode 100644 index 00000000..481c1bbf --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-share-feasibility-mpc.xml @@ -0,0 +1,124 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-single-medic-result-share-feasibility-mpc" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskSingleMedicResultShareFeasibilityMpc" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/executeFeasibilityMpcMultiShare/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="4" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="resultShareSingleMedicFeasibilityMpcMessage" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:single-medic-result-share"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="single-medic-result-share" /> + <min value="1" /> + <max value="*" /> + </element> + <element id="Task.input:single-medic-result-share.extension"> + <path value="Task.input.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.input:single-medic-result-share.extension:group-id"> + <path value="Task.input.extension" /> + <sliceName value="group-id" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> + </type> + </element> + <element id="Task.input:single-medic-result-share.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:single-medic-result-share.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:single-medic-result-share.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:single-medic-result-share.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="single-medic-result-share" /> + </element> + <element id="Task.input:single-medic-result-share.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="unsignedInt" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/FeasibilityMpcProcessPluginDefinitionTest.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/FeasibilityMpcProcessPluginDefinitionTest.java new file mode 100644 index 00000000..e1e90228 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/FeasibilityMpcProcessPluginDefinitionTest.java @@ -0,0 +1,44 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.*; +import static org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class FeasibilityMpcProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition dataSharing = new DataSharingProcessPluginDefinition(); + ResourceProvider dataSharingProvider = dataSharing.getResourceProvider(FhirContext.forR4(), + getClass().getClassLoader(), new StandardEnvironment()); + assertNotNull(dataSharingProvider); + + ProcessPluginDefinition definition = new FeasibilityMpcProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var executeFeasibilityMpcMultiShare = provider.getResources( + PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE + "/" + VERSION, s -> dataSharingProvider); + assertNotNull(executeFeasibilityMpcMultiShare); + assertEquals(5, executeFeasibilityMpcMultiShare.count()); + + var executeFeasibilityMpcSingleShare = provider.getResources( + PROCESS_NAME_FULL_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE + "/" + VERSION, s -> dataSharingProvider); + assertNotNull(executeFeasibilityMpcSingleShare); + assertEquals(4, executeFeasibilityMpcSingleShare.count()); + + var requestFeasibilityMpc = provider.getResources(PROCESS_NAME_FULL_REQUEST_FEASIBILITY_MPC + "/" + VERSION, + s -> dataSharingProvider); + assertNotNull(requestFeasibilityMpc); + assertEquals(5, requestFeasibilityMpc.count()); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/mpc/ArithmeticSharingTest.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/mpc/ArithmeticSharingTest.java new file mode 100644 index 00000000..909c2f0f --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/mpc/ArithmeticSharingTest.java @@ -0,0 +1,150 @@ +package org.highmed.dsf.bpe.mpc; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.highmed.dsf.bpe.variable.QueryResult; +import org.junit.Test; + +public class ArithmeticSharingTest +{ + @Test(expected = IllegalStateException.class) + public void testMaxSecret() + { + int numParties = 3; + int secret = 1000000000; + int maxSecret = new ArithmeticSharing(numParties).getRingSize().divide(BigInteger.valueOf(numParties)) + .intValueExact(); + + if (secret > maxSecret) + { + throw new IllegalStateException("Secret to big for numParties"); + } + } + + @Test + public void arithmeticSharingValid() + { + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(3); + + ArithmeticShare[] singleMedicSharesOrg1 = arithmeticSharing.createShares(10); + ArithmeticShare[] singleMedicSharesOrg2 = arithmeticSharing.createShares(20); + ArithmeticShare[] singleMedicSharesOrg3 = arithmeticSharing.createShares(30); + + List<QueryResult> queryResultsSingleMedicSharesOrg1 = IntStream.range(0, arithmeticSharing.getNumParties()) + .mapToObj(i -> QueryResult.mpcCountResult("", "", singleMedicSharesOrg1[i].getValue().intValueExact())) + .collect(Collectors.toList()); + List<QueryResult> queryResultsSingleMedicSharesOrg2 = IntStream.range(0, arithmeticSharing.getNumParties()) + .mapToObj(i -> QueryResult.mpcCountResult("", "", singleMedicSharesOrg2[i].getValue().intValueExact())) + .collect(Collectors.toList()); + List<QueryResult> queryResultsSingleMedicSharesOrg3 = IntStream.range(0, arithmeticSharing.getNumParties()) + .mapToObj(i -> QueryResult.mpcCountResult("", "", singleMedicSharesOrg3[i].getValue().intValueExact())) + .collect(Collectors.toList()); + + ArithmeticShare[] reconstructedSingleMedicSharesOrg1 = queryResultsSingleMedicSharesOrg1.stream() + .map(QueryResult::getCohortSize).map(ArithmeticShare::new).toArray(ArithmeticShare[]::new); + ArithmeticShare[] reconstructedSingleMedicSharesOrg2 = queryResultsSingleMedicSharesOrg2.stream() + .map(QueryResult::getCohortSize).map(ArithmeticShare::new).toArray(ArithmeticShare[]::new); + ArithmeticShare[] reconstructedSingleMedicSharesOrg3 = queryResultsSingleMedicSharesOrg3.stream() + .map(QueryResult::getCohortSize).map(ArithmeticShare::new).toArray(ArithmeticShare[]::new); + + int multiMedicShareOrg1 = arithmeticSharing + .reconstructSecretToInt(new ArithmeticShare[] { reconstructedSingleMedicSharesOrg1[0], + reconstructedSingleMedicSharesOrg2[1], reconstructedSingleMedicSharesOrg3[2] }); + int multiMedicShareOrg2 = arithmeticSharing + .reconstructSecretToInt(new ArithmeticShare[] { reconstructedSingleMedicSharesOrg1[1], + reconstructedSingleMedicSharesOrg2[2], reconstructedSingleMedicSharesOrg3[0] }); + int multiMedicShareOrg3 = arithmeticSharing + .reconstructSecretToInt(new ArithmeticShare[] { reconstructedSingleMedicSharesOrg1[2], + reconstructedSingleMedicSharesOrg2[0], reconstructedSingleMedicSharesOrg3[1] }); + + long total = arithmeticSharing + .reconstructSecretToInt(new ArithmeticShare[] { new ArithmeticShare(multiMedicShareOrg1), + new ArithmeticShare(multiMedicShareOrg2), new ArithmeticShare(multiMedicShareOrg3) }); + + assertEquals(60, total); + } + + @Test + public void fiftyPartiesAndSecrets() + { + SecureRandom randomGenerator = new SecureRandom(); + + int numParties = 50; + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(numParties); + + int maxSecret = arithmeticSharing.getRingSize().divide(BigInteger.valueOf(numParties)).intValueExact(); + + int[] secrets = new int[numParties]; + List<ArithmeticShare[]> shares = new ArrayList<>(); + + for (int i = 0; i < numParties; i++) + { + secrets[i] = randomGenerator.nextInt(maxSecret); + ArithmeticShare[] sharesI = arithmeticSharing.createShares(secrets[i]); + + shares.add(sharesI); + } + + for (int i = 0; i < numParties; i++) + { + assertEquals(secrets[i], arithmeticSharing.reconstructSecretToInt(shares.get(i))); + } + } + + @Test + public void homomorphicAddition() + { + SecureRandom randomGenerator = new SecureRandom(); + + int numParties = 5; + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(numParties); + + int maxSecret = arithmeticSharing.getRingSize().divide(BigInteger.valueOf(numParties)).intValueExact(); + + int[] secrets = new int[numParties]; + for (int i = 0; i < numParties; i++) + { + secrets[i] = randomGenerator.nextInt(maxSecret); + } + + ArithmeticShare[] shares1 = arithmeticSharing.createShares(secrets[0]); + ArithmeticShare[] shares2 = arithmeticSharing.createShares(secrets[1]); + ArithmeticShare[] shares3 = arithmeticSharing.createShares(secrets[2]); + ArithmeticShare[] shares4 = arithmeticSharing.createShares(secrets[3]); + ArithmeticShare[] shares5 = arithmeticSharing.createShares(secrets[4]); + + List<Integer> sumShares = new ArrayList<>(); + for (int i = 0; i < numParties; i++) + { + sumShares.add(arithmeticSharing.reconstructSecretToInt( + new ArithmeticShare[] { shares1[i], shares2[i], shares3[i], shares4[i], shares5[i] })); + } + + int reconstructedResult = arithmeticSharing + .reconstructSecretToInt(sumShares.stream().map(ArithmeticShare::new).toArray(ArithmeticShare[]::new)); + + int cleartextResult = Arrays.stream(secrets).sum(); + + assertEquals(reconstructedResult, cleartextResult); + } + + @Test + public void manyManyParties() + { + int secret = Integer.MAX_VALUE - 1; + ArithmeticSharing arithmeticSharing = new ArithmeticSharing(54321); + + ArithmeticShare[] shares = arithmeticSharing.createShares(secret); + int reconstructed = arithmeticSharing.reconstructSecretToInt(shares); + + assertEquals(secret, reconstructed); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter.java new file mode 100644 index 00000000..43892db2 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter.java @@ -0,0 +1,177 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.CODE_TYPE_AQL_QUERY; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.PROFILE_HIGHEMD_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsBase.PROFILE_HIGHMED_GROUP; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_PARTICIPATING_TTP; +import static org.highmed.dsf.bpe.ConstantsDataSharing.EXTENSION_HIGHMED_QUERY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_CONSORTIUM_HIGHMED; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_2; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_3; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; + +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelperImpl; +import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleType; +import org.hl7.fhir.r4.model.Bundle.HTTPVerb; +import org.hl7.fhir.r4.model.Expression; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.Group.GroupType; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Narrative; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.ResearchStudy.ResearchStudyStatus; +import org.hl7.fhir.r4.model.ResourceType; +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; + +public abstract class AbstractRequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter +{ + private final boolean needsConsentCheck = true; + + private final String query = "SELECT COUNT(e) FROM EHR e"; + + private final String[] medicIdentifier = new String[] { NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1, + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_2, + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_3 }; + private final String ttpIdentifier = NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; + + private final ReadAccessHelper readAccessHelper = new ReadAccessHelperImpl(); + + protected void main(String[] args, String baseUrl) throws Exception + { + Bundle bundle = createStartResource(); + ExampleStarter.forServer(args, baseUrl).startWith(bundle); + } + + private Bundle createStartResource() + { + Group group1 = createGroup("Group 1"); + Group group2 = createGroup("Group 2"); + ResearchStudy researchStudy = createResearchStudy(group1, group2); + Task task = createTask(researchStudy); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setResource(group1).setFullUrl(group1.getIdElement().getIdPart()).getRequest() + .setMethod(HTTPVerb.POST).setUrl(ResourceType.Group.name()); + bundle.addEntry().setResource(group2).setFullUrl(group2.getIdElement().getIdPart()).getRequest() + .setMethod(HTTPVerb.POST).setUrl(ResourceType.Group.name()); + bundle.addEntry().setResource(researchStudy).setFullUrl(researchStudy.getIdElement().getIdPart()).getRequest() + .setMethod(HTTPVerb.POST).setUrl(ResourceType.ResearchStudy.name()); + bundle.addEntry().setResource(task).setFullUrl(task.getIdElement().getIdPart()).getRequest() + .setMethod(HTTPVerb.POST).setUrl(ResourceType.Task.name()); + + return bundle; + } + + private Group createGroup(String name) + { + Group group = new Group(); + group.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + + group.getMeta().addProfile(PROFILE_HIGHMED_GROUP); + group.getText().getDiv().addText("This is the description"); + group.getText().setStatus(Narrative.NarrativeStatus.ADDITIONAL); + group.setType(GroupType.PERSON); + group.setActual(false); + group.setActive(true); + group.addExtension().setUrl(EXTENSION_HIGHMED_QUERY) + .setValue(new Expression().setLanguageElement(CODE_TYPE_AQL_QUERY).setExpression(query)); + group.setName(name); + + Arrays.stream(medicIdentifier).forEach(i -> readAccessHelper.addOrganization(group, i)); + readAccessHelper.addOrganization(group, ttpIdentifier); + + return group; + } + + private ResearchStudy createResearchStudy(Group group1, Group group2) + { + ResearchStudy researchStudy = new ResearchStudy(); + researchStudy.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + + researchStudy.getMeta().addProfile(PROFILE_HIGHEMD_RESEARCH_STUDY); + researchStudy.addIdentifier().setSystem(NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER) + .setValue(UUID.randomUUID().toString()); + researchStudy.setStatus(ResearchStudyStatus.ACTIVE); + researchStudy.addEnrollment().setReference(group1.getIdElement().getIdPart()); + researchStudy.addEnrollment().setReference(group2.getIdElement().getIdPart()); + + Arrays.stream(medicIdentifier) + .forEach(i -> researchStudy.addExtension().setUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC) + .setValue(new Reference().setType(ResourceType.Organization.name()).setIdentifier( + new Identifier().setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(i)))); + + Arrays.stream(medicIdentifier).forEach(i -> readAccessHelper.addOrganization(researchStudy, i)); + readAccessHelper.addOrganization(researchStudy, ttpIdentifier); + + // TODO: remove tpp from research study profile + researchStudy.addExtension().setUrl(EXTENSION_HIGHMED_PARTICIPATING_TTP) + .setValue(new Reference().setType(ResourceType.Organization.name()).setIdentifier(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue(ttpIdentifier))); + + return researchStudy; + } + + private Task createTask(ResearchStudy researchStudy) + { + Task task = new Task(); + task.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_AND_LATEST_VERSION); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput() + .setValue(new Reference().setReference(researchStudy.getIdElement().getIdPart()) + .setType(ResourceType.ResearchStudy.name())) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput() + .setValue(new Reference() + .setIdentifier(new Identifier().setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_CONSORTIUM_HIGHMED)) + .setType(ResourceType.Organization.name())) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER); + task.addInput().setValue(new BooleanType(needsConsentCheck)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + + return task; + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/RequestFeasibilityMpcFromMedicsViaMedic1DockerExampleStarter.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/RequestFeasibilityMpcFromMedicsViaMedic1DockerExampleStarter.java new file mode 100644 index 00000000..73700c5a --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/RequestFeasibilityMpcFromMedicsViaMedic1DockerExampleStarter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.MEDIC_1_DOCKER_FHIR_BASE_URL; + +public class RequestFeasibilityMpcFromMedicsViaMedic1DockerExampleStarter + extends AbstractRequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new RequestFeasibilityMpcFromMedicsViaMedic1DockerExampleStarter().main(args, MEDIC_1_DOCKER_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/RequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/RequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter.java new file mode 100644 index 00000000..14c68f2b --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/start/RequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.MEDIC_1_FHIR_BASE_URL; + +public class RequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter + extends AbstractRequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new RequestFeasibilityMpcFromMedicsViaMedic1ExampleStarter().main(args, MEDIC_1_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsSerializationTest.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsSerializationTest.java new file mode 100644 index 00000000..8a3b55b0 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/variables/FinalFeasibilityMpcQueryResultsSerializationTest.java @@ -0,0 +1,67 @@ +package org.highmed.dsf.bpe.variables; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; + +import org.highmed.dsf.fhir.json.ObjectMapperFactory; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +public class FinalFeasibilityMpcQueryResultsSerializationTest +{ + private static final Logger logger = LoggerFactory + .getLogger(FinalFeasibilityMpcQueryResultsSerializationTest.class); + + @Test + public void testEmptyFinalFeasibilityMpcQueryResultsSerialization() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + FinalFeasibilityMpcQueryResults results = new FinalFeasibilityMpcQueryResults(Collections.emptyList()); + + String resultsAsString = mapper.writeValueAsString(results); + assertNotNull(resultsAsString); + + logger.debug("FinalFeasibilityMpcQueryResults (empty): '{}'", resultsAsString); + + FinalFeasibilityMpcQueryResults readResults = mapper.readValue(resultsAsString, + FinalFeasibilityMpcQueryResults.class); + assertNotNull(readResults); + assertNotNull(readResults.getResults()); + assertTrue(readResults.getResults().isEmpty()); + } + + @Test + public void testNonEmptyFinalFeasibilityMpcQueryResultsSerialization() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + FinalFeasibilityMpcQueryResult result = new FinalFeasibilityMpcQueryResult("cohortId", 1, 2); + FinalFeasibilityMpcQueryResults results = new FinalFeasibilityMpcQueryResults(Collections.singleton(result)); + + String resultsAsString = mapper.writeValueAsString(results); + assertNotNull(resultsAsString); + + logger.debug("FinalFeasibilityMpcQueryResults (non empty): '{}'", resultsAsString); + + FinalFeasibilityMpcQueryResults readResults = mapper.readValue(resultsAsString, + FinalFeasibilityMpcQueryResults.class); + assertNotNull(readResults); + assertNotNull(readResults.getResults()); + assertFalse(readResults.getResults().isEmpty()); + assertEquals(1, readResults.getResults().size()); + assertNotNull(readResults.getResults().get(0)); + assertEquals(result.getCohortId(), readResults.getResults().get(0).getCohortId()); + assertEquals(result.getCohortSize(), readResults.getResults().get(0).getCohortSize()); + assertEquals(result.getParticipatingMedics(), readResults.getResults().get(0).getParticipatingMedics()); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/variables/TargetsSerializationTest.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/variables/TargetsSerializationTest.java new file mode 100644 index 00000000..36c94b9a --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/bpe/variables/TargetsSerializationTest.java @@ -0,0 +1,46 @@ +package org.highmed.dsf.bpe.variables; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; + +import org.highmed.dsf.fhir.json.ObjectMapperFactory; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +public class TargetsSerializationTest +{ + private static final Logger logger = LoggerFactory.getLogger(TargetsSerializationTest.class); + + @Test + public void serializeDeserializeTargets() throws Exception + { + ObjectMapper objectMapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + Target target = Target.createUniDirectionalTarget("target.org", "endpoint.target.org", + "https://endpoint.target.org/fhir"); + Targets targets = new Targets(List.of(target)); + + String serialized = objectMapper.writeValueAsString(targets); + + logger.debug("Targets: '{}'", serialized); + + Targets deserialized = objectMapper.readValue(serialized, Targets.class); + + assertNotNull(deserialized); + assertEquals(1, deserialized.getEntries().size()); + assertNotNull(deserialized.getEntries().get(0)); + assertEquals(deserialized.getEntries().get(0).getOrganizationIdentifierValue(), + target.getOrganizationIdentifierValue()); + assertEquals(deserialized.getEntries().get(0).getEndpointUrl(), target.getEndpointUrl()); + assertEquals(deserialized.getEntries().get(0).getCorrelationKey(), target.getCorrelationKey()); + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java new file mode 100644 index 00000000..d0f241f2 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java @@ -0,0 +1,96 @@ +package org.highmed.dsf.fhir.profile; + +import static org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition.RELEASE_DATE; +import static org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.nio.file.Paths; +import java.util.Arrays; + +import org.highmed.dsf.fhir.authorization.process.ProcessAuthorizationHelper; +import org.highmed.dsf.fhir.authorization.process.ProcessAuthorizationHelperImpl; +import org.highmed.dsf.fhir.validation.ResourceValidator; +import org.highmed.dsf.fhir.validation.ResourceValidatorImpl; +import org.highmed.dsf.fhir.validation.ValidationSupportRule; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.validation.ResultSeverityEnum; +import ca.uhn.fhir.validation.ValidationResult; + +public class ActivityDefinitionProfileTest +{ + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); + + @ClassRule + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, + Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", + "highmed-extension-process-authorization-consortium-role-0.5.0.xml", + "highmed-extension-process-authorization-organization-0.5.0.xml", + "highmed-coding-process-authorization-local-all-0.5.0.xml", + "highmed-coding-process-authorization-local-consortium-role-0.5.0.xml", + "highmed-coding-process-authorization-local-organization-0.5.0.xml", + "highmed-coding-process-authorization-remote-all-0.5.0.xml", + "highmed-coding-process-authorization-remote-consortium-role-0.5.0.xml", + "highmed-coding-process-authorization-remote-organization-0.5.0.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-process-authorization-0.5.0.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-process-authorization-recipient-0.5.0.xml", + "highmed-process-authorization-requester-0.5.0.xml")); + + private final ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), + validationRule.getValidationSupport()); + + private final ProcessAuthorizationHelper processAuthorizationHelper = new ProcessAuthorizationHelperImpl(); + + @Test + public void testExecuteFeasibilityMpcMultiShareValid() throws Exception + { + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcMultiShare.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); + } + + @Test + public void testExecuteFeasibilityMpcSingleShareValid() throws Exception + { + + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibilityMpcSingleShare.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); + + } + + @Test + public void testRequestFeasibilityMpcValid() throws Exception + { + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibilityMpc.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); + + } +} \ No newline at end of file diff --git a/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java new file mode 100644 index 00000000..b415f142 --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java @@ -0,0 +1,348 @@ +package org.highmed.dsf.fhir.profile; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC; +import static org.highmed.dsf.bpe.ConstantsFeasibilityMpc.PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_MESSAGE_NAME; +import static org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition.RELEASE_DATE; +import static org.highmed.dsf.bpe.FeasibilityMpcProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Date; +import java.util.UUID; + +import org.highmed.dsf.fhir.validation.ResourceValidator; +import org.highmed.dsf.fhir.validation.ResourceValidatorImpl; +import org.highmed.dsf.fhir.validation.ValidationSupportRule; +import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResourceType; +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.TaskIntent; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; +import org.hl7.fhir.r4.model.Task.TaskStatus; +import org.hl7.fhir.r4.model.UnsignedIntType; +import org.junit.ClassRule; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.validation.ResultSeverityEnum; +import ca.uhn.fhir.validation.ValidationResult; + +public class TaskProfileTest +{ + private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); + + @ClassRule + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, + Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-group-0.5.0.xml", + "highmed-extension-group-id-0.5.0.xml", "highmed-research-study-0.5.0.xml", + "highmed-task-request-feasibility-mpc.xml", "highmed-task-execute-feasibility-mpc-multi-share.xml", + "highmed-task-execute-feasibility-mpc-single-share.xml", + "highmed-task-single-medic-result-share-feasibility-mpc.xml", + "highmed-task-multi-medic-result-share-feasibility-mpc.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", + "highmed-data-sharing.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", + "highmed-data-sharing.xml")); + + private ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), + validationRule.getValidationSupport()); + + @Test + public void testTaskRequestFeasibilityMpcValid() throws Exception + { + Task task = createValidTaskRequestFeasibilityMpc(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskRequestFeasibilityMpcValidWithOutput() throws Exception + { + String groupId1 = "Group/" + UUID.randomUUID().toString(); + String groupId2 = "Group/" + UUID.randomUUID().toString(); + + Task task = createValidTaskRequestFeasibilityMpc(); + + TaskOutputComponent outParticipatingMedics1 = task.addOutput(); + outParticipatingMedics1.setValue(new UnsignedIntType(5)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS); + outParticipatingMedics1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); + TaskOutputComponent outMultiMedicResult1 = task.addOutput(); + outMultiMedicResult1.setValue(new UnsignedIntType(25)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); + outMultiMedicResult1.addExtension("http://highmed.org/fhir/StructureDefinition/extension-group-id", + new Reference(groupId1)); + + TaskOutputComponent outParticipatingMedics2 = task.addOutput(); + outParticipatingMedics2.setValue(new UnsignedIntType(5)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS); + outParticipatingMedics2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + TaskOutputComponent outMultiMedicResult2 = task.addOutput(); + outMultiMedicResult2.setValue(new UnsignedIntType(25)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); + outMultiMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskRequestFeasibilityMpc() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new Reference("ResearchStudy/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput() + .setValue(new Reference().setIdentifier(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Consortium"))) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + + return task; + } + + @Test + public void testTaskExecuteFeasibilityMpcMultiShareValid() throws Exception + { + Task task = createValidTaskExecuteFeasibilityMpcMultiShare(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskExecuteFeasibilityMpcMultiShare() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE); + task.setInstantiatesUri( + PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 2"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_MESSAGE_NAME)) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); + + return task; + } + + @Test + public void testTaskExecuteFeasibilityMpcSingleShareValid() throws Exception + { + Task task = createValidTaskExecuteFeasibilityMpcSingleShare(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskExecuteFeasibilityMpcSingleShare() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE); + task.setInstantiatesUri( + PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 2"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_SINGLE_SHARE_MESSAGE_NAME)) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + + task.addInput().setValue(new Reference("ResearchStudy/" + UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + + return task; + } + + @Test + public void testTaskSingleMedicResultShareFeasibilityMpc() throws Exception + { + Task task = createValidTaskSingleMedicResultShareFeasibilityMpc(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskSingleMedicResultShareFeasibilityMpc() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC); + task.setInstantiatesUri( + PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MPC_MULTI_SHARE_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 2"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + + task.addInput() + .setValue(new StringType(PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_MESSAGE_NAME)) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + + String groupId1 = "Group/" + UUID.randomUUID().toString(); + String groupId2 = "Group/" + UUID.randomUUID().toString(); + + ParameterComponent inSingleMedicResult1 = task.addInput(); + inSingleMedicResult1.setValue(new UnsignedIntType(5)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE); + inSingleMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); + ParameterComponent inSingleMedicResult2 = task.addInput(); + inSingleMedicResult2.setValue(new UnsignedIntType(10)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SHARE); + inSingleMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + + return task; + } + + @Test + public void testTaskMultiMedicResultShareFeasibilityMpc() throws Exception + { + Task task = createValidTaskMultiMedicResultShareFeasibilityMpc(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskMultiMedicResultShareFeasibilityMpc() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MPC_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 2"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("MeDIC 1"); + + task.addInput() + .setValue(new StringType(PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_SHARE_FEASIBILITY_MPC_MESSAGE_NAME)) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + + String groupId1 = "Group/" + UUID.randomUUID().toString(); + String groupId2 = "Group/" + UUID.randomUUID().toString(); + + ParameterComponent inSingleMedicResult1 = task.addInput(); + inSingleMedicResult1.setValue(new UnsignedIntType(15)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE); + inSingleMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); + ParameterComponent inSingleMedicResult2 = task.addInput(); + inSingleMedicResult2.setValue(new UnsignedIntType(25)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_RESULT_SHARE); + inSingleMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); + + return task; + } +} diff --git a/dsf-bpe-process-feasibility-mpc/src/test/resources/log4j2.xml b/dsf-bpe-process-feasibility-mpc/src/test/resources/log4j2.xml new file mode 100644 index 00000000..f1afe81d --- /dev/null +++ b/dsf-bpe-process-feasibility-mpc/src/test/resources/log4j2.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration status="INFO" monitorInterval="30" + verbose="false"> + + <Appenders> + <Console name="CONSOLE" target="SYSTEM_OUT"> + <PatternLayout pattern="%p\t%t - %C{1}.%M(%L) | %m%n"/> + </Console> + <!-- <RollingFile name="FILE" fileName="log/adt_db.log" + filePattern="log/adt_db_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy /> + <TimeBasedTriggeringPolicy /> + </Policies> + </RollingFile> --> + + <!-- <SMTP name="MAIL" subject="Production RWH LAB Gateway Error" + to="hauke.hund@med.uni-heidelberg.de, thomas.hilbel@med.uni-heidelberg.de" + from="med3-kvm15@med.uni-heidelberg.de" + replyTo="hauke.hund@med.uni-heidelberg.de" smtpHost="localhost" + smtpPort="25" bufferSize="50"> + </SMTP> + <SMTP name="MAIL_CERTIFICATE" subject="Production RWH LAB Gateway Certificate Warning" + to="hauke.hund@med.uni-heidelberg.de, thomas.hilbel@med.uni-heidelberg.de" + from="med3-kvm15@med.uni-heidelberg.de" + replyTo="hauke.hund@med.uni-heidelberg.de" smtpHost="localhost" + smtpPort="25" bufferSize="1"> + <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/> + </SMTP> + <SMTP name="MAIL_HL7" subject="Production RWH ADT Gateway HL7 Warning" + to="hauke.hund@med.uni-heidelberg.de, thomas.hilbel@med.uni-heidelberg.de" + from="med3-kvm15@med.uni-heidelberg.de" + replyTo="hauke.hund@med.uni-heidelberg.de" smtpHost="localhost" + smtpPort="25" bufferSize="1"> + <ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/> + </SMTP> --> + </Appenders> + + <Loggers> + <Logger name="de.rwh" level="TRACE"/> + <Logger name="org.highmed" level="TRACE"/> + <Logger name="org.apache" level="WARN"/> + <Logger name="org.springframework" level="WARN"/> + <Logger name="jndi" level="WARN"/> + <Logger name="org.eclipse.jetty" level="INFO"/> + <Logger name="com.sun.jersey" level="WARN"/> + <Logger name="liquibase" level="WARN"/> + <Logger name="ca.uhn.hl7v2" level="WARN"/> + + <!-- <Logger name="certificate-warning-logger" level="INFO"> + <AppenderRef ref="MAIL_CERTIFICATE" /> + </Logger> + <Logger name="async-message-handler-warning-logger" level="INFO"> + <AppenderRef ref="MAIL_HL7" /> + </Logger> --> + + <Root level="WARN"> + <AppenderRef ref="CONSOLE"/> + <!-- <AppenderRef ref="FILE" /> --> + <!-- <AppenderRef ref="MAIL" /> --> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility/pom.xml b/dsf-bpe-process-feasibility/pom.xml index 7c54622c..8597bff8 100644 --- a/dsf-bpe-process-feasibility/pom.xml +++ b/dsf-bpe-process-feasibility/pom.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> -<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>dsf-bpe-process-feasibility</artifactId> @@ -8,7 +9,7 @@ <parent> <artifactId>dsf-bpe-highmed-processes-pom</artifactId> <groupId>org.highmed.dsf</groupId> - <version>0.5.0</version> + <version>0.6.0</version> </parent> <properties> @@ -22,6 +23,12 @@ <artifactId>dsf-bpe-process-base</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-data-sharing</artifactId> + <scope>provided</scope> + </dependency> + <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> @@ -45,7 +52,7 @@ <type>test-jar</type> </dependency> </dependencies> - + <profiles> <profile> <id>copy-to-highmed-dsf-process</id> diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibility.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibility.java index ebf11c54..8e993889 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibility.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/ConstantsFeasibility.java @@ -5,16 +5,16 @@ public interface ConstantsFeasibility { - String BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY = "researchStudy"; - String BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK = "needsConsentCheck"; - String BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE = "needsRecordLinkage"; - String BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG = "bloomFilterConfig"; - String BPMN_EXECUTION_VARIABLE_COHORTS = "cohorts"; - String BPMN_EXECUTION_VARIABLE_QUERIES = "queries"; - String BPMN_EXECUTION_VARIABLE_QUERY_RESULTS = "queryResults"; - String BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS = "finalQueryResults"; + String PROCESS_NAME_COMPUTE_FEASIBILITY = "computeFeasibility"; + String PROCESS_NAME_EXECUTE_FEASIBILITY = "executeFeasibility"; + String PROCESS_NAME_REQUEST_FEASIBILITY = "requestFeasibility"; - String BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_RESULT = "errorMultiMedicFeasibilityResult"; + String PROCESS_NAME_FULL_COMPUTE_FEASIBILITY = "highmedorg_" + PROCESS_NAME_COMPUTE_FEASIBILITY; + String PROCESS_NAME_FULL_EXECUTE_FEASIBILITY = "highmedorg_" + PROCESS_NAME_EXECUTE_FEASIBILITY; + String PROCESS_NAME_FULL_REQUEST_FEASIBILITY = "highmedorg_" + PROCESS_NAME_REQUEST_FEASIBILITY; + + + String BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_FEASIBILITY_RESULT = "errorMultiMedicFeasibilityResult"; // Must be 3 or larger, as otherwise it is possible to draw conclusions about the individual MeDICs // (if I already know the cohort size in my MeDIC) @@ -22,20 +22,11 @@ public interface ConstantsFeasibility int MIN_COHORT_DEFINITIONS = 1; String FEASIBILITY_QUERY_PREFIX = "SELECT COUNT"; - String CODESYSTEM_HIGHMED_FEASIBILITY = "http://highmed.org/fhir/CodeSystem/feasibility"; - 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 PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY = "http://highmed.org/fhir/StructureDefinition/task-request-feasibility"; - String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "requestFeasibility/"; + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY + "|" + + VERSION; + String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_REQUEST_FEASIBILITY + "/"; String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MESSAGE_NAME = "requestFeasibilityMessage"; @@ -43,23 +34,35 @@ public interface ConstantsFeasibility String PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "localServicesIntegration/"; String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY = "http://highmed.org/fhir/StructureDefinition/task-execute-feasibility"; - String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "executeFeasibility/"; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY + "|" + + VERSION; + String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_EXECUTE_FEASIBILITY + "/"; String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_EXECUTE_FEASIBILITY_MESSAGE_NAME = "executeFeasibilityMessage"; String PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY = "http://highmed.org/fhir/StructureDefinition/task-compute-feasibility"; - String PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "computeFeasibility/"; + String PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY + "|" + + VERSION; + String PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_COMPUTE_FEASIBILITY + "/"; String PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_MESSAGE_NAME = "computeFeasibilityMessage"; String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_FEASIBILITY = "http://highmed.org/fhir/StructureDefinition/task-single-medic-result-feasibility"; + String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_FEASIBILITY_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_FEASIBILITY + + "|" + VERSION; String PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_FEASIBILITY_MESSAGE_NAME = "resultSingleMedicFeasibilityMessage"; String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_FEASIBILITY = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-feasibility"; + String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_FEASIBILITY_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_FEASIBILITY + + "|" + VERSION; String PROFILE_HIGHMED_TASK_MULTI_MEDIC_RESULT_FEASIBILITY_MESSAGE_NAME = "resultMultiMedicFeasibilityMessage"; String PROFILE_HIGHMED_TASK_ERROR_FEASIBILITY = "http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-feasibility"; + String PROFILE_HIGHMED_TASK_ERROR_FEASIBILITY_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_ERROR_FEASIBILITY + "|" + + VERSION; String PROFILE_HIGHMED_TASK_ERROR_FEASIBILITY_MESSAGE_NAME = "errorMultiMedicFeasibilityMessage"; } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinition.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinition.java index 8bd27bbe..38edeafc 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinition.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinition.java @@ -1,10 +1,16 @@ package org.highmed.dsf.bpe; +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROCESS_NAME_FULL_COMPUTE_FEASIBILITY; +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROCESS_NAME_FULL_EXECUTE_FEASIBILITY; +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROCESS_NAME_FULL_REQUEST_FEASIBILITY; + +import java.time.LocalDate; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Stream; +import org.highmed.dsf.bpe.spring.config.DataSharingSerializerConfig; import org.highmed.dsf.bpe.spring.config.FeasibilityConfig; import org.highmed.dsf.bpe.spring.config.FeasibilitySerializerConfig; import org.highmed.dsf.fhir.resources.AbstractResource; @@ -19,7 +25,11 @@ public class FeasibilityProcessPluginDefinition implements ProcessPluginDefinition { - public static final String VERSION = "0.5.0"; + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); + + private static final String DEPENDENCY_DATA_SHARING_VERSION = "0.6.0"; + private static final String DEPENDENCY_DATA_SHARING_NAME_AND_VERSION = "dsf-bpe-process-data-sharing-0.6.0"; @Override public String getName() @@ -33,6 +43,12 @@ public String getVersion() return VERSION; } + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + @Override public Stream<String> getBpmnFiles() { @@ -42,36 +58,45 @@ public Stream<String> getBpmnFiles() @Override public Stream<Class<?>> getSpringConfigClasses() { - return Stream.of(FeasibilityConfig.class, FeasibilitySerializerConfig.class); + return Stream.of(FeasibilityConfig.class, FeasibilitySerializerConfig.class, DataSharingSerializerConfig.class); + } + + @Override + public List<String> getDependencyNamesAndVersions() + { + return Arrays.asList(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION); } @Override public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader classLoader, PropertyResolver resolver) { + var c = CodeSystemResource.dependency(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION, + "http://highmed.org/fhir/CodeSystem/data-sharing", DEPENDENCY_DATA_SHARING_VERSION); + var aCom = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-computeFeasibility.xml"); var aExe = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-executeFeasibility.xml"); var aReq = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-requestFeasibility.xml"); - var cF = CodeSystemResource.file("fhir/CodeSystem/highmed-feasibility.xml"); - - var sTCom = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-compute-feasibility.xml"); - var sTErr = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-error-feasibility.xml"); - var sTExe = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-execute-feasibility.xml"); - var sTResM = StructureDefinitionResource + var sCom = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-compute-feasibility.xml"); + var sErr = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-error-feasibility.xml"); + var sExe = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-execute-feasibility.xml"); + var sResM = StructureDefinitionResource .file("fhir/StructureDefinition/highmed-task-multi-medic-result-feasibility.xml"); - var sTReq = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-request-feasibility.xml"); - var sTResS = StructureDefinitionResource + var sReq = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-request-feasibility.xml"); + var sResS = StructureDefinitionResource .file("fhir/StructureDefinition/highmed-task-single-medic-result-feasibility.xml"); - var vF = ValueSetResource.file("fhir/ValueSet/highmed-feasibility.xml"); + var v = ValueSetResource.dependency(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION, + "http://highmed.org/fhir/ValueSet/data-sharing", DEPENDENCY_DATA_SHARING_VERSION); Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map.of( - "highmedorg_computeFeasibility/" + VERSION, Arrays.asList(aCom, cF, sTCom, sTResS, vF), - "highmedorg_executeFeasibility/" + VERSION, Arrays.asList(aExe, cF, sTExe, vF), - "highmedorg_requestFeasibility/" + VERSION, Arrays.asList(aReq, cF, sTReq, sTResM, sTErr, vF)); + PROCESS_NAME_FULL_COMPUTE_FEASIBILITY + "/" + VERSION, Arrays.asList(c, aCom, sCom, sResS, v), + PROCESS_NAME_FULL_EXECUTE_FEASIBILITY + "/" + VERSION, Arrays.asList(c, aExe, sExe, v), + PROCESS_NAME_FULL_REQUEST_FEASIBILITY + "/" + VERSION, Arrays.asList(c, aReq, sReq, sResM, sErr, v)); - return ResourceProvider.read(VERSION, () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), - classLoader, resolver, resourcesByProcessKeyAndVersion); + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java index 83c00837..9cd80ba0 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMedicRequest.java @@ -1,19 +1,19 @@ package org.highmed.dsf.bpe.message; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; import java.util.stream.Stream; import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.highmed.dsf.bpe.variables.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.OrganizationProvider; @@ -41,24 +41,24 @@ protected Stream<ParameterComponent> getAdditionalInputParameters(DelegateExecut IdType researchStudyId = new IdType( getFhirWebserviceClientProvider().getLocalBaseUrl() + "/" + researchStudy.getId()); - ParameterComponent inputResearchStudyReference = getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE, + ParameterComponent inputResearchStudyReference = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE, new Reference().setReference(researchStudyId.toVersionless().getValueAsString())); boolean needsConsentCheck = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK); - ParameterComponent inputNeedsConsentCheck = getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck); + ParameterComponent inputNeedsConsentCheck = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK, needsConsentCheck); boolean needsRecordLinkage = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); - ParameterComponent inputNeedsRecordLinkage = getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + ParameterComponent inputNeedsRecordLinkage = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); if (needsRecordLinkage) { BloomFilterConfig bloomFilterConfig = (BloomFilterConfig) execution .getVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG); - ParameterComponent inputBloomFilterConfig = getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG, bloomFilterConfig.toBytes()); + ParameterComponent inputBloomFilterConfig = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG, bloomFilterConfig.toBytes()); return Stream.of(inputResearchStudyReference, inputNeedsConsentCheck, inputNeedsRecordLinkage, inputBloomFilterConfig); diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java index ecba92d7..156b4878 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendMultiMedicResults.java @@ -3,10 +3,10 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS; import java.util.List; import java.util.stream.Stream; @@ -49,12 +49,12 @@ protected Stream<ParameterComponent> getAdditionalInputParameters(DelegateExecut private Stream<ParameterComponent> toInputs(FinalFeasibilityQueryResult result) { - ParameterComponent input1 = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT, result.getCohortSize()); + ParameterComponent input1 = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT, result.getCohortSize()); input1.addExtension(createCohortIdExtension(result.getCohortId())); - ParameterComponent input2 = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT, result.getParticipatingMedics()); + ParameterComponent input2 = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS, result.getParticipatingMedics()); input2.addExtension(createCohortIdExtension(result.getCohortId())); return Stream.of(input1, input2); diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java index ba5fb173..773f9989 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendSingleMedicResults.java @@ -1,16 +1,16 @@ package org.highmed.dsf.bpe.message; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; import java.util.stream.Stream; import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.OrganizationProvider; @@ -38,25 +38,23 @@ public SendSingleMedicResults(FhirWebserviceClientProvider clientProvider, TaskH @Override protected Stream<Task.ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); - - return results.getResults().stream().map(result -> toInput(result)); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + return results.getResults().stream().map(this::toInput); } - private Task.ParameterComponent toInput(FeasibilityQueryResult result) + private Task.ParameterComponent toInput(QueryResult result) { if (result.isCohortSizeResult()) { - ParameterComponent input = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT, result.getCohortSize()); + ParameterComponent input = getTaskHelper().createInputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT, result.getCohortSize()); input.addExtension(createCohortIdExtension(result.getCohortId())); return input; } else if (result.isIdResultSetUrlResult()) { - ParameterComponent input = getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE, + ParameterComponent input = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE, new Reference(result.getResultSetUrl())); input.addExtension(createCohortIdExtension(result.getCohortId())); return input; diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java index 1992ec01..c81697cc 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/message/SendTtpRequest.java @@ -1,10 +1,10 @@ package org.highmed.dsf.bpe.message; import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; import java.util.stream.Stream; @@ -33,13 +33,13 @@ protected Stream<Task.ParameterComponent> getAdditionalInputParameters(DelegateE Targets multiInstanceTargets = (Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS); Stream<Task.ParameterComponent> inputTargets = multiInstanceTargets.getEntries().stream() - .map(target -> getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY, + .map(target -> getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY, target.getCorrelationKey())); boolean needsRecordLinkage = (boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); - Task.ParameterComponent inputNeedsRecordLinkage = getTaskHelper().createInput(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + Task.ParameterComponent inputNeedsRecordLinkage = getTaskHelper().createInput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); return Stream.concat(inputTargets, Stream.of(inputNeedsRecordLinkage)); } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java index f5ae3c9a..54922abc 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CalculateMultiMedicResults.java @@ -1,7 +1,7 @@ package org.highmed.dsf.bpe.service; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import java.util.List; import java.util.Map; @@ -9,8 +9,8 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResult; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResults; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResultsValues; @@ -29,8 +29,8 @@ public CalculateMultiMedicResults(FhirWebserviceClientProvider clientProvider, T @Override protected void doExecute(DelegateExecution execution) throws Exception { - List<FeasibilityQueryResult> results = ((FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS)).getResults(); + List<QueryResult> results = ((QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS)) + .getResults(); List<FinalFeasibilityQueryResult> finalResults = calculateResults(results); @@ -38,15 +38,15 @@ protected void doExecute(DelegateExecution execution) throws Exception FinalFeasibilityQueryResultsValues.create(new FinalFeasibilityQueryResults(finalResults))); } - private List<FinalFeasibilityQueryResult> calculateResults(List<FeasibilityQueryResult> results) + private List<FinalFeasibilityQueryResult> calculateResults(List<QueryResult> results) { - Map<String, List<FeasibilityQueryResult>> byCohortId = results.stream() - .collect(Collectors.groupingBy(FeasibilityQueryResult::getCohortId)); + Map<String, List<QueryResult>> byCohortId = results.stream() + .collect(Collectors.groupingBy(QueryResult::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()))) + toInt(e.getValue().stream().mapToLong(QueryResult::getCohortSize).sum()))) .collect(Collectors.toList()); } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java index 1fe346a9..579a17b7 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java @@ -2,8 +2,8 @@ import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_COHORTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; import static org.highmed.dsf.bpe.ConstantsFeasibility.MIN_COHORT_DEFINITIONS; import static org.highmed.dsf.bpe.ConstantsFeasibility.MIN_PARTICIPATING_MEDICS; diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java index d8f9f83e..70112737 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckMultiMedicResults.java @@ -3,9 +3,9 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS; import java.util.List; import java.util.stream.Collectors; @@ -65,8 +65,8 @@ private FinalFeasibilityQueryResults readFinalFeasibilityQueryResultsFromCurrent { List<FinalFeasibilityQueryResult> results = task.getInput().stream() .filter(in -> in.hasType() && in.getType().hasCoding() - && CODESYSTEM_HIGHMED_FEASIBILITY.equals(in.getType().getCodingFirstRep().getSystem()) - && CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT + && CODESYSTEM_HIGHMED_DATA_SHARING.equals(in.getType().getCodingFirstRep().getSystem()) + && CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT .equals(in.getType().getCodingFirstRep().getCode())) .map(in -> toResult(task, in)).collect(Collectors.toList()); return new FinalFeasibilityQueryResults(results); @@ -83,8 +83,8 @@ private FinalFeasibilityQueryResult toResult(Task task, ParameterComponent in) private int getParticipatingMedicsCountByCohortId(Task task, String cohortId) { return task.getInput().stream().filter(in -> in.hasType() && in.getType().hasCoding() - && CODESYSTEM_HIGHMED_FEASIBILITY.equals(in.getType().getCodingFirstRep().getSystem()) - && CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT + && CODESYSTEM_HIGHMED_DATA_SHARING.equals(in.getType().getCodingFirstRep().getSystem()) + && CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS .equals(in.getType().getCodingFirstRep().getCode()) && cohortId.equals( ((Reference) in.getExtensionByUrl(EXTENSION_HIGHMED_GROUP_ID).getValue()).getReference())) @@ -105,13 +105,13 @@ private void addFinalFeasibilityQueryResultsToLeadingTask(FinalFeasibilityQueryR private void addResultOutput(FinalFeasibilityQueryResult result, Task toWrite) { - TaskOutputComponent output1 = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT, result.getCohortSize()); + TaskOutputComponent output1 = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT, result.getCohortSize()); output1.addExtension(createCohortIdExtension(result.getCohortId())); toWrite.addOutput(output1); - TaskOutputComponent output2 = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT, result.getParticipatingMedics()); + TaskOutputComponent output2 = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS, result.getParticipatingMedics()); output2.addExtension(createCohortIdExtension(result.getCohortId())); toWrite.addOutput(output2); } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java index e2ca8358..b5c0fa56 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java @@ -2,8 +2,8 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_COHORTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; import static org.highmed.dsf.bpe.ConstantsFeasibility.FEASIBILITY_QUERY_PREFIX; import java.util.HashMap; @@ -12,7 +12,6 @@ import java.util.Objects; import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.camunda.bpm.engine.delegate.JavaDelegate; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; @@ -25,7 +24,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -public class CheckQueries extends AbstractServiceDelegate implements InitializingBean, JavaDelegate +public class CheckQueries extends AbstractServiceDelegate implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(CheckQueries.class); diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java index 019f2ea8..cce17fd7 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckSingleMedicResults.java @@ -2,7 +2,7 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import java.util.ArrayList; import java.util.List; @@ -10,9 +10,9 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -33,24 +33,22 @@ public CheckSingleMedicResults(FhirWebserviceClientProvider clientProvider, Task @Override protected void doExecute(DelegateExecution execution) throws Exception { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); Task currentTask = getCurrentTaskFromExecutionVariables(); - List<FeasibilityQueryResult> filteredResults = filterErroneousResultsAndAddErrorsToCurrentTaskOutputs(results, + List<QueryResult> filteredResults = filterErroneousResultsAndAddErrorsToCurrentTaskOutputs(results, currentTask); // TODO: add percentage filter over results execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(filteredResults))); + QueryResultsValues.create(new QueryResults(filteredResults))); } - private List<FeasibilityQueryResult> filterErroneousResultsAndAddErrorsToCurrentTaskOutputs( - FeasibilityQueryResults results, Task task) + private List<QueryResult> filterErroneousResultsAndAddErrorsToCurrentTaskOutputs(QueryResults results, Task task) { - List<FeasibilityQueryResult> filteredResults = new ArrayList<>(); - for (FeasibilityQueryResult result : results.getResults()) + List<QueryResult> filteredResults = new ArrayList<>(); + for (QueryResult result : results.getResults()) { Optional<String> errorReason = testResultAndReturnErrorReason(result); if (errorReason.isPresent()) @@ -62,7 +60,7 @@ private List<FeasibilityQueryResult> filterErroneousResultsAndAddErrorsToCurrent return filteredResults; } - protected Optional<String> testResultAndReturnErrorReason(FeasibilityQueryResult result) + protected Optional<String> testResultAndReturnErrorReason(QueryResult result) { // TODO: implement check // cohort size > 0 diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckTtpComputedMultiMedicResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckTtpComputedMultiMedicResults.java index fc7f1501..f0f61c87 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckTtpComputedMultiMedicResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckTtpComputedMultiMedicResults.java @@ -4,8 +4,8 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_ERROR; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_FEASIBILITY_RESULT; import static org.highmed.dsf.bpe.ConstantsFeasibility.MIN_PARTICIPATING_MEDICS; import java.util.List; @@ -51,7 +51,7 @@ protected void doExecute(DelegateExecution execution) throws Exception resultsWithEnoughParticipatingMedics); if (!existsAtLeastOneResult) - throw new BpmnError(BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_RESULT); + throw new BpmnError(BPMN_EXECUTION_ERROR_CODE_MULTI_MEDIC_FEASIBILITY_RESULT); } private List<FinalFeasibilityQueryResult> filterResultsByParticipatingMedics(Task leadingTask, diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java index cf5b8b76..e5c25b46 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java @@ -1,16 +1,17 @@ package org.highmed.dsf.bpe.service; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_TTP; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_COHORTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; import java.util.Collections; import java.util.List; @@ -19,10 +20,9 @@ import java.util.stream.Collectors; import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.highmed.dsf.bpe.ConstantsBase; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.BloomFilterConfig; -import org.highmed.dsf.bpe.variables.BloomFilterConfigValues; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfigValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.OrganizationProvider; @@ -79,7 +79,7 @@ protected void doExecute(DelegateExecution execution) throws Exception execution.setVariable(BPMN_EXECUTION_VARIABLE_COHORTS, FhirResourcesListValues.create(cohortDefinitions)); String ttpIdentifier = getTtpIdentifier(researchStudy, client); - execution.setVariable(ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER, ttpIdentifier); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER, ttpIdentifier); boolean needsConsentCheck = getNeedsConsentCheck(task); execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck); @@ -98,7 +98,7 @@ protected void doExecute(DelegateExecution execution) throws Exception private IdType getResearchStudyId(Task task) { Reference researchStudyReference = getTaskHelper().getInputParameterReferenceValues(task, - CODESYSTEM_HIGHMED_FEASIBILITY, CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE) + CODESYSTEM_HIGHMED_DATA_SHARING, CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE) .findFirst().get(); return new IdType(researchStudyReference.getReference()); @@ -172,8 +172,8 @@ private String getTtpIdentifier(ResearchStudy researchStudy, FhirWebserviceClien private boolean getNeedsConsentCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); } @@ -181,8 +181,8 @@ private boolean getNeedsConsentCheck(Task task) private boolean getNeedsRecordLinkageCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) .orElseThrow( () -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='" + task.getId() + "', this error should " + "have been caught by resource validation")); @@ -191,8 +191,8 @@ private boolean getNeedsRecordLinkageCheck(Task task) private BloomFilterConfig getBloomFilterConfig(Task task) { return BloomFilterConfig.fromBytes(getTaskHelper() - .getFirstInputParameterByteValue(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG) + .getFirstInputParameterByteValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java index f18ba427..a0dfc127 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java @@ -1,16 +1,18 @@ package org.highmed.dsf.bpe.service; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE; - +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; + +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -62,7 +64,10 @@ protected void doExecute(DelegateExecution execution) throws Exception IdType researchStudyId = getResearchStudyId(task); FhirWebserviceClient client = getFhirWebserviceClientProvider().getLocalWebserviceClient(); ResearchStudy researchStudy = getResearchStudy(researchStudyId, client); - researchStudy = addMissingOrganizations(researchStudy, client); + String consortiumIdentifier = getConsortiumIdentifier(task); + + researchStudy = checkConsortiumAffiliationAndAddMissingOrganizations(researchStudy, consortiumIdentifier, + client); execution.setVariable(BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY, researchStudy); boolean needsConsentCheck = getNeedsConsentCheck(task); @@ -75,8 +80,8 @@ protected void doExecute(DelegateExecution execution) throws Exception private IdType getResearchStudyId(Task task) { Reference researchStudyReference = getTaskHelper() - .getInputParameterReferenceValues(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE) + .getInputParameterReferenceValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE) .findFirst() .orElseThrow(() -> new IllegalArgumentException("ResearchStudy reference is not set in task with id='" + task.getId() + "', this error should " + "have been caught by resource validation")); @@ -98,23 +103,61 @@ private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceCli } } - private ResearchStudy addMissingOrganizations(ResearchStudy researchStudy, FhirWebserviceClient client) + private ResearchStudy checkConsortiumAffiliationAndAddMissingOrganizations(ResearchStudy researchStudy, + String consortiumIdentifier, FhirWebserviceClient client) { - List<String> identifiers = organizationProvider - .getOrganizationsByType(CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_MEDIC) + List<String> identifiersConsortium = getOrganizationIdentifiersOfConsortium(consortiumIdentifier); + List<String> identifiersResearchStudy = getOrganizationIdentifiersOfResearchStudy(researchStudy); + + checkConsortiumAffiliation(identifiersConsortium, identifiersResearchStudy, researchStudy.getId(), + consortiumIdentifier); + + return addMissingOrganizations(identifiersConsortium, identifiersResearchStudy, researchStudy, client); + } + + private List<String> getOrganizationIdentifiersOfConsortium(String consortiumIdentifier) + { + return organizationProvider + .getOrganizationsByConsortiumAndRole(consortiumIdentifier, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC) .flatMap(o -> o.getIdentifier().stream()) .filter(i -> NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER.equals(i.getSystem())).map(i -> i.getValue()) .collect(Collectors.toList()); + } - List<String> existingIdentifiers = researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC) - .stream().filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue()) + private List<String> getOrganizationIdentifiersOfResearchStudy(ResearchStudy researchStudy) + { + return researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).stream() + .filter(e -> e.getValue() instanceof Reference).map(e -> (Reference) e.getValue()) .map(r -> r.getIdentifier().getValue()).collect(Collectors.toList()); + } - identifiers.removeAll(existingIdentifiers); + private void checkConsortiumAffiliation(List<String> identifiersConsortium, List<String> identifiersResearchStudy, + String researchStudyId, String consortiumIdentifier) + { + List<String> identifiersWrongConsortium = new ArrayList<>(identifiersResearchStudy); + identifiersWrongConsortium.removeAll(identifiersConsortium); + if (!identifiersWrongConsortium.isEmpty()) + { + logger.warn( + "Organizations with identifiers='{}' are part of feasibility research study with id='{}' but do " + + "not belong to the consortium with identifier='{}'", + identifiersWrongConsortium, researchStudyId, consortiumIdentifier); + + throw new RuntimeException("Organizations with identifiers='" + identifiersWrongConsortium + + "' are part of feasibility research study with id='" + researchStudyId + + "' but do not belong to the consortium with identifier='" + consortiumIdentifier + "'"); + } + } + + private ResearchStudy addMissingOrganizations(List<String> identifiersConsortium, + List<String> identifiersResearchStudy, ResearchStudy researchStudy, FhirWebserviceClient client) + { + identifiersConsortium.removeAll(identifiersResearchStudy); - if (!identifiers.isEmpty()) + if (!identifiersConsortium.isEmpty()) { - identifiers.forEach(identifier -> + identifiersConsortium.forEach(identifier -> { logger.warn( "Adding missing organization with identifier='{}' to feasibility research study with id='{}'", @@ -140,25 +183,35 @@ private ResearchStudy update(ResearchStudy researchStudy, FhirWebserviceClient c } catch (Exception e) { - logger.warn("Error while updating ResearchStudy resoruce: " + e.getMessage(), e); + logger.warn("Error while updating ResearchStudy resource: " + e.getMessage()); throw e; } } + private String getConsortiumIdentifier(Task task) + { + return getTaskHelper() + .getFirstInputParameterReferenceValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER) + .orElseThrow(() -> new IllegalArgumentException("ConsortiumIdentifier is not set in task with id='" + + task.getId() + "', this error should have been caught by resource validation")) + .getIdentifier().getValue(); + } + private boolean getNeedsConsentCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); + + task.getId() + "', this error should have been caught by resource validation")); } private boolean getNeedsRecordLinkageCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) .orElseThrow( () -> new IllegalArgumentException("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-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResultSets.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResults.java similarity index 70% rename from dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResultSets.java rename to dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResults.java index 6f49b179..f30bf278 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResultSets.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResults.java @@ -1,7 +1,7 @@ package org.highmed.dsf.bpe.service; import static org.highmed.dsf.bpe.ConstantsBase.OPENEHR_MIMETYPE_JSON; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import java.io.IOException; import java.io.InputStream; @@ -13,9 +13,9 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -27,13 +27,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; -public class DownloadResultSets extends AbstractServiceDelegate +public class DownloadResults extends AbstractServiceDelegate { - private static final Logger logger = LoggerFactory.getLogger(DownloadResultSets.class); + private static final Logger logger = LoggerFactory.getLogger(AbstractDownloadResults.class); private final ObjectMapper openEhrObjectMapper; - public DownloadResultSets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public DownloadResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper, ObjectMapper openEhrObjectMapper) { super(clientProvider, taskHelper, readAccessHelper); @@ -52,21 +52,20 @@ public void afterPropertiesSet() throws Exception @Override protected void doExecute(DelegateExecution execution) throws Exception { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); - List<FeasibilityQueryResult> resultsWithResultSets = download(results); + List<QueryResult> resultsWithResultSets = download(results); execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(resultsWithResultSets))); + QueryResultsValues.create(new QueryResults(resultsWithResultSets))); } - private List<FeasibilityQueryResult> download(FeasibilityQueryResults results) + private List<QueryResult> download(QueryResults results) { return results.getResults().stream().map(r -> download(r)).collect(Collectors.toList()); } - private FeasibilityQueryResult download(FeasibilityQueryResult result) + private QueryResult download(QueryResult result) { IdType id = new IdType(result.getResultSetUrl()); FhirWebserviceClient client = getFhirWebserviceClientProvider().getWebserviceClient(id.getBaseUrl()); @@ -74,7 +73,7 @@ private FeasibilityQueryResult download(FeasibilityQueryResult result) InputStream binary = readBinaryResource(client, id.getIdPart()); ResultSet resultSet = deserializeResultSet(binary); - return FeasibilityQueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), resultSet); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), resultSet); } private InputStream readBinaryResource(FhirWebserviceClient client, String id) diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java index 7c814ecd..77a19753 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteQueries.java @@ -1,9 +1,9 @@ package org.highmed.dsf.bpe.service; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERIES; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import java.util.List; import java.util.Map; @@ -12,9 +12,9 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.OrganizationProvider; @@ -57,14 +57,14 @@ protected void doExecute(DelegateExecution execution) throws Exception Boolean needsRecordLinkage = (Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE); boolean idQuery = Boolean.TRUE.equals(needsConsentCheck) || Boolean.TRUE.equals(needsRecordLinkage); - List<FeasibilityQueryResult> results = queries.entrySet().stream() + List<QueryResult> results = queries.entrySet().stream() .map(entry -> executeQuery(entry.getKey(), entry.getValue(), idQuery)).collect(Collectors.toList()); execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(results))); + QueryResultsValues.create(new QueryResults(results))); } - private FeasibilityQueryResult executeQuery(String cohortId, String cohortQuery, boolean idQuery) + private QueryResult 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. @@ -73,12 +73,12 @@ private FeasibilityQueryResult executeQuery(String cohortId, String cohortQuery, if (idQuery) { - return FeasibilityQueryResult.idResult(organizationProvider.getLocalIdentifierValue(), cohortId, resultSet); + return QueryResult.idResult(organizationProvider.getLocalIdentifierValue(), cohortId, resultSet); } else { int count = Integer.parseInt(resultSet.getRow(0).get(0).getValueAsString()); - return FeasibilityQueryResult.countResult(organizationProvider.getLocalIdentifierValue(), cohortId, count); + return QueryResult.countResult(organizationProvider.getLocalIdentifierValue(), cohortId, count); } } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java index 34159b7d..5b1ed9da 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ExecuteRecordLink.java @@ -1,7 +1,7 @@ package org.highmed.dsf.bpe.service; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_FINAL_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import java.util.List; import java.util.Map; @@ -11,8 +11,8 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResult; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResults; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResultsValues; @@ -52,11 +52,10 @@ public void afterPropertiesSet() throws Exception @Override protected void doExecute(DelegateExecution execution) throws Exception { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); - Map<String, List<FeasibilityQueryResult>> byCohortId = results.getResults().stream() - .collect(Collectors.groupingBy(FeasibilityQueryResult::getCohortId)); + Map<String, List<QueryResult>> byCohortId = results.getResults().stream() + .collect(Collectors.groupingBy(QueryResult::getCohortId)); FederatedMatcherImpl<PersonWithMdat> matcher = createMatcher(); @@ -68,7 +67,7 @@ protected void doExecute(DelegateExecution execution) throws Exception } private FinalFeasibilityQueryResult match(FederatedMatcherImpl<PersonWithMdat> matcher, String cohortId, - List<FeasibilityQueryResult> results) + List<QueryResult> results) { logger.debug("Matching results for cohort {}", cohortId); @@ -81,7 +80,7 @@ private FinalFeasibilityQueryResult match(FederatedMatcherImpl<PersonWithMdat> m toInt(matchedPersons.size())); } - private List<PersonWithMdat> translate(FeasibilityQueryResult result) + private List<PersonWithMdat> translate(QueryResult result) { return translator.translate(result.getOrganizationIdentifier(), result.getResultSet()); } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java deleted file mode 100644 index 7a16b970..00000000 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterQueryResultsByConsent.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.highmed.dsf.bpe.service; - -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; - -import java.util.List; -import java.util.stream.Collectors; - -import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; -import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; -import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; -import org.highmed.dsf.fhir.task.TaskHelper; -import org.highmed.openehr.model.structure.ResultSet; - -public class FilterQueryResultsByConsent extends AbstractServiceDelegate -{ - public FilterQueryResultsByConsent(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper) - { - super(clientProvider, taskHelper, readAccessHelper); - } - - @Override - protected void doExecute(DelegateExecution execution) throws Exception - { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); - - List<FeasibilityQueryResult> filteredResults = filterResults(results.getResults()); - - execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(filteredResults))); - } - - private List<FeasibilityQueryResult> filterResults(List<FeasibilityQueryResult> 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-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java new file mode 100644 index 00000000..13b776ed --- /dev/null +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/FilterResultsByConsent.java @@ -0,0 +1,78 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.consent.client.ConsentClient; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.openehr.model.structure.ResultSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class FilterResultsByConsent extends AbstractServiceDelegate implements InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(FilterResultsByConsent.class); + + private final ConsentClient consentClient; + + public FilterResultsByConsent(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, ConsentClient consentClient) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.consentClient = consentClient; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(consentClient, "consentClient"); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + List<QueryResult> checkedResults = filterResultsByConsent(results); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, + QueryResultsValues.create(new QueryResults(checkedResults))); + } + + private List<QueryResult> filterResultsByConsent(QueryResults results) + { + return results.getResults().stream().map(result -> filterResultByConsent(result)).collect(Collectors.toList()); + } + + private QueryResult filterResultByConsent(QueryResult result) + { + ResultSet checkedResultSet = removeRowsWithoutConsent(result.getResultSet()); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), checkedResultSet); + } + + private ResultSet removeRowsWithoutConsent(ResultSet resultSet) + { + try + { + return consentClient.removeRowsWithoutConsent(resultSet); + } + catch (Exception exception) + { + logger.warn("Error while filtering ResultSet: " + exception.getMessage()); + throw exception; + } + } +} diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java index faa94230..b8c0b1e7 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateBloomFilters.java @@ -2,10 +2,10 @@ import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.OPENEHR_MIMETYPE_JSON; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI; -import static org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpRbfOnlyImpl.FILTER_ON_IDAT_NOT_FOUND_EXCEPTION; +import static org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumnsImpl.FILTER_ON_IDAT_NOT_FOUND_EXCEPTION; import java.security.Key; import java.util.List; @@ -15,10 +15,10 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.BloomFilterConfig; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -29,8 +29,8 @@ 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.highmed.pseudonymization.translation.ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumns; +import org.highmed.pseudonymization.translation.ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumnsImpl; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.ResourceType; @@ -84,22 +84,22 @@ public void afterPropertiesSet() throws Exception @Override protected void doExecute(DelegateExecution execution) throws Exception { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); String securityIdentifier = getSecurityIdentifier(execution); BloomFilterConfig bloomFilterConfig = (BloomFilterConfig) execution .getVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG); - ResultSetTranslatorToTtpRbfOnly resultSetTranslator = createResultSetTranslator(bloomFilterConfig); + ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumns resultSetTranslator = createResultSetTranslator( + bloomFilterConfig); - List<FeasibilityQueryResult> translatedResults = results.getResults().stream() + List<QueryResult> translatedResults = results.getResults().stream() .map(result -> translateAndCreateBinary(resultSetTranslator, result, securityIdentifier)) .collect(Collectors.toList()); execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(translatedResults))); + QueryResultsValues.create(new QueryResults(translatedResults))); } private String getSecurityIdentifier(DelegateExecution execution) @@ -112,9 +112,10 @@ private String getSecurityIdentifier(DelegateExecution execution) return (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER); } - protected ResultSetTranslatorToTtpRbfOnly createResultSetTranslator(BloomFilterConfig bloomFilterConfig) + protected ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumns createResultSetTranslator( + BloomFilterConfig bloomFilterConfig) { - return new ResultSetTranslatorToTtpRbfOnlyImpl(ehrIdColumnPath, + return new ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumnsImpl(ehrIdColumnPath, createRecordBloomFilterGenerator(bloomFilterConfig.getPermutationSeed(), bloomFilterConfig.getHmacSha2Key(), bloomFilterConfig.getHmacSha3Key()), masterPatientIndexClient, FILTER_ON_IDAT_NOT_FOUND_EXCEPTION); @@ -128,16 +129,18 @@ protected RecordBloomFilterGenerator createRecordBloomFilterGenerator(long permu bouncyCastleProvider)); } - private FeasibilityQueryResult translateAndCreateBinary(ResultSetTranslatorToTtpRbfOnly resultSetTranslator, - FeasibilityQueryResult result, String ttpIdentifier) + private QueryResult translateAndCreateBinary( + ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumns resultSetTranslator, QueryResult result, + String ttpIdentifier) { ResultSet translatedResultSet = translate(resultSetTranslator, result.getResultSet()); String resultSetUrl = saveResultSetAsBinaryForTtp(translatedResultSet, ttpIdentifier); - return FeasibilityQueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), resultSetUrl); + return QueryResult.idResult(result.getOrganizationIdentifier(), result.getCohortId(), resultSetUrl); } - private ResultSet translate(ResultSetTranslatorToTtpRbfOnly resultSetTranslator, ResultSet resultSet) + private ResultSet translate(ResultSetTranslatorToTtpCreateRbfOnlyDropOtherColumns resultSetTranslator, + ResultSet resultSet) { try { @@ -167,10 +170,10 @@ private byte[] serializeResultSet(ResultSet resultSet) { return openEhrObjectMapper.writeValueAsBytes(resultSet); } - catch (JsonProcessingException e) + catch (JsonProcessingException exception) { - logger.warn("Error while serializing ResultSet: " + e.getMessage(), e); - throw new RuntimeException(e); + logger.warn("Error while serializing ResultSet: " + exception.getMessage()); + throw new RuntimeException(exception); } } @@ -180,11 +183,11 @@ private IdType createBinaryResource(Binary binary) { return getFhirWebserviceClientProvider().getLocalWebserviceClient().withMinimalReturn().create(binary); } - catch (Exception e) + catch (Exception exception) { logger.debug("Binary to create {}", FhirContext.forR4().newJsonParser().encodeResourceToString(binary)); - logger.warn("Error while creating Binary resoruce: " + e.getMessage(), e); - throw e; + logger.warn("Error while creating Binary resource: " + exception.getMessage()); + throw exception; } } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java index ccc83771..80f71f97 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/GenerateCountFromIds.java @@ -1,15 +1,15 @@ package org.highmed.dsf.bpe.service; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; import java.util.List; import java.util.stream.Collectors; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -25,23 +25,22 @@ public GenerateCountFromIds(FhirWebserviceClientProvider clientProvider, TaskHel @Override protected void doExecute(DelegateExecution execution) throws Exception { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); - List<FeasibilityQueryResult> filteredResults = count(results.getResults()); + List<QueryResult> filteredResults = count(results.getResults()); execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(filteredResults))); + QueryResultsValues.create(new QueryResults(filteredResults))); } - private List<FeasibilityQueryResult> count(List<FeasibilityQueryResult> results) + private List<QueryResult> count(List<QueryResult> results) { return results.stream().map(this::count).collect(Collectors.toList()); } - protected FeasibilityQueryResult count(FeasibilityQueryResult result) + protected QueryResult count(QueryResult result) { - return FeasibilityQueryResult.countResult(result.getOrganizationIdentifier(), result.getCohortId(), + return QueryResult.countResult(result.getOrganizationIdentifier(), result.getCohortId(), result.getResultSet().getRows().size()); } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java index 1df227ae..7f7d7c9b 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/ModifyQueries.java @@ -1,8 +1,9 @@ package org.highmed.dsf.bpe.service; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERIES; +import static org.highmed.pseudonymization.openehr.Constants.EHRID_COLUMN_NAME; import java.util.HashMap; import java.util.Map; @@ -68,6 +69,6 @@ private Map<String, String> modifyQueries(Map<String, String> queries) protected String replaceSelectCountWithSelectMpiId(String value) { // TODO Implement correct replacement for default id query - return value.replace("SELECT COUNT(e)", "SELECT e" + ehrIdColumnPath + " as EHRID"); + return value.replace("SELECT COUNT(e)", "SELECT e" + ehrIdColumnPath + " as " + EHRID_COLUMN_NAME); } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java index 08795a72..a593364f 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectRequestTargets.java @@ -2,17 +2,19 @@ import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_MEDIC; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_TTP; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_MEDIC; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_PARTICIPATING_TTP; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_RESEARCH_STUDY; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.List; import java.util.Objects; import java.util.Random; @@ -24,8 +26,8 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.BloomFilterConfig; -import org.highmed.dsf.bpe.variables.BloomFilterConfigValues; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfigValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.EndpointProvider; @@ -34,6 +36,7 @@ import org.highmed.dsf.fhir.variables.TargetValues; import org.highmed.dsf.fhir.variables.Targets; import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Endpoint; import org.hl7.fhir.r4.model.Extension; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; @@ -41,7 +44,7 @@ public class SelectRequestTargets extends AbstractServiceDelegate { - private static final Random random = new Random(); + private static final Random random = new SecureRandom(); private final EndpointProvider endpointProvider; private final KeyGenerator hmacSha2Generator; @@ -62,9 +65,9 @@ public SelectRequestTargets(FhirWebserviceClientProvider clientProvider, TaskHel hmacSha2Generator = KeyGenerator.getInstance("HmacSHA256", bouncyCastleProvider); hmacSha3Generator = KeyGenerator.getInstance("HmacSHA3-256", bouncyCastleProvider); } - catch (NoSuchAlgorithmException e) + catch (NoSuchAlgorithmException exception) { - throw new RuntimeException(e); + throw new RuntimeException(exception); } } @@ -103,11 +106,12 @@ private Targets getMedicTargets(ResearchStudy researchStudy) List<Target> targets = researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_MEDIC).stream() .filter(Extension::hasValue).map(Extension::getValue).filter(v -> v instanceof Reference) .map(v -> (Reference) v).filter(Reference::hasIdentifier).map(Reference::getIdentifier) - .filter(Identifier::hasValue).map(Identifier::getValue) - .map(medicIdentifier -> Target.createBiDirectionalTarget(medicIdentifier, - getAddress(CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_MEDIC, medicIdentifier), - UUID.randomUUID().toString())) - .collect(Collectors.toList()); + .filter(Identifier::hasValue).map(Identifier::getValue).map(medicIdentifier -> + { + Endpoint endpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIdentifier); + return Target.createBiDirectionalTarget(medicIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), UUID.randomUUID().toString()); + }).collect(Collectors.toList()); return new Targets(targets); } @@ -117,17 +121,26 @@ private Target getTtpTarget(ResearchStudy researchStudy) return researchStudy.getExtensionsByUrl(EXTENSION_HIGHMED_PARTICIPATING_TTP).stream() .filter(Extension::hasValue).map(Extension::getValue).filter(v -> v instanceof Reference) .map(v -> (Reference) v).filter(Reference::hasIdentifier).map(Reference::getIdentifier) - .filter(Identifier::hasValue).map(Identifier::getValue) - .map(ttpIdentifier -> Target.createUniDirectionalTarget(ttpIdentifier, - getAddress(CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_TTP, ttpIdentifier))) - .findFirst().get(); + .filter(Identifier::hasValue).map(Identifier::getValue).map(ttpIdentifier -> + { + Endpoint endpoint = getEndpoint(CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP, ttpIdentifier); + return Target.createUniDirectionalTarget(ttpIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress()); + }).findFirst().get(); } - private String getAddress(String role, String identifier) + private Endpoint getEndpoint(String role, String identifier) { return endpointProvider - .getFirstConsortiumEndpointAdress(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, - CODESYSTEM_HIGHMED_ORGANIZATION_TYPE, role, identifier) + .getFirstConsortiumEndpoint(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, role, identifier) .get(); } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java index c087f26c..71139dee 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetMedic.java @@ -1,8 +1,9 @@ package org.highmed.dsf.bpe.service; import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; import java.util.Objects; @@ -15,6 +16,8 @@ import org.highmed.dsf.fhir.task.TaskHelper; import org.highmed.dsf.fhir.variables.Target; import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Identifier; import org.springframework.beans.factory.InitializingBean; public class SelectResponseTargetMedic extends AbstractServiceDelegate implements InitializingBean @@ -42,11 +45,20 @@ protected void doExecute(DelegateExecution execution) throws Exception { String medicIndentifier = getLeadingTaskFromExecutionVariables().getRequester().getIdentifier().getValue(); - Target medicTarget = Target.createUniDirectionalTarget(medicIndentifier, - endpointProvider.getFirstConsortiumEndpointAdress( - NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, - CODESYSTEM_HIGHMED_ORGANIZATION_TYPE, CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_MEDIC, - medicIndentifier).get()); + Endpoint endpoint = endpointProvider.getFirstConsortiumEndpoint( + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_MEDIC, medicIndentifier).get(); + + Target medicTarget = Target.createUniDirectionalTarget(medicIndentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress()); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, TargetValues.create(medicTarget)); } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java index 328701e1..a4e5c987 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/SelectResponseTargetTtp.java @@ -4,8 +4,9 @@ import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE; -import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_TTP; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM; import java.util.Objects; @@ -18,6 +19,8 @@ import org.highmed.dsf.fhir.task.TaskHelper; import org.highmed.dsf.fhir.variables.Target; import org.highmed.dsf.fhir.variables.TargetValues; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Task; import org.springframework.beans.factory.InitializingBean; @@ -47,12 +50,13 @@ protected void doExecute(DelegateExecution execution) throws Exception String ttpIdentifier = (String) execution.getVariable(BPMN_EXECUTION_VARIABLE_TTP_IDENTIFIER); String correlationKey = getCorrelationKey(execution); - Target ttpTarget = Target.createBiDirectionalTarget(ttpIdentifier, - endpointProvider.getFirstConsortiumEndpointAdress( - NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, - CODESYSTEM_HIGHMED_ORGANIZATION_TYPE, CODESYSTEM_HIGHMED_ORGANIZATION_TYPE_VALUE_TTP, - ttpIdentifier).get(), - correlationKey); + Endpoint endpoint = endpointProvider.getFirstConsortiumEndpoint( + NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_HIGHMED_CONSORTIUM, CODESYSTEM_HIGHMED_ORGANIZATION_ROLE, + CODESYSTEM_HIGHMED_ORGANIZATION_ROLE_VALUE_TTP, ttpIdentifier).get(); + + Target ttpTarget = Target.createBiDirectionalTarget(ttpIdentifier, getEndpointIdentifierValue(endpoint), + endpoint.getAddress(), correlationKey); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, TargetValues.create(ttpTarget)); } @@ -66,4 +70,11 @@ private String getCorrelationKey(DelegateExecution execution) .orElseThrow(() -> new IllegalStateException( "No correlation key found, this error should have been caught by resource validation")); } + + private String getEndpointIdentifierValue(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue).get(); + } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java index ab70cc74..0eeb37a3 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreCorrelationKeys.java @@ -1,19 +1,19 @@ package org.highmed.dsf.bpe.service; import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; import java.util.List; import java.util.stream.Collectors; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -36,9 +36,9 @@ protected void doExecute(DelegateExecution execution) throws Exception Task task = getCurrentTaskFromExecutionVariables(); List<Target> targets = getTaskHelper() - .getInputParameterStringValues(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY) - .map(correlationKey -> Target.createBiDirectionalTarget("", "", correlationKey)) + .getInputParameterStringValues(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY) + .map(correlationKey -> Target.createBiDirectionalTarget("", "", "", correlationKey)) .collect(Collectors.toList()); execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(new Targets(targets))); @@ -46,15 +46,14 @@ protected void doExecute(DelegateExecution execution) throws Exception boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task); execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); - execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(null))); + execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, QueryResultsValues.create(new QueryResults(null))); } private boolean getNeedsRecordLinkageCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) .orElseThrow( () -> new IllegalArgumentException("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-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java index 9ebdab5d..2037366e 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java @@ -1,11 +1,11 @@ package org.highmed.dsf.bpe.service; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; import java.util.ArrayList; import java.util.List; @@ -14,9 +14,9 @@ import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsValues; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; +import org.highmed.dsf.bpe.variable.QueryResultsValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.OrganizationProvider; @@ -49,52 +49,49 @@ public void afterPropertiesSet() throws Exception @Override protected void doExecute(DelegateExecution execution) throws Exception { - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); boolean needsRecordLinkage = Boolean.TRUE - .equals((Boolean) execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE)); + .equals(execution.getVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE)); Task task = getCurrentTaskFromExecutionVariables(); - List<FeasibilityQueryResult> extendedResults = new ArrayList<>(); + List<QueryResult> extendedResults = new ArrayList<>(); extendedResults.addAll(results.getResults()); extendedResults.addAll(getResults(task, needsRecordLinkage)); execution.setVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS, - FeasibilityQueryResultsValues.create(new FeasibilityQueryResults(extendedResults))); + QueryResultsValues.create(new QueryResults(extendedResults))); } - private List<FeasibilityQueryResult> getResults(Task task, boolean needsRecordLinkage) + private List<QueryResult> getResults(Task task, boolean needsRecordLinkage) { TaskHelper taskHelper = getTaskHelper(); Reference requester = task.getRequester(); if (needsRecordLinkage) { - return taskHelper.getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE, EXTENSION_HIGHMED_GROUP_ID) + return taskHelper.getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE, EXTENSION_HIGHMED_GROUP_ID) .map(input -> { String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference(); String resultSetUrl = ((Reference) input.getValue()).getReference(); - return FeasibilityQueryResult.idResult(requester.getIdentifier().getValue(), cohortId, - resultSetUrl); + return QueryResult.idResult(requester.getIdentifier().getValue(), cohortId, resultSetUrl); }).collect(Collectors.toList()); } else { return taskHelper - .getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_FEASIBILITY, - CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT, EXTENSION_HIGHMED_GROUP_ID) + .getInputParameterWithExtension(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT, EXTENSION_HIGHMED_GROUP_ID) .map(input -> { String cohortId = ((Reference) input.getExtension().get(0).getValue()).getReference(); int cohortSize = ((UnsignedIntType) input.getValue()).getValue(); - return FeasibilityQueryResult.countResult(requester.getIdentifier().getValue(), cohortId, - cohortSize); + return QueryResult.countResult(requester.getIdentifier().getValue(), cohortId, cohortSize); }).collect(Collectors.toList()); } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java index b674a878..2deee0b0 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilityConfig.java @@ -1,6 +1,8 @@ package org.highmed.dsf.bpe.spring.config; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.highmed.consent.client.ConsentClient; +import org.highmed.consent.client.ConsentClientFactory; import org.highmed.dsf.bpe.message.SendMedicRequest; import org.highmed.dsf.bpe.message.SendMultiMedicErrors; import org.highmed.dsf.bpe.message.SendMultiMedicResults; @@ -14,10 +16,10 @@ import org.highmed.dsf.bpe.service.CheckTtpComputedMultiMedicResults; import org.highmed.dsf.bpe.service.DownloadFeasibilityResources; import org.highmed.dsf.bpe.service.DownloadResearchStudyResource; -import org.highmed.dsf.bpe.service.DownloadResultSets; +import org.highmed.dsf.bpe.service.DownloadResults; 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.FilterResultsByConsent; import org.highmed.dsf.bpe.service.GenerateBloomFilters; import org.highmed.dsf.bpe.service.GenerateCountFromIds; import org.highmed.dsf.bpe.service.HandleErrorMultiMedicResults; @@ -55,6 +57,9 @@ public class FeasibilityConfig @Autowired private FhirWebserviceClientProvider fhirClientProvider; + @Autowired + private ConsentClientFactory consentClientFactory; + @Autowired private MasterPatientIndexClientFactory masterPatientIndexClientFactory; @@ -85,7 +90,7 @@ public class FeasibilityConfig @Autowired private Environment environment; - @Value("${org.highmed.dsf.bpe.openehr.subject_external_id.path:/ehr_status/subject/external_ref/id/value}") + @Value("${org.highmed.dsf.bpe.openehr.subject.external.id.path:/ehr_status/subject/external_ref/id/value}") private String ehrIdColumnPath; // @@ -167,9 +172,15 @@ public ExecuteQueries executeQueries() } @Bean - public FilterQueryResultsByConsent filterQueryResultsByConsent() + public ConsentClient consentClient() + { + return consentClientFactory.createClient(environment::getProperty); + } + + @Bean + public FilterResultsByConsent filterResultsByConsent() { - return new FilterQueryResultsByConsent(fhirClientProvider, taskHelper, readAccessHelper); + return new FilterResultsByConsent(fhirClientProvider, taskHelper, readAccessHelper, consentClient()); } @Bean @@ -239,9 +250,9 @@ public StoreResults storeResults() } @Bean - public DownloadResultSets downloadResultSets() + public DownloadResults downloadResults() { - return new DownloadResultSets(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); + return new DownloadResults(fhirClientProvider, taskHelper, readAccessHelper, objectMapper); } @Bean diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilitySerializerConfig.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilitySerializerConfig.java index 05418ecd..28fc9bf4 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilitySerializerConfig.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/spring/config/FeasibilitySerializerConfig.java @@ -1,8 +1,5 @@ package org.highmed.dsf.bpe.spring.config; -import org.highmed.dsf.bpe.variables.BloomFilterConfigSerializer; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultSerializer; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResultsSerializer; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResultSerializer; import org.highmed.dsf.bpe.variables.FinalFeasibilityQueryResultsSerializer; import org.springframework.beans.factory.annotation.Autowired; @@ -17,18 +14,6 @@ public class FeasibilitySerializerConfig @Autowired private ObjectMapper objectMapper; - @Bean - public FeasibilityQueryResultSerializer feasibilityQueryResultSerializer() - { - return new FeasibilityQueryResultSerializer(objectMapper); - } - - @Bean - public FeasibilityQueryResultsSerializer feasibilityQueryResultsSerializer() - { - return new FeasibilityQueryResultsSerializer(objectMapper); - } - @Bean public FinalFeasibilityQueryResultSerializer finalFeasibilityQueryResultSerializer() { @@ -40,10 +25,4 @@ public FinalFeasibilityQueryResultsSerializer finalFeasibilityQueryResultsSerial { return new FinalFeasibilityQueryResultsSerializer(objectMapper); } - - @Bean - public BloomFilterConfigSerializer bloomFilterConfigSerializer() - { - return new BloomFilterConfigSerializer(objectMapper); - } } diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResult.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResult.java index 9cbd2324..5c82d02f 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResult.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResult.java @@ -18,16 +18,19 @@ public FinalFeasibilityQueryResult(@JsonProperty("cohortId") String cohortId, this.cohortSize = cohortSize; } + @JsonProperty("cohortId") public String getCohortId() { return cohortId; } + @JsonProperty("participatingMedics") public int getParticipatingMedics() { return participatingMedics; } + @JsonProperty("cohortSize") public int getCohortSize() { return cohortSize; diff --git a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResults.java b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResults.java index 65f413db..0ba16484 100644 --- a/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResults.java +++ b/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResults.java @@ -32,6 +32,7 @@ public void addAll(Collection<FinalFeasibilityQueryResult> results) this.results.addAll(results); } + @JsonProperty("results") public List<FinalFeasibilityQueryResult> getResults() { return Collections.unmodifiableList(results); diff --git a/dsf-bpe-process-feasibility/src/main/resources/bpe/computeFeasibility.bpmn b/dsf-bpe-process-feasibility/src/main/resources/bpe/computeFeasibility.bpmn index ee7d301d..15001ec2 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/bpe/computeFeasibility.bpmn +++ b/dsf-bpe-process-feasibility/src/main/resources/bpe/computeFeasibility.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1yff9tp" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_computeFeasibility" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_computeFeasibility" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:subProcess id="SubProcess_1gopxt4"> <bpmn:incoming>SequenceFlow_1lfe4wr</bpmn:incoming> <bpmn:outgoing>SequenceFlow_0xxpamp</bpmn:outgoing> @@ -42,12 +42,12 @@ <bpmn:outgoing>SequenceFlow_01pjftq</bpmn:outgoing> <bpmn:messageEventDefinition messageRef="Message_08676wn" /> </bpmn:startEvent> - <bpmn:endEvent id="EndEventSuccess" name="send final result to leading MeDIC"> + <bpmn:endEvent id="EndEventSuccess" name="send final results to leading MeDIC"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/requestFeasibility/0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/requestFeasibility/#{version}</camunda:inputParameter> <camunda:inputParameter name="messageName">resultMultiMedicFeasibilityMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-feasibility|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-feasibility|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>Flow_1r6dq8y</bpmn:incoming> @@ -66,7 +66,7 @@ <bpmn:sequenceFlow id="SequenceFlow_0t4lx4v" name="else" sourceRef="ExclusiveGateway_07e71aa" targetRef="calculateMultimedicCohortSize"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!needsRecordLinkage}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="SequenceFlow_0calilw" name="needs record linkage" sourceRef="ExclusiveGateway_07e71aa" targetRef="downloadResultSets"> + <bpmn:sequenceFlow id="SequenceFlow_0calilw" name="needs record linkage" sourceRef="ExclusiveGateway_07e71aa" targetRef="downloadResults"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsRecordLinkage}</bpmn:conditionExpression> </bpmn:sequenceFlow> <bpmn:serviceTask id="executeRecordLink" name="execute record link" camunda:class="org.highmed.dsf.bpe.service.ExecuteRecordLink"> @@ -87,8 +87,8 @@ <bpmn:incoming>Flow_1ixeke2</bpmn:incoming> <bpmn:outgoing>Flow_1k0sqwo</bpmn:outgoing> </bpmn:serviceTask> - <bpmn:sequenceFlow id="SequenceFlow_0zp76kj" sourceRef="downloadResultSets" targetRef="executeRecordLink" /> - <bpmn:serviceTask id="downloadResultSets" name="download ResultSets" camunda:class="org.highmed.dsf.bpe.service.DownloadResultSets"> + <bpmn:sequenceFlow id="SequenceFlow_0zp76kj" sourceRef="downloadResults" targetRef="executeRecordLink" /> + <bpmn:serviceTask id="downloadResults" name="download results" camunda:class="org.highmed.dsf.bpe.service.DownloadResults"> <bpmn:incoming>SequenceFlow_0calilw</bpmn:incoming> <bpmn:outgoing>SequenceFlow_0zp76kj</bpmn:outgoing> </bpmn:serviceTask> @@ -96,15 +96,15 @@ <bpmn:endEvent id="EndEventError" name="send error to leading MeDIC"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/requestFeasibility/0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/requestFeasibility/#{version}</camunda:inputParameter> <camunda:inputParameter name="messageName">errorMultiMedicFeasibilityMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-feasibility|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-feasibility|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>Flow_1tmnvhl</bpmn:incoming> <bpmn:messageEventDefinition id="MessageEventDefinition_19y5diw" messageRef="Message_0kix95m" camunda:class="org.highmed.dsf.bpe.message.SendMultiMedicErrors" /> </bpmn:endEvent> - <bpmn:serviceTask id="checkComputedResults" name="check computed result" camunda:class="org.highmed.dsf.bpe.service.CheckTtpComputedMultiMedicResults"> + <bpmn:serviceTask id="checkComputedResults" name="check computed results" camunda:class="org.highmed.dsf.bpe.service.CheckTtpComputedMultiMedicResults"> <bpmn:incoming>Flow_1k0sqwo</bpmn:incoming> <bpmn:outgoing>Flow_1r6dq8y</bpmn:outgoing> </bpmn:serviceTask> @@ -245,7 +245,7 @@ <bpmndi:BPMNShape id="ServiceTask_0uk3eyz_di" bpmnElement="selectResponseTargetMedic"> <dc:Bounds x="1540" y="202" width="100" height="80" /> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="ServiceTask_09wyp6g_di" bpmnElement="downloadResultSets"> + <bpmndi:BPMNShape id="ServiceTask_09wyp6g_di" bpmnElement="downloadResults"> <dc:Bounds x="1230" y="86" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Event_1hmug5i_di" bpmnElement="EndEventError"> diff --git a/dsf-bpe-process-feasibility/src/main/resources/bpe/executeFeasibility.bpmn b/dsf-bpe-process-feasibility/src/main/resources/bpe/executeFeasibility.bpmn index 230c52c7..d1d58a32 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/bpe/executeFeasibility.bpmn +++ b/dsf-bpe-process-feasibility/src/main/resources/bpe/executeFeasibility.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0drkcb5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_executeFeasibility" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_executeFeasibility" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:serviceTask id="checkResults" name="check results" camunda:class="org.highmed.dsf.bpe.service.CheckSingleMedicResults"> <bpmn:incoming>SequenceFlow_0q803rh</bpmn:incoming> <bpmn:outgoing>SequenceFlow_04ouilq</bpmn:outgoing> @@ -21,12 +21,12 @@ <bpmn:incoming>SequenceFlow_14cn0vs</bpmn:incoming> <bpmn:outgoing>SequenceFlow_1etju4m</bpmn:outgoing> </bpmn:serviceTask> - <bpmn:endEvent id="EndEvent" name="send result to TTP"> + <bpmn:endEvent id="EndEvent" name="send results to TTP"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/computeFeasibility/0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/computeFeasibility/#{version}</camunda:inputParameter> <camunda:inputParameter name="messageName">resultSingleMedicFeasibilityMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-single-medic-result-feasibility|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-single-medic-result-feasibility|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_0ascyjc</bpmn:incoming> @@ -71,7 +71,7 @@ <bpmn:sequenceFlow id="SequenceFlow_0isxkuy" name="needs consent check" sourceRef="ExclusiveGateway_0bq7zdz" targetRef="filterByConsent"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsConsentCheck}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:serviceTask id="filterByConsent" name="filter by consent" camunda:class="org.highmed.dsf.bpe.service.FilterQueryResultsByConsent"> + <bpmn:serviceTask id="filterByConsent" name="filter results by consent" camunda:class="org.highmed.dsf.bpe.service.FilterResultsByConsent"> <bpmn:incoming>SequenceFlow_0isxkuy</bpmn:incoming> <bpmn:outgoing>SequenceFlow_0kzp6tl</bpmn:outgoing> </bpmn:serviceTask> @@ -259,7 +259,7 @@ <bpmndi:BPMNShape id="EndEvent_10xdh63_di" bpmnElement="EndEvent"> <dc:Bounds x="2201" y="254" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="2186" y="297" width="67" height="27" /> + <dc:Bounds x="2184" y="297" width="72" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_1pt9xhp_di" bpmnElement="checkQueries"> diff --git a/dsf-bpe-process-feasibility/src/main/resources/bpe/requestFeasibility.bpmn b/dsf-bpe-process-feasibility/src/main/resources/bpe/requestFeasibility.bpmn index 597e131c..c9fe4471 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/bpe/requestFeasibility.bpmn +++ b/dsf-bpe-process-feasibility/src/main/resources/bpe/requestFeasibility.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0inb4ax" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_requestFeasibility" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_requestFeasibility" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:startEvent id="StartEvent" name="start"> <bpmn:outgoing>SequenceFlow_11k77gx</bpmn:outgoing> <bpmn:messageEventDefinition id="MessageEventDefinition_10c2suu" messageRef="Message_1pq9qxp" /> @@ -12,9 +12,9 @@ <bpmn:sendTask id="sendRequestToMedics" name="send request to medics" camunda:class="org.highmed.dsf.bpe.message.SendMedicRequest"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeFeasibility/0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeFeasibility/#{version}</camunda:inputParameter> <camunda:inputParameter name="messageName">executeFeasibilityMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-execute-feasibility|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-execute-feasibility|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_035oihl</bpmn:incoming> @@ -32,9 +32,9 @@ <bpmn:intermediateThrowEvent id="sendCorreltationKeysToTTP" name="send correlation keys to TTP"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/computeFeasibility/0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/computeFeasibility/#{version}</camunda:inputParameter> <camunda:inputParameter name="messageName">computeFeasibilityMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-compute-feasibility|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-compute-feasibility|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_0b5s4ef</bpmn:incoming> @@ -44,7 +44,7 @@ <bpmn:endEvent id="EndEvent" name="success"> <bpmn:incoming>Flow_15k4oa2</bpmn:incoming> </bpmn:endEvent> - <bpmn:serviceTask id="checkFinalResult" name="check final result" camunda:class="org.highmed.dsf.bpe.service.CheckMultiMedicResults"> + <bpmn:serviceTask id="checkFinalResults" name="check final results" camunda:class="org.highmed.dsf.bpe.service.CheckMultiMedicResults"> <bpmn:incoming>Flow_0fd2zcr</bpmn:incoming> <bpmn:outgoing>Flow_0pn3dsm</bpmn:outgoing> </bpmn:serviceTask> @@ -70,14 +70,14 @@ <bpmn:messageEventDefinition id="MessageEventDefinition_07z0ktw" messageRef="Message_1vrxfsk" /> </bpmn:intermediateCatchEvent> <bpmn:sequenceFlow id="Flow_113qgvb" sourceRef="Gateway_1elix41" targetRef="receiveFinalResultFromTTP" /> - <bpmn:sequenceFlow id="Flow_0fd2zcr" sourceRef="receiveFinalResultFromTTP" targetRef="checkFinalResult" /> + <bpmn:sequenceFlow id="Flow_0fd2zcr" sourceRef="receiveFinalResultFromTTP" targetRef="checkFinalResults" /> <bpmn:sequenceFlow id="Flow_0xgrywb" sourceRef="receiveErrorFromTTP" targetRef="handelError" /> <bpmn:exclusiveGateway id="Gateway_12ly33g"> <bpmn:incoming>Flow_0pn3dsm</bpmn:incoming> <bpmn:incoming>Flow_0rkdr4f</bpmn:incoming> <bpmn:outgoing>Flow_15k4oa2</bpmn:outgoing> </bpmn:exclusiveGateway> - <bpmn:sequenceFlow id="Flow_0pn3dsm" sourceRef="checkFinalResult" targetRef="Gateway_12ly33g" /> + <bpmn:sequenceFlow id="Flow_0pn3dsm" sourceRef="checkFinalResults" targetRef="Gateway_12ly33g" /> <bpmn:sequenceFlow id="Flow_0rkdr4f" sourceRef="handelError" targetRef="Gateway_12ly33g" /> <bpmn:sequenceFlow id="Flow_15k4oa2" sourceRef="Gateway_12ly33g" targetRef="EndEvent" /> </bpmn:process> @@ -175,7 +175,7 @@ <dc:Bounds x="1450" y="245" width="40" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="ServiceTask_00phx5l_di" bpmnElement="checkFinalResult"> + <bpmndi:BPMNShape id="ServiceTask_00phx5l_di" bpmnElement="checkFinalResults"> <dc:Bounds x="1190" y="100" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Activity_0g5gqtl_di" bpmnElement="handelError"> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-computeFeasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-computeFeasibility.xml index 2149ad7e..78a0e027 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-computeFeasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-computeFeasibility.xml @@ -10,7 +10,7 @@ <valueString value="computeFeasibilityMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-compute-feasibility|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-compute-feasibility|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -23,7 +23,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -43,7 +43,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="TTP" /> </valueCoding> </extension> @@ -58,7 +58,7 @@ <valueString value="resultSingleMedicFeasibilityMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-single-medic-result-feasibility|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-single-medic-result-feasibility|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -71,7 +71,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -91,7 +91,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="TTP" /> </valueCoding> </extension> @@ -103,14 +103,15 @@ </extension> <url value="http://highmed.org/bpe/Process/computeFeasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="ComputeFeasibility" /> <title value="Compute Feasibility" /> <subtitle value="Process to compute feasibility result" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> @@ -119,6 +120,6 @@ <value value="pmo@highmed.org" /> </telecom> </contact> - <description value="Process to compute a fesibility result and to send the result back to the requesting organization" /> + <description value="Process to compute a feasibility result and to send the result back to the requesting organization" /> <kind value="Task" /> </ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibility.xml index ceb27b2c..506fd2cd 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibility.xml @@ -10,7 +10,7 @@ <valueString value="executeFeasibilityMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -23,7 +23,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -43,7 +43,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -63,7 +63,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -75,14 +75,15 @@ </extension> <url value="http://highmed.org/bpe/Process/executeFeasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="ExecuteFeasibility" /> <title value="Execute a Feasibility" /> <subtitle value="Process to execute a feasibility query" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibility.xml index 44c96360..3307bdda 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibility.xml @@ -10,7 +10,7 @@ <valueString value="requestFeasibilityMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-request-feasibility|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-request-feasibility|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -23,7 +23,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -43,7 +43,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -58,7 +58,7 @@ <valueString value="resultMultiMedicFeasibilityMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-feasibility|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-feasibility|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -71,7 +71,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="TTP" /> </valueCoding> </extension> @@ -91,7 +91,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -106,7 +106,7 @@ <valueString value="errorMultiMedicFeasibilityMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-feasibility|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-feasibility|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -119,7 +119,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="TTP" /> </valueCoding> </extension> @@ -139,7 +139,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -151,14 +151,15 @@ </extension> <url value="http://highmed.org/bpe/Process/requestFeasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="RequestFeasibility" /> <title value="Request feasibility" /> <subtitle value="Feasibility Request Process" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/CodeSystem/highmed-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/CodeSystem/highmed-feasibility.xml deleted file mode 100644 index 12c62aa2..00000000 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/CodeSystem/highmed-feasibility.xml +++ /dev/null @@ -1,68 +0,0 @@ -<CodeSystem xmlns="http://hl7.org/fhir"> - <meta> - <tag> - <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> - <code value="ALL" /> - </tag> - </meta> - <url value="http://highmed.org/fhir/CodeSystem/feasibility" /> - <!-- version managed by bpe --> - <version value="${version}" /> - <name value="HiGHmed_Feasibility" /> - <title value="HiGHmed Feasibility" /> - <!-- status managed by bpe --> - <status value="unknown" /> - <experimental value="false" /> - <date value="2021-08-24" /> - <publisher value="HiGHmed" /> - <description value="CodeSystem with standard values for feasibility processes" /> - <caseSensitive value="true" /> - <hierarchyMeaning value="grouped-by" /> - <versionNeeded value="false" /> - <content value="complete" /> - <concept> - <code value="research-study-reference" /> - <display value="Research Study Reference" /> - <definition value="HiGHmed Research Study Reference to define what data is requested from which MeDICs and for what purpose" /> - </concept> - <concept> - <code value="needs-record-linkage" /> - <display value="Needs Record Linkage" /> - <definition value="Boolean indicating if a data analysis needs record linkage" /> - </concept> - <concept> - <code value="needs-consent-check" /> - <display value="Needs Consent Check" /> - <definition value="Boolean indicating if a data analysis needs consent check" /> - </concept> - <concept> - <code value="bloom-filter-configuration" /> - <display value="Bloom Filter Cconfiguration" /> - <definition value="Base64 binary encoded bloom filter configuration" /> - </concept> - <concept> - <code value="medic-correlation-key" /> - <display value="MeDIC Correlation Key" /> - <definition value="MeDIC Correlation Key transfered to TTP for correlating incoming medic results" /> - </concept> - <concept> - <code value="single-medic-result" /> - <display value="Single MeDIC Result" /> - <definition value="Result of a single feasibility query execution" /> - </concept> - <concept> - <code value="single-medic-result-reference" /> - <display value="Single MeDIC Result Reference" /> - <definition value="Reference to an openEHR ResultSet as a result of a single feasibility query execution" /> - </concept> - <concept> - <code value="participating-medics" /> - <display value="Participating MeDICs" /> - <definition value="Count of all MeDICs who participated in a feasibility query" /> - </concept> - <concept> - <code value="multi-medic-result" /> - <display value="Multi MeDIC Result" /> - <definition value="Aggregated result of all single medic results" /> - </concept> -</CodeSystem> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-compute-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-compute-feasibility.xml index d550ac41..838e2802 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-compute-feasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-compute-feasibility.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-compute-feasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskComputeFeasibility" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/computeFeasibility/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/computeFeasibility/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -74,7 +75,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:medic-correlation-key.type.coding"> @@ -85,7 +86,7 @@ <element id="Task.input:medic-correlation-key.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:medic-correlation-key.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -114,7 +115,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-record-linkage.type.coding"> @@ -125,7 +126,7 @@ <element id="Task.input:needs-record-linkage.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-record-linkage.type.coding.code"> <path value="Task.input.type.coding.code" /> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-error-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-error-feasibility.xml index a225592d..6fc4694e 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-error-feasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-error-feasibility.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-error-feasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskErrorFeasibility" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/requestFeasibility/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/requestFeasibility/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility.xml index f0c63dff..0f10b3ac 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-execute-feasibility.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-execute-feasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskExecuteFeasibility" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/executeFeasibility/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/executeFeasibility/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -75,7 +76,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:research-study.type.coding"> @@ -86,7 +87,7 @@ <element id="Task.input:research-study.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:research-study.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -116,7 +117,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-record-linkage.type.coding"> @@ -127,7 +128,7 @@ <element id="Task.input:needs-record-linkage.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-record-linkage.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -156,7 +157,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-consent-check.type.coding"> @@ -167,7 +168,7 @@ <element id="Task.input:needs-consent-check.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-consent-check.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -196,7 +197,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:bloom-filter-configuration.type.coding"> @@ -207,7 +208,7 @@ <element id="Task.input:bloom-filter-configuration.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:bloom-filter-configuration.type.coding.code"> <path value="Task.input.type.coding.code" /> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-feasibility.xml index fbdd3578..96515028 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-feasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-feasibility.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-multi-medic-result-feasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskMultiMedicResultFeasibility" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/requestFeasibility/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/requestFeasibility/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -93,7 +94,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:participating-medics.type.coding"> @@ -104,7 +105,7 @@ <element id="Task.input:participating-medics.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:participating-medics.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -117,15 +118,15 @@ <code value="unsignedInt" /> </type> </element> - <element id="Task.input:multi-medic-result"> + <element id="Task.input:multi-medic-count-result"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.input" /> - <sliceName value="multi-medic-result" /> + <sliceName value="multi-medic-count-result" /> <min value="1" /> </element> - <element id="Task.input:multi-medic-result.extension"> + <element id="Task.input:multi-medic-count-result.extension"> <path value="Task.input.extension" /> <slicing> <discriminator> @@ -135,7 +136,7 @@ <rules value="open" /> </slicing> </element> - <element id="Task.input:multi-medic-result.extension:group-id"> + <element id="Task.input:multi-medic-count-result.extension:group-id"> <path value="Task.input.extension" /> <sliceName value="group-id" /> <min value="1" /> @@ -144,32 +145,32 @@ <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> </type> </element> - <element id="Task.input:multi-medic-result.type"> + <element id="Task.input:multi-medic-count-result.type"> <path value="Task.input.type" /> <binding> <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> - <element id="Task.input:multi-medic-result.type.coding"> + <element id="Task.input:multi-medic-count-result.type.coding"> <path value="Task.input.type.coding" /> <min value="1" /> <max value="1" /> </element> - <element id="Task.input:multi-medic-result.type.coding.system"> + <element id="Task.input:multi-medic-count-result.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> - <element id="Task.input:multi-medic-result.type.coding.code"> + <element id="Task.input:multi-medic-count-result.type.coding.code"> <path value="Task.input.type.coding.code" /> <min value="1" /> - <fixedCode value="multi-medic-result" /> + <fixedCode value="multi-medic-count-result" /> </element> - <element id="Task.input:multi-medic-result.value[x]"> + <element id="Task.input:multi-medic-count-result.value[x]"> <path value="Task.input.value[x]" /> <type> <code value="unsignedInt" /> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility.xml index 185e164c..f32ef12b 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-request-feasibility.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-request-feasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskRequestFeasibility" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,15 +23,15 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/requestFeasibility/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/requestFeasibility/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.input" /> - <min value="4" /> - <max value="4" /> + <min value="5" /> + <max value="5" /> </element> <element id="Task.input:message-name"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -75,7 +76,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:research-study-reference.type.coding"> @@ -86,7 +87,7 @@ <element id="Task.input:research-study-reference.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:research-study-reference.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -108,6 +109,55 @@ <path value="Task.input.value[x].identifier" /> <max value="0" /> </element> + <element id="Task.input:consortium-identifier"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="consortium-identifier" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:consortium-identifier.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> + </binding> + </element> + <element id="Task.input:consortium-identifier.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:consortium-identifier.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> + </element> + <element id="Task.input:consortium-identifier.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="consortium-identifier" /> + </element> + <element id="Task.input:consortium-identifier.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/organization" /> + </type> + </element> + <element id="Task.input:consortium-identifier.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <max value="0" /> + </element> + <element id="Task.input:consortium-identifier.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <min value="1" /> + </element> <element id="Task.input:needs-record-linkage"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> @@ -124,7 +174,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-record-linkage.type.coding"> @@ -135,7 +185,7 @@ <element id="Task.input:needs-record-linkage.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-record-linkage.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -164,7 +214,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-consent-check.type.coding"> @@ -175,7 +225,7 @@ <element id="Task.input:needs-consent-check.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-consent-check.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -218,7 +268,7 @@ <valueString value="TaskOutputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.output:participating-medics.type.coding"> @@ -229,7 +279,7 @@ <element id="Task.output:participating-medics.type.coding.system"> <path value="Task.output.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.output:participating-medics.type.coding.code"> <path value="Task.output.type.coding.code" /> @@ -242,11 +292,11 @@ <code value="unsignedInt" /> </type> </element> - <element id="Task.output:multi-medic-result"> + <element id="Task.output:multi-medic-count-result"> <path value="Task.output" /> - <sliceName value="multi-medic-result" /> + <sliceName value="multi-medic-count-result" /> </element> - <element id="Task.output:multi-medic-result.extension"> + <element id="Task.output:multi-medic-count-result.extension"> <path value="Task.output.extension" /> <slicing> <discriminator> @@ -256,7 +306,7 @@ <rules value="open" /> </slicing> </element> - <element id="Task.output:multi-medic-result.extension:group-id"> + <element id="Task.output:multi-medic-count-result.extension:group-id"> <path value="Task.output.extension" /> <sliceName value="group-id" /> <min value="1" /> @@ -265,32 +315,32 @@ <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> </type> </element> - <element id="Task.output:multi-medic-result.type"> + <element id="Task.output:multi-medic-count-result.type"> <path value="Task.output.type" /> <binding> <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> <valueString value="TaskOutputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> - <element id="Task.output:multi-medic-result.type.coding"> + <element id="Task.output:multi-medic-count-result.type.coding"> <path value="Task.output.type.coding" /> <min value="1" /> <max value="1" /> </element> - <element id="Task.output:multi-medic-result.type.coding.system"> + <element id="Task.output:multi-medic-count-result.type.coding.system"> <path value="Task.output.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> - <element id="Task.output:multi-medic-result.type.coding.code"> + <element id="Task.output:multi-medic-count-result.type.coding.code"> <path value="Task.output.type.coding.code" /> <min value="1" /> - <fixedCode value="multi-medic-result" /> + <fixedCode value="multi-medic-count-result" /> </element> - <element id="Task.output:multi-medic-result.value[x]"> + <element id="Task.output:multi-medic-count-result.value[x]"> <path value="Task.output.value[x]" /> <type> <code value="unsignedInt" /> diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-feasibility.xml b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-feasibility.xml index 54aa89e8..873432dd 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-feasibility.xml +++ b/dsf-bpe-process-feasibility/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-feasibility.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-single-medic-result-feasibility" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskSingleMedicResultFeasibility" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/computeFeasibility/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/computeFeasibility/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -58,16 +59,16 @@ <sliceName value="correlation-key" /> <min value="1" /> </element> - <element id="Task.input:single-medic-result"> + <element id="Task.input:single-medic-count-result"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.input" /> - <sliceName value="single-medic-result" /> + <sliceName value="single-medic-count-result" /> <min value="0" /> <max value="*" /> </element> - <element id="Task.input:single-medic-result.extension"> + <element id="Task.input:single-medic-count-result.extension"> <path value="Task.input.extension" /> <slicing> <discriminator> @@ -77,7 +78,7 @@ <rules value="open" /> </slicing> </element> - <element id="Task.input:single-medic-result.extension:group-id"> + <element id="Task.input:single-medic-count-result.extension:group-id"> <path value="Task.input.extension" /> <sliceName value="group-id" /> <min value="1" /> @@ -86,47 +87,47 @@ <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> </type> </element> - <element id="Task.input:single-medic-result.type"> + <element id="Task.input:single-medic-count-result.type"> <path value="Task.input.type" /> <binding> <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> - <element id="Task.input:single-medic-result.type.coding"> + <element id="Task.input:single-medic-count-result.type.coding"> <path value="Task.input.type.coding" /> <min value="1" /> <max value="1" /> </element> - <element id="Task.input:single-medic-result.type.coding.system"> + <element id="Task.input:single-medic-count-result.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> - <element id="Task.input:single-medic-result.type.coding.code"> + <element id="Task.input:single-medic-count-result.type.coding.code"> <path value="Task.input.type.coding.code" /> <min value="1" /> - <fixedCode value="single-medic-result" /> + <fixedCode value="single-medic-count-result" /> </element> - <element id="Task.input:single-medic-result.value[x]"> + <element id="Task.input:single-medic-count-result.value[x]"> <path value="Task.input.value[x]" /> <type> <code value="unsignedInt" /> </type> </element> - <element id="Task.input:single-medic-result-reference"> + <element id="Task.input:single-medic-result-set-reference"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.input" /> - <sliceName value="single-medic-result-reference" /> + <sliceName value="single-medic-result-set-reference" /> <min value="0" /> <max value="*" /> </element> - <element id="Task.input:single-medic-result-reference.extension"> + <element id="Task.input:single-medic-result-set-reference.extension"> <path value="Task.input.extension" /> <slicing> <discriminator> @@ -136,7 +137,7 @@ <rules value="open" /> </slicing> </element> - <element id="Task.input:single-medic-result-reference.extension:group-id"> + <element id="Task.input:single-medic-result-set-reference.extension:group-id"> <path value="Task.input.extension" /> <sliceName value="group-id" /> <min value="1" /> @@ -145,43 +146,43 @@ <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> </type> </element> - <element id="Task.input:single-medic-result-reference.type"> + <element id="Task.input:single-medic-result-set-reference.type"> <path value="Task.input.type" /> <binding> <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> - <element id="Task.input:single-medic-result-reference.type.coding"> + <element id="Task.input:single-medic-result-set-reference.type.coding"> <path value="Task.input.type.coding" /> <min value="1" /> <max value="1" /> </element> - <element id="Task.input:single-medic-result-reference.type.coding.system"> + <element id="Task.input:single-medic-result-set-reference.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> - <element id="Task.input:single-medic-result-reference.type.coding.code"> + <element id="Task.input:single-medic-result-set-reference.type.coding.code"> <path value="Task.input.type.coding.code" /> <min value="1" /> - <fixedCode value="single-medic-result-reference" /> + <fixedCode value="single-medic-result-set-reference" /> </element> - <element id="Task.input:single-medic-result-reference.value[x]"> + <element id="Task.input:single-medic-result-set-reference.value[x]"> <path value="Task.input.value[x]" /> <type> <code value="Reference" /> <targetProfile value="http://hl7.org/fhir/StructureDefinition/Binary" /> </type> </element> - <element id="Task.input:single-medic-result-reference.value[x].reference"> + <element id="Task.input:single-medic-result-set-reference.value[x].reference"> <path value="Task.input.value[x].reference" /> <min value="1" /> </element> - <element id="Task.input:single-medic-result-reference.value[x].identifier"> + <element id="Task.input:single-medic-result-set-reference.value[x].identifier"> <path value="Task.input.value[x].identifier" /> <max value="0" /> </element> diff --git a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinitionTest.java b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinitionTest.java new file mode 100644 index 00000000..2b85e8e0 --- /dev/null +++ b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/FeasibilityProcessPluginDefinitionTest.java @@ -0,0 +1,46 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROCESS_NAME_FULL_COMPUTE_FEASIBILITY; +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROCESS_NAME_FULL_EXECUTE_FEASIBILITY; +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROCESS_NAME_FULL_REQUEST_FEASIBILITY; +import static org.highmed.dsf.bpe.FeasibilityProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class FeasibilityProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition dataSharing = new DataSharingProcessPluginDefinition(); + ResourceProvider dataSharingProvider = dataSharing.getResourceProvider(FhirContext.forR4(), + getClass().getClassLoader(), new StandardEnvironment()); + assertNotNull(dataSharingProvider); + + ProcessPluginDefinition definition = new FeasibilityProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var computeFeasibility = provider.getResources(PROCESS_NAME_FULL_COMPUTE_FEASIBILITY + "/" + VERSION, + s -> dataSharingProvider); + assertNotNull(computeFeasibility); + assertEquals(5, computeFeasibility.count()); + + var executeFeasibilityMpcSingleShare = provider + .getResources(PROCESS_NAME_FULL_EXECUTE_FEASIBILITY + "/" + VERSION, s -> dataSharingProvider); + assertNotNull(executeFeasibilityMpcSingleShare); + assertEquals(4, executeFeasibilityMpcSingleShare.count()); + + var requestFeasibilityMpc = provider.getResources(PROCESS_NAME_FULL_REQUEST_FEASIBILITY + "/" + VERSION, + s -> dataSharingProvider); + assertNotNull(requestFeasibilityMpc); + assertEquals(6, requestFeasibilityMpc.count()); + } +} diff --git a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityFromMedicsViaMedic1ExampleStarter.java index 1cc918ac..97aa98f8 100644 --- a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityFromMedicsViaMedic1ExampleStarter.java +++ b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/AbstractRequestFeasibilityFromMedicsViaMedic1ExampleStarter.java @@ -10,13 +10,15 @@ import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_RESEARCH_STUDY_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.PROFILE_HIGHEMD_RESEARCH_STUDY; import static org.highmed.dsf.bpe.ConstantsBase.PROFILE_HIGHMED_GROUP; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_CONSORTIUM_HIGHMED; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_2; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_3; @@ -49,6 +51,11 @@ public abstract class AbstractRequestFeasibilityFromMedicsViaMedic1ExampleStarter { + private final boolean needsConsentCheck = true; + private final boolean needsRecordLinkage = true; + + private final String query = "SELECT COUNT(e) FROM EHR e"; + private final String[] medicIdentifier = new String[] { NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1, NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_2, NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_3 }; @@ -94,8 +101,8 @@ private Group createGroup(String name) group.setType(GroupType.PERSON); group.setActual(false); group.setActive(true); - group.addExtension().setUrl(EXTENSION_HIGHMED_QUERY).setValue( - new Expression().setLanguageElement(CODE_TYPE_AQL_QUERY).setExpression("SELECT COUNT(e) FROM EHR e")); + group.addExtension().setUrl(EXTENSION_HIGHMED_QUERY) + .setValue(new Expression().setLanguageElement(CODE_TYPE_AQL_QUERY).setExpression(query)); group.setName(name); Arrays.stream(medicIdentifier).forEach(i -> readAccessHelper.addOrganization(group, i)); @@ -136,7 +143,7 @@ private Task createTask(ResearchStudy researchStudy) Task task = new Task(); task.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); - task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_AND_LATEST_VERSION); task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); @@ -153,12 +160,21 @@ private Task createTask(ResearchStudy researchStudy) task.addInput() .setValue(new Reference().setReference(researchStudy.getIdElement().getIdPart()) .setType(ResourceType.ResearchStudy.name())) - .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE); - task.addInput().setValue(new BooleanType(true)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE); - task.addInput().setValue(new BooleanType(true)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK); + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput() + .setValue(new Reference() + .setIdentifier(new Identifier().setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_CONSORTIUM_HIGHMED)) + .setType(ResourceType.Organization.name())) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER); + task.addInput().setValue(new BooleanType(needsRecordLinkage)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(needsConsentCheck)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); return task; } diff --git a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResultsSerializationTest.java b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResultsSerializationTest.java new file mode 100644 index 00000000..9e691aa2 --- /dev/null +++ b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/variables/FinalFeasibilityQueryResultsSerializationTest.java @@ -0,0 +1,66 @@ +package org.highmed.dsf.bpe.variables; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; + +import org.highmed.dsf.fhir.json.ObjectMapperFactory; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import ca.uhn.fhir.context.FhirContext; + +public class FinalFeasibilityQueryResultsSerializationTest +{ + private static final Logger logger = LoggerFactory.getLogger(FinalFeasibilityQueryResultsSerializationTest.class); + + @Test + public void testEmptyFinalFeasibilityQueryResultsSerialization() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + FinalFeasibilityQueryResults results = new FinalFeasibilityQueryResults(Collections.emptyList()); + + String resultsAsString = mapper.writeValueAsString(results); + assertNotNull(resultsAsString); + + logger.debug("FinalFeasibilityQueryResults (empty): '{}'", resultsAsString); + + FinalFeasibilityQueryResults readResults = mapper.readValue(resultsAsString, + FinalFeasibilityQueryResults.class); + assertNotNull(readResults); + assertNotNull(readResults.getResults()); + assertTrue(readResults.getResults().isEmpty()); + } + + @Test + public void testNonEmptyFinalFeasibilityQueryResultsSerialization() throws Exception + { + ObjectMapper mapper = ObjectMapperFactory.createObjectMapper(FhirContext.forR4()); + + FinalFeasibilityQueryResult result = new FinalFeasibilityQueryResult("cohortId", 1, 2); + FinalFeasibilityQueryResults results = new FinalFeasibilityQueryResults(Collections.singleton(result)); + + String resultsAsString = mapper.writeValueAsString(results); + assertNotNull(resultsAsString); + + logger.debug("FinalFeasibilityQueryResults (non empty): '{}'", resultsAsString); + + FinalFeasibilityQueryResults readResults = mapper.readValue(resultsAsString, + FinalFeasibilityQueryResults.class); + assertNotNull(readResults); + assertNotNull(readResults.getResults()); + assertFalse(readResults.getResults().isEmpty()); + assertEquals(1, readResults.getResults().size()); + assertNotNull(readResults.getResults().get(0)); + assertEquals(result.getCohortId(), readResults.getResults().get(0).getCohortId()); + assertEquals(result.getCohortSize(), readResults.getResults().get(0).getCohortSize()); + assertEquals(result.getParticipatingMedics(), readResults.getResults().get(0).getParticipatingMedics()); + } +} diff --git a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java index e12cd5bc..e4e43c74 100644 --- a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java +++ b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java @@ -1,11 +1,10 @@ package org.highmed.dsf.fhir.profile; +import static org.highmed.dsf.bpe.FeasibilityProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.FeasibilityProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -28,7 +27,7 @@ public class ActivityDefinitionProfileTest private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", "highmed-extension-process-authorization-consortium-role-0.5.0.xml", "highmed-extension-process-authorization-organization-0.5.0.xml", @@ -50,67 +49,53 @@ public class ActivityDefinitionProfileTest @Test public void testComputeFeasibilityValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-computeFeasibility.xml"))) + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-computeFeasibility.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); - - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); - - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - - assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> - { - System.err.println("Org: " + orgIdentifier); - return true; - }, role -> - { - System.err.println("Role:" + role); - return true; - })); - } + System.err.println("Org: " + orgIdentifier); + return true; + }, role -> + { + System.err.println("Role:" + role); + return true; + })); } @Test public void testExecuteFeasibilityValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibility.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeFeasibility.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } @Test public void testRequestFeasibilityValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibility.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-requestFeasibility.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } } \ No newline at end of file diff --git a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java index b3cea862..ac64270f 100644 --- a/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java +++ b/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java @@ -7,16 +7,17 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_COMPUTE_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION; @@ -32,6 +33,7 @@ import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_FEASIBILITY; import static org.highmed.dsf.bpe.ConstantsFeasibility.PROFILE_HIGHMED_TASK_SINGLE_MEDIC_RESULT_FEASIBILITY_MESSAGE_NAME; +import static org.highmed.dsf.bpe.FeasibilityProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.FeasibilityProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; @@ -45,6 +47,7 @@ import org.highmed.dsf.fhir.validation.ValidationSupportRule; import org.hl7.fhir.r4.model.Base64BinaryType; import org.hl7.fhir.r4.model.BooleanType; +import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResourceType; import org.hl7.fhir.r4.model.StringType; @@ -67,16 +70,16 @@ public class TaskProfileTest private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-group-0.5.0.xml", "highmed-extension-group-id-0.5.0.xml", "highmed-research-study-0.5.0.xml", "highmed-task-request-feasibility.xml", "highmed-task-execute-feasibility.xml", "highmed-task-single-medic-result-feasibility.xml", "highmed-task-compute-feasibility.xml", "highmed-task-multi-medic-result-feasibility.xml", "highmed-task-error-feasibility.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", - "highmed-feasibility.xml"), + "highmed-data-sharing.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", - "highmed-feasibility.xml")); + "highmed-data-sharing.xml")); private ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), validationRule.getValidationSupport()); @@ -103,24 +106,25 @@ public void testTaskRequestFeasibilityValidWithOutput() throws Exception TaskOutputComponent outParticipatingMedics1 = task.addOutput(); outParticipatingMedics1.setValue(new UnsignedIntType(5)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS); outParticipatingMedics1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); TaskOutputComponent outMultiMedicResult1 = task.addOutput(); outMultiMedicResult1.setValue(new UnsignedIntType(25)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY).setCode("multi-medic-result"); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); outMultiMedicResult1.addExtension("http://highmed.org/fhir/StructureDefinition/extension-group-id", new Reference(groupId1)); TaskOutputComponent outParticipatingMedics2 = task.addOutput(); outParticipatingMedics2.setValue(new UnsignedIntType(5)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS); outParticipatingMedics2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); TaskOutputComponent outMultiMedicResult2 = task.addOutput(); outMultiMedicResult2.setValue(new UnsignedIntType(25)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); outMultiMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); ValidationResult result = resourceValidator.validate(task); @@ -146,12 +150,19 @@ private Task createValidTaskRequestFeasibility() task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_REQUEST_FEASIBILITY_MESSAGE_NAME)).getType() .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); task.addInput().setValue(new Reference("ResearchStudy/" + UUID.randomUUID().toString())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE); - task.addInput().setValue(new BooleanType(false)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE); - task.addInput().setValue(new BooleanType(false)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput() + .setValue(new Reference().setIdentifier(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("Consortium"))) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_CONSORTIUM_IDENTIFIER); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); return task; } @@ -173,8 +184,8 @@ public void testTaskExecuteFeasibilityValidWithBloomFilterConfig() throws Except { Task task = createValidTaskExecuteFeasibility(); task.addInput().setValue(new Base64BinaryType("TEST".getBytes(StandardCharsets.UTF_8))).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG); ValidationResult result = resourceValidator.validate(task); ValidationSupportRule.logValidationMessages(logger, result); @@ -204,12 +215,14 @@ private Task createValidTaskExecuteFeasibility() .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); task.addInput().setValue(new Reference("ResearchStudy/" + UUID.randomUUID().toString())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE); - task.addInput().setValue(new BooleanType(false)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE); - task.addInput().setValue(new BooleanType(false)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_RESEARCH_STUDY_REFERENCE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); return task; } @@ -271,13 +284,13 @@ private Task createValidTaskSingleMedicResultFeasibilityUnsignedIntResult() ParameterComponent inSingleMedicResult1 = task.addInput(); inSingleMedicResult1.setValue(new UnsignedIntType(5)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT); inSingleMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); ParameterComponent inSingleMedicResult2 = task.addInput(); inSingleMedicResult2.setValue(new UnsignedIntType(10)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT); inSingleMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); return task; @@ -292,13 +305,13 @@ private Task createValidTaskSingleMedicResultFeasibilityReferenceResult() ParameterComponent inSingleMedicResult1 = task.addInput(); inSingleMedicResult1.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE); inSingleMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); ParameterComponent inSingleMedicResult2 = task.addInput(); inSingleMedicResult2.setValue(new Reference("Binary/" + UUID.randomUUID().toString())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE); inSingleMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); return task; @@ -335,14 +348,15 @@ private Task createValidTaskComputeFeasibility() .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDIC_CORRELATION_KEY); - task.addInput().setValue(new BooleanType(false)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(false)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); return task; } @@ -383,24 +397,24 @@ private Task createValidTaskMultiMedicResultFeasibility() ParameterComponent inParticipatingMedics1 = task.addInput(); inParticipatingMedics1.setValue(new UnsignedIntType(5)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS); inParticipatingMedics1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); ParameterComponent inMultiMedicResult1 = task.addInput(); inMultiMedicResult1.setValue(new UnsignedIntType(25)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); inMultiMedicResult1.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId1)); ParameterComponent inParticipatingMedics2 = task.addInput(); inParticipatingMedics2.setValue(new UnsignedIntType(5)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_PARTICIPATING_MEDICS_COUNT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_PARTICIPATING_MEDICS); inParticipatingMedics2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); ParameterComponent inMultiMedicResult2 = task.addInput(); inMultiMedicResult2.setValue(new UnsignedIntType(25)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_MULTI_MEDIC_RESULT); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_MULTI_MEDIC_COUNT_RESULT); inMultiMedicResult2.addExtension(EXTENSION_HIGHMED_GROUP_ID, new Reference(groupId2)); return task; diff --git a/dsf-bpe-process-local-services/pom.xml b/dsf-bpe-process-local-services/pom.xml index 710ff991..d3d6ed72 100644 --- a/dsf-bpe-process-local-services/pom.xml +++ b/dsf-bpe-process-local-services/pom.xml @@ -9,7 +9,7 @@ <parent> <artifactId>dsf-bpe-highmed-processes-pom</artifactId> <groupId>org.highmed.dsf</groupId> - <version>0.5.0</version> + <version>0.6.0</version> </parent> <properties> @@ -28,6 +28,11 @@ <artifactId>dsf-bpe-process-feasibility</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-data-sharing</artifactId> + <scope>provided</scope> + </dependency> <dependency> <groupId>de.hs-heilbronn.mi</groupId> diff --git a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/ConstantsLocalServices.java b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/ConstantsLocalServices.java index 70562d56..9fc9b45c 100644 --- a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/ConstantsLocalServices.java +++ b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/ConstantsLocalServices.java @@ -5,7 +5,10 @@ public interface ConstantsLocalServices { + String PROCESS_NAME_FULL_LOCAL_SERVICES_INTEGRATION = "highmedorg_localServicesIntegration"; + String PROFILE_HIGHMED_TASK_LOCAL_SERVICES = "http://highmed.org/fhir/StructureDefinition/task-local-services-integration"; + String PROFILE_HIGHMED_TASK_LOCAL_SERVICES_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_LOCAL_SERVICES + "|" + VERSION; String PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_LOCAL_SERVICES_MESSAGE_NAME = "localServicesIntegrationMessage"; diff --git a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinition.java b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinition.java index c9e431f4..654ff7f4 100644 --- a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinition.java +++ b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinition.java @@ -1,10 +1,14 @@ package org.highmed.dsf.bpe; +import static org.highmed.dsf.bpe.ConstantsLocalServices.PROCESS_NAME_FULL_LOCAL_SERVICES_INTEGRATION; + +import java.time.LocalDate; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Stream; +import org.highmed.dsf.bpe.spring.config.DataSharingSerializerConfig; import org.highmed.dsf.bpe.spring.config.FeasibilitySerializerConfig; import org.highmed.dsf.bpe.spring.config.LocalServicesConfig; import org.highmed.dsf.fhir.resources.AbstractResource; @@ -19,10 +23,12 @@ public class LocalServicesProcessPluginDefinition implements ProcessPluginDefinition { - public static final String VERSION = "0.5.0"; + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); - private static final String DEPENDENCY_FEASIBILITY_VERSION = "0.5.0"; - private static final String DEPENDENCY_FEASIBILITY_NAME_AND_VERSION = "dsf-bpe-process-feasibility-0.5.0"; + private static final String DEPENDENCY_DATA_SHARING_VERSION = "0.6.0"; + private static final String DEPENDENCY_DATA_SHARING_NAME_AND_VERSION = "dsf-bpe-process-data-sharing-0.6.0"; + private static final String DEPENDENCY_FEASIBILITY_NAME_AND_VERSION = "dsf-bpe-process-feasibility-0.6.0"; @Override public String getName() @@ -36,6 +42,12 @@ public String getVersion() return VERSION; } + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + @Override public Stream<String> getBpmnFiles() { @@ -45,32 +57,36 @@ public Stream<String> getBpmnFiles() @Override public Stream<Class<?>> getSpringConfigClasses() { - return Stream.of(LocalServicesConfig.class, FeasibilitySerializerConfig.class); + return Stream.of(LocalServicesConfig.class, FeasibilitySerializerConfig.class, + DataSharingSerializerConfig.class); } @Override public List<String> getDependencyNamesAndVersions() { - return Arrays.asList(DEPENDENCY_FEASIBILITY_NAME_AND_VERSION); + return Arrays.asList(DEPENDENCY_FEASIBILITY_NAME_AND_VERSION, DEPENDENCY_DATA_SHARING_NAME_AND_VERSION); } @Override public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader classLoader, PropertyResolver resolver) { - var aL = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-localServicesIntegration.xml"); - var sTL = StructureDefinitionResource + var c = CodeSystemResource.dependency(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION, + "http://highmed.org/fhir/CodeSystem/data-sharing", DEPENDENCY_DATA_SHARING_VERSION); + + var a = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-localServicesIntegration.xml"); + + var s = StructureDefinitionResource .file("fhir/StructureDefinition/highmed-task-local-services-integration.xml"); - var vF = ValueSetResource.dependency(DEPENDENCY_FEASIBILITY_NAME_AND_VERSION, - "http://highmed.org/fhir/ValueSet/feasibility", DEPENDENCY_FEASIBILITY_VERSION); - var cF = CodeSystemResource.dependency(DEPENDENCY_FEASIBILITY_NAME_AND_VERSION, - "http://highmed.org/fhir/CodeSystem/feasibility", DEPENDENCY_FEASIBILITY_VERSION); + var v = ValueSetResource.dependency(DEPENDENCY_DATA_SHARING_NAME_AND_VERSION, + "http://highmed.org/fhir/ValueSet/data-sharing", DEPENDENCY_DATA_SHARING_VERSION); Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map - .of("highmedorg_localServicesIntegration/" + VERSION, Arrays.asList(aL, sTL, vF, cF)); + .of(PROCESS_NAME_FULL_LOCAL_SERVICES_INTEGRATION + "/" + VERSION, Arrays.asList(c, a, s, v)); - return ResourceProvider.read(VERSION, () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), - classLoader, resolver, resourcesByProcessKeyAndVersion); + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); } } diff --git a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/ExtractInputValues.java b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/ExtractInputValues.java index e80f59cb..e4161ad0 100644 --- a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/ExtractInputValues.java +++ b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/ExtractInputValues.java @@ -4,18 +4,23 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGMED_QUERY_TYPE_VALUE_AQL; import static org.highmed.dsf.bpe.ConstantsBase.CODE_TYPE_AQL_QUERY; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_QUERY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_COHORTS; -import static org.highmed.dsf.bpe.ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_COHORTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.highmed.dsf.bpe.ConstantsFeasibility; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.BloomFilterConfig; -import org.highmed.dsf.bpe.variables.BloomFilterConfigValues; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfigValues; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -47,12 +52,12 @@ protected void doExecute(DelegateExecution execution) throws Exception execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_CONSENT_CHECK, needsConsentCheck); boolean needsRecordLinkage = getNeedsRecordLinkageCheck(task); - execution.setVariable(ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); + execution.setVariable(BPMN_EXECUTION_VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); if (needsRecordLinkage) { BloomFilterConfig bloomFilterConfig = getBloomFilterConfig(task); - execution.setVariable(ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG, + execution.setVariable(BPMN_EXECUTION_VARIABLE_BLOOM_FILTER_CONFIG, BloomFilterConfigValues.create(bloomFilterConfig)); } } @@ -81,8 +86,8 @@ private List<Group> getCohortDefinitions(Stream<String> queries) private boolean getNeedsConsentCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY, - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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")); } @@ -90,8 +95,8 @@ private boolean getNeedsConsentCheck(Task task) private boolean getNeedsRecordLinkageCheck(Task task) { return getTaskHelper() - .getFirstInputParameterBooleanValue(task, ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY, - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE) + .getFirstInputParameterBooleanValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE) .orElseThrow( () -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='" + task.getId() + "', this error should " + "have been caught by resource validation")); @@ -100,8 +105,8 @@ private boolean getNeedsRecordLinkageCheck(Task task) private BloomFilterConfig getBloomFilterConfig(Task task) { return BloomFilterConfig.fromBytes(getTaskHelper() - .getFirstInputParameterByteValue(task, ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY, - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG) + .getFirstInputParameterByteValue(task, CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_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-process-local-services/src/main/java/org/highmed/dsf/bpe/service/StoreResult.java b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java similarity index 62% rename from dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/StoreResult.java rename to dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java index 0d1b19dd..18bcd30f 100644 --- a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/StoreResult.java +++ b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/service/StoreResults.java @@ -1,12 +1,15 @@ package org.highmed.dsf.bpe.service; import static org.highmed.dsf.bpe.ConstantsBase.EXTENSION_HIGHMED_GROUP_ID; +import static org.highmed.dsf.bpe.ConstantsDataSharing.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE; import org.camunda.bpm.engine.delegate.DelegateExecution; -import org.highmed.dsf.bpe.ConstantsFeasibility; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResult; -import org.highmed.dsf.bpe.variables.FeasibilityQueryResults; +import org.highmed.dsf.bpe.variable.QueryResult; +import org.highmed.dsf.bpe.variable.QueryResults; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; @@ -17,11 +20,11 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -public class StoreResult extends AbstractServiceDelegate implements InitializingBean +public class StoreResults extends AbstractServiceDelegate implements InitializingBean { - private static final Logger logger = LoggerFactory.getLogger(StoreResult.class); + private static final Logger logger = LoggerFactory.getLogger(StoreResults.class); - public StoreResult(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + public StoreResults(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, ReadAccessHelper readAccessHelper) { super(clientProvider, taskHelper, readAccessHelper); @@ -31,33 +34,30 @@ public StoreResult(FhirWebserviceClientProvider clientProvider, TaskHelper taskH protected void doExecute(DelegateExecution execution) throws Exception { Task task = getCurrentTaskFromExecutionVariables(); - FeasibilityQueryResults results = (FeasibilityQueryResults) execution - .getVariable(ConstantsFeasibility.BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); + QueryResults results = (QueryResults) execution.getVariable(BPMN_EXECUTION_VARIABLE_QUERY_RESULTS); addOutputs(task, results); } - private void addOutputs(Task task, FeasibilityQueryResults results) + private void addOutputs(Task task, QueryResults results) { results.getResults().forEach(result -> addOutput(task, result)); } - private void addOutput(Task task, FeasibilityQueryResult result) + private void addOutput(Task task, QueryResult result) { if (result.isCohortSizeResult()) { - Task.TaskOutputComponent output = getTaskHelper().createOutputUnsignedInt( - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY, - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT, - result.getCohortSize()); + Task.TaskOutputComponent output = getTaskHelper().createOutputUnsignedInt(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_COUNT_RESULT, result.getCohortSize()); + output.addExtension(createCohortIdExtension(result.getCohortId())); task.addOutput(output); } else if (result.isIdResultSetUrlResult()) { - Task.TaskOutputComponent output = getTaskHelper().createOutput( - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY, - ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_SINGLE_MEDIC_RESULT_REFERENCE, + Task.TaskOutputComponent output = getTaskHelper().createOutput(CODESYSTEM_HIGHMED_DATA_SHARING, + CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_SINGLE_MEDIC_RESULT_SET_REFERENCE, new Reference(result.getResultSetUrl())); output.addExtension(createCohortIdExtension(result.getCohortId())); task.addOutput(output); diff --git a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/spring/config/LocalServicesConfig.java b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/spring/config/LocalServicesConfig.java index 12681ab6..39ff4fa0 100644 --- a/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/spring/config/LocalServicesConfig.java +++ b/dsf-bpe-process-local-services/src/main/java/org/highmed/dsf/bpe/spring/config/LocalServicesConfig.java @@ -1,15 +1,17 @@ package org.highmed.dsf.bpe.spring.config; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.highmed.consent.client.ConsentClient; +import org.highmed.consent.client.ConsentClientFactory; import org.highmed.dsf.bpe.service.CheckQueries; import org.highmed.dsf.bpe.service.CheckSingleMedicResults; import org.highmed.dsf.bpe.service.ExecuteQueries; import org.highmed.dsf.bpe.service.ExtractInputValues; -import org.highmed.dsf.bpe.service.FilterQueryResultsByConsent; +import org.highmed.dsf.bpe.service.FilterResultsByConsent; import org.highmed.dsf.bpe.service.GenerateBloomFilters; import org.highmed.dsf.bpe.service.GenerateCountFromIds; import org.highmed.dsf.bpe.service.ModifyQueries; -import org.highmed.dsf.bpe.service.StoreResult; +import org.highmed.dsf.bpe.service.StoreResults; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.group.GroupHelper; @@ -33,6 +35,9 @@ public class LocalServicesConfig @Autowired private FhirWebserviceClientProvider fhirClientProvider; + @Autowired + private ConsentClientFactory consentClientFactory; + @Autowired private MasterPatientIndexClientFactory masterPatientIndexClientFactory; @@ -67,9 +72,9 @@ public ExtractInputValues extractInputValues() } @Bean - public StoreResult storeResult() + public StoreResults storeResults() { - return new StoreResult(fhirClientProvider, taskHelper, readAccessHelper); + return new StoreResults(fhirClientProvider, taskHelper, readAccessHelper); } @Bean @@ -85,9 +90,15 @@ public ModifyQueries modifyQueries() } @Bean - public FilterQueryResultsByConsent filterQueryResultsByConsent() + public ConsentClient consentClient() + { + return consentClientFactory.createClient(environment::getProperty); + } + + @Bean + public FilterResultsByConsent filterResultsByConsent() { - return new FilterQueryResultsByConsent(fhirClientProvider, taskHelper, readAccessHelper); + return new FilterResultsByConsent(fhirClientProvider, taskHelper, readAccessHelper, consentClient()); } @Bean diff --git a/dsf-bpe-process-local-services/src/main/resources/bpe/localServicesIntegration.bpmn b/dsf-bpe-process-local-services/src/main/resources/bpe/localServicesIntegration.bpmn index bac4e414..9e64a4b6 100644 --- a/dsf-bpe-process-local-services/src/main/resources/bpe/localServicesIntegration.bpmn +++ b/dsf-bpe-process-local-services/src/main/resources/bpe/localServicesIntegration.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0drkcb5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_localServicesIntegration" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_localServicesIntegration" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:serviceTask id="checkResults" name="check results" camunda:class="org.highmed.dsf.bpe.service.CheckSingleMedicResults"> <bpmn:incoming>SequenceFlow_0q803rh</bpmn:incoming> <bpmn:outgoing>SequenceFlow_04ouilq</bpmn:outgoing> @@ -44,7 +44,7 @@ <bpmn:sequenceFlow id="SequenceFlow_0isxkuy" name="needs consent check" sourceRef="ExclusiveGateway_0bq7zdz" targetRef="filterByConsent"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsConsentCheck == true}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:serviceTask id="filterByConsent" name="filter by consent" camunda:class="org.highmed.dsf.bpe.service.FilterQueryResultsByConsent"> + <bpmn:serviceTask id="filterByConsent" name="filter by consent" camunda:class="org.highmed.dsf.bpe.service.FilterResultsByConsent"> <bpmn:incoming>SequenceFlow_0isxkuy</bpmn:incoming> <bpmn:outgoing>SequenceFlow_0kzp6tl</bpmn:outgoing> </bpmn:serviceTask> @@ -101,7 +101,7 @@ <bpmn:incoming>Flow_1yjkp7k</bpmn:incoming> <bpmn:outgoing>Flow_125i149</bpmn:outgoing> </bpmn:serviceTask> - <bpmn:serviceTask id="storeResult" name="store result" camunda:class="org.highmed.dsf.bpe.service.StoreResult"> + <bpmn:serviceTask id="storeResult" name="store results" camunda:class="org.highmed.dsf.bpe.service.StoreResults"> <bpmn:incoming>SequenceFlow_04ouilq</bpmn:incoming> <bpmn:outgoing>Flow_0m4rhl9</bpmn:outgoing> </bpmn:serviceTask> diff --git a/dsf-bpe-process-local-services/src/main/resources/fhir/ActivityDefinition/highmed-localServicesIntegration.xml b/dsf-bpe-process-local-services/src/main/resources/fhir/ActivityDefinition/highmed-localServicesIntegration.xml index 510b6a7d..621c6a3c 100644 --- a/dsf-bpe-process-local-services/src/main/resources/fhir/ActivityDefinition/highmed-localServicesIntegration.xml +++ b/dsf-bpe-process-local-services/src/main/resources/fhir/ActivityDefinition/highmed-localServicesIntegration.xml @@ -10,7 +10,7 @@ <valueString value="localServicesIntegrationMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-local-services-integration|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-local-services-integration|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -23,7 +23,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -43,7 +43,7 @@ </extension> <extension url="role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-role" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -55,14 +55,15 @@ </extension> <url value="http://highmed.org/bpe/Process/localServicesIntegration" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="LocalServicesIntegration" /> <title value="Local services integration" /> <subtitle value="Service integration process" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-local-services/src/main/resources/fhir/StructureDefinition/highmed-task-local-services-integration.xml b/dsf-bpe-process-local-services/src/main/resources/fhir/StructureDefinition/highmed-task-local-services-integration.xml index b56866de..600ea09a 100644 --- a/dsf-bpe-process-local-services/src/main/resources/fhir/StructureDefinition/highmed-task-local-services-integration.xml +++ b/dsf-bpe-process-local-services/src/main/resources/fhir/StructureDefinition/highmed-task-local-services-integration.xml @@ -8,12 +8,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-local-services-integration" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskLocalServicesIntegration" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -23,7 +24,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/localServicesIntegration/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/localServicesIntegration/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -75,7 +76,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-record-linkage.type.coding"> @@ -86,7 +87,7 @@ <element id="Task.input:needs-record-linkage.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-record-linkage.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -115,7 +116,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:needs-consent-check.type.coding"> @@ -126,7 +127,7 @@ <element id="Task.input:needs-consent-check.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:needs-consent-check.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -155,7 +156,7 @@ <valueString value="TaskInputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> <element id="Task.input:bloom-filter-configuration.type.coding"> @@ -166,7 +167,7 @@ <element id="Task.input:bloom-filter-configuration.type.coding.system"> <path value="Task.input.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> <element id="Task.input:bloom-filter-configuration.type.coding.code"> <path value="Task.input.type.coding.code" /> @@ -212,14 +213,14 @@ <code value="string" /> </type> </element> - <element id="Task.output:single-medic-result"> + <element id="Task.output:single-medic-count-result"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.output" /> - <sliceName value="single-medic-result" /> + <sliceName value="single-medic-count-result" /> </element> - <element id="Task.output:single-medic-result.extension"> + <element id="Task.output:single-medic-count-result.extension"> <path value="Task.output.extension" /> <slicing> <discriminator> @@ -229,7 +230,7 @@ <rules value="open" /> </slicing> </element> - <element id="Task.output:single-medic-result.extension:group-id"> + <element id="Task.output:single-medic-count-result.extension:group-id"> <path value="Task.output.extension" /> <sliceName value="group-id" /> <min value="1" /> @@ -238,45 +239,45 @@ <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> </type> </element> - <element id="Task.output:single-medic-result.type"> + <element id="Task.output:single-medic-count-result.type"> <path value="Task.output.type" /> <binding> <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> <valueString value="TaskOutputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> - <element id="Task.output:single-medic-result.type.coding"> + <element id="Task.output:single-medic-count-result.type.coding"> <path value="Task.output.type.coding" /> <min value="1" /> <max value="1" /> </element> - <element id="Task.output:single-medic-result.type.coding.system"> + <element id="Task.output:single-medic-count-result.type.coding.system"> <path value="Task.output.type.coding.system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> - <element id="Task.output:single-medic-result.type.coding.code"> + <element id="Task.output:single-medic-count-result.type.coding.code"> <path value="Task.output.type.coding.code" /> <min value="1" /> - <fixedCode value="single-medic-result" /> + <fixedCode value="single-medic-count-result" /> </element> - <element id="Task.output:single-medic-result.value[x]"> + <element id="Task.output:single-medic-count-result.value[x]"> <path value="Task.output.value[x]" /> <type> <code value="unsignedInt" /> </type> </element> - <element id="Task.output:single-medic-result-reference"> + <element id="Task.output:single-medic-result-set-reference"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.output" /> - <sliceName value="single-medic-result-reference" /> + <sliceName value="single-medic-result-set-reference" /> </element> - <element id="Task.output:single-medic-result-reference.extension"> + <element id="Task.output:single-medic-result-set-reference.extension"> <path value="Task.output.extension" /> <slicing> <discriminator> @@ -286,7 +287,7 @@ <rules value="open" /> </slicing> </element> - <element id="Task.output:single-medic-result-reference.extension:group-id"> + <element id="Task.output:single-medic-result-set-reference.extension:group-id"> <path value="Task.output.extension" /> <sliceName value="group-id" /> <min value="1" /> @@ -295,43 +296,43 @@ <profile value="http://highmed.org/fhir/StructureDefinition/extension-group-id" /> </type> </element> - <element id="Task.output:single-medic-result-reference.type"> + <element id="Task.output:single-medic-result-set-reference.type"> <path value="Task.output.type" /> <binding> <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> <valueString value="TaskOutputParameterType" /> </extension> <strength value="required" /> - <valueSet value="http://highmed.org/fhir/ValueSet/feasibility" /> + <valueSet value="http://highmed.org/fhir/ValueSet/data-sharing" /> </binding> </element> - <element id="Task.output:single-medic-result-reference.type.coding"> + <element id="Task.output:single-medic-result-set-reference.type.coding"> <path value="Task.output.type.coding" /> <min value="1" /> <max value="1" /> </element> - <element id="Task.output:single-medic-result-reference.type.coding.system"> + <element id="Task.output:single-medic-result-set-reference.type.coding.system"> <path value="Task.output.type.coding.system" /> <min value="0" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/data-sharing" /> </element> - <element id="Task.output:single-medic-result-reference.type.coding.code"> + <element id="Task.output:single-medic-result-set-reference.type.coding.code"> <path value="Task.output.type.coding.code" /> <min value="0" /> - <fixedCode value="single-medic-result-reference" /> + <fixedCode value="single-medic-result-set-reference" /> </element> - <element id="Task.output:single-medic-result-reference.value[x]"> + <element id="Task.output:single-medic-result-set-reference.value[x]"> <path value="Task.output.value[x]" /> <type> <code value="Reference" /> <targetProfile value="http://hl7.org/fhir/StructureDefinition/Binary" /> </type> </element> - <element id="Task.output:single-medic-result-reference.value[x].reference"> + <element id="Task.output:single-medic-result-set-reference.value[x].reference"> <path value="Task.output.value[x].reference" /> <min value="0" /> </element> - <element id="Task.output:single-medic-result-reference.value[x].identifier"> + <element id="Task.output:single-medic-result-set-reference.value[x].identifier"> <path value="Task.output.value[x].identifier" /> <max value="0" /> </element> diff --git a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinitionTest.java b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinitionTest.java new file mode 100644 index 00000000..90e449ca --- /dev/null +++ b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/LocalServicesProcessPluginDefinitionTest.java @@ -0,0 +1,39 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsLocalServices.*; +import static org.highmed.dsf.bpe.LocalServicesProcessPluginDefinition.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class LocalServicesProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition dataSharing = new DataSharingProcessPluginDefinition(); + ResourceProvider dataSharingProvider = dataSharing.getResourceProvider(FhirContext.forR4(), + getClass().getClassLoader(), new StandardEnvironment()); + assertNotNull(dataSharingProvider); + + ProcessPluginDefinition feasibility = new FeasibilityProcessPluginDefinition(); + ResourceProvider feasibilityProvider = feasibility.getResourceProvider(FhirContext.forR4(), + getClass().getClassLoader(), new StandardEnvironment()); + assertNotNull(feasibilityProvider); + + ProcessPluginDefinition definition = new LocalServicesProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var localServicesIntegration = provider + .getResources(PROCESS_NAME_FULL_LOCAL_SERVICES_INTEGRATION + "/" + VERSION, s -> dataSharingProvider); + assertNotNull(localServicesIntegration); + assertEquals(4, localServicesIntegration.count()); + } +} diff --git a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/start/AbstractLocalServicesMedic1ExampleStarter.java b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/start/AbstractLocalServicesMedic1ExampleStarter.java index 853f315e..5e0325b0 100644 --- a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/start/AbstractLocalServicesMedic1ExampleStarter.java +++ b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/bpe/start/AbstractLocalServicesMedic1ExampleStarter.java @@ -5,11 +5,11 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_QUERY_TYPE; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGMED_QUERY_TYPE_VALUE_AQL; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; -import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1; @@ -20,7 +20,7 @@ import javax.crypto.KeyGenerator; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.highmed.dsf.bpe.variables.BloomFilterConfig; +import org.highmed.dsf.bpe.variable.BloomFilterConfig; import org.hl7.fhir.r4.model.Base64BinaryType; import org.hl7.fhir.r4.model.BooleanType; import org.hl7.fhir.r4.model.ResourceType; @@ -42,7 +42,7 @@ private Task createStartResource() { Task task = new Task(); - task.getMeta().addProfile(PROFILE_HIGHMED_TASK_LOCAL_SERVICES); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_LOCAL_SERVICES_AND_LATEST_VERSION); task.setInstantiatesUri(PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI_AND_LATEST_VERSION); task.setStatus(Task.TaskStatus.REQUESTED); task.setIntent(Task.TaskIntent.ORDER); @@ -61,11 +61,11 @@ private Task createStartResource() task.addInput().setValue(new StringType("SELECT COUNT(e) FROM EHR e;")).getType().addCoding() .setSystem(CODESYSTEM_HIGHMED_QUERY_TYPE).setCode(CODESYSTEM_HIGMED_QUERY_TYPE_VALUE_AQL); task.addInput().setValue(new BooleanType(NEEDS_CONSENT_CHECK)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); task.addInput().setValue(new BooleanType(NEEDS_RECORD_LINKAGE)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); if (NEEDS_RECORD_LINKAGE) { @@ -77,8 +77,8 @@ private Task createStartResource() KeyGenerator.getInstance("HmacSHA3-256", bouncyCastleProvider).generateKey()); task.addInput().setValue(new Base64BinaryType(bloomFilterConfig.toBytes())).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG); } catch (Exception exception) { diff --git a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java index c804f720..a990b3ea 100644 --- a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java +++ b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java @@ -1,11 +1,10 @@ package org.highmed.dsf.fhir.profile; +import static org.highmed.dsf.bpe.LocalServicesProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.LocalServicesProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -28,7 +27,7 @@ public class ActivityDefinitionProfileTest private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", "highmed-extension-process-authorization-consortium-role-0.5.0.xml", "highmed-extension-process-authorization-organization-0.5.0.xml", @@ -50,20 +49,15 @@ public class ActivityDefinitionProfileTest @Test public void testLocalServicesIntegrationValid() throws Exception { - try (InputStream in = Files.newInputStream( - Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-localServicesIntegration.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-localServicesIntegration.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } } \ No newline at end of file diff --git a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java index fa64f641..8ff4f411 100644 --- a/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java +++ b/dsf-bpe-process-local-services/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java @@ -5,13 +5,14 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_QUERY_TYPE; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGMED_QUERY_TYPE_VALUE_AQL; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK; -import static org.highmed.dsf.bpe.ConstantsFeasibility.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK; +import static org.highmed.dsf.bpe.ConstantsDataSharing.CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE; import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES; import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsLocalServices.PROFILE_HIGHMED_TASK_LOCAL_SERVICES_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.LocalServicesProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.LocalServicesProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; @@ -40,14 +41,14 @@ public class TaskProfileTest private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-group-0.5.0.xml", "highmed-extension-group-id-0.5.0.xml", "highmed-extension-query-0.5.0.xml", "highmed-task-local-services-integration.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", - "highmed-feasibility.xml", "highmed-query-type-0.5.0.xml"), + "highmed-data-sharing.xml", "highmed-query-type-0.5.0.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", - "highmed-feasibility.xml", "highmed-query-type-0.5.0.xml")); + "highmed-data-sharing.xml", "highmed-query-type-0.5.0.xml")); private ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), validationRule.getValidationSupport()); @@ -84,17 +85,17 @@ private Task createValidTaskLocalServiceIntegration() task.addInput().setValue(new StringType("SELECT COUNT(e) FROM EHR e;")).getType().addCoding() .setSystem(CODESYSTEM_HIGHMED_QUERY_TYPE).setCode(CODESYSTEM_HIGMED_QUERY_TYPE_VALUE_AQL); - task.addInput().setValue(new BooleanType(true)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK); - task.addInput().setValue(new BooleanType(true)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE); + task.addInput().setValue(new BooleanType(true)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_CONSENT_CHECK); + task.addInput().setValue(new BooleanType(true)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_NEEDS_RECORD_LINKAGE); byte[] bloomFilterConfig = Base64.getDecoder().decode( "CIw/x19d3Oj+GLOKgYAX5KrFAl11q6qMi0qkDiyUOCvMXuF2KffVvSnjUjkTvqh4z8Xs+MuQdK6FqTedM5FY9t4qm+k92A+P"); task.addInput().setValue(new Base64BinaryType(bloomFilterConfig)).getType().addCoding() - .setSystem(CODESYSTEM_HIGHMED_FEASIBILITY) - .setCode(CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_BLOOM_FILTER_CONFIG); + .setSystem(CODESYSTEM_HIGHMED_DATA_SHARING) + .setCode(CODESYSTEM_HIGHMED_DATA_SHARING_VALUE_BLOOM_FILTER_CONFIG); return task; } diff --git a/dsf-bpe-process-ping/pom.xml b/dsf-bpe-process-ping/pom.xml index 50af9679..fcf272a7 100644 --- a/dsf-bpe-process-ping/pom.xml +++ b/dsf-bpe-process-ping/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-highmed-processes-pom</artifactId> - <version>0.5.0</version> + <version>0.6.0</version> </parent> <properties> @@ -21,6 +21,11 @@ <artifactId>dsf-bpe-process-base</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + <scope>provided</scope> + </dependency> <dependency> <groupId>de.hs-heilbronn.mi</groupId> diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/ConstantsPing.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/ConstantsPing.java index f3c80bb2..e5acecfc 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/ConstantsPing.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/ConstantsPing.java @@ -5,16 +5,70 @@ public interface ConstantsPing { - String PROFILE_HIGHMED_TASK_START_PING = "http://highmed.org/fhir/StructureDefinition/task-start-ping-process"; - String PROFILE_HIGHMED_TASK_START_PING_MESSAGE_NAME = "startPingProcessMessage"; + String PROCESS_NAME_PING_AUTOSTART = "pingAutostart"; + String PROCESS_NAME_PING = "ping"; + String PROCESS_NAME_PONG = "pong"; + + String PROCESS_NAME_FULL_PING_AUTOSTART = "highmedorg_" + PROCESS_NAME_PING_AUTOSTART; + String PROCESS_NAME_FULL_PING = "highmedorg_" + PROCESS_NAME_PING; + String PROCESS_NAME_FULL_PONG = "highmedorg_" + PROCESS_NAME_PONG; + + String PROFILE_HIGHMED_TASK_START_PING_AUTOSTART = "http://highmed.org/fhir/StructureDefinition/task-start-ping-autostart"; + String PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_START_PING_AUTOSTART + + "|" + VERSION; + String PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_PING_AUTOSTART + "/"; + String PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_MESSAGE_NAME = "startPingAutostart"; + + String PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART = "http://highmed.org/fhir/StructureDefinition/task-stop-ping-autostart"; + String PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART + "|" + + VERSION; + String PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + PROCESS_NAME_PING_AUTOSTART + + "/"; + String PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI + + VERSION; + String PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_MESSAGE_NAME = "stopPingAutostart"; + + String PROFILE_HIGHMED_TASK_START_PING = "http://highmed.org/fhir/StructureDefinition/task-start-ping"; + String PROFILE_HIGHMED_TASK_START_PING_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_START_PING + "|" + VERSION; + String PROFILE_HIGHMED_TASK_START_PING_MESSAGE_NAME = "startPing"; String PROFILE_HIGHMED_TASK_PING = "http://highmed.org/fhir/StructureDefinition/task-ping"; - String PROFILE_HIGHMED_TASK_PING_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "ping/"; + String PROFILE_HIGHMED_TASK_PING_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_PING + "|" + VERSION; + String PROFILE_HIGHMED_TASK_PING_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + PROCESS_NAME_PING + "/"; String PROFILE_HIGHMED_TASK_PING_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_PING_PROCESS_URI + VERSION; - String PROFILE_HIGHMED_TASK_PING_MESSAGE_NAME = "pingMessage"; + String PROFILE_HIGHMED_TASK_PING_MESSAGE_NAME = "ping"; String PROFILE_HIGHMED_TASK_PONG_TASK = "http://highmed.org/fhir/StructureDefinition/task-pong"; - String PROFILE_HIGHMED_TASK_PONG_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "pong/"; + String PROFILE_HIGHMED_TASK_PONG_TASK_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_PONG_TASK + "|" + VERSION; + String PROFILE_HIGHMED_TASK_PONG_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + PROCESS_NAME_PONG + "/"; String PROFILE_HIGHMED_TASK_PONG_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_PONG_PROCESS_URI + VERSION; - String PROFILE_HIGHMED_TASK_PONG_MESSAGE_NAME = "pongMessage"; + String PROFILE_HIGHMED_TASK_PONG_MESSAGE_NAME = "pong"; + + String CODESYSTEM_HIGHMED_PING = "http://highmed.org/fhir/CodeSystem/ping"; + String CODESYSTEM_HIGHMED_PING_VALUE_PING_STATUS = "ping-status"; + String CODESYSTEM_HIGHMED_PING_VALUE_PONG_STATUS = "pong-status"; + String CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER = "endpoint-identifier"; + String CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS = "target-endpoints"; + String CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL = "timer-interval"; + + String CODESYSTEM_HIGHMED_PING_STATUS = "http://highmed.org/fhir/CodeSystem/ping-status"; + String CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_ALLOWED = "not-allowed"; + String CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE = "not-reachable"; + String CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_MISSING = "pong-missing"; + String CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_RECEIVED = "pong-received"; + String CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_SEND = "pong-send"; + + String EXTENSION_URL_PING_STATUS = "http://highmed.org/fhir/StructureDefinition/extension-ping-status"; + String EXTENSION_URL_CORRELATION_KEY = "correlation-key"; + String EXTENSION_URL_ORGANIZATION_IDENTIFIER = "organization-identifier"; + String EXTENSION_URL_ENDPOINT_IDENTIFIER = "endpoint-identifier"; + String EXTENSION_URL_ERROR_MESSAGE = "error-message"; + + String BPMN_EXECUTION_VARIABLE_TIMER_INTERVAL = "timerInterval"; + String BPMN_EXECUTION_VARIABLE_STOP_TIMER = "stopTimer"; + + String TIMER_INTERVAL_DEFAULT_VALUE = "PT24H"; } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/PingProcessPluginDefinition.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/PingProcessPluginDefinition.java index 180a53a7..b1a90c2e 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/PingProcessPluginDefinition.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/PingProcessPluginDefinition.java @@ -1,5 +1,10 @@ package org.highmed.dsf.bpe; +import static org.highmed.dsf.bpe.ConstantsPing.PROCESS_NAME_FULL_PING; +import static org.highmed.dsf.bpe.ConstantsPing.PROCESS_NAME_FULL_PING_AUTOSTART; +import static org.highmed.dsf.bpe.ConstantsPing.PROCESS_NAME_FULL_PONG; + +import java.time.LocalDate; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -8,15 +13,18 @@ import org.highmed.dsf.bpe.spring.config.PingConfig; import org.highmed.dsf.fhir.resources.AbstractResource; import org.highmed.dsf.fhir.resources.ActivityDefinitionResource; +import org.highmed.dsf.fhir.resources.CodeSystemResource; import org.highmed.dsf.fhir.resources.ResourceProvider; import org.highmed.dsf.fhir.resources.StructureDefinitionResource; +import org.highmed.dsf.fhir.resources.ValueSetResource; import org.springframework.core.env.PropertyResolver; import ca.uhn.fhir.context.FhirContext; public class PingProcessPluginDefinition implements ProcessPluginDefinition { - public static final String VERSION = "0.5.0"; + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); @Override public String getName() @@ -30,10 +38,16 @@ public String getVersion() return VERSION; } + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + @Override public Stream<String> getBpmnFiles() { - return Stream.of("bpe/ping.bpmn", "bpe/pong.bpmn"); + return Stream.of("bpe/ping-autostart.bpmn", "bpe/ping.bpmn", "bpe/pong.bpmn"); } @Override @@ -47,16 +61,36 @@ public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader PropertyResolver resolver) { var aPing = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-ping.xml"); + var aPingAutostart = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-ping-autostart.xml"); var aPong = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-pong.xml"); - var tPing = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-pong.xml"); - var tStartPing = StructureDefinitionResource - .file("fhir/StructureDefinition/highmed-task-start-ping-process.xml"); - var tPong = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-ping.xml"); - Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map.of("highmedorg_ping/" + VERSION, - Arrays.asList(aPing, tPong, tStartPing), "highmedorg_pong/" + VERSION, Arrays.asList(aPong, tPing)); + var cPing = CodeSystemResource.file("fhir/CodeSystem/highmed-ping.xml"); + var cPingStatus = CodeSystemResource.file("fhir/CodeSystem/highmed-ping-status.xml"); + + var sPingStatus = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-extension-ping-status.xml"); + var sPing = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-ping.xml"); + var sPong = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-pong.xml"); + var sStartPing = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-start-ping.xml"); + var sStartPingAutostart = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-start-ping-autostart.xml"); + var sStopPingAutostart = StructureDefinitionResource + .file("fhir/StructureDefinition/highmed-task-stop-ping-autostart.xml"); + + var vPing = ValueSetResource.file("fhir/ValueSet/highmed-ping.xml"); + var vPingStatus = ValueSetResource.file("fhir/ValueSet/highmed-ping-status.xml"); + var vPongStatus = ValueSetResource.file("fhir/ValueSet/highmed-pong-status.xml"); + + Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map.of( + PROCESS_NAME_FULL_PING + "/" + VERSION, + Arrays.asList(aPing, cPing, cPingStatus, sPingStatus, sStartPing, sPong, vPing, vPingStatus), + PROCESS_NAME_FULL_PING_AUTOSTART + "/" + VERSION, + Arrays.asList(aPingAutostart, cPing, sStartPingAutostart, sStopPingAutostart, vPing), + PROCESS_NAME_FULL_PONG + "/" + VERSION, + Arrays.asList(aPong, cPing, cPingStatus, sPingStatus, sPing, vPing, vPongStatus)); - return ResourceProvider.read(VERSION, () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), - classLoader, resolver, resourcesByProcessKeyAndVersion); + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); } } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/logging/ErrorLogger.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/logging/ErrorLogger.java new file mode 100644 index 00000000..415e3fd0 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/logging/ErrorLogger.java @@ -0,0 +1,29 @@ +package org.highmed.dsf.bpe.logging; + +import org.highmed.dsf.fhir.variables.Target; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ErrorLogger +{ + private static final Logger pingLogger = LoggerFactory.getLogger("ping-error-logger"); + private static final Logger pongLogger = LoggerFactory.getLogger("pong-error-logger"); + + public void logPingStatus(Target target, String statusCode) + { + pingLogger.debug("Ping: Organization {} at Endpoint {} {}", target.getOrganizationIdentifierValue(), + target.getEndpointIdentifierValue(), statusCode); + } + + public void logPingStatus(Target target, String statusCode, String errorMessage) + { + pingLogger.debug("Ping: Organization {} at Endpoint {} {}: {}", target.getOrganizationIdentifierValue(), + target.getEndpointIdentifierValue(), statusCode, errorMessage); + } + + public void logPongStatus(Target target, String statusCode, String errorMessage) + { + pongLogger.debug("Pong: Organization {} at Endpoint {} {}: {}", target.getOrganizationIdentifierValue(), + target.getEndpointIdentifierValue(), statusCode, errorMessage); + } +} diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPing.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPing.java index 8a64cc1e..b8206517 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPing.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPing.java @@ -1,18 +1,111 @@ package org.highmed.dsf.bpe.message; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_ALLOWED; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER; + +import java.util.Objects; +import java.util.stream.Stream; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.logging.ErrorLogger; +import org.highmed.dsf.bpe.util.PingStatusGenerator; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; 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.Target; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResourceType; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.ParameterComponent; import ca.uhn.fhir.context.FhirContext; public class SendPing extends AbstractTaskMessageSend { + private final EndpointProvider endpointProvider; + private final PingStatusGenerator statusGenerator; + private final ErrorLogger errorLogger; + public SendPing(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext, + EndpointProvider endpointProvider, PingStatusGenerator statusGenerator, ErrorLogger errorLogger) { super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + + this.endpointProvider = endpointProvider; + this.statusGenerator = statusGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(endpointProvider, "endpointProvider"); + Objects.requireNonNull(statusGenerator, "statusGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + protected Stream<ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) + { + return Stream.of( + getTaskHelper().createInput(CODESYSTEM_HIGHMED_PING, CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER, + new Reference().setIdentifier(endpointProvider.getLocalEndpointIdentifier()) + .setType(ResourceType.Endpoint.name()))); + } + + @Override + protected void handleSendTaskError(Exception exception, String errorMessage) + { + Target target = getTarget(); + Task task = getLeadingTaskFromExecutionVariables(); + + if (task != null) + { + String statusCode = CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE; + if (exception instanceof WebApplicationException) + { + WebApplicationException webApplicationException = (WebApplicationException) exception; + if (webApplicationException.getResponse() != null && webApplicationException.getResponse() + .getStatus() == Response.Status.FORBIDDEN.getStatusCode()) + { + statusCode = CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_ALLOWED; + } + } + + String specialErrorMessage = createErrorMessage(exception); + + task.addOutput(statusGenerator.createPingStatusOutput(target, statusCode, specialErrorMessage)); + updateLeadingTaskInExecutionVariables(task); + + errorLogger.logPingStatus(target, statusCode, specialErrorMessage); + } + + super.handleSendTaskError(exception, errorMessage); + + } + + @Override + protected void addErrorMessage(Task task, String errorMessage) + { + // error message part of + } + + private String createErrorMessage(Exception exception) + { + return exception.getClass().getSimpleName() + + ((exception.getMessage() != null && !exception.getMessage().isBlank()) + ? (": " + exception.getMessage()) + : ""); } } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPong.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPong.java index 3ba8659c..0cd05d96 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPong.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendPong.java @@ -1,18 +1,97 @@ package org.highmed.dsf.bpe.message; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_ALLOWED; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_SEND; + +import java.util.Objects; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.logging.ErrorLogger; +import org.highmed.dsf.bpe.util.PingStatusGenerator; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; 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.Target; +import org.hl7.fhir.r4.model.Task; import ca.uhn.fhir.context.FhirContext; public class SendPong extends AbstractTaskMessageSend { + private final PingStatusGenerator statusGenerator; + private final ErrorLogger errorLogger; + public SendPong(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext, + PingStatusGenerator statusGenerator, ErrorLogger errorLogger) { super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + + this.statusGenerator = statusGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(statusGenerator, "statusGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + public void doExecute(DelegateExecution execution) throws Exception + { + super.doExecute(execution); + + Target target = getTarget(); + Task task = getLeadingTaskFromExecutionVariables(); + task.addOutput(statusGenerator.createPongStatusOutput(target, CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_SEND)); + updateLeadingTaskInExecutionVariables(task); + } + + @Override + protected void handleEndEventError(Exception exception, String errorMessage) + { + Target target = getTarget(); + Task task = getLeadingTaskFromExecutionVariables(); + + if (task != null) + { + String statusCode = CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE; + if (exception instanceof WebApplicationException) + { + WebApplicationException webApplicationException = (WebApplicationException) exception; + if (webApplicationException.getResponse() != null && webApplicationException.getResponse() + .getStatus() == Response.Status.FORBIDDEN.getStatusCode()) + { + statusCode = CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_ALLOWED; + } + } + + String specialErrorMessage = createErrorMessage(exception); + + task.addOutput(statusGenerator.createPongStatusOutput(target, statusCode, specialErrorMessage)); + updateLeadingTaskInExecutionVariables(task); + + errorLogger.logPongStatus(target, statusCode, specialErrorMessage); + } + + super.handleEndEventError(exception, errorMessage); + } + + private String createErrorMessage(Exception exception) + { + return exception.getClass().getSimpleName() + + ((exception.getMessage() != null && !exception.getMessage().isBlank()) + ? (": " + exception.getMessage()) + : ""); } } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendStartPing.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendStartPing.java new file mode 100644 index 00000000..ae056fa9 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/message/SendStartPing.java @@ -0,0 +1,34 @@ +package org.highmed.dsf.bpe.message; + +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS; + +import java.util.stream.Stream; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.AbstractTaskMessageSend; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.hl7.fhir.r4.model.Task; + +import ca.uhn.fhir.context.FhirContext; + +public class SendStartPing extends AbstractTaskMessageSend +{ + public SendStartPing(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, FhirContext fhirContext) + { + super(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Override + protected Stream<Task.ParameterComponent> getAdditionalInputParameters(DelegateExecution execution) + { + return getLeadingTaskFromExecutionVariables().getInput().stream().filter(Task.ParameterComponent::hasType) + .filter(i -> i.getType().getCoding().stream() + .anyMatch(c -> CODESYSTEM_HIGHMED_PING.equals(c.getSystem()) + && CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS.equals(c.getCode()))); + } +} diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogNoResponse.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogNoResponse.java new file mode 100644 index 00000000..a86f4cda --- /dev/null +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogNoResponse.java @@ -0,0 +1,68 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_LEADING_TASK; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_MISSING; + +import java.util.Objects; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.logging.ErrorLogger; +import org.highmed.dsf.bpe.util.PingStatusGenerator; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourceValues; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogNoResponse extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(LogNoResponse.class); + + private final PingStatusGenerator responseGenerator; + private final ErrorLogger errorLogger; + + public LogNoResponse(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, PingStatusGenerator responseGenerator, ErrorLogger errorLogger) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.responseGenerator = responseGenerator; + this.errorLogger = errorLogger; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(responseGenerator, "responseGenerator"); + Objects.requireNonNull(errorLogger, "errorLogger"); + } + + @Override + public void doExecute(DelegateExecution execution) throws Exception + { + Task task = getLeadingTaskFromExecutionVariables(); + + Targets targets = (Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS); + targets.getEntries().forEach(t -> logAndAddResponseToTask(task, t)); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_LEADING_TASK, FhirResourceValues.create(task)); + } + + private void logAndAddResponseToTask(Task task, Target target) + { + logger.warn("PONG from organization {} (endpoint {}) missing", target.getOrganizationIdentifierValue(), + target.getEndpointIdentifierValue()); + + task.addOutput( + responseGenerator.createPingStatusOutput(target, CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_MISSING)); + errorLogger.logPingStatus(target, CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_MISSING); + } +} diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java index 400ee43d..5f967bcb 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/LogPong.java @@ -1,10 +1,20 @@ package org.highmed.dsf.bpe.service; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_RECEIVED; + +import java.util.Objects; + import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.bpe.util.PingStatusGenerator; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.Targets; +import org.highmed.dsf.fhir.variables.TargetsValues; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,17 +23,44 @@ public class LogPong extends AbstractServiceDelegate { private static final Logger logger = LoggerFactory.getLogger(LogPong.class); + private final PingStatusGenerator responseGenerator; + public LogPong(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper) + ReadAccessHelper readAccessHelper, PingStatusGenerator responseGenerator) { super(clientProvider, taskHelper, readAccessHelper); + + this.responseGenerator = responseGenerator; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(responseGenerator, "responseGenerator"); } @Override - public void doExecute(DelegateExecution execution) throws Exception + public void doExecute(DelegateExecution execution) { - Task task = getCurrentTaskFromExecutionVariables(); + Target target = getTarget(execution); + + logger.info("PONG from {} (endpoint: {})", target.getOrganizationIdentifierValue(), + target.getEndpointIdentifierValue()); + + Task leading = getLeadingTaskFromExecutionVariables(); + leading.addOutput( + responseGenerator.createPingStatusOutput(target, CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_RECEIVED)); + updateLeadingTaskInExecutionVariables(leading); - logger.info("PONG from {}", task.getRequester().getIdentifier().getValue()); + Targets targets = (Targets) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGETS); + targets = targets.removeByEndpointIdentifierValue(target.getEndpointIdentifierValue()); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(targets)); + } + + private Target getTarget(DelegateExecution execution) + { + return (Target) execution.getVariable(BPMN_EXECUTION_VARIABLE_TARGET); } } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPingTargets.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPingTargets.java index 9066782e..eb142450 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPingTargets.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPingTargets.java @@ -1,33 +1,61 @@ package org.highmed.dsf.bpe.service; import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.UUID; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; -import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; import org.highmed.dsf.fhir.task.TaskHelper; import org.highmed.dsf.fhir.variables.Target; import org.highmed.dsf.fhir.variables.Targets; import org.highmed.dsf.fhir.variables.TargetsValues; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Endpoint.EndpointStatus; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; public class SelectPingTargets extends AbstractServiceDelegate implements InitializingBean { - private final EndpointProvider endpointProvider; + private static final Logger logger = LoggerFactory.getLogger(SelectPingTargets.class); + + private final OrganizationProvider organizationProvider; + + private static final Pattern endpointResouceTypes = Pattern.compile( + "Endpoint|HealthcareService|ImagingStudy|InsurancePlan|Location|Organization|OrganizationAffiliation|PractitionerRole"); public SelectPingTargets(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, - ReadAccessHelper readAccessHelper, EndpointProvider endpointProvider) + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider) { super(clientProvider, taskHelper, readAccessHelper); - this.endpointProvider = endpointProvider; + this.organizationProvider = organizationProvider; } @Override @@ -35,19 +63,158 @@ public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); - Objects.requireNonNull(endpointProvider, "endpointProvider"); + Objects.requireNonNull(organizationProvider, "organizationProvider"); } @Override public void doExecute(DelegateExecution execution) throws Exception { - String localAddress = endpointProvider.getLocalEndpoint().getAddress(); + Task task = getLeadingTaskFromExecutionVariables(); + task.addOutput(getTaskHelper().createOutput(CODESYSTEM_HIGHMED_BPMN, CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY, + execution.getBusinessKey())); + updateLeadingTaskInExecutionVariables(task); + + // String localAddress = endpointProvider.getLocalEndpoint().getAddress(); + // List<Target> targets = endpointProvider.getDefaultEndpointsByOrganizationIdentifier().entrySet().stream() + // .filter(a -> !localAddress.equals(a.getValue().getAddress())) + // .map(e -> Target.createBiDirectionalTarget(e.getKey(), + // e.getValue().getIdentifier().stream() + // .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + // .map(Identifier::getValue).get(), + // e.getValue().getAddress(), UUID.randomUUID().toString())) + // .collect(Collectors.toList()); + + Stream<Endpoint> targetEndpoints = getTargetEndpointsSearchParameter().map(this::searchForEndpoints) + .orElse(allEndpoints()); + + Map<String, Identifier> organizationIdentifierByOrganizationId = organizationProvider.getRemoteOrganizations() + .stream() + .collect(Collectors.toMap(o -> o.getIdElement().getIdPart(), + o -> o.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER.equals(i.getSystem())) + .findFirst().get())); + + Stream<Endpoint> remoteTargetEndpointsWithActiveOrganization = targetEndpoints + .filter(e -> getOrganizationIdentifier(e, organizationIdentifierByOrganizationId).isPresent()); - List<Target> targets = endpointProvider.getDefaultEndpointAdressesByOrganizationIdentifier().entrySet().stream() - .filter(a -> !localAddress.equals(a.getValue())) - .map(e -> Target.createBiDirectionalTarget(e.getKey(), e.getValue(), UUID.randomUUID().toString())) - .collect(Collectors.toList()); + List<Target> targets = remoteTargetEndpointsWithActiveOrganization.map(e -> + { + String organizationIdentifier = getOrganizationIdentifier(e, organizationIdentifierByOrganizationId).get(); + String endpointIdentifier = getEndpointIdentifier(e).get(); + String endpointAddress = getEndpointAddress(e).get(); + return Target.createBiDirectionalTarget(organizationIdentifier, endpointIdentifier, endpointAddress, + UUID.randomUUID().toString()); + }).collect(Collectors.toList()); execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(new Targets(targets))); } + + private Optional<UriComponents> getTargetEndpointsSearchParameter() + { + Task task = getLeadingTaskFromExecutionVariables(); + return getTaskHelper() + .getFirstInputParameterStringValue(task, CODESYSTEM_HIGHMED_PING, + CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS) + .map(requestUrl -> UriComponentsBuilder.fromUriString(requestUrl).build()); + } + + private Stream<Endpoint> searchForEndpoints(UriComponents searchParameters) + { + return searchForEndpoints(searchParameters, 1, 0); + } + + private Stream<Endpoint> searchForEndpoints(UriComponents searchParameters, int page, int currentTotal) + { + if (searchParameters.getPathSegments().isEmpty()) + return Stream.empty(); + + Optional<Class<? extends Resource>> resourceType = getResourceType(searchParameters); + if (resourceType.isEmpty()) + return Stream.empty(); + + Map<String, List<String>> queryParameters = new HashMap<String, List<String>>(); + queryParameters.putAll(searchParameters.getQueryParams()); + queryParameters.put("_page", Collections.singletonList(String.valueOf(page))); + + Bundle searchResult = getFhirWebserviceClientProvider().getLocalWebserviceClient() + .searchWithStrictHandling(resourceType.get(), queryParameters); + + if (searchResult.getTotal() > currentTotal + searchResult.getEntry().size()) + return Stream.concat(toEndpoints(searchResult), + searchForEndpoints(searchParameters, page + 1, currentTotal + searchResult.getEntry().size())); + else + return toEndpoints(searchResult); + } + + @SuppressWarnings("unchecked") + private Optional<Class<? extends Resource>> getResourceType(UriComponents searchParameters) + { + if (searchParameters.getPathSegments().isEmpty()) + return Optional.empty(); + + String type = searchParameters.getPathSegments().get(searchParameters.getPathSegments().size() - 1); + if (!endpointResouceTypes.matcher(type).matches()) + return Optional.empty(); + + try + { + return Optional.of((Class<? extends Resource>) Class.forName("org.hl7.fhir.r4.model." + type)); + } + catch (ClassNotFoundException e) + { + logger.error("Unable to find class for FHIR resource type " + type, e); + return Optional.empty(); + } + } + + private Stream<Endpoint> allEndpoints() + { + return allEndpoints(1, 0); + } + + private Stream<Endpoint> allEndpoints(int page, int currentTotal) + { + Bundle searchResult = getFhirWebserviceClientProvider().getLocalWebserviceClient() + .searchWithStrictHandling(Endpoint.class, Map.of("status", Collections.singletonList("active"), "_page", + Collections.singletonList(String.valueOf(page)))); + + if (searchResult.getTotal() > currentTotal + searchResult.getEntry().size()) + return Stream.concat(toEndpoints(searchResult), + allEndpoints(page + 1, currentTotal + searchResult.getEntry().size())); + else + return toEndpoints(searchResult); + } + + private Stream<Endpoint> toEndpoints(Bundle searchResult) + { + Objects.requireNonNull(searchResult, "searchResult"); + + return searchResult.getEntry().stream().filter(BundleEntryComponent::hasResource) + .filter(e -> e.getResource() instanceof Endpoint).map(e -> (Endpoint) e.getResource()) + .filter(Endpoint::hasStatus).filter(e -> EndpointStatus.ACTIVE.equals(e.getStatus())); + } + + private Optional<String> getOrganizationIdentifier(Endpoint endpoint, + Map<String, Identifier> organizationIdentifierByOrganizationId) + { + if (!endpoint.hasManagingOrganization() || !endpoint.getManagingOrganization().hasReferenceElement()) + return Optional.empty(); + + return Optional + .ofNullable(organizationIdentifierByOrganizationId + .get(endpoint.getManagingOrganization().getReferenceElement().getIdPart())) + .map(Identifier::getValue); + } + + private Optional<String> getEndpointIdentifier(Endpoint endpoint) + { + return endpoint.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst() + .map(Identifier::getValue); + } + + private Optional<String> getEndpointAddress(Endpoint endpoint) + { + return endpoint.hasAddress() ? Optional.of(endpoint.getAddress()) : Optional.empty(); + } } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java index b064d657..427aacf6 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/SelectPongTarget.java @@ -3,9 +3,12 @@ import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER; import java.util.Objects; +import org.camunda.bpm.engine.delegate.BpmnError; import org.camunda.bpm.engine.delegate.DelegateExecution; import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; @@ -15,11 +18,16 @@ import org.highmed.dsf.fhir.variables.Target; import org.highmed.dsf.fhir.variables.TargetValues; import org.hl7.fhir.r4.model.Identifier; +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 SelectPongTarget extends AbstractServiceDelegate implements InitializingBean { + private static final Logger logger = LoggerFactory.getLogger(SelectPongTarget.class); + private final EndpointProvider endpointProvider; public SelectPongTarget(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, @@ -45,11 +53,28 @@ public void doExecute(DelegateExecution execution) throws Exception String correlationKey = getTaskHelper().getFirstInputParameterStringValue(task, CODESYSTEM_HIGHMED_BPMN, CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).get(); - Identifier targetOrganizationIdentifier = task.getRequester().getIdentifier(); + String targetOrganizationIdentifierValue = task.getRequester().getIdentifier().getValue(); + String targetEndpointIdentifierValue = getEndpointIdentifierValue(task); + + String targetEndpointAddress = endpointProvider.getEndpointAddress(targetEndpointIdentifierValue) + .orElseThrow(() -> + { + logger.warn( + "Pong response target (organization {}, endpoint {}) not found locally or not active, not sending pong", + targetOrganizationIdentifierValue, targetEndpointIdentifierValue); + return new BpmnError("target_not_allowed"); + }); execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, - TargetValues.create(Target.createBiDirectionalTarget(targetOrganizationIdentifier.getValue(), - endpointProvider.getFirstDefaultEndpointAddress(targetOrganizationIdentifier.getValue()).get(), - correlationKey))); + TargetValues.create(Target.createBiDirectionalTarget(targetOrganizationIdentifierValue, + targetEndpointIdentifierValue, targetEndpointAddress, correlationKey))); + } + + private String getEndpointIdentifierValue(Task task) + { + return getTaskHelper() + .getFirstInputParameterReferenceValue(task, CODESYSTEM_HIGHMED_PING, + CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER) + .map(Reference::getIdentifier).map(Identifier::getValue).get(); } } diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/StartTimer.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/StartTimer.java new file mode 100644 index 00000000..c14e3d4a --- /dev/null +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/StartTimer.java @@ -0,0 +1,62 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGET; +import static org.highmed.dsf.bpe.ConstantsPing.BPMN_EXECUTION_VARIABLE_STOP_TIMER; +import static org.highmed.dsf.bpe.ConstantsPing.BPMN_EXECUTION_VARIABLE_TIMER_INTERVAL; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL; +import static org.highmed.dsf.bpe.ConstantsPing.TIMER_INTERVAL_DEFAULT_VALUE; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.variable.Variables; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.organization.EndpointProvider; +import org.highmed.dsf.fhir.organization.OrganizationProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.Target; +import org.highmed.dsf.fhir.variables.TargetValues; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StartTimer extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(StartTimer.class); + + private final OrganizationProvider organizationProvider; + private final EndpointProvider endpointProvider; + + public StartTimer(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper, OrganizationProvider organizationProvider, + EndpointProvider endpointProvider) + { + super(clientProvider, taskHelper, readAccessHelper); + + this.organizationProvider = organizationProvider; + this.endpointProvider = endpointProvider; + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + logger.debug("Setting variable '{}' to false", BPMN_EXECUTION_VARIABLE_STOP_TIMER); + execution.setVariable(BPMN_EXECUTION_VARIABLE_STOP_TIMER, Variables.booleanValue(false)); + + String timerInterval = getTimerInterval(); + logger.debug("Setting variable '{}' to {}", BPMN_EXECUTION_VARIABLE_TIMER_INTERVAL, timerInterval); + execution.setVariable(BPMN_EXECUTION_VARIABLE_TIMER_INTERVAL, Variables.stringValue(timerInterval)); + + execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGET, + TargetValues.create(Target.createUniDirectionalTarget(organizationProvider.getLocalIdentifierValue(), + endpointProvider.getLocalEndpointIdentifier().getValue(), + endpointProvider.getLocalEndpointAddress()))); + } + + private String getTimerInterval() + { + return getTaskHelper().getFirstInputParameterStringValue(getLeadingTaskFromExecutionVariables(), + CODESYSTEM_HIGHMED_PING, CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL) + .orElse(TIMER_INTERVAL_DEFAULT_VALUE); + } +} diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/StopTimer.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/StopTimer.java new file mode 100644 index 00000000..d8efeae3 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/service/StopTimer.java @@ -0,0 +1,30 @@ +package org.highmed.dsf.bpe.service; + +import static org.highmed.dsf.bpe.ConstantsPing.BPMN_EXECUTION_VARIABLE_STOP_TIMER; + +import org.camunda.bpm.engine.delegate.DelegateExecution; +import org.camunda.bpm.engine.variable.Variables; +import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; +import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; +import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; +import org.highmed.dsf.fhir.task.TaskHelper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class StopTimer extends AbstractServiceDelegate +{ + private static final Logger logger = LoggerFactory.getLogger(StopTimer.class); + + public StopTimer(FhirWebserviceClientProvider clientProvider, TaskHelper taskHelper, + ReadAccessHelper readAccessHelper) + { + super(clientProvider, taskHelper, readAccessHelper); + } + + @Override + protected void doExecute(DelegateExecution execution) throws Exception + { + logger.debug("Setting variable '{}' to true", BPMN_EXECUTION_VARIABLE_STOP_TIMER); + execution.setVariable(BPMN_EXECUTION_VARIABLE_STOP_TIMER, Variables.booleanValue(true)); + } +} diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java index a67497cf..8082453f 100644 --- a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/spring/config/PingConfig.java @@ -1,11 +1,17 @@ package org.highmed.dsf.bpe.spring.config; +import org.highmed.dsf.bpe.logging.ErrorLogger; import org.highmed.dsf.bpe.message.SendPing; import org.highmed.dsf.bpe.message.SendPong; +import org.highmed.dsf.bpe.message.SendStartPing; +import org.highmed.dsf.bpe.service.LogNoResponse; import org.highmed.dsf.bpe.service.LogPing; import org.highmed.dsf.bpe.service.LogPong; import org.highmed.dsf.bpe.service.SelectPingTargets; import org.highmed.dsf.bpe.service.SelectPongTarget; +import org.highmed.dsf.bpe.service.StartTimer; +import org.highmed.dsf.bpe.service.StopTimer; +import org.highmed.dsf.bpe.util.PingStatusGenerator; import org.highmed.dsf.fhir.authorization.read.ReadAccessHelper; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.EndpointProvider; @@ -38,16 +44,48 @@ public class PingConfig @Autowired private FhirContext fhirContext; + @Bean + public StartTimer startTimer() + { + return new StartTimer(clientProvider, taskHelper, readAccessHelper, organizationProvider, endpointProvider); + } + + @Bean + public SendStartPing sendStartPing() + { + return new SendStartPing(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + } + + @Bean + public StopTimer stopTimer() + { + return new StopTimer(clientProvider, taskHelper, readAccessHelper); + } + + @Bean + public PingStatusGenerator responseGenerator() + { + return new PingStatusGenerator(); + } + + @Bean + public ErrorLogger errorLogger() + { + return new ErrorLogger(); + } + @Bean public SendPing sendPing() { - return new SendPing(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + return new SendPing(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext, + endpointProvider, responseGenerator(), errorLogger()); } @Bean public SendPong sendPong() { - return new SendPong(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext); + return new SendPong(clientProvider, taskHelper, readAccessHelper, organizationProvider, fhirContext, + responseGenerator(), errorLogger()); } @Bean @@ -59,13 +97,19 @@ public LogPing logPing() @Bean public LogPong logPong() { - return new LogPong(clientProvider, taskHelper, readAccessHelper); + return new LogPong(clientProvider, taskHelper, readAccessHelper, responseGenerator()); + } + + @Bean + public LogNoResponse logNoResponse() + { + return new LogNoResponse(clientProvider, taskHelper, readAccessHelper, responseGenerator(), errorLogger()); } @Bean public SelectPingTargets selectPingTargets() { - return new SelectPingTargets(clientProvider, taskHelper, readAccessHelper, endpointProvider); + return new SelectPingTargets(clientProvider, taskHelper, readAccessHelper, organizationProvider); } @Bean diff --git a/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/util/PingStatusGenerator.java b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/util/PingStatusGenerator.java new file mode 100644 index 00000000..8e762c5d --- /dev/null +++ b/dsf-bpe-process-ping/src/main/java/org/highmed/dsf/bpe/util/PingStatusGenerator.java @@ -0,0 +1,64 @@ +package org.highmed.dsf.bpe.util; + +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_PING_STATUS; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_PONG_STATUS; +import static org.highmed.dsf.bpe.ConstantsPing.EXTENSION_URL_CORRELATION_KEY; +import static org.highmed.dsf.bpe.ConstantsPing.EXTENSION_URL_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.EXTENSION_URL_ERROR_MESSAGE; +import static org.highmed.dsf.bpe.ConstantsPing.EXTENSION_URL_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.EXTENSION_URL_PING_STATUS; + +import org.highmed.dsf.fhir.variables.Target; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Task.TaskOutputComponent; + +public class PingStatusGenerator +{ + public TaskOutputComponent createPingStatusOutput(Target target, String statusCode) + { + return createPingStatusOutput(target, statusCode, null); + } + + public TaskOutputComponent createPingStatusOutput(Target target, String statusCode, String errorMessage) + { + return createStatusOutput(target, CODESYSTEM_HIGHMED_PING_VALUE_PING_STATUS, statusCode, errorMessage); + } + + public TaskOutputComponent createPongStatusOutput(Target target, String statusCode) + { + return createPongStatusOutput(target, statusCode, null); + } + + public TaskOutputComponent createPongStatusOutput(Target target, String statusCode, String errorMessage) + { + return createStatusOutput(target, CODESYSTEM_HIGHMED_PING_VALUE_PONG_STATUS, statusCode, errorMessage); + } + + private TaskOutputComponent createStatusOutput(Target target, String outputParameter, String statusCode, + String errorMessage) + { + TaskOutputComponent output = new TaskOutputComponent(); + output.setValue(new Coding().setSystem(CODESYSTEM_HIGHMED_PING_STATUS).setCode(statusCode)); + output.getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING).setCode(outputParameter); + + Extension extension = output.addExtension(); + extension.setUrl(EXTENSION_URL_PING_STATUS); + extension.addExtension(EXTENSION_URL_CORRELATION_KEY, new StringType(target.getCorrelationKey())); + extension.addExtension().setUrl(EXTENSION_URL_ORGANIZATION_IDENTIFIER) + .setValue(new Identifier().setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(target.getOrganizationIdentifierValue())); + extension.addExtension().setUrl(EXTENSION_URL_ENDPOINT_IDENTIFIER).setValue(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER).setValue(target.getEndpointIdentifierValue())); + if (errorMessage != null) + extension.addExtension().setUrl(EXTENSION_URL_ERROR_MESSAGE).setValue(new StringType(errorMessage)); + + return output; + } +} diff --git a/dsf-bpe-process-ping/src/main/resources/bpe/ping-autostart.bpmn b/dsf-bpe-process-ping/src/main/resources/bpe/ping-autostart.bpmn new file mode 100644 index 00000000..2a8d18fc --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/bpe/ping-autostart.bpmn @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="UTF-8"?> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1bd6yss" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.11.1"> + <bpmn:process id="highmedorg_pingAutostart" isExecutable="true" camunda:versionTag="#{version}"> + <bpmn:endEvent id="Event_1ukqals"> + <bpmn:incoming>Flow_0stek1z</bpmn:incoming> + </bpmn:endEvent> + <bpmn:exclusiveGateway id="Gateway_1xqxerc"> + <bpmn:incoming>Flow_05mfu8d</bpmn:incoming> + <bpmn:incoming>Flow_1ltiore</bpmn:incoming> + <bpmn:outgoing>Flow_0g1txh0</bpmn:outgoing> + <bpmn:outgoing>Flow_0jy9ipp</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:startEvent id="AutostartPingStartMessageStartEvent" name="start ping autostart"> + <bpmn:outgoing>Flow_09o8bb5</bpmn:outgoing> + <bpmn:messageEventDefinition id="MessageEventDefinition_1ot9xdv" messageRef="Message_13deqwn" /> + </bpmn:startEvent> + <bpmn:parallelGateway id="Gateway_00tj0cp"> + <bpmn:incoming>Flow_1bbw6lm</bpmn:incoming> + <bpmn:outgoing>Flow_05mfu8d</bpmn:outgoing> + <bpmn:outgoing>Flow_06toths</bpmn:outgoing> + </bpmn:parallelGateway> + <bpmn:intermediateCatchEvent id="Event_0eqigaq" name="wait"> + <bpmn:incoming>Flow_1asxc2j</bpmn:incoming> + <bpmn:outgoing>Flow_1ltiore</bpmn:outgoing> + <bpmn:timerEventDefinition id="TimerEventDefinition_0f3gxu4"> + <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">${timerInterval}</bpmn:timeDuration> + </bpmn:timerEventDefinition> + </bpmn:intermediateCatchEvent> + <bpmn:parallelGateway id="Gateway_0oa1bkj"> + <bpmn:incoming>Flow_0y9pdwn</bpmn:incoming> + <bpmn:incoming>Flow_13osd7u</bpmn:incoming> + <bpmn:outgoing>Flow_0stek1z</bpmn:outgoing> + </bpmn:parallelGateway> + <bpmn:sequenceFlow id="Flow_0stek1z" sourceRef="Gateway_0oa1bkj" targetRef="Event_1ukqals" /> + <bpmn:sequenceFlow id="Flow_09o8bb5" sourceRef="AutostartPingStartMessageStartEvent" targetRef="startTimer" /> + <bpmn:sequenceFlow id="Flow_1ltiore" sourceRef="Event_0eqigaq" targetRef="Gateway_1xqxerc" /> + <bpmn:sequenceFlow id="Flow_05mfu8d" sourceRef="Gateway_00tj0cp" targetRef="Gateway_1xqxerc" /> + <bpmn:sequenceFlow id="Flow_0g1txh0" name="stop timer set" sourceRef="Gateway_1xqxerc" targetRef="Gateway_129hw90"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${stopTimer}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:exclusiveGateway id="Gateway_0sx5e0s"> + <bpmn:incoming>Flow_1yj8623</bpmn:incoming> + <bpmn:outgoing>Flow_1asxc2j</bpmn:outgoing> + <bpmn:outgoing>Flow_1h835ja</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="Flow_1asxc2j" sourceRef="Gateway_0sx5e0s" targetRef="Event_0eqigaq"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!stopTimer}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:sequenceFlow id="Flow_1h835ja" name="stop timer set" sourceRef="Gateway_0sx5e0s" targetRef="Gateway_129hw90"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${stopTimer}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:subProcess id="StopSubProcess"> + <bpmn:incoming>Flow_06toths</bpmn:incoming> + <bpmn:outgoing>Flow_0y9pdwn</bpmn:outgoing> + <bpmn:startEvent id="Event_02xmnq6"> + <bpmn:outgoing>Flow_1x5v76c</bpmn:outgoing> + </bpmn:startEvent> + <bpmn:serviceTask id="StopTimer" name="stop timer" camunda:class="org.highmed.dsf.bpe.service.StopTimer"> + <bpmn:incoming>Flow_0m0cias</bpmn:incoming> + <bpmn:outgoing>Flow_1vxlaau</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:intermediateCatchEvent id="AutostartPingStopMessageStartEvent" name="stop ping autostart"> + <bpmn:incoming>Flow_1x5v76c</bpmn:incoming> + <bpmn:outgoing>Flow_0m0cias</bpmn:outgoing> + <bpmn:messageEventDefinition id="MessageEventDefinition_1d7e8jd" messageRef="Message_1ws42uv" /> + </bpmn:intermediateCatchEvent> + <bpmn:sequenceFlow id="Flow_0m0cias" sourceRef="AutostartPingStopMessageStartEvent" targetRef="StopTimer" /> + <bpmn:sequenceFlow id="Flow_1x5v76c" sourceRef="Event_02xmnq6" targetRef="AutostartPingStopMessageStartEvent" /> + <bpmn:endEvent id="Event_1ckek3z"> + <bpmn:incoming>Flow_1vxlaau</bpmn:incoming> + </bpmn:endEvent> + <bpmn:sequenceFlow id="Flow_1vxlaau" sourceRef="StopTimer" targetRef="Event_1ckek3z" /> + </bpmn:subProcess> + <bpmn:sequenceFlow id="Flow_06toths" sourceRef="Gateway_00tj0cp" targetRef="StopSubProcess" /> + <bpmn:sequenceFlow id="Flow_0y9pdwn" sourceRef="StopSubProcess" targetRef="Gateway_0oa1bkj" /> + <bpmn:sequenceFlow id="Flow_0jy9ipp" sourceRef="Gateway_1xqxerc" targetRef="startPing"> + <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${!stopTimer}</bpmn:conditionExpression> + </bpmn:sequenceFlow> + <bpmn:sequenceFlow id="Flow_1bbw6lm" sourceRef="startTimer" targetRef="Gateway_00tj0cp" /> + <bpmn:serviceTask id="startTimer" name="start timer" camunda:class="org.highmed.dsf.bpe.service.StartTimer"> + <bpmn:incoming>Flow_09o8bb5</bpmn:incoming> + <bpmn:outgoing>Flow_1bbw6lm</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:exclusiveGateway id="Gateway_129hw90"> + <bpmn:incoming>Flow_1h835ja</bpmn:incoming> + <bpmn:incoming>Flow_0g1txh0</bpmn:incoming> + <bpmn:outgoing>Flow_13osd7u</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:sequenceFlow id="Flow_13osd7u" sourceRef="Gateway_129hw90" targetRef="Gateway_0oa1bkj" /> + <bpmn:sequenceFlow id="Flow_1yj8623" sourceRef="startPing" targetRef="Gateway_0sx5e0s" /> + <bpmn:intermediateThrowEvent id="startPing" name="start ping"> + <bpmn:extensionElements> + <camunda:inputOutput> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-start-ping|#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">startPing</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/ping/#{version}</camunda:inputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_0jy9ipp</bpmn:incoming> + <bpmn:outgoing>Flow_1yj8623</bpmn:outgoing> + <bpmn:messageEventDefinition id="MessageEventDefinition_1gjl6d4" camunda:class="org.highmed.dsf.bpe.message.SendStartPing" /> + </bpmn:intermediateThrowEvent> + </bpmn:process> + <bpmn:message id="Message_13deqwn" name="startPingAutostart" /> + <bpmn:message id="Message_1ws42uv" name="stopPingAutostart" /> + <bpmndi:BPMNDiagram id="BPMNDiagram_1"> + <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="highmedorg_pingAutostart"> + <bpmndi:BPMNEdge id="Flow_1yj8623_di" bpmnElement="Flow_1yj8623"> + <di:waypoint x="668" y="197" /> + <di:waypoint x="725" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_13osd7u_di" bpmnElement="Flow_13osd7u"> + <di:waypoint x="915" y="197" /> + <di:waypoint x="985" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1bbw6lm_di" bpmnElement="Flow_1bbw6lm"> + <di:waypoint x="360" y="197" /> + <di:waypoint x="415" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0jy9ipp_di" bpmnElement="Flow_0jy9ipp"> + <di:waypoint x="575" y="197" /> + <di:waypoint x="632" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0y9pdwn_di" bpmnElement="Flow_0y9pdwn"> + <di:waypoint x="818" y="390" /> + <di:waypoint x="1010" y="390" /> + <di:waypoint x="1010" y="222" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_06toths_di" bpmnElement="Flow_06toths"> + <di:waypoint x="440" y="222" /> + <di:waypoint x="440" y="330" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1h835ja_di" bpmnElement="Flow_1h835ja"> + <di:waypoint x="775" y="197" /> + <di:waypoint x="865" y="197" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="777" y="176" width="67" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1asxc2j_di" bpmnElement="Flow_1asxc2j"> + <di:waypoint x="750" y="222" /> + <di:waypoint x="750" y="262" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0g1txh0_di" bpmnElement="Flow_0g1txh0"> + <di:waypoint x="550" y="172" /> + <di:waypoint x="550" y="100" /> + <di:waypoint x="890" y="100" /> + <di:waypoint x="890" y="172" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="553" y="82" width="67" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_05mfu8d_di" bpmnElement="Flow_05mfu8d"> + <di:waypoint x="465" y="197" /> + <di:waypoint x="525" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1ltiore_di" bpmnElement="Flow_1ltiore"> + <di:waypoint x="732" y="280" /> + <di:waypoint x="550" y="280" /> + <di:waypoint x="550" y="222" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_09o8bb5_di" bpmnElement="Flow_09o8bb5"> + <di:waypoint x="198" y="197" /> + <di:waypoint x="260" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0stek1z_di" bpmnElement="Flow_0stek1z"> + <di:waypoint x="1035" y="197" /> + <di:waypoint x="1122" y="197" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Event_1ukqals_di" bpmnElement="Event_1ukqals"> + <dc:Bounds x="1122" y="179" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_1xqxerc_di" bpmnElement="Gateway_1xqxerc" isMarkerVisible="true"> + <dc:Bounds x="525" y="172" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0g2pqnk_di" bpmnElement="AutostartPingStartMessageStartEvent"> + <dc:Bounds x="162" y="179" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="161" y="222" width="46" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_00tj0cp_di" bpmnElement="Gateway_00tj0cp"> + <dc:Bounds x="415" y="172" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0eqigaq_di" bpmnElement="Event_0eqigaq"> + <dc:Bounds x="732" y="262" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="740" y="301" width="20" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_0oa1bkj_di" bpmnElement="Gateway_0oa1bkj"> + <dc:Bounds x="985" y="172" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_0sx5e0s_di" bpmnElement="Gateway_0sx5e0s" isMarkerVisible="true"> + <dc:Bounds x="725" y="172" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0laouxt_di" bpmnElement="startTimer"> + <dc:Bounds x="260" y="157" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_129hw90_di" bpmnElement="Gateway_129hw90" isMarkerVisible="true"> + <dc:Bounds x="865" y="172" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0dsz1xu_di" bpmnElement="startPing"> + <dc:Bounds x="632" y="179" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="628" y="222" width="46" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1kspnah_di" bpmnElement="StopSubProcess" isExpanded="true"> + <dc:Bounds x="390" y="330" width="428" height="120" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Flow_1vxlaau_di" bpmnElement="Flow_1vxlaau"> + <di:waypoint x="710" y="390" /> + <di:waypoint x="762" y="390" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_1x5v76c_di" bpmnElement="Flow_1x5v76c"> + <di:waypoint x="456" y="390" /> + <di:waypoint x="522" y="390" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0m0cias_di" bpmnElement="Flow_0m0cias"> + <di:waypoint x="558" y="390" /> + <di:waypoint x="610" y="390" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="Event_02xmnq6_di" bpmnElement="Event_02xmnq6"> + <dc:Bounds x="420" y="372" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1cin90r_di" bpmnElement="StopTimer"> + <dc:Bounds x="610" y="350" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_1maglns_di" bpmnElement="AutostartPingStopMessageStartEvent"> + <dc:Bounds x="522" y="372" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="520" y="415" width="45" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_1ckek3z_di" bpmnElement="Event_1ckek3z"> + <dc:Bounds x="762" y="372" width="36" height="36" /> + </bpmndi:BPMNShape> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</bpmn:definitions> diff --git a/dsf-bpe-process-ping/src/main/resources/bpe/ping.bpmn b/dsf-bpe-process-ping/src/main/resources/bpe/ping.bpmn index 1b87ce4b..b726dc37 100644 --- a/dsf-bpe-process-ping/src/main/resources/bpe/ping.bpmn +++ b/dsf-bpe-process-ping/src/main/resources/bpe/ping.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0azvmx1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_ping" isExecutable="true" camunda:versionTag="0.5.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0azvmx1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.11.1"> + <bpmn:process id="highmedorg_ping" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:sequenceFlow id="SequenceFlow_0k1j79c" sourceRef="StartEvent_1" targetRef="selectTargets" /> <bpmn:sequenceFlow id="SequenceFlow_05ia6lz" sourceRef="selectTargets" targetRef="sendPing" /> <bpmn:serviceTask id="selectTargets" name="selectTargets" camunda:class="org.highmed.dsf.bpe.service.SelectPingTargets"> @@ -10,9 +10,9 @@ <bpmn:sendTask id="sendPing" name="sendPing" camunda:class="org.highmed.dsf.bpe.message.SendPing"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/pong/0.5.0</camunda:inputParameter> - <camunda:inputParameter name="messageName">pingMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-ping|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/pong/#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">ping</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-ping|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_05ia6lz</bpmn:incoming> @@ -28,13 +28,8 @@ </bpmn:startEvent> <bpmn:sequenceFlow id="SequenceFlow_1jv4kfm" sourceRef="StartEvent_18et3pb" targetRef="receivePong" /> <bpmn:endEvent id="EndEvent_1yf8pjt"> - <bpmn:incoming>SequenceFlow_0vxiwg9</bpmn:incoming> + <bpmn:incoming>Flow_0brn8vt</bpmn:incoming> </bpmn:endEvent> - <bpmn:sequenceFlow id="SequenceFlow_0vxiwg9" sourceRef="logPong" targetRef="EndEvent_1yf8pjt" /> - <bpmn:serviceTask id="logPong" name="logPong" camunda:class="org.highmed.dsf.bpe.service.LogPong"> - <bpmn:incoming>SequenceFlow_0r89tc0</bpmn:incoming> - <bpmn:outgoing>SequenceFlow_0vxiwg9</bpmn:outgoing> - </bpmn:serviceTask> <bpmn:receiveTask id="receivePong" name="receivePong" messageRef="Message_10o3b8y"> <bpmn:extensionElements> <camunda:inputOutput> @@ -45,91 +40,108 @@ <bpmn:outgoing>SequenceFlow_0r89tc0</bpmn:outgoing> </bpmn:receiveTask> <bpmn:sequenceFlow id="SequenceFlow_0r89tc0" sourceRef="receivePong" targetRef="logPong" /> + <bpmn:sequenceFlow id="Flow_0brn8vt" sourceRef="logPong" targetRef="EndEvent_1yf8pjt" /> + <bpmn:serviceTask id="logPong" name="logPong" camunda:class="org.highmed.dsf.bpe.service.LogPong"> + <bpmn:incoming>SequenceFlow_0r89tc0</bpmn:incoming> + <bpmn:outgoing>Flow_0brn8vt</bpmn:outgoing> + </bpmn:serviceTask> </bpmn:subProcess> - <bpmn:boundaryEvent id="BoundaryEvent_0s1l6j2" attachedToRef="SubProcess_0szmntn"> - <bpmn:outgoing>SequenceFlow_01v9yzp</bpmn:outgoing> - <bpmn:timerEventDefinition> - <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT5M</bpmn:timeDuration> - </bpmn:timerEventDefinition> - </bpmn:boundaryEvent> <bpmn:endEvent id="EndEvent_1rdxonv"> - <bpmn:incoming>SequenceFlow_10d3jfk</bpmn:incoming> - <bpmn:incoming>SequenceFlow_01v9yzp</bpmn:incoming> + <bpmn:incoming>Flow_0d1hhpd</bpmn:incoming> </bpmn:endEvent> - <bpmn:sequenceFlow id="SequenceFlow_10d3jfk" sourceRef="SubProcess_0szmntn" targetRef="EndEvent_1rdxonv" /> - <bpmn:sequenceFlow id="SequenceFlow_01v9yzp" sourceRef="BoundaryEvent_0s1l6j2" targetRef="EndEvent_1rdxonv" /> + <bpmn:sequenceFlow id="SequenceFlow_10d3jfk" sourceRef="SubProcess_0szmntn" targetRef="logNoResponse" /> <bpmn:sequenceFlow id="SequenceFlow_1vng5zz" sourceRef="sendPing" targetRef="SubProcess_0szmntn" /> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>SequenceFlow_0k1j79c</bpmn:outgoing> <bpmn:messageEventDefinition messageRef="Message_1pklz6t" /> </bpmn:startEvent> + <bpmn:sequenceFlow id="Flow_0d1hhpd" sourceRef="logNoResponse" targetRef="EndEvent_1rdxonv" /> + <bpmn:serviceTask id="logNoResponse" name="logNoResponse" camunda:class="org.highmed.dsf.bpe.service.LogNoResponse"> + <bpmn:incoming>SequenceFlow_10d3jfk</bpmn:incoming> + <bpmn:incoming>Flow_1mpgmm5</bpmn:incoming> + <bpmn:outgoing>Flow_0d1hhpd</bpmn:outgoing> + </bpmn:serviceTask> + <bpmn:boundaryEvent id="BoundaryEvent_0s1l6j2" attachedToRef="SubProcess_0szmntn"> + <bpmn:outgoing>Flow_1mpgmm5</bpmn:outgoing> + <bpmn:timerEventDefinition> + <bpmn:timeDuration xsi:type="bpmn:tFormalExpression">PT5M</bpmn:timeDuration> + </bpmn:timerEventDefinition> + </bpmn:boundaryEvent> + <bpmn:sequenceFlow id="Flow_1mpgmm5" sourceRef="BoundaryEvent_0s1l6j2" targetRef="logNoResponse" /> </bpmn:process> - <bpmn:message id="Message_10o3b8y" name="pongMessage" /> - <bpmn:message id="Message_1pklz6t" name="startPingProcessMessage" /> + <bpmn:message id="Message_10o3b8y" name="pong" /> + <bpmn:message id="Message_1pklz6t" name="startPing" /> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="highmedorg_ping"> - <bpmndi:BPMNEdge id="SequenceFlow_1vng5zz_di" bpmnElement="SequenceFlow_1vng5zz"> - <di:waypoint x="530" y="120" /> - <di:waypoint x="606" y="120" /> + <bpmndi:BPMNEdge id="Flow_1mpgmm5_di" bpmnElement="Flow_1mpgmm5"> + <di:waypoint x="1108" y="180" /> + <di:waypoint x="1220" y="180" /> + <di:waypoint x="1220" y="160" /> </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="SequenceFlow_01v9yzp_di" bpmnElement="SequenceFlow_01v9yzp"> - <di:waypoint x="1082" y="180" /> - <di:waypoint x="1172" y="180" /> - <di:waypoint x="1172" y="138" /> + <bpmndi:BPMNEdge id="Flow_0d1hhpd_di" bpmnElement="Flow_0d1hhpd"> + <di:waypoint x="1270" y="120" /> + <di:waypoint x="1322" y="120" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="SequenceFlow_1vng5zz_di" bpmnElement="SequenceFlow_1vng5zz"> + <di:waypoint x="520" y="120" /> + <di:waypoint x="596" y="120" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_10d3jfk_di" bpmnElement="SequenceFlow_10d3jfk"> - <di:waypoint x="1064" y="120" /> - <di:waypoint x="1154" y="120" /> + <di:waypoint x="1090" y="120" /> + <di:waypoint x="1170" y="120" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_05ia6lz_di" bpmnElement="SequenceFlow_05ia6lz"> - <di:waypoint x="370" y="120" /> - <di:waypoint x="430" y="120" /> + <di:waypoint x="360" y="120" /> + <di:waypoint x="420" y="120" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0k1j79c_di" bpmnElement="SequenceFlow_0k1j79c"> - <di:waypoint x="209" y="120" /> - <di:waypoint x="270" y="120" /> + <di:waypoint x="188" y="120" /> + <di:waypoint x="260" y="120" /> </bpmndi:BPMNEdge> - <bpmndi:BPMNShape id="SendTask_01t32b2_di" bpmnElement="sendPing"> - <dc:Bounds x="430" y="80" width="100" height="80" /> - </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_1cxtndb_di" bpmnElement="selectTargets"> - <dc:Bounds x="270" y="80" width="100" height="80" /> + <dc:Bounds x="260" y="80" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="SendTask_01t32b2_di" bpmnElement="sendPing"> + <dc:Bounds x="420" y="80" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="SubProcess_0szmntn_di" bpmnElement="SubProcess_0szmntn" isExpanded="true"> - <dc:Bounds x="606" y="60" width="458" height="120" /> + <dc:Bounds x="596" y="60" width="494" height="120" /> </bpmndi:BPMNShape> - <bpmndi:BPMNEdge id="SequenceFlow_0r89tc0_di" bpmnElement="SequenceFlow_0r89tc0"> - <di:waypoint x="808" y="120" /> - <di:waypoint x="858" y="120" /> + <bpmndi:BPMNEdge id="Flow_0brn8vt_di" bpmnElement="Flow_0brn8vt"> + <di:waypoint x="970" y="120" /> + <di:waypoint x="1022" y="120" /> </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="SequenceFlow_0vxiwg9_di" bpmnElement="SequenceFlow_0vxiwg9"> - <di:waypoint x="958" y="120" /> - <di:waypoint x="1008" y="120" /> + <bpmndi:BPMNEdge id="SequenceFlow_0r89tc0_di" bpmnElement="SequenceFlow_0r89tc0"> + <di:waypoint x="798" y="120" /> + <di:waypoint x="870" y="120" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1jv4kfm_di" bpmnElement="SequenceFlow_1jv4kfm"> - <di:waypoint x="662" y="120" /> - <di:waypoint x="708" y="120" /> + <di:waypoint x="652" y="120" /> + <di:waypoint x="698" y="120" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="StartEvent_18et3pb_di" bpmnElement="StartEvent_18et3pb"> - <dc:Bounds x="626" y="102" width="36" height="36" /> + <dc:Bounds x="616" y="102" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="EndEvent_1yf8pjt_di" bpmnElement="EndEvent_1yf8pjt"> - <dc:Bounds x="1008" y="102" width="36" height="36" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="ServiceTask_1tf139x_di" bpmnElement="logPong"> - <dc:Bounds x="858" y="80" width="100" height="80" /> + <dc:Bounds x="1022" y="102" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ReceiveTask_1n4t6gv_di" bpmnElement="receivePong"> - <dc:Bounds x="708" y="80" width="100" height="80" /> + <dc:Bounds x="698" y="80" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1m8zy1k_di" bpmnElement="logPong"> + <dc:Bounds x="870" y="80" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="EndEvent_1rdxonv_di" bpmnElement="EndEvent_1rdxonv"> - <dc:Bounds x="1154" y="102" width="36" height="36" /> + <dc:Bounds x="1322" y="102" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="StartEvent_1dlqln5_di" bpmnElement="StartEvent_1"> - <dc:Bounds x="173" y="102" width="36" height="36" /> + <dc:Bounds x="152" y="102" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0byox2n_di" bpmnElement="logNoResponse"> + <dc:Bounds x="1170" y="80" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="BoundaryEvent_0nix4ox_di" bpmnElement="BoundaryEvent_0s1l6j2"> - <dc:Bounds x="1046" y="162" width="36" height="36" /> + <dc:Bounds x="1072" y="162" width="36" height="36" /> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> diff --git a/dsf-bpe-process-ping/src/main/resources/bpe/pong.bpmn b/dsf-bpe-process-ping/src/main/resources/bpe/pong.bpmn index 94580681..8fa87d19 100644 --- a/dsf-bpe-process-ping/src/main/resources/bpe/pong.bpmn +++ b/dsf-bpe-process-ping/src/main/resources/bpe/pong.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_15v05m6" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_pong" isExecutable="true" camunda:versionTag="0.5.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_15v05m6" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.11.1"> + <bpmn:process id="highmedorg_pong" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>SequenceFlow_07w11cw</bpmn:outgoing> <bpmn:messageEventDefinition messageRef="Message_0u91abp" /> @@ -9,9 +9,9 @@ <bpmn:endEvent id="EndEvent_1ivxrjg"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/ping/0.5.0</camunda:inputParameter> - <camunda:inputParameter name="messageName">pongMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-pong|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/ping/#{version}</camunda:inputParameter> + <camunda:inputParameter name="messageName">pong</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-pong|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_1ism9wt</bpmn:incoming> @@ -27,11 +27,25 @@ <bpmn:outgoing>SequenceFlow_1ism9wt</bpmn:outgoing> </bpmn:serviceTask> <bpmn:sequenceFlow id="SequenceFlow_1ism9wt" sourceRef="selectTarget" targetRef="EndEvent_1ivxrjg" /> + <bpmn:endEvent id="Event_05zzvx3"> + <bpmn:incoming>Flow_0yr2pmf</bpmn:incoming> + </bpmn:endEvent> + <bpmn:boundaryEvent id="Event_1u9ooa5" name="target not allowed" attachedToRef="selectTarget"> + <bpmn:outgoing>Flow_0yr2pmf</bpmn:outgoing> + <bpmn:errorEventDefinition id="ErrorEventDefinition_0ty7e1r" errorRef="Error_1j0t9ud" /> + </bpmn:boundaryEvent> + <bpmn:sequenceFlow id="Flow_0yr2pmf" sourceRef="Event_1u9ooa5" targetRef="Event_05zzvx3" /> </bpmn:process> - <bpmn:message id="Message_0u91abp" name="pingMessage" /> + <bpmn:message id="Message_0u91abp" name="ping" /> <bpmn:message id="Message_1h0kvyq" name="pong" /> + <bpmn:error id="Error_1j0t9ud" name="target_not_allowed" errorCode="target_not_allowed" /> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="highmedorg_pong"> + <bpmndi:BPMNEdge id="Flow_0yr2pmf_di" bpmnElement="Flow_0yr2pmf"> + <di:waypoint x="528" y="178" /> + <di:waypoint x="528" y="210" /> + <di:waypoint x="580" y="210" /> + </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1ism9wt_di" bpmnElement="SequenceFlow_1ism9wt"> <di:waypoint x="528" y="120" /> <di:waypoint x="580" y="120" /> @@ -56,6 +70,15 @@ <bpmndi:BPMNShape id="ServiceTask_0ko681m_di" bpmnElement="selectTarget"> <dc:Bounds x="428" y="80" width="100" height="80" /> </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_05zzvx3_di" bpmnElement="Event_05zzvx3"> + <dc:Bounds x="580" y="192" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_143ftxn_di" bpmnElement="Event_1u9ooa5"> + <dc:Bounds x="510" y="142" width="36" height="36" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="547" y="173" width="86" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </bpmn:definitions> diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping-autostart.xml b/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping-autostart.xml new file mode 100644 index 00000000..e19a77b3 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping-autostart.xml @@ -0,0 +1,69 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="startPingAutostart" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-start-ping-autostart|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ALL" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ALL" /> + </valueCoding> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> + <extension url="message-name"> + <valueString value="stopPingAutostart" /> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-stop-ping-autostart|#{version}" /> + </extension> + <extension url="requester"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ALL" /> + </valueCoding> + </extension> + <extension url="recipient"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/process-authorization" /> + <code value="LOCAL_ALL" /> + </valueCoding> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/pingAutostart" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="Ping Autostart" /> + <title value="PING Autostart process" /> + <subtitle value="Autostart Communication Testing Process" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to autostart sending PING messages to remote Organizations and to receive corresponding PONG messages in a predefined interval" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping.xml b/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping.xml index fb074ac7..5a0c1bf3 100644 --- a/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping.xml +++ b/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-ping.xml @@ -7,10 +7,10 @@ </meta> <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> <extension url="message-name"> - <valueString value="startPingProcessMessage" /> + <valueString value="startPing" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-start-ping-process|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-start-ping|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -27,10 +27,10 @@ </extension> <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> <extension url="message-name"> - <valueString value="pongMessage" /> + <valueString value="pong" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-pong|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-pong|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -47,14 +47,15 @@ </extension> <url value="http://highmed.org/bpe/Process/ping" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="Ping" /> <title value="PING process" /> <subtitle value="Communication Testing Process" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-pong.xml b/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-pong.xml index fb6d1ce4..50fc615d 100644 --- a/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-pong.xml +++ b/dsf-bpe-process-ping/src/main/resources/fhir/ActivityDefinition/highmed-pong.xml @@ -7,10 +7,10 @@ </meta> <extension url="http://highmed.org/fhir/StructureDefinition/extension-process-authorization"> <extension url="message-name"> - <valueString value="pingMessage" /> + <valueString value="ping" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-ping|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-ping|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -27,14 +27,15 @@ </extension> <url value="http://highmed.org/bpe/Process/pong" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="Pong" /> <title value="PONG process" /> <subtitle value="Communication Testing Process" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/CodeSystem/highmed-ping-status.xml b/dsf-bpe-process-ping/src/main/resources/fhir/CodeSystem/highmed-ping-status.xml new file mode 100644 index 00000000..454c1dab --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/CodeSystem/highmed-ping-status.xml @@ -0,0 +1,49 @@ +<CodeSystem xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/CodeSystem/ping-status" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="HiGHmed_Ping_Status" /> + <title value="HiGHmed Ping Status" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <description value="CodeSystem with ping/pong status values" /> + <caseSensitive value="true" /> + <hierarchyMeaning value="grouped-by" /> + <versionNeeded value="false" /> + <content value="complete" /> + <concept> + <code value="not-allowed" /> + <display value="Not allowed" /> + <definition value="Not allowed to start pong-process at target organization" /> + </concept> + <concept> + <code value="not-reachable" /> + <display value="Not reachable" /> + <definition value="Ping could not be sent to target organization" /> + </concept> + <concept> + <code value="pong-missing" /> + <display value="Pong missing" /> + <definition value="No pong received from target organization" /> + </concept> + <concept> + <code value="pong-received" /> + <display value="Pong received" /> + <definition value="Pong received from target organization" /> + </concept> + <concept> + <code value="pong-send" /> + <display value="Pong send" /> + <definition value="Pong successfully sent to target organization" /> + </concept> +</CodeSystem> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/CodeSystem/highmed-ping.xml b/dsf-bpe-process-ping/src/main/resources/fhir/CodeSystem/highmed-ping.xml new file mode 100644 index 00000000..a0fa2ebe --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/CodeSystem/highmed-ping.xml @@ -0,0 +1,49 @@ +<CodeSystem xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/CodeSystem/ping" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="HiGHmed_Ping" /> + <title value="HiGHmed Ping" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <description value="CodeSystem with standard values for the process ping/pong" /> + <caseSensitive value="true" /> + <hierarchyMeaning value="grouped-by" /> + <versionNeeded value="false" /> + <content value="complete" /> + <concept> + <code value="ping-status" /> + <display value="Ping Status" /> + <definition value="Ping status of target organization" /> + </concept> + <concept> + <code value="pong-status" /> + <display value="Pong Status" /> + <definition value="Pong status of target organization" /> + </concept> + <concept> + <code value="endpoint-identifier" /> + <display value="Endpoint Identifier" /> + <definition value="Identifier of endpoint expecting pong (response) message" /> + </concept> + <concept> + <code value="target-endpoints" /> + <display value="Target Endpoints" /> + <definition value="Ping target endpoints, search query resulting in match or include results with Endpoint resources" /> + </concept> + <concept> + <code value="timer-interval" /> + <display value="Timer Interval" /> + <definition value="Interval between two autostarts of the ping process" /> + </concept> +</CodeSystem> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-extension-ping-status.xml b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-extension-ping-status.xml new file mode 100644 index 00000000..c1f8c1a4 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-extension-ping-status.xml @@ -0,0 +1,134 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag"/> + <code value="ALL"/> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/extension-ping-status"/> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="PingResponse"/> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1"/> + <kind value="complex-type"/> + <abstract value="false"/> + <context> + <type value="element"/> + <expression value="Task.output"/> + </context> + <type value="Extension"/> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension"/> + <derivation value="constraint"/> + <differential> + <element id="Extension.extension"> + <path value="Extension.extension"/> + <slicing> + <discriminator> + <type value="value"/> + <path value="url"/> + </discriminator> + <rules value="open"/> + </slicing> + <min value="3"/> + </element> + <element id="Extension.extension:correlation-key"> + <path value="Extension.extension"/> + <sliceName value="correlation-key"/> + <min value="1"/> + <max value="1"/> + </element> + <element id="Extension.extension:correlation-key.url"> + <path value="Extension.extension.url"/> + <fixedUri value="correlation-key"/> + </element> + <element id="Extension.extension:correlation-key.value[x]"> + <path value="Extension.extension.value[x]"/> + <min value="1"/> + <type> + <code value="string"/> + </type> + </element> + <element id="Extension.extension:organization-identifier"> + <path value="Extension.extension"/> + <sliceName value="organization-identifier"/> + <min value="1"/> + <max value="1"/> + </element> + <element id="Extension.extension:organization-identifier.url"> + <path value="Extension.extension.url"/> + <fixedUri value="organization-identifier"/> + </element> + <element id="Extension.extension:organization-identifier.value[x]"> + <path value="Extension.extension.value[x]"/> + <min value="1"/> + <type> + <code value="Identifier"/> + </type> + </element> + <element id="Extension.extension:organization-identifier.value[x].system"> + <path value="Extension.extension.value[x].system"/> + <min value="1"/> + <fixedUri value="http://highmed.org/sid/organization-identifier"/> + </element> + <element id="Extension.extension:organization-identifier.value[x].value"> + <path value="Extension.extension.value[x].value"/> + <min value="1"/> + </element> + <element id="Extension.extension:endpoint-identifier"> + <path value="Extension.extension"/> + <sliceName value="endpoint-identifier"/> + <min value="1"/> + <max value="1"/> + </element> + <element id="Extension.extension:endpoint-identifier.url"> + <path value="Extension.extension.url"/> + <fixedUri value="endpoint-identifier"/> + </element> + <element id="Extension.extension:endpoint-identifier.value[x]"> + <path value="Extension.extension.value[x]"/> + <min value="1"/> + <type> + <code value="Identifier"/> + </type> + </element> + <element id="Extension.extension:endpoint-identifier.value[x].system"> + <path value="Extension.extension.value[x].system"/> + <min value="1"/> + <fixedUri value="http://highmed.org/sid/endpoint-identifier"/> + </element> + <element id="Extension.extension:endpoint-identifier.value[x].value"> + <path value="Extension.extension.value[x].value"/> + <min value="1"/> + </element> + <element id="Extension.extension:error-message"> + <path value="Extension.extension"/> + <sliceName value="error-message"/> + <min value="0"/> + <max value="1"/> + </element> + <element id="Extension.extension:error-message.url"> + <path value="Extension.extension.url"/> + <fixedUri value="error-message"/> + </element> + <element id="Extension.extension:error-message.value[x]"> + <path value="Extension.extension.value[x]"/> + <min value="1"/> + <type> + <code value="string"/> + </type> + </element> + <element id="Extension.url"> + <path value="Extension.url"/> + <fixedUri value="http://highmed.org/fhir/StructureDefinition/extension-ping-status"/> + </element> + <element id="Extension.value[x]"> + <path value="Extension.value[x]"/> + <max value="0"/> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-ping.xml b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-ping.xml index f388c627..fa9266d4 100644 --- a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-ping.xml +++ b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-ping.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-ping" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskPing" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,15 +23,15 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/pong/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/pong/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.input" /> - <min value="3" /> - <max value="3" /> + <min value="4" /> + <max value="4" /> </element> <element id="Task.input:message-name"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -41,7 +42,7 @@ </element> <element id="Task.input:message-name.value[x]"> <path value="Task.input.value[x]" /> - <fixedString value="pingMessage" /> + <fixedString value="ping" /> </element> <element id="Task.input:business-key"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -59,5 +60,126 @@ <sliceName value="correlation-key" /> <min value="1" /> </element> + <element id="Task.input:endpoint-identifier"> + <path value="Task.input" /> + <sliceName value="endpoint-identifier" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:endpoint-identifier.type"> + <path value="Task.input.type" /> + <binding> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/ping" /> + </binding> + </element> + <element id="Task.input:endpoint-identifier.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:endpoint-identifier.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping" /> + </element> + <element id="Task.input:endpoint-identifier.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="endpoint-identifier" /> + </element> + <element id="Task.input:endpoint-identifier.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/endpoint" /> + </type> + </element> + <element id="Task.input:endpoint-identifier.value[x].reference"> + <path value="Task.input.value[x].reference" /> + <min value="0" /> + </element> + <element id="Task.input:endpoint-identifier.value[x].type"> + <path value="Task.input.value[x].type" /> + <max value="1" /> + <fixedUri value="Endpoint" /> + </element> + <element id="Task.input:endpoint-identifier.value[x].identifier"> + <path value="Task.input.value[x].identifier" /> + <max value="1" /> + </element> + <element id="Task.input:endpoint-identifier.value[x].identifier.system"> + <path value="Task.input.value[x].identifier.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/sid/endpoint-identifier" /> + </element> + <element id="Task.input:endpoint-identifier.value[x].identifier.value"> + <path value="Task.input.value[x].identifier.value" /> + <min value="1" /> + </element> + <element id="Task.output:pong-status"> + <path value="Task.output"/> + <sliceName value="pong-status"/> + </element> + <element id="Task.output:pong-status.extension"> + <path value="Task.output.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.output:pong-status.extension:pong-status-extension"> + <path value="Task.output.extension" /> + <sliceName value="pong-status-extension" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-ping-status" /> + </type> + </element> + <element id="Task.output:pong-status.type"> + <path value="Task.output.type"/> + <binding> + <strength value="required"/> + <valueSet value="http://highmed.org/fhir/ValueSet/ping"/> + </binding> + </element> + <element id="Task.output:pong-status.type.coding"> + <path value="Task.output.type.coding"/> + <min value="1"/> + <max value="1"/> + </element> + <element id="Task.output:pong-status.type.coding.system"> + <path value="Task.output.type.coding.system"/> + <min value="1"/> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping"/> + </element> + <element id="Task.output:pong-status.type.coding.code"> + <path value="Task.output.type.coding.code"/> + <min value="1"/> + <fixedCode value="pong-status"/> + </element> + <element id="Task.output:pong-status.value[x]"> + <path value="Task.output.value[x]"/> + <type> + <code value="Coding"/> + </type> + </element> + <element id="Task.output:pong-status.value[x].system"> + <path value="Task.output.value[x].system"/> + <min value="1"/> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping-status"/> + </element> + <element id="Task.output:pong-status.value[x].code"> + <path value="Task.output.value[x].code"/> + <min value="1"/> + <binding> + <strength value="required"/> + <valueSet value="http://highmed.org/fhir/ValueSet/pong-status"/> + </binding> + </element> </differential> </StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-pong.xml b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-pong.xml index d4084cf4..8902c126 100644 --- a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-pong.xml +++ b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-pong.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-pong" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskPong" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/ping/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/ping/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -41,7 +42,7 @@ </element> <element id="Task.input:message-name.value[x]"> <path value="Task.input.value[x]" /> - <fixedString value="pongMessage" /> + <fixedString value="pong" /> </element> <element id="Task.input:business-key"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping-autostart.xml b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping-autostart.xml new file mode 100644 index 00000000..3b5adddd --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping-autostart.xml @@ -0,0 +1,150 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-start-ping-autostart" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskStartPingAutostart" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/pingAutostart/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="2" /> + <max value="4" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="startPingAutostart" /> + </element> + <element id="Task.input:business-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="business-key" /> + <max value="1" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:target-endpoints"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="target-endpoints" /> + <min value="0" /> + <max value="1" /> + </element> + <element id="Task.input:target-endpoints.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/ping" /> + </binding> + </element> + <element id="Task.input:target-endpoints.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:target-endpoints.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping" /> + </element> + <element id="Task.input:target-endpoints.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="target-endpoints" /> + </element> + <element id="Task.input:target-endpoints.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="string" /> + </type> + </element> + <element id="Task.input:timer-interval"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="timer-interval" /> + <min value="0" /> + <max value="1" /> + </element> + <element id="Task.input:timer-interval.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/ping" /> + </binding> + </element> + <element id="Task.input:timer-interval.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:timer-interval.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping" /> + </element> + <element id="Task.input:timer-interval.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="timer-interval" /> + </element> + <element id="Task.input:timer-interval.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="string" /> + </type> + <constraint> + <key value="timer-interval-regex" /> + <severity value="error" /> + <human value="Must be ISO 8601 time duration pattern" /> + <expression value="matches('^P(?:([0-9]+)Y)?(?:([0-9]+)M)?(?:([0-9]+)D)?(T(?:([0-9]+)H)?(?:([0-9]+)M)?(?:([0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?$')" /> + </constraint> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping.xml b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping.xml new file mode 100644 index 00000000..4d532a07 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping.xml @@ -0,0 +1,199 @@ +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/task-start-ping" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="TaskStartPing" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <fhirVersion value="4.0.1" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Task" /> + <baseDefinition value="http://highmed.org/fhir/StructureDefinition/task-base" /> + <derivation value="constraint" /> + <differential> + <element id="Task.instantiatesUri"> + <path value="Task.instantiatesUri" /> + <fixedUri value="http://highmed.org/bpe/Process/ping/#{version}" /> + </element> + <element id="Task.input"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <min value="1" /> + <max value="3" /> + </element> + <element id="Task.input:message-name"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="message-name" /> + </element> + <element id="Task.input:message-name.value[x]"> + <path value="Task.input.value[x]" /> + <fixedString value="startPing" /> + </element> + <element id="Task.input:correlation-key"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="correlation-key" /> + <max value="0" /> + </element> + <element id="Task.input:target-endpoints"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.input" /> + <sliceName value="target-endpoints" /> + <min value="0" /> + <max value="1" /> + </element> + <element id="Task.input:target-endpoints.type"> + <path value="Task.input.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskInputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/ping" /> + </binding> + </element> + <element id="Task.input:target-endpoints.type.coding"> + <path value="Task.input.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.input:target-endpoints.type.coding.system"> + <path value="Task.input.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping" /> + </element> + <element id="Task.input:target-endpoints.type.coding.code"> + <path value="Task.input.type.coding.code" /> + <min value="1" /> + <fixedCode value="target-endpoints" /> + </element> + <element id="Task.input:target-endpoints.value[x]"> + <path value="Task.input.value[x]" /> + <type> + <code value="string" /> + </type> + </element> + <element id="Task.output:business-key-out"> + <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> + <valueString value="Parameter" /> + </extension> + <path value="Task.output" /> + <sliceName value="business-key-out" /> + <max value="1" /> + </element> + <element id="Task.output:business-key-out.type"> + <path value="Task.output.type" /> + <binding> + <extension url="http://hl7.org/fhir/StructureDefinition/elementdefinition-bindingName"> + <valueString value="TaskOutputParameterType" /> + </extension> + <strength value="required" /> + <valueSet value="http://highmed.org/fhir/ValueSet/bpmn-message" /> + </binding> + </element> + <element id="Task.output:business-key-out.type.coding"> + <path value="Task.output.type.coding" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Task.output:business-key-out.type.coding.system"> + <path value="Task.output.type.coding.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/bpmn-message" /> + </element> + <element id="Task.output:business-key-out.type.coding.code"> + <path value="Task.output.type.coding.code" /> + <min value="1" /> + <fixedCode value="business-key" /> + </element> + <element id="Task.output:business-key-out.value[x]"> + <path value="Task.output.value[x]" /> + <type> + <code value="string" /> + </type> + </element> + <element id="Task.output:ping-status"> + <path value="Task.output"/> + <sliceName value="ping-status"/> + </element> + <element id="Task.output:ping-status.extension"> + <path value="Task.output.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Task.output:ping-status.extension:ping-status-extension"> + <path value="Task.output.extension" /> + <sliceName value="ping-status-extension" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/extension-ping-status" /> + </type> + </element> + <element id="Task.output:ping-status.type"> + <path value="Task.output.type"/> + <binding> + <strength value="required"/> + <valueSet value="http://highmed.org/fhir/ValueSet/ping"/> + </binding> + </element> + <element id="Task.output:ping-status.type.coding"> + <path value="Task.output.type.coding"/> + <min value="1"/> + <max value="1"/> + </element> + <element id="Task.output:ping-status.type.coding.system"> + <path value="Task.output.type.coding.system"/> + <min value="1"/> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping"/> + </element> + <element id="Task.output:ping-status.type.coding.code"> + <path value="Task.output.type.coding.code"/> + <min value="1"/> + <fixedCode value="ping-status"/> + </element> + <element id="Task.output:ping-status.value[x]"> + <path value="Task.output.value[x]"/> + <type> + <code value="Coding"/> + </type> + </element> + <element id="Task.output:ping-status.value[x].system"> + <path value="Task.output.value[x].system"/> + <min value="1"/> + <fixedUri value="http://highmed.org/fhir/CodeSystem/ping-status"/> + </element> + <element id="Task.output:ping-status.value[x].code"> + <path value="Task.output.value[x].code"/> + <min value="1"/> + <binding> + <strength value="required"/> + <valueSet value="http://highmed.org/fhir/ValueSet/ping-status"/> + </binding> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping-process.xml b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-stop-ping-autostart.xml similarity index 85% rename from dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping-process.xml rename to dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-stop-ping-autostart.xml index aebc6cde..72316cf3 100644 --- a/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-start-ping-process.xml +++ b/dsf-bpe-process-ping/src/main/resources/fhir/StructureDefinition/highmed-task-stop-ping-autostart.xml @@ -5,14 +5,15 @@ <code value="ALL" /> </tag> </meta> - <url value="http://highmed.org/fhir/StructureDefinition/task-start-ping-process" /> + <url value="http://highmed.org/fhir/StructureDefinition/task-stop-ping-autostart" /> <!-- version managed by bpe --> - <version value="${version}" /> - <name value="TaskStartProcess" /> + <version value="#{version}" /> + <name value="TaskStopPingAutostart" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,14 +23,15 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/ping/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/pingAutostart/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> <valueString value="Parameter" /> </extension> <path value="Task.input" /> - <max value="1" /> + <min value="2" /> + <max value="2" /> </element> <element id="Task.input:message-name"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -40,7 +42,7 @@ </element> <element id="Task.input:message-name.value[x]"> <path value="Task.input.value[x]" /> - <fixedString value="startPingProcessMessage" /> + <fixedString value="stopPingAutostart" /> </element> <element id="Task.input:business-key"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> @@ -48,7 +50,7 @@ </extension> <path value="Task.input" /> <sliceName value="business-key" /> - <max value="0" /> + <min value="1" /> </element> <element id="Task.input:correlation-key"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-ping-status.xml b/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-ping-status.xml new file mode 100644 index 00000000..ded7431a --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-ping-status.xml @@ -0,0 +1,43 @@ +<ValueSet xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system + value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/ValueSet/ping-status" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="HiGHmed_Ping_Status" /> + <title value="HiGHmed Ping Status" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <description value="ValueSet with ping status values" /> + <immutable value="true" /> + <compose> + <include> + <system value="http://highmed.org/fhir/CodeSystem/ping-status" /> + <concept> + <code value="not-allowed" /> + <display value="Not allowed" /> + </concept> + <concept> + <code value="not-reachable" /> + <display value="Not reachable" /> + </concept> + <concept> + <code value="pong-missing" /> + <display value="Pong missing" /> + </concept> + <concept> + <code value="pong-received" /> + <display value="Pong received" /> + </concept> + </include> + </compose> +</ValueSet> \ No newline at end of file diff --git a/dsf-bpe-process-feasibility/src/main/resources/fhir/ValueSet/highmed-feasibility.xml b/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-ping.xml similarity index 54% rename from dsf-bpe-process-feasibility/src/main/resources/fhir/ValueSet/highmed-feasibility.xml rename to dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-ping.xml index 6c7289ba..a1731a31 100644 --- a/dsf-bpe-process-feasibility/src/main/resources/fhir/ValueSet/highmed-feasibility.xml +++ b/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-ping.xml @@ -5,21 +5,22 @@ <code value="ALL" /> </tag> </meta> - <url value="http://highmed.org/fhir/ValueSet/feasibility" /> + <url value="http://highmed.org/fhir/ValueSet/ping" /> <!-- version managed by bpe --> - <version value="${version}" /> - <name value="HiGHmed_Feasibility" /> - <title value="HiGHmed Feasibility" /> + <version value="#{version}" /> + <name value="HiGHmed_Ping" /> + <title value="HiGHmed Ping" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> - <description value="ValueSet with standard values for feasibility processes" /> + <description value="ValueSet with standard values for the process ping/pong" /> <immutable value="true" /> <compose> <include> - <system value="http://highmed.org/fhir/CodeSystem/feasibility" /> + <system value="http://highmed.org/fhir/CodeSystem/ping" /> </include> </compose> </ValueSet> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-pong-status.xml b/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-pong-status.xml new file mode 100644 index 00000000..e9d98650 --- /dev/null +++ b/dsf-bpe-process-ping/src/main/resources/fhir/ValueSet/highmed-pong-status.xml @@ -0,0 +1,38 @@ +<ValueSet xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/read-access-tag" /> + <code value="ALL" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/ValueSet/pong-status" /> + <!-- version managed by bpe --> + <version value="#{version}" /> + <name value="HiGHmed_Pong_Status" /> + <title value="HiGHmed Pong Status" /> + <!-- status managed by bpe --> + <status value="unknown" /> + <experimental value="false" /> + <!-- date managed by bpe --> + <date value="#{date}" /> + <publisher value="HiGHmed" /> + <description value="ValueSet with pong status values" /> + <immutable value="true" /> + <compose> + <include> + <system value="http://highmed.org/fhir/CodeSystem/ping-status" /> + <concept> + <code value="not-allowed" /> + <display value="Not allowed" /> + </concept> + <concept> + <code value="not-reachable" /> + <display value="Not reachable" /> + </concept> + <concept> + <code value="pong-send" /> + <display value="Pong send" /> + </concept> + </include> + </compose> +</ValueSet> \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/PingProcessPluginDefinitionTest.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/PingProcessPluginDefinitionTest.java new file mode 100644 index 00000000..a7a97404 --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/PingProcessPluginDefinitionTest.java @@ -0,0 +1,39 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsPing.PROCESS_NAME_FULL_PING; +import static org.highmed.dsf.bpe.ConstantsPing.PROCESS_NAME_FULL_PING_AUTOSTART; +import static org.highmed.dsf.bpe.ConstantsPing.PROCESS_NAME_FULL_PONG; +import static org.highmed.dsf.bpe.PingProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class PingProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition definition = new PingProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var ping = provider.getResources(PROCESS_NAME_FULL_PING + "/" + VERSION, s -> ResourceProvider.empty()); + assertNotNull(ping); + assertEquals(8, ping.count()); + + var pingAutostart = provider.getResources(PROCESS_NAME_FULL_PING_AUTOSTART + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(pingAutostart); + assertEquals(5, pingAutostart.count()); + + var pong = provider.getResources(PROCESS_NAME_FULL_PONG + "/" + VERSION, s -> ResourceProvider.empty()); + assertNotNull(pong); + assertEquals(7, pong.count()); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPing3MedicFromTtpExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPing3MedicFromTtpExampleStarter.java index ee760643..00081f17 100644 --- a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPing3MedicFromTtpExampleStarter.java +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPing3MedicFromTtpExampleStarter.java @@ -4,7 +4,7 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PING_PROCESS_URI_AND_LATEST_VERSION; -import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_MESSAGE_NAME; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; @@ -27,7 +27,7 @@ protected void main(String[] args, String baseUrl) throws Exception private Task createStartResource() { Task task = new Task(); - task.getMeta().addProfile(PROFILE_HIGHMED_TASK_START_PING); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_START_PING_AND_LATEST_VERSION); task.setInstantiatesUri(PROFILE_HIGHMED_TASK_PING_PROCESS_URI_AND_LATEST_VERSION); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPingTtpsFromMedic1ExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPingTtpsFromMedic1ExampleStarter.java new file mode 100644 index 00000000..eddc5952 --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractPingTtpsFromMedic1ExampleStarter.java @@ -0,0 +1,56 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PING_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.*; + +import java.util.Date; + +import org.hl7.fhir.r4.model.ResourceType; +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; + +public abstract class AbstractPingTtpsFromMedic1ExampleStarter +{ + protected void main(String[] args, String baseUrl) throws Exception + { + Task task = createStartResource(); + ExampleStarter.forServer(args, baseUrl).startWith(task); + } + + private Task createStartResource() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_START_PING_AND_LATEST_VERSION); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_PING_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_START_PING_MESSAGE_NAME)).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + + task.addInput().setValue(new StringType( + "OrganizationAffiliation?primary-organization:identifier=http://highmed.org/sid/organization-identifier|highmed.org" + + "&role=http://highmed.org/fhir/CodeSystem/organization-role|TTP" + + "&_include=OrganizationAffiliation:endpoint")) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS); + + return task; + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractStartAutostartPing3MedicFromTtpExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractStartAutostartPing3MedicFromTtpExampleStarter.java new file mode 100644 index 00000000..50de460c --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractStartAutostartPing3MedicFromTtpExampleStarter.java @@ -0,0 +1,60 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; + +import java.util.Date; + +import org.hl7.fhir.r4.model.ResourceType; +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; + +public abstract class AbstractStartAutostartPing3MedicFromTtpExampleStarter +{ + public static final String BUSINESS_KEY = "95decd83-eb93-410b-b0df-6046256edd7d"; + + protected void main(String[] args, String baseUrl) throws Exception + { + Task task = createStartResource(); + ExampleStarter.forServer(args, baseUrl).startWith(task); + } + + private Task createStartResource() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_AND_LATEST_VERSION); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(BUSINESS_KEY)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + task.addInput().setValue(new StringType("Endpoint?identifier=http://highmed.org/sid/endpoint-identifier|")) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS); + task.addInput().setValue(new StringType("PT7M")).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL); + + return task; + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractStopAutostartPing3MedicFromTtpExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractStopAutostartPing3MedicFromTtpExampleStarter.java new file mode 100644 index 00000000..82b1675a --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/AbstractStopAutostartPing3MedicFromTtpExampleStarter.java @@ -0,0 +1,51 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; +import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.start.AbstractStartAutostartPing3MedicFromTtpExampleStarter.BUSINESS_KEY; +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; + +import java.util.Date; + +import org.hl7.fhir.r4.model.ResourceType; +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; + +public abstract class AbstractStopAutostartPing3MedicFromTtpExampleStarter +{ + protected void main(String[] args, String baseUrl) throws Exception + { + Task task = createStartResource(); + ExampleStarter.forServer(args, baseUrl).startWith(task); + } + + private Task createStartResource() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_AND_LATEST_VERSION); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER) + .setValue(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(BUSINESS_KEY)).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN) + .setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + return task; + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/PingTtpsFromMedic1DockerExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/PingTtpsFromMedic1DockerExampleStarter.java new file mode 100644 index 00000000..aad47ef6 --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/PingTtpsFromMedic1DockerExampleStarter.java @@ -0,0 +1,15 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.MEDIC_1_DOCKER_FHIR_BASE_URL; + +public class PingTtpsFromMedic1DockerExampleStarter extends AbstractPingTtpsFromMedic1ExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new PingTtpsFromMedic1DockerExampleStarter().main(args, MEDIC_1_DOCKER_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/PingTtpsFromMedic1ExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/PingTtpsFromMedic1ExampleStarter.java new file mode 100644 index 00000000..64d912cd --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/PingTtpsFromMedic1ExampleStarter.java @@ -0,0 +1,15 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.MEDIC_1_FHIR_BASE_URL; + +public class PingTtpsFromMedic1ExampleStarter extends AbstractPingTtpsFromMedic1ExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new PingTtpsFromMedic1ExampleStarter().main(args, MEDIC_1_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StartAutostartPing3MedicFromTtpDockerExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StartAutostartPing3MedicFromTtpDockerExampleStarter.java new file mode 100644 index 00000000..34fab06f --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StartAutostartPing3MedicFromTtpDockerExampleStarter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.TTP_DOCKER_FHIR_BASE_URL; + +public class StartAutostartPing3MedicFromTtpDockerExampleStarter + extends AbstractStartAutostartPing3MedicFromTtpExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new StartAutostartPing3MedicFromTtpDockerExampleStarter().main(args, TTP_DOCKER_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StartAutostartPing3MedicFromTtpExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StartAutostartPing3MedicFromTtpExampleStarter.java new file mode 100644 index 00000000..df77c909 --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StartAutostartPing3MedicFromTtpExampleStarter.java @@ -0,0 +1,15 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.TTP_FHIR_BASE_URL; + +public class StartAutostartPing3MedicFromTtpExampleStarter extends AbstractStartAutostartPing3MedicFromTtpExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new StartAutostartPing3MedicFromTtpExampleStarter().main(args, TTP_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StopAutostartPing3MedicFromTtpDockerExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StopAutostartPing3MedicFromTtpDockerExampleStarter.java new file mode 100644 index 00000000..11fd0cb3 --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StopAutostartPing3MedicFromTtpDockerExampleStarter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.TTP_DOCKER_FHIR_BASE_URL; + +public class StopAutostartPing3MedicFromTtpDockerExampleStarter + extends AbstractStopAutostartPing3MedicFromTtpExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new StopAutostartPing3MedicFromTtpDockerExampleStarter().main(args, TTP_DOCKER_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StopAutostartPing3MedicFromTtpExampleStarter.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StopAutostartPing3MedicFromTtpExampleStarter.java new file mode 100644 index 00000000..22769b7c --- /dev/null +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/StopAutostartPing3MedicFromTtpExampleStarter.java @@ -0,0 +1,15 @@ +package org.highmed.dsf.bpe.start; + +import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.TTP_FHIR_BASE_URL; + +public class StopAutostartPing3MedicFromTtpExampleStarter extends AbstractStopAutostartPing3MedicFromTtpExampleStarter +{ + // Environment variable "DSF_CLIENT_CERTIFICATE_PATH" or args[0]: the path to the client-certificate + // highmed-dsf/dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12 + // Environment variable "DSF_CLIENT_CERTIFICATE_PASSWORD" or args[1]: the password of the client-certificate + // password + public static void main(String[] args) throws Exception + { + new StopAutostartPing3MedicFromTtpExampleStarter().main(args, TTP_FHIR_BASE_URL); + } +} diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/ActivityDefinitionProfileTest.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/ActivityDefinitionProfileTest.java index 36e45fae..66cc035c 100644 --- a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/ActivityDefinitionProfileTest.java +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/ActivityDefinitionProfileTest.java @@ -1,11 +1,10 @@ package org.highmed.dsf.fhir.profiles; +import static org.highmed.dsf.bpe.PingProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.PingProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -28,7 +27,7 @@ public class ActivityDefinitionProfileTest private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", "highmed-extension-process-authorization-consortium-role-0.5.0.xml", "highmed-extension-process-authorization-organization-0.5.0.xml", @@ -47,43 +46,48 @@ public class ActivityDefinitionProfileTest private final ProcessAuthorizationHelper processAuthorizationHelper = new ProcessAuthorizationHelperImpl(); + @Test + public void testAutostartValid() throws Exception + { + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-ping-autostart.xml")); + + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); + } + @Test public void testPingValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-ping.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule + .readActivityDefinition(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-ping.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } @Test public void testPongValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-pong.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule + .readActivityDefinition(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-pong.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } } \ No newline at end of file diff --git a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/TaskProfileTest.java b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/TaskProfileTest.java index a89d86dd..558d0568 100644 --- a/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/TaskProfileTest.java +++ b/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/fhir/profiles/TaskProfileTest.java @@ -4,7 +4,14 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_SEND; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS; +import static org.highmed.dsf.bpe.ConstantsPing.CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PING; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PING_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PING_PROCESS_URI_AND_LATEST_VERSION; @@ -12,7 +19,14 @@ import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PONG_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_PONG_TASK; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AUTOSTART; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_START_PING_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_MESSAGE_NAME; +import static org.highmed.dsf.bpe.ConstantsPing.PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.PingProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.PingProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; @@ -20,9 +34,13 @@ import java.util.Date; import java.util.UUID; +import org.highmed.dsf.bpe.util.PingStatusGenerator; import org.highmed.dsf.fhir.validation.ResourceValidator; import org.highmed.dsf.fhir.validation.ResourceValidatorImpl; import org.highmed.dsf.fhir.validation.ValidationSupportRule; +import org.highmed.dsf.fhir.variables.Target; +import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResourceType; import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.Task; @@ -41,15 +59,129 @@ public class TaskProfileTest private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, - Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-task-start-ping-process.xml", "highmed-task-ping.xml", - "highmed-task-pong.xml"), - Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml"), - Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml")); + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, + Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-extension-ping-status.xml", "highmed-task-ping.xml", + "highmed-task-pong.xml", "highmed-task-start-ping.xml", "highmed-task-start-ping-autostart.xml", + "highmed-task-stop-ping-autostart.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", "highmed-ping.xml", + "highmed-ping-status.xml"), + Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", "highmed-ping.xml", + "highmed-ping-status.xml", "highmed-pong-status.xml")); private ResourceValidator resourceValidator = new ResourceValidatorImpl(validationRule.getFhirContext(), validationRule.getValidationSupport()); + @Test + public void testTaskStartAutostartProcessProfileValid() throws Exception + { + Task task = createValidTaskStartAutostartProcess(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskStartAutostartProcessProfileValidWithTargetEndpoints() throws Exception + { + Task task = createValidTaskStartAutostartProcess(); + task.addInput() + .setValue(new StringType( + "Endpoint?identifier=http://highmed.org/sid/endpoint-identifier|endpoint.target.org")) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskStartAutostartProcessProfileValidTimerInterval() throws Exception + { + Task task = createValidTaskStartAutostartProcess(); + task.addInput().setValue(new StringType("PT24H")).getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskStartAutostartProcessProfileNotValidTimerInterval() throws Exception + { + Task task = createValidTaskStartAutostartProcess(); + task.addInput().setValue(new StringType("invalid_duration")).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_PING).setCode(CODESYSTEM_HIGHMED_PING_VALUE_TIMER_INTERVAL); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(1, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskStartAutostartProcess() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_START_PING_AUTOSTART); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_START_PING_AUTOSTART_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + return task; + } + + @Test + public void testTaskStopAutostartProcessProfileValid() throws Exception + { + Task task = createValidTaskStopAutostartProcess(); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + private Task createValidTaskStopAutostartProcess() + { + Task task = new Task(); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART); + task.setInstantiatesUri(PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_PROCESS_URI_AND_LATEST_VERSION); + task.setStatus(TaskStatus.REQUESTED); + task.setIntent(TaskIntent.ORDER); + task.setAuthoredOn(new Date()); + task.getRequester().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + task.getRestriction().addRecipient().setType(ResourceType.Organization.name()).getIdentifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER).setValue("TTP"); + + task.addInput().setValue(new StringType(PROFILE_HIGHMED_TASK_STOP_PING_AUTOSTART_MESSAGE_NAME)).getType() + .addCoding().setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME); + task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + return task; + } + @Test public void testTaskStartPingProcessProfileValid() throws Exception { @@ -62,6 +194,56 @@ public void testTaskStartPingProcessProfileValid() throws Exception || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); } + @Test + public void testTaskStartPingProcessProfileValidWithTargetEndpoints() throws Exception + { + Task task = createValidTaskStartPingProcess(); + task.addInput() + .setValue(new StringType( + "Endpoint?identifier=http://highmed.org/sid/endpoint-identifier|endpoint.target.org")) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_TARGET_ENDPOINTS); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskStartPingProcessProfileValidWithBuisnessKeyOutput() throws Exception + { + Task task = createValidTaskStartPingProcess(); + task.addOutput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + + @Test + public void testTaskStartPingProcessProfileValidWithBusinessKeyAndPingStatusOutput() throws Exception + { + Task task = createValidTaskStartPingProcess(); + task.addOutput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() + .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); + + Target target = Target.createBiDirectionalTarget("target.org", "endpoint.target.org", + "https://endpoint.target.org/fhir", UUID.randomUUID().toString()); + task.addOutput(new PingStatusGenerator().createPingStatusOutput(target, + CODESYSTEM_HIGHMED_PING_STATUS_VALUE_NOT_REACHABLE, "some error message")); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + @Test public void testTaskStartPingProcessProfileNotValid1() throws Exception { @@ -132,6 +314,22 @@ public void testTaskPingValid() throws Exception || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); } + @Test + public void testTaskPingValidWithPingStatusOutput() throws Exception + { + Task task = createValidTaskPing(); + task.addOutput(new PingStatusGenerator().createPongStatusOutput( + Target.createBiDirectionalTarget("target.org", "endpoint.target.org", + "https://endpoint.target.org/fhir", UUID.randomUUID().toString()), + CODESYSTEM_HIGHMED_PING_STATUS_VALUE_PONG_SEND)); + + ValidationResult result = resourceValidator.validate(task); + ValidationSupportRule.logValidationMessages(logger, result); + + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + } + private Task createValidTaskPing() { Task task = new Task(); @@ -151,6 +349,12 @@ private Task createValidTaskPing() .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_BUSINESS_KEY); task.addInput().setValue(new StringType(UUID.randomUUID().toString())).getType().addCoding() .setSystem(CODESYSTEM_HIGHMED_BPMN).setCode(CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY); + task.addInput() + .setValue(new Reference().setIdentifier(new Identifier() + .setSystem(NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER).setValue("endpoint.target.org")) + .setType(ResourceType.Endpoint.name())) + .getType().addCoding().setSystem(CODESYSTEM_HIGHMED_PING) + .setCode(CODESYSTEM_HIGHMED_PING_VALUE_ENDPOINT_IDENTIFIER); return task; } diff --git a/dsf-bpe-process-update-allow-list/pom.xml b/dsf-bpe-process-update-allow-list/pom.xml index 5c39fb5f..141d56fc 100644 --- a/dsf-bpe-process-update-allow-list/pom.xml +++ b/dsf-bpe-process-update-allow-list/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-highmed-processes-pom</artifactId> - <version>0.5.0</version> + <version>0.6.0</version> </parent> <properties> diff --git a/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateAllowList.java b/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateAllowList.java index 2e0c3e33..c3ae2371 100644 --- a/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateAllowList.java +++ b/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateAllowList.java @@ -5,17 +5,29 @@ public interface ConstantsUpdateAllowList { + String PROCESS_NAME_DOWNLOAD_ALLOW_LIST = "downloadAllowList"; + String PROCESS_NAME_UPDATE_ALLOW_LIST = "updateAllowList"; + + String PROCESS_NAME_FULL_DOWNLOAD_ALLOW_LIST = "highmedorg_" + PROCESS_NAME_DOWNLOAD_ALLOW_LIST; + String PROCESS_NAME_FULL_UPDATE_ALLOW_LIST = "highmedorg_" + PROCESS_NAME_UPDATE_ALLOW_LIST; + String CODESYSTEM_HIGHMED_UPDATE_ALLOW_LIST = "http://highmed.org/fhir/CodeSystem/update-allow-list"; String CODESYSTEM_HIGHMED_UPDATE_ALLOW_LIST_VALUE_ALLOW_LIST = "allow_list"; String PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST = "http://highmed.org/fhir/StructureDefinition/task-download-allow-list"; - String PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "downloadAllowList/"; + String PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST + "|" + + VERSION; + String PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_DOWNLOAD_ALLOW_LIST + "/"; String PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_MESSAGE_NAME = "downloadAllowListMessage"; String PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST = "http://highmed.org/fhir/StructureDefinition/task-update-allow-list"; - String PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + "updateAllowList/"; + String PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST + "|" + + VERSION; + String PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI = PROCESS_HIGHMED_URI_BASE + + PROCESS_NAME_UPDATE_ALLOW_LIST + "/"; String PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_MESSAGE_NAME = "updateAllowListMessage"; diff --git a/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinition.java b/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinition.java index 0f330987..1786e221 100644 --- a/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinition.java +++ b/dsf-bpe-process-update-allow-list/src/main/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinition.java @@ -1,5 +1,9 @@ package org.highmed.dsf.bpe; +import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROCESS_NAME_FULL_DOWNLOAD_ALLOW_LIST; +import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROCESS_NAME_FULL_UPDATE_ALLOW_LIST; + +import java.time.LocalDate; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -18,7 +22,8 @@ public class UpdateAllowListProcessPluginDefinition implements ProcessPluginDefinition { - public static final String VERSION = "0.5.0"; + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); @Override public String getName() @@ -32,6 +37,12 @@ public String getVersion() return VERSION; } + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + @Override public Stream<String> getBpmnFiles() { @@ -48,18 +59,22 @@ public Stream<Class<?>> getSpringConfigClasses() public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader classLoader, PropertyResolver resolver) { + var c = CodeSystemResource.file("fhir/CodeSystem/highmed-update-allow-list.xml"); + var aDown = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-downloadAllowList.xml"); var aUp = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-updateAllowList.xml"); - var c = CodeSystemResource.file("fhir/CodeSystem/highmed-update-allow-list.xml"); + var sDown = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-download-allow-list.xml"); var sUp = StructureDefinitionResource.file("fhir/StructureDefinition/highmed-task-update-allow-list.xml"); + var v = ValueSetResource.file("fhir/ValueSet/highmed-update-allow-list.xml"); Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map.of( - "highmedorg_downloadAllowList/" + VERSION, Arrays.asList(aDown, c, sDown, v), - "highmedorg_updateAllowList/" + VERSION, Arrays.asList(aUp, c, sUp, v)); + PROCESS_NAME_FULL_DOWNLOAD_ALLOW_LIST + "/" + VERSION, Arrays.asList(c, aDown, sDown, v), + PROCESS_NAME_FULL_UPDATE_ALLOW_LIST + "/" + VERSION, Arrays.asList(c, aUp, sUp, v)); - return ResourceProvider.read(VERSION, () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), - classLoader, resolver, resourcesByProcessKeyAndVersion); + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); } } diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/bpe/downloadAllowList.bpmn b/dsf-bpe-process-update-allow-list/src/main/resources/bpe/downloadAllowList.bpmn index 2ac200dd..9ef3dd42 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/bpe/downloadAllowList.bpmn +++ b/dsf-bpe-process-update-allow-list/src/main/resources/bpe/downloadAllowList.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1yb5vw3" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_downloadAllowList" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_downloadAllowList" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:sequenceFlow id="SequenceFlow_0bbhq2r" sourceRef="StartEvent_1" targetRef="downloadAllowListTask" /> <bpmn:endEvent id="EndEvent_0xd0x8k"> <bpmn:incoming>SequenceFlow_0oyvmcd</bpmn:incoming> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/bpe/updateAllowList.bpmn b/dsf-bpe-process-update-allow-list/src/main/resources/bpe/updateAllowList.bpmn index 58003231..f80bc0b7 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/bpe/updateAllowList.bpmn +++ b/dsf-bpe-process-update-allow-list/src/main/resources/bpe/updateAllowList.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1yb5vw3" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_updateAllowList" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_updateAllowList" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:sequenceFlow id="SequenceFlow_0bbhq2r" sourceRef="StartEvent_1" targetRef="updateAllowListTask" /> <bpmn:endEvent id="EndEvent_0xd0x8k"> <bpmn:incoming>SequenceFlow_0oyvmcd</bpmn:incoming> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-downloadAllowList.xml b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-downloadAllowList.xml index 639af2d6..1b60be2f 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-downloadAllowList.xml +++ b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-downloadAllowList.xml @@ -10,7 +10,7 @@ <valueString value="downloadAllowListMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-download-allow-list|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-download-allow-list|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -27,14 +27,15 @@ </extension> <url value="http://highmed.org/bpe/Process/downloadAllowList" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="DownloadAllowList" /> <title value="Download Allow List" /> <subtitle value="Download Allow List Bundle Process" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-updateAllowList.xml b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-updateAllowList.xml index d1c7cf33..c5dabcc1 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-updateAllowList.xml +++ b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ActivityDefinition/highmed-updateAllowList.xml @@ -10,7 +10,7 @@ <valueString value="updateAllowListMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-update-allow-list|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-update-allow-list|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -39,14 +39,15 @@ </extension> <url value="http://highmed.org/bpe/Process/updateAllowList" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="UpdateAllowList" /> <title value="Update Allow List" /> <subtitle value="Update Allow List Bundle Process" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/CodeSystem/highmed-update-allow-list.xml b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/CodeSystem/highmed-update-allow-list.xml index fbce2f2b..5bc40951 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/CodeSystem/highmed-update-allow-list.xml +++ b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/CodeSystem/highmed-update-allow-list.xml @@ -7,13 +7,14 @@ </meta> <url value="http://highmed.org/fhir/CodeSystem/update-allow-list" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="HiGHmed_Update_Allow_List" /> <title value="HiGHmed Update Allow List" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <description value="CodeSystem with standard values for the processes update and download allow list" /> <caseSensitive value="true" /> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-download-allow-list.xml b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-download-allow-list.xml index afcb991c..3ee0eb28 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-download-allow-list.xml +++ b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-download-allow-list.xml @@ -8,12 +8,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-download-allow-list" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskDownloadAllowList" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -23,7 +24,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/downloadAllowList/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/downloadAllowList/#{version}" /> </element> <element id="Task.input"> <path value="Task.input" /> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-update-allow-list.xml b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-update-allow-list.xml index 83f474ba..3c2d0813 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-update-allow-list.xml +++ b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/StructureDefinition/highmed-task-update-allow-list.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-update-allow-list" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskUpdateAllowList" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/updateAllowList/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/updateAllowList/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> diff --git a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ValueSet/highmed-update-allow-list.xml b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ValueSet/highmed-update-allow-list.xml index 44450c21..6b3696c2 100644 --- a/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ValueSet/highmed-update-allow-list.xml +++ b/dsf-bpe-process-update-allow-list/src/main/resources/fhir/ValueSet/highmed-update-allow-list.xml @@ -7,13 +7,14 @@ </meta> <url value="http://highmed.org/fhir/ValueSet/update-allow-list" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="HiGHmed_Update_Allow_List" /> <title value="HiGHmed Update Allow List" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <description value="ValueSet with standard values for the process update allow list" /> <immutable value="true" /> diff --git a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinitionTest.java b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinitionTest.java new file mode 100644 index 00000000..e0ed70bc --- /dev/null +++ b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/UpdateAllowListProcessPluginDefinitionTest.java @@ -0,0 +1,35 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROCESS_NAME_FULL_DOWNLOAD_ALLOW_LIST; +import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROCESS_NAME_FULL_UPDATE_ALLOW_LIST; +import static org.highmed.dsf.bpe.UpdateAllowListProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class UpdateAllowListProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition definition = new UpdateAllowListProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var download = provider.getResources(PROCESS_NAME_FULL_DOWNLOAD_ALLOW_LIST + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(download); + assertEquals(4, download.count()); + + var update = provider.getResources(PROCESS_NAME_FULL_UPDATE_ALLOW_LIST + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(update); + assertEquals(4, update.count()); + } +} diff --git a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractDownloadAllowListFromTtpViaMedic1ExampleStarter.java b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractDownloadAllowListFromTtpViaMedic1ExampleStarter.java index 1410f258..57c9c855 100644 --- a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractDownloadAllowListFromTtpViaMedic1ExampleStarter.java +++ b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractDownloadAllowListFromTtpViaMedic1ExampleStarter.java @@ -5,7 +5,7 @@ import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.CODESYSTEM_HIGHMED_UPDATE_ALLOW_LIST; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.CODESYSTEM_HIGHMED_UPDATE_ALLOW_LIST_VALUE_ALLOW_LIST; -import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST; +import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_MEDIC_1; @@ -38,7 +38,7 @@ private Task createStartResource(ExampleStarter starter, String ttpUrl) throws E Bundle allowList = getAllowList(starter, ttpUrl); Task task = new Task(); - task.getMeta().addProfile(PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_AND_LATEST_VERSION); task.setInstantiatesUri(PROFILE_HIGHMED_TASK_DOWNLOAD_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); diff --git a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateAllowList3MedicTtpExampleStarter.java b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateAllowList3MedicTtpExampleStarter.java index 89920cf7..c7907118 100644 --- a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateAllowList3MedicTtpExampleStarter.java +++ b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateAllowList3MedicTtpExampleStarter.java @@ -3,7 +3,7 @@ import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN; import static org.highmed.dsf.bpe.ConstantsBase.CODESYSTEM_HIGHMED_BPMN_VALUE_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER; -import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST; +import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; @@ -27,7 +27,7 @@ protected void main(String[] args, String baseUrl) throws Exception private Task createStartResource() { Task task = new Task(); - task.getMeta().addProfile(PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_AND_LATEST_VERSION); task.setInstantiatesUri(PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); diff --git a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java index 1d1797f1..6aa85cc8 100644 --- a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java +++ b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java @@ -1,11 +1,10 @@ package org.highmed.dsf.fhir.profile; +import static org.highmed.dsf.bpe.UpdateAllowListProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.UpdateAllowListProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -28,7 +27,7 @@ public class ActivityDefinitionProfileTest private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", "highmed-extension-process-authorization-consortium-role-0.5.0.xml", "highmed-extension-process-authorization-organization-0.5.0.xml", @@ -50,40 +49,30 @@ public class ActivityDefinitionProfileTest @Test public void testDownloadAllowListValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-downloadAllowList.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-downloadAllowList.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } @Test public void testUpdateAllowListValid() throws Exception { - try (InputStream in = Files - .newInputStream(Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-updateAllowList.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-updateAllowList.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } } \ No newline at end of file diff --git a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java index fef1465d..b689bf4c 100644 --- a/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java +++ b/dsf-bpe-process-update-allow-list/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java @@ -11,6 +11,7 @@ import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsUpdateAllowList.PROFILE_HIGHMED_TASK_UPDATE_ALLOW_LIST_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.UpdateAllowListProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.UpdateAllowListProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; @@ -41,7 +42,7 @@ public class TaskProfileTest private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-task-update-allow-list.xml", "highmed-task-download-allow-list.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", diff --git a/dsf-bpe-process-update-resources/pom.xml b/dsf-bpe-process-update-resources/pom.xml index 856c7a6f..8aa9d21a 100644 --- a/dsf-bpe-process-update-resources/pom.xml +++ b/dsf-bpe-process-update-resources/pom.xml @@ -7,7 +7,7 @@ <parent> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-highmed-processes-pom</artifactId> - <version>0.5.0</version> + <version>0.6.0</version> </parent> <properties> diff --git a/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateResources.java b/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateResources.java index a4a56881..4670e3cf 100644 --- a/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateResources.java +++ b/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/ConstantsUpdateResources.java @@ -5,6 +5,12 @@ public interface ConstantsUpdateResources { + String PROCESS_NAME_EXECUTE_UPDATE_RESOURCES = "executeUpdateResources"; + String PROCESS_NAME_REQUEST_UPDATE_RESOURCES = "requestUpdateResources"; + + String PROCESS_NAME_FULL_EXECUTE_UPDATE_RESOURCES = "highmedorg_" + PROCESS_NAME_EXECUTE_UPDATE_RESOURCES; + String PROCESS_NAME_FULL_REQUEST_UPDATE_RESOURCES = "highmedorg_" + PROCESS_NAME_REQUEST_UPDATE_RESOURCES; + String BPMN_EXECUTION_VARIABLE_BUNDLE = "bundle"; String CODESYSTEM_HIGHMED_UPDATE_RESOURCE = "http://highmed.org/fhir/CodeSystem/update-resources"; @@ -12,15 +18,19 @@ public interface ConstantsUpdateResources String CODESYSTEM_HIGHMED_UPDATE_RESOURCE_VALUE_ORGANIZATION_IDENTIFIER_SEARCH_PARAMETER = "organization-identifier-search-parameter"; String PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES = "http://highmed.org/fhir/StructureDefinition/task-request-update-resources"; + String PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES + + "|" + VERSION; String PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_PROCESS_URI = PROCESS_HIGHMED_URI_BASE - + "requestUpdateResources/"; + + PROCESS_NAME_REQUEST_UPDATE_RESOURCES + "/"; String PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_MESSAGE_NAME = "requestUpdateResourcesMessage"; String PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES = "http://highmed.org/fhir/StructureDefinition/task-execute-update-resources"; + String PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES + + "|" + VERSION; String PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES_PROCESS_URI = PROCESS_HIGHMED_URI_BASE - + "executeUpdateResources/"; + + PROCESS_NAME_EXECUTE_UPDATE_RESOURCES + "/"; String PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES_PROCESS_URI_AND_LATEST_VERSION = PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES_PROCESS_URI + VERSION; String PROFILE_HIGHMED_TASK_EXECUTE_UPDATE_RESOURCES_MESSAGE_NAME = "executeUpdateResourcesMessage"; diff --git a/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinition.java b/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinition.java index 8bde102e..6f40a879 100644 --- a/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinition.java +++ b/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinition.java @@ -1,5 +1,9 @@ package org.highmed.dsf.bpe; +import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROCESS_NAME_FULL_EXECUTE_UPDATE_RESOURCES; +import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROCESS_NAME_FULL_REQUEST_UPDATE_RESOURCES; + +import java.time.LocalDate; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -18,7 +22,8 @@ public class UpdateResourcesProcessPluginDefinition implements ProcessPluginDefinition { - public static final String VERSION = "0.5.0"; + public static final String VERSION = "0.6.0"; + public static final LocalDate RELEASE_DATE = LocalDate.of(2022, 5, 10); @Override public String getName() @@ -32,6 +37,12 @@ public String getVersion() return VERSION; } + @Override + public LocalDate getReleaseDate() + { + return RELEASE_DATE; + } + @Override public Stream<String> getBpmnFiles() { @@ -48,20 +59,24 @@ public Stream<Class<?>> getSpringConfigClasses() public ResourceProvider getResourceProvider(FhirContext fhirContext, ClassLoader classLoader, PropertyResolver resolver) { + var c = CodeSystemResource.file("fhir/CodeSystem/highmed-update-resources.xml"); + var aExec = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-executeUpdateResources.xml"); var aReq = ActivityDefinitionResource.file("fhir/ActivityDefinition/highmed-requestUpdateResources.xml"); - var c = CodeSystemResource.file("fhir/CodeSystem/highmed-update-resources.xml"); + var sExec = StructureDefinitionResource .file("fhir/StructureDefinition/highmed-task-execute-update-resources.xml"); var sReq = StructureDefinitionResource .file("fhir/StructureDefinition/highmed-task-request-update-resources.xml"); + var v = ValueSetResource.file("fhir/ValueSet/highmed-update-resources.xml"); Map<String, List<AbstractResource>> resourcesByProcessKeyAndVersion = Map.of( - "highmedorg_executeUpdateResources/" + VERSION, Arrays.asList(aExec, c, sExec, v), - "highmedorg_requestUpdateResources/" + VERSION, Arrays.asList(aReq, c, sReq, v)); + PROCESS_NAME_FULL_EXECUTE_UPDATE_RESOURCES + "/" + VERSION, Arrays.asList(c, aExec, sExec, v), + PROCESS_NAME_FULL_REQUEST_UPDATE_RESOURCES + "/" + VERSION, Arrays.asList(c, aReq, sReq, v)); - return ResourceProvider.read(VERSION, () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), - classLoader, resolver, resourcesByProcessKeyAndVersion); + return ResourceProvider.read(VERSION, RELEASE_DATE, + () -> fhirContext.newXmlParser().setStripVersionsFromReferences(false), classLoader, resolver, + resourcesByProcessKeyAndVersion); } } diff --git a/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/SelectResourceAndTargets.java b/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/SelectResourceAndTargets.java index 17410614..b825b119 100644 --- a/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/SelectResourceAndTargets.java +++ b/dsf-bpe-process-update-resources/src/main/java/org/highmed/dsf/bpe/service/SelectResourceAndTargets.java @@ -2,12 +2,14 @@ import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_BUNDLE_ID; import static org.highmed.dsf.bpe.ConstantsBase.BPMN_EXECUTION_VARIABLE_TARGETS; +import static org.highmed.dsf.bpe.ConstantsBase.NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER; import static org.highmed.dsf.bpe.ConstantsUpdateResources.CODESYSTEM_HIGHMED_UPDATE_RESOURCE; import static org.highmed.dsf.bpe.ConstantsUpdateResources.CODESYSTEM_HIGHMED_UPDATE_RESOURCE_VALUE_BUNDLE_REFERENCE; import static org.highmed.dsf.bpe.ConstantsUpdateResources.CODESYSTEM_HIGHMED_UPDATE_RESOURCE_VALUE_ORGANIZATION_IDENTIFIER_SEARCH_PARAMETER; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -22,6 +24,7 @@ import org.highmed.dsf.fhir.variables.Targets; import org.highmed.dsf.fhir.variables.TargetsValues; import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; @@ -85,11 +88,22 @@ else if (!BUNDLE_ID_PATTERN.matcher(references.get(0).getReference()).matches()) .collect(Collectors.toList()); List<Target> targets = targetIdentifierSearchParameters.stream() - .flatMap(organizationProvider::searchRemoteOrganizationsIdentifiers) - .map(identifier -> Target.createUniDirectionalTarget(identifier.getValue(), - endpointProvider.getFirstDefaultEndpoint(identifier.getValue()).filter(Endpoint::hasAddress) - .map(Endpoint::getAddress).orElse(null))) - .filter(t -> t.getTargetEndpointUrl() != null).collect(Collectors.toList()); + .flatMap(organizationProvider::searchRemoteOrganizationsIdentifiers).map(identifier -> + { + Optional<Endpoint> endpoint = endpointProvider.getFirstDefaultEndpoint(identifier.getValue()); + return Target.createUniDirectionalTarget(identifier.getValue(), + getEndpointIdentifierValue(endpoint).orElse(null), + endpoint.filter(Endpoint::hasAddress).map(Endpoint::getAddress).orElse(null)); + }).filter(t -> t.getEndpointIdentifierValue() != null && t.getEndpointUrl() != null) + .collect(Collectors.toList()); execution.setVariable(BPMN_EXECUTION_VARIABLE_TARGETS, TargetsValues.create(new Targets(targets))); } + + private Optional<String> getEndpointIdentifierValue(Optional<Endpoint> endpoint) + { + return endpoint + .flatMap(e -> e.getIdentifier().stream() + .filter(i -> NAMINGSYSTEM_HIGHMED_ENDPOINT_IDENTIFIER.equals(i.getSystem())).findFirst()) + .map(Identifier::getValue); + } } diff --git a/dsf-bpe-process-update-resources/src/main/resources/bpe/executeUpdateResources.bpmn b/dsf-bpe-process-update-resources/src/main/resources/bpe/executeUpdateResources.bpmn index b19a714c..5b8d0d8b 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/bpe/executeUpdateResources.bpmn +++ b/dsf-bpe-process-update-resources/src/main/resources/bpe/executeUpdateResources.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0k0v4i2" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_executeUpdateResources" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_executeUpdateResources" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>SequenceFlow_0djh0eg</bpmn:outgoing> <bpmn:messageEventDefinition messageRef="Message_1r6vnvn" /> diff --git a/dsf-bpe-process-update-resources/src/main/resources/bpe/requestUpdateResources.bpmn b/dsf-bpe-process-update-resources/src/main/resources/bpe/requestUpdateResources.bpmn index 595694e7..12831980 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/bpe/requestUpdateResources.bpmn +++ b/dsf-bpe-process-update-resources/src/main/resources/bpe/requestUpdateResources.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0os0n0z" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.8.1"> - <bpmn:process id="highmedorg_requestUpdateResources" isExecutable="true" camunda:versionTag="0.5.0"> + <bpmn:process id="highmedorg_requestUpdateResources" isExecutable="true" camunda:versionTag="#{version}"> <bpmn:sequenceFlow id="SequenceFlow_1ryplwc" sourceRef="StartEvent_1" targetRef="selectResourceAndTargets" /> <bpmn:sequenceFlow id="SequenceFlow_1u4zxix" sourceRef="selectResourceAndTargets" targetRef="sendRequest" /> <bpmn:endEvent id="EndEvent_1f9cjs7"> @@ -10,9 +10,9 @@ <bpmn:sendTask id="sendRequest" name="sendRequest" camunda:class="org.highmed.dsf.bpe.message.SendRequest"> <bpmn:extensionElements> <camunda:inputOutput> - <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeUpdateResources/0.5.0</camunda:inputParameter> + <camunda:inputParameter name="instantiatesUri">http://highmed.org/bpe/Process/executeUpdateResources/#{version}</camunda:inputParameter> <camunda:inputParameter name="messageName">executeUpdateResourcesMessage</camunda:inputParameter> - <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-execute-update-resources|0.5.0</camunda:inputParameter> + <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/task-execute-update-resources|#{version}</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> <bpmn:incoming>SequenceFlow_1u4zxix</bpmn:incoming> diff --git a/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-executeUpdateResources.xml b/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-executeUpdateResources.xml index bdaa2b5f..96c4ca3f 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-executeUpdateResources.xml +++ b/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-executeUpdateResources.xml @@ -10,7 +10,7 @@ <valueString value="executeUpdateResourcesMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-execute-update-resources|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-execute-update-resources|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -33,14 +33,15 @@ </extension> <url value="http://highmed.org/bpe/Process/executeUpdateResources" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="ExecuteUpdateResources" /> <title value="Execute Update of Resources" /> <subtitle value="Process to Download and Execute FHIR Bundle" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-requestUpdateResources.xml b/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-requestUpdateResources.xml index d71a67b2..9cf917f4 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-requestUpdateResources.xml +++ b/dsf-bpe-process-update-resources/src/main/resources/fhir/ActivityDefinition/highmed-requestUpdateResources.xml @@ -10,7 +10,7 @@ <valueString value="requestUpdateResourcesMessage" /> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-request-update-resources|${version}" /> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/task-request-update-resources|#{version}" /> </extension> <extension url="requester"> <valueCoding> @@ -39,14 +39,15 @@ </extension> <url value="http://highmed.org/bpe/Process/requestUpdateResources" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="RequestUpdateResources" /> <title value="Request Update of Resources" /> <subtitle value="Process to Request a Bundle Download" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <contact> <name value="HiGHmed" /> diff --git a/dsf-bpe-process-update-resources/src/main/resources/fhir/CodeSystem/highmed-update-resources.xml b/dsf-bpe-process-update-resources/src/main/resources/fhir/CodeSystem/highmed-update-resources.xml index 6589ed88..3798441e 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/fhir/CodeSystem/highmed-update-resources.xml +++ b/dsf-bpe-process-update-resources/src/main/resources/fhir/CodeSystem/highmed-update-resources.xml @@ -7,13 +7,14 @@ </meta> <url value="http://highmed.org/fhir/CodeSystem/update-resources" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="HiGHmed_Update_Resources" /> <title value="HiGHmed Update Resources" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <description value="CodeSystem with standard values for the process update resources" /> <caseSensitive value="true" /> diff --git a/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources.xml b/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources.xml index 276e9aad..fce399be 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources.xml +++ b/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-execute-update-resources" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskExecuteUpdateResources" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/executeUpdateResources/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/executeUpdateResources/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> diff --git a/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources.xml b/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources.xml index 50b69c78..e8611fb9 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources.xml +++ b/dsf-bpe-process-update-resources/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources.xml @@ -7,12 +7,13 @@ </meta> <url value="http://highmed.org/fhir/StructureDefinition/task-request-update-resources" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="TaskRequestUpdateResources" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <fhirVersion value="4.0.1" /> <kind value="resource" /> <abstract value="false" /> @@ -22,7 +23,7 @@ <differential> <element id="Task.instantiatesUri"> <path value="Task.instantiatesUri" /> - <fixedUri value="http://highmed.org/bpe/Process/requestUpdateResources/${version}" /> + <fixedUri value="http://highmed.org/bpe/Process/requestUpdateResources/#{version}" /> </element> <element id="Task.input"> <extension url="http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name"> diff --git a/dsf-bpe-process-update-resources/src/main/resources/fhir/ValueSet/highmed-update-resources.xml b/dsf-bpe-process-update-resources/src/main/resources/fhir/ValueSet/highmed-update-resources.xml index 6ab0bb9d..f16f7642 100644 --- a/dsf-bpe-process-update-resources/src/main/resources/fhir/ValueSet/highmed-update-resources.xml +++ b/dsf-bpe-process-update-resources/src/main/resources/fhir/ValueSet/highmed-update-resources.xml @@ -7,13 +7,14 @@ </meta> <url value="http://highmed.org/fhir/ValueSet/update-resources" /> <!-- version managed by bpe --> - <version value="${version}" /> + <version value="#{version}" /> <name value="HiGHmed_Update_Resources" /> <title value="HiGHmed Update Resources" /> <!-- status managed by bpe --> <status value="unknown" /> <experimental value="false" /> - <date value="2021-08-24" /> + <!-- date managed by bpe --> + <date value="#{date}" /> <publisher value="HiGHmed" /> <description value="ValueSet with standard values for the process update resources" /> <immutable value="true" /> diff --git a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinitionTest.java b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinitionTest.java new file mode 100644 index 00000000..08c25ee3 --- /dev/null +++ b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/UpdateResourcesProcessPluginDefinitionTest.java @@ -0,0 +1,36 @@ +package org.highmed.dsf.bpe; + +import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROCESS_NAME_FULL_EXECUTE_UPDATE_RESOURCES; +import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROCESS_NAME_FULL_REQUEST_UPDATE_RESOURCES; +import static org.highmed.dsf.bpe.UpdateResourcesProcessPluginDefinition.VERSION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.highmed.dsf.fhir.resources.ResourceProvider; +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +import ca.uhn.fhir.context.FhirContext; + +public class UpdateResourcesProcessPluginDefinitionTest +{ + @Test + public void testResourceLoading() throws Exception + { + ProcessPluginDefinition definition = new UpdateResourcesProcessPluginDefinition(); + ResourceProvider provider = definition.getResourceProvider(FhirContext.forR4(), getClass().getClassLoader(), + new StandardEnvironment()); + assertNotNull(provider); + + var exec = provider.getResources(PROCESS_NAME_FULL_EXECUTE_UPDATE_RESOURCES + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(exec); + assertEquals(4, exec.count()); + + + var req = provider.getResources(PROCESS_NAME_FULL_REQUEST_UPDATE_RESOURCES + "/" + VERSION, + s -> ResourceProvider.empty()); + assertNotNull(req); + assertEquals(4, req.count()); + } +} diff --git a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateResource3MedicTtpExampleStarter.java b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateResource3MedicTtpExampleStarter.java index 9fa0731b..c6475c15 100644 --- a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateResource3MedicTtpExampleStarter.java +++ b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/AbstractUpdateResource3MedicTtpExampleStarter.java @@ -6,7 +6,7 @@ import static org.highmed.dsf.bpe.ConstantsUpdateResources.CODESYSTEM_HIGHMED_UPDATE_RESOURCE; import static org.highmed.dsf.bpe.ConstantsUpdateResources.CODESYSTEM_HIGHMED_UPDATE_RESOURCE_VALUE_BUNDLE_REFERENCE; import static org.highmed.dsf.bpe.ConstantsUpdateResources.CODESYSTEM_HIGHMED_UPDATE_RESOURCE_VALUE_ORGANIZATION_IDENTIFIER_SEARCH_PARAMETER; -import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES; +import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_PROCESS_URI_AND_LATEST_VERSION; import static org.highmed.dsf.bpe.start.ConstantsExampleStarters.NAMINGSYSTEM_HIGHMED_ORGANIZATION_IDENTIFIER_VALUE_TTP; @@ -39,7 +39,7 @@ private Task createStartResource(ExampleStarter starter, String ttpUrl) throws E Bundle allowList = getAllowList(starter, ttpUrl); Task task = new Task(); - task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES); + task.getMeta().addProfile(PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_AND_LATEST_VERSION); task.setInstantiatesUri(PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_PROCESS_URI_AND_LATEST_VERSION); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); diff --git a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java index 8c763dfa..d7c77bc6 100644 --- a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java +++ b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/ActivityDefinitionProfileTest.java @@ -1,11 +1,10 @@ package org.highmed.dsf.fhir.profile; +import static org.highmed.dsf.bpe.UpdateResourcesProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.UpdateResourcesProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.io.InputStream; -import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; @@ -28,7 +27,7 @@ public class ActivityDefinitionProfileTest private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-activity-definition-0.5.0.xml", "highmed-extension-process-authorization-0.5.0.xml", "highmed-extension-process-authorization-consortium-role-0.5.0.xml", "highmed-extension-process-authorization-organization-0.5.0.xml", @@ -50,40 +49,30 @@ public class ActivityDefinitionProfileTest @Test public void testExecuteUpdateResourcesValid() throws Exception { - try (InputStream in = Files.newInputStream( - Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeUpdateResources.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-executeUpdateResources.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } @Test public void testRequestUpdateResourcesValid() throws Exception { - try (InputStream in = Files.newInputStream( - Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-requestUpdateResources.xml"))) - { - ActivityDefinition ad = validationRule.getFhirContext().newXmlParser() - .parseResource(ActivityDefinition.class, in); + ActivityDefinition ad = validationRule.readActivityDefinition( + Paths.get("src/main/resources/fhir/ActivityDefinition/highmed-requestUpdateResources.xml")); - ValidationResult result = resourceValidator.validate(ad); - ValidationSupportRule.logValidationMessages(logger, result); + ValidationResult result = resourceValidator.validate(ad); + ValidationSupportRule.logValidationMessages(logger, result); - assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) - || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); + assertEquals(0, result.getMessages().stream().filter(m -> ResultSeverityEnum.ERROR.equals(m.getSeverity()) + || ResultSeverityEnum.FATAL.equals(m.getSeverity())).count()); - assertTrue( - processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); - } + assertTrue(processAuthorizationHelper.isValid(ad, taskProfile -> true, orgIdentifier -> true, role -> true)); } } \ No newline at end of file diff --git a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java index b90a947f..1057c8fc 100644 --- a/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java +++ b/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/fhir/profile/TaskProfileTest.java @@ -13,6 +13,7 @@ import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES; import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_MESSAGE_NAME; import static org.highmed.dsf.bpe.ConstantsUpdateResources.PROFILE_HIGHMED_TASK_REQUEST_UPDATE_RESOURCES_PROCESS_URI_AND_LATEST_VERSION; +import static org.highmed.dsf.bpe.UpdateResourcesProcessPluginDefinition.RELEASE_DATE; import static org.highmed.dsf.bpe.UpdateResourcesProcessPluginDefinition.VERSION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -52,7 +53,7 @@ public class TaskProfileTest private static final Logger logger = LoggerFactory.getLogger(TaskProfileTest.class); @ClassRule - public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, + public static final ValidationSupportRule validationRule = new ValidationSupportRule(VERSION, RELEASE_DATE, Arrays.asList("highmed-task-base-0.5.0.xml", "highmed-task-request-update-resources.xml", "highmed-task-execute-update-resources.xml"), Arrays.asList("highmed-read-access-tag-0.5.0.xml", "highmed-bpmn-message-0.5.0.xml", @@ -66,7 +67,7 @@ public class TaskProfileTest @Test public void testGenerateSnapshotNotWorkingWithoutBaseSnapshot() throws Exception { - var reader = new StructureDefinitionReader(validationRule.getFhirContext()); + var reader = new StructureDefinitionReader(validationRule.getFhirContext(), VERSION, RELEASE_DATE); StructureDefinition base = reader.readXml("/fhir/StructureDefinition/highmed-task-base-0.5.0.xml"); StructureDefinition differential = reader diff --git a/pom.xml b/pom.xml index 24452a06..eeba23df 100644 --- a/pom.xml +++ b/pom.xml @@ -6,27 +6,30 @@ <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-highmed-processes-pom</artifactId> - <version>0.5.0</version> + <version>0.6.0</version> <packaging>pom</packaging> <modules> + <module>dsf-bpe-process-data-sharing</module> <module>dsf-bpe-process-feasibility</module> + <module>dsf-bpe-process-feasibility-mpc</module> <module>dsf-bpe-process-local-services</module> <module>dsf-bpe-process-ping</module> <module>dsf-bpe-process-update-allow-list</module> <module>dsf-bpe-process-update-resources</module> </modules> - + <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <compileSource>11</compileSource> <compileTarget>11</compileTarget> <main.basedir>${project.basedir}</main.basedir> + <dsf.version>0.6.0</dsf.version> </properties> <name>highmed-processes</name> - <description>HiGHmed Processes</description> + <description>Processes of the HiGHmed consortium to be deployed on the HiGHmed DSF</description> <url>https://github.com/highmed/highmed-processes</url> <scm> @@ -60,23 +63,32 @@ <dependencyManagement> <dependencies> - <!-- highmed-dsf --> <dependency> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-process-base</artifactId> - <version>0.5.0</version> + <version>${dsf.version}</version> </dependency> <dependency> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-fhir-validation</artifactId> - <version>0.5.0</version> + <version>${dsf.version}</version> </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-data-sharing</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-process-feasibility</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.highmed.dsf</groupId> + <artifactId>dsf-bpe-process-feasibility-mpc</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-process-local-services</artifactId> @@ -102,7 +114,7 @@ <dependency> <groupId>de.hs-heilbronn.mi</groupId> <artifactId>log4j2-utils</artifactId> - <version>0.10.0</version> + <version>0.13.0</version> </dependency> <!-- logging --> @@ -115,7 +127,12 @@ <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> - <version>2.12.4</version> + <version>2.13.2</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + <version>5.3.19</version> </dependency> <!-- testing --> @@ -127,7 +144,7 @@ <dependency> <groupId>org.highmed.dsf</groupId> <artifactId>dsf-bpe-process-base</artifactId> - <version>0.5.0</version> + <version>${dsf.version}</version> <scope>test</scope> <type>test-jar</type> </dependency> @@ -140,7 +157,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.8.1</version> + <version>3.10.1</version> <configuration> <source>${compileSource}</source> <target>${compileTarget}</target> @@ -154,7 +171,7 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> - <version>3.2.0</version> + <version>3.2.2</version> <configuration> <archive> <manifest> @@ -168,17 +185,15 @@ </archive> </configuration> </plugin> - <!-- <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> </plugin> - --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> - <version>3.2.0</version> + <version>3.3.0</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -188,13 +203,18 @@ <plugin> <groupId>net.revelc.code.formatter</groupId> <artifactId>formatter-maven-plugin</artifactId> - <version>2.16.0</version> + <version>2.18.0</version> </plugin> <plugin> <groupId>net.revelc.code</groupId> <artifactId>impsort-maven-plugin</artifactId> <version>1.6.2</version> </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <version>1.4</version> + </plugin> </plugins> </pluginManagement> @@ -202,7 +222,6 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>buildnumber-maven-plugin</artifactId> - <version>1.4</version> <executions> <execution> <phase>validate</phase>